Skip to content

feat: enforce TLS for Vault gRPC#25

Open
jh-lee-cryptolab wants to merge 4 commits intomainfrom
issue-17-tls
Open

feat: enforce TLS for Vault gRPC#25
jh-lee-cryptolab wants to merge 4 commits intomainfrom
issue-17-tls

Conversation

@jh-lee-cryptolab
Copy link
Contributor

@jh-lee-cryptolab jh-lee-cryptolab commented Mar 4, 2026

Summary

  • Enforce TLS by default for Vault gRPC (fail-secure: server refuses to start without certs unless VAULT_TLS_DISABLE=true)
  • Docker entrypoint auto-generates self-signed certificates for zero-config TLS
  • Add scripts/generate-certs.sh for manual cert generation (CA 4096-bit + server 2048-bit with SAN)
  • Server-side TLS only (no mTLS) — token auth handles identity, TLS handles confidentiality
  • Client-side changes (vault_client.py) deferred to a separate issue

Changes

File Description
vault/vault_grpc_server.py _load_tls_credentials() + serve_grpc() uses add_secure_port() / add_insecure_port()
vault/docker-entrypoint.sh New — auto self-signed cert gen, defaults VAULT_TLS_CERT/VAULT_TLS_KEY
vault/Dockerfile Added openssl, entrypoint, /app/certs directory
scripts/generate-certs.sh New — manual CA + server cert generation with configurable output dir and hostname
vault/.env.example TLS section (VAULT_TLS_CERT, VAULT_TLS_KEY, VAULT_TLS_DISABLE)
vault/docker-compose.yml TLS env vars + ./certs:/app/certs:rw volume
vault/vault-deployment.yml tls-certs volumeMount + vault-tls Secret (optional)
.gitignore certs/ directory pattern
vault/README.md TLS Configuration section with 4 deployment scenarios

Env Vars

Variable Purpose Required
VAULT_TLS_CERT Server certificate PEM path Yes (auto in Docker)
VAULT_TLS_KEY Server private key PEM path Yes (auto in Docker)
VAULT_TLS_DISABLE Set true for insecure mode No (default: TLS required)

Test Results (on production server)

Tested by building the TLS image and running a separate container on port 50061 alongside the existing production server (50052), without disrupting it.

Test Result
Self-signed cert auto-generation (Docker entrypoint) PASS
TLS server startup (TLS configured, TLSv1.3 AES_256_GCM_SHA384) PASS
Plaintext connection rejected PASS (_InactiveRpcError)
TLS + ca.pem gRPC health check PASS (SERVING)
VAULT_TLS_DISABLE=true → insecure mode PASS
Plaintext connection succeeds when TLS disabled PASS
# TLS handshake verification (openssl s_client)
subject=CN = rune-vault
issuer=CN = Rune-Vault CA
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Verify return code: 0 (ok)

# In-container test output
PASS: plaintext rejected — _InactiveRpcError
PASS: TLS health check — 1
PASS: plaintext works when TLS disabled — 1

Out of Scope

  • rune client TLS (rune/mcp/adapter/vault_client.py): insecure_channelsecure_channel with VAULT_CA_CERT support — requires rune install UX changes, tracked separately

Closes #17

TLS is required by default (fail-secure). Server refuses to start
without certificates unless VAULT_TLS_DISABLE=true is set.

- Add _load_tls_credentials() to vault_grpc_server.py
- Add docker-entrypoint.sh for auto self-signed cert generation
- Add scripts/generate-certs.sh for manual cert generation
- Update Dockerfile with openssl, entrypoint, /app/certs
- Add TLS env vars to docker-compose.yml, vault-deployment.yml
- Update .env.example and README.md with TLS documentation

Closes #17

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Container starts as root to fix ownership on bind-mounted volumes
(certs, vault_keys), then drops to the vault user via gosu.
This follows the same pattern as postgres/redis official images.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jh-lee-cryptolab jh-lee-cryptolab marked this pull request as draft March 6, 2026 00:58
jh-lee-cryptolab and others added 2 commits March 6, 2026 10:48
Vault container handles TLS natively via docker-entrypoint.sh,
so nginx/ngrok proxying is unnecessary. Bind gRPC port to 0.0.0.0
for direct TLS connections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Certificates generated without the actual server hostname/IP in SAN
cause TLSV1_ALERT_UNKNOWN_CA on client connections. Now the script
auto-detects the public IP via ifconfig.me and includes both the
hostname argument and public IP in the certificate SAN.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jh-lee-cryptolab jh-lee-cryptolab marked this pull request as ready for review March 6, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enforce TLS for Vault gRPC with developer-friendly certificate setup

1 participant