Skip to content

fix(client): honor VAULT_CACERT and TLS env vars when connecting to Vault#114

Open
linuxus wants to merge 1 commit into
hashicorp:mainfrom
linuxus:fix/tls-cacert
Open

fix(client): honor VAULT_CACERT and TLS env vars when connecting to Vault#114
linuxus wants to merge 1 commit into
hashicorp:mainfrom
linuxus:fix/tls-cacert

Conversation

@linuxus

@linuxus linuxus commented Jun 10, 2026

Copy link
Copy Markdown

Problem

NewVaultClient (pkg/client/client.go) overwrites the Vault API client's HTTP transport with a fresh tls.Config that sets only InsecureSkipVerify:

tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: vaultSkipTLSVerify},
}
config.HttpClient = &http.Client{Transport: tr}

This discards the RootCAs (and client certificate / server name) that api.DefaultConfig() configures from the standard Vault TLS environment variables via ReadEnvironment(). As a result there is no way to trust a private or self-signed CA — for example a Vault started with vault server -dev-tls, or any Vault behind an internal PKI. The only available options are adding the CA to the host trust store or disabling verification entirely with VAULT_SKIP_VERIFY=true.

Fix

Configure TLS via config.ConfigureTLS(...), which updates the existing transport's TLSClientConfig in place (RootCAs, client certificate, ServerName) instead of replacing it. This honors the standard Vault env vars, consistent with the Vault CLI and other vault/api consumers:

Env var Effect
VAULT_CACERT CA bundle that signed Vault's listener cert
VAULT_CAPATH Directory of PEM CA files
VAULT_CLIENT_CERT / VAULT_CLIENT_KEY Mutual TLS
VAULT_TLS_SERVER_NAME Override SNI / certificate hostname

Skip-verify is then applied explicitly from the caller-resolved value. ConfigureTLS (and ReadEnvironment) only ever set InsecureSkipVerify to true and never clear it, so the flag is set directly to preserve the existing context-over-env precedence in both directions (this keeps TestCreateVaultClientForSession_SkipTLSVerify passing, including "context false wins over env true").

No public signature change; CreateVaultClientForSession is unaffected.

Testing

  • Added TestNewVaultClientHonorsCACert: spins up an httptest.NewTLSServer, writes its cert as a CA bundle, and asserts that a request succeeds with VAULT_CACERT set and fails without it (i.e. verification is not silently disabled).
  • go build ./..., go vet ./..., gofmt clean.
  • Full suite green: go test ./... (e2e, pkg/client, pkg/tools/kv), including the existing skip-verify precedence tests.

Manual verification

vault server -dev -dev-tls          # prints a CA at $TMPDIR/vault-ca.pem
export VAULT_ADDR=https://127.0.0.1:8200
export VAULT_CACERT=$TMPDIR/vault-ca.pem
# requests now verify against the dev CA instead of failing with
# "x509: certificate signed by unknown authority"

…ault

NewVaultClient replaced the Vault API client's HTTP transport with a fresh
tls.Config that set only InsecureSkipVerify, discarding the RootCAs (and
client cert / server name) that api.DefaultConfig() derives from the
standard Vault TLS environment variables via ReadEnvironment(). As a
result a private or self-signed CA (e.g. `vault server -dev-tls`, or Vault
behind internal PKI) could not be trusted: the only options were adding
the CA to the host trust store or disabling verification with
VAULT_SKIP_VERIFY=true.

Configure TLS through config.ConfigureTLS, which updates the existing
transport's TLSClientConfig in place (RootCAs, client certificate,
ServerName) instead of replacing it. This honors the standard Vault env
vars VAULT_CACERT, VAULT_CAPATH, VAULT_CLIENT_CERT, VAULT_CLIENT_KEY and
VAULT_TLS_SERVER_NAME.

Skip-verify is then applied explicitly from the caller-resolved value:
ConfigureTLS (and ReadEnvironment) only ever set InsecureSkipVerify to
true and never clear it, so setting it directly preserves the existing
context-over-env precedence in both directions. No public signature
change.

Add a test verifying that VAULT_CACERT lets the client verify a server
presenting a self-signed certificate, and that verification still fails
without it.
@linuxus linuxus requested a review from a team as a code owner June 10, 2026 21:42
@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

1 similar comment
@hashicorp-cla-app

Copy link
Copy Markdown

CLA assistant check

Thank you for your submission! We require that all contributors sign our Contributor License Agreement ("CLA") before we can accept the contribution. Read and sign the agreement

Learn more about why HashiCorp requires a CLA and what the CLA includes

Have you signed the CLA already but the status is still pending? Recheck it.

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.

1 participant