Add vault_sni config for container TLS hostname override
The web UI connects to the vault API via gRPC using the Docker compose service name (e.g., "metacrypt:9443"), but the vault's TLS certificate has SANs for "crypt.metacircular.net" and "localhost". The new vault_sni config field overrides the TLS ServerName so certificate verification succeeds despite the hostname mismatch. Also updates metacrypt-rift.toml with vault_sni and temporarily binds the web UI port to 0.0.0.0 for direct access until mc-proxy is deployed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
user: "0:0"
|
user: "0:0"
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:18080:8080"
|
- "0.0.0.0:18080:8080" # TODO: revert to 127.0.0.1 once mc-proxy is deployed
|
||||||
volumes:
|
volumes:
|
||||||
- /srv/metacrypt:/srv/metacrypt
|
- /srv/metacrypt:/srv/metacrypt
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ type WebConfig struct {
|
|||||||
VaultGRPC string `toml:"vault_grpc"`
|
VaultGRPC string `toml:"vault_grpc"`
|
||||||
// VaultCACert is the path to the CA certificate used to verify the vault's TLS cert.
|
// VaultCACert is the path to the CA certificate used to verify the vault's TLS cert.
|
||||||
VaultCACert string `toml:"vault_ca_cert"`
|
VaultCACert string `toml:"vault_ca_cert"`
|
||||||
|
// VaultSNI overrides the TLS server name used to verify the vault's
|
||||||
|
// certificate. Use when the dial address (e.g., a container hostname)
|
||||||
|
// does not match any SAN on the vault's TLS certificate.
|
||||||
|
VaultSNI string `toml:"vault_sni"`
|
||||||
// TLSCert and TLSKey are optional. If empty, the web server uses plain HTTP
|
// TLSCert and TLSKey are optional. If empty, the web server uses plain HTTP
|
||||||
// (suitable for deployment behind a TLS-terminating reverse proxy).
|
// (suitable for deployment behind a TLS-terminating reverse proxy).
|
||||||
TLSCert string `toml:"tls_cert"`
|
TLSCert string `toml:"tls_cert"`
|
||||||
|
|||||||
@@ -31,10 +31,16 @@ type VaultClient struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewVaultClient dials the vault gRPC server and returns a client.
|
// NewVaultClient dials the vault gRPC server and returns a client.
|
||||||
func NewVaultClient(addr, caCertPath string, logger *slog.Logger) (*VaultClient, error) {
|
// NewVaultClient creates a gRPC client to the metacrypt vault API server.
|
||||||
|
// If sni is non-empty, it overrides the TLS server name for certificate
|
||||||
|
// verification (use when the dial address doesn't match a cert SAN).
|
||||||
|
func NewVaultClient(addr, caCertPath, sni string, logger *slog.Logger) (*VaultClient, error) {
|
||||||
logger.Debug("connecting to vault", "addr", addr, "ca_cert", caCertPath)
|
logger.Debug("connecting to vault", "addr", addr, "ca_cert", caCertPath)
|
||||||
|
|
||||||
tlsCfg := &tls.Config{MinVersion: tls.VersionTLS13}
|
tlsCfg := &tls.Config{MinVersion: tls.VersionTLS13} //nolint:gosec // TLS 1.3 minimum
|
||||||
|
if sni != "" {
|
||||||
|
tlsCfg.ServerName = sni
|
||||||
|
}
|
||||||
if caCertPath != "" {
|
if caCertPath != "" {
|
||||||
logger.Debug("loading vault CA certificate", "path", caCertPath)
|
logger.Debug("loading vault CA certificate", "path", caCertPath)
|
||||||
pemData, err := os.ReadFile(caCertPath) //nolint:gosec
|
pemData, err := os.ReadFile(caCertPath) //nolint:gosec
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ func (ws *WebServer) resolveUser(id string) string {
|
|||||||
// New creates a new WebServer. It dials the vault gRPC endpoint.
|
// New creates a new WebServer. It dials the vault gRPC endpoint.
|
||||||
func New(cfg *config.Config, logger *slog.Logger) (*WebServer, error) {
|
func New(cfg *config.Config, logger *slog.Logger) (*WebServer, error) {
|
||||||
logger.Info("connecting to vault", "addr", cfg.Web.VaultGRPC, "ca_cert", cfg.Web.VaultCACert)
|
logger.Info("connecting to vault", "addr", cfg.Web.VaultGRPC, "ca_cert", cfg.Web.VaultCACert)
|
||||||
vault, err := NewVaultClient(cfg.Web.VaultGRPC, cfg.Web.VaultCACert, logger)
|
vault, err := NewVaultClient(cfg.Web.VaultGRPC, cfg.Web.VaultCACert, cfg.Web.VaultSNI, logger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("webserver: connect to vault: %w", err)
|
return nil, fmt.Errorf("webserver: connect to vault: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user