Skip to content

Cache Vault KV version by mount path to reduce preflight calls (CONCOURSE_VAULT_ENABLE_KV_MOUNT_CACHE)#9530

Merged
taylorsilva merged 10 commits into
concourse:masterfrom
IvanChalukov:vault_opt
Apr 20, 2026
Merged

Cache Vault KV version by mount path to reduce preflight calls (CONCOURSE_VAULT_ENABLE_KV_MOUNT_CACHE)#9530
taylorsilva merged 10 commits into
concourse:masterfrom
IvanChalukov:vault_opt

Conversation

@IvanChalukov

Copy link
Copy Markdown
Contributor

Changes proposed by this PR

closes #9514

This PR adds KV mount version caching for Vault so Concourse does not run mount preflight on every secret read.

What changed

  • Cache KV mount version by mount path.
  • Reuse cached value on subsequent reads under the same mount.
  • Keep preflight behavior for cache misses.

Notes to reviewer

Enablement

  • Feature flag env var: CONCOURSE_VAULT_ENABLE_KV_MOUNT_CACHE. Values are "true" or "false". Default behavior in this change: cache is disabled unless explicitly set (set to "true" to enable)
  • For var_sources:
var_sources:
  - name: main
    type: vault
    config:
      url: https://vault:8200
      path_prefix: /concourse
      namespace: main
      lookup_templates:
        - /main/test-iamge/{{.Secret}}
      auth_backend: token
      client_token: ...
      insecure_skip_verify: true
      enable_kv_mount_cache: true

Signed-off-by: IvanChalukov <ichalukov@gmail.com>
Signed-off-by: IvanChalukov <ichalukov@gmail.com>
Signed-off-by: IvanChalukov <ichalukov@gmail.com>
@IvanChalukov IvanChalukov requested a review from a team as a code owner April 14, 2026 15:11
…sions

Signed-off-by: IvanChalukov <ichalukov@gmail.com>
These tests validate that enabling the KV mount cache does not break
end-to-end credential resolution for both KV v1 and v2 mounts.

Signed-off-by: IvanChalukov <ichalukov@gmail.com>
Signed-off-by: IvanChalukov <ichalukov@gmail.com>

@Kump3r Kump3r left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, I tested by configuring the compose yaml with an internal Vault we use trough approle auth. I used debug logs as I do not have server side access to the Vault and the web container doesn't have ngrep, wireshark etc. and the cache is in memory. As I already spoke to you what is TBD from my perspective is the docs, helm and bosh packaging stuff. Logs from testing in collapsed details section.

Details

Logs enabled:

docker logs fork-concourse-ivan-web-1 | grep kv-mount-cache
{"timestamp":"2026-04-20T08:30:12.879820721Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-miss","data":{"name":"vault","secret-path":"test/test/concourse/test-vault/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T08:30:13.005661930Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-fetched-from-vault","data":{"is-v2":true,"mount-path":"test/","name":"vault","secret-path":"test/test/concourse/test-vault/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T08:30:13.005750680Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-stored","data":{"is-v2":true,"mount-path":"test/","name":"vault","session":"7"}}
{"timestamp":"2026-04-20T08:30:13.057563763Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-hit","data":{"is-v2":true,"mount-path":"test/","name":"vault","secret-path":"test/test/concourse/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T08:32:22.410623961Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-hit","data":{"is-v2":true,"mount-path":"test/","name":"vault","secret-path":"test/test/concourse/test-vault/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T08:32:22.694515545Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-hit","data":{"is-v2":true,"mount-path":"test/","name":"vault","secret-path":"test/test/concourse/test-secret/","session":"7"}}

Logs disabled:

docker logs fork-concourse-ivan-web-1 | grep kv-mount-cache
{"timestamp":"2026-04-20T09:36:32.028043715Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-disabled","data":{"name":"vault","secret-path":"test/test/concourse/test-vault/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T09:36:32.324927382Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-disabled","data":{"name":"vault","secret-path":"test/test/concourse/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T09:38:11.160152428Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-disabled","data":{"name":"vault","secret-path":"test/test/concourse/test-vault/test-secret/","session":"7"}}
{"timestamp":"2026-04-20T09:38:11.547221345Z","level":"debug","source":"atc","message":"atc.credential-manager.kv-mount-cache-disabled","data":{"name":"vault","secret-path":"test/test/concourse/test-secret/","session":"7"}}

Edit: let me know if you need help/reviews in the packaging stuff as well.

Signed-off-by: Taylor Silva <dev@taydev.net>
Signed-off-by: Taylor Silva <dev@taydev.net>
Signed-off-by: Taylor Silva <dev@taydev.net>
These tests pass even when the cache is disabled. They don't validate
that the cache has been hit.

The way the cache is implemented, it falls back to doing the `isKVv2()`
pre-flight request. So even if there was an error in the caching code,
this test would not catch it because we would be falling back to doing
the pre-flight request.

Signed-off-by: Taylor Silva <dev@taydev.net>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these tests, why is the cache disabled for the v2 client and enabled for the v1 client?

path "secret*" {
policy = "read"
}
`)).Run(t, "policy", "write", "concourse", "-")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is this needed? A /secret mount doesn't appear to be used in the tests here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a leftover from testing, it should be deleted as you did. Thanks for that!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure integration tests are very useful here. I think these tests pass regardless if the KV cache is enabled or not.

Update: yup, they pass even when the cache is disabled.

Integration tests take longer, so I'm always a bit hesitant to add them. As-is, these tests don't error if the mount cache is not being used.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for raising your concerns about the integration tests. I was unsure where the functionality should be validated and didn’t realize the tests would pass in both scenarios (enabled and disabled).

I’ll keep this in mind for future PRs.

@taylorsilva

Copy link
Copy Markdown
Member

I've gone ahead and removed the integration-level tests and added unit tests instead that fail if the cache is not hit on subsequent calls.

Cleaned up the small nits I mentioned as well.

I didn't make any other changes. Everything else LGTM. Feature works as expected. TY for working on this Ivan!

@taylorsilva taylorsilva moved this from Todo to In Progress in Pull Requests Apr 20, 2026
@taylorsilva taylorsilva added this to the v8.2.0 milestone Apr 20, 2026
@taylorsilva taylorsilva merged commit 0123f4e into concourse:master Apr 20, 2026
12 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Pull Requests Apr 20, 2026
@taylorsilva taylorsilva changed the title Cache Vault KV version by mount path to reduce preflight calls Cache Vault KV version by mount path to reduce preflight calls (CONCOURSE_VAULT_ENABLE_KV_MOUNT_CACHE) Apr 20, 2026
@IvanChalukov

Copy link
Copy Markdown
Contributor Author

@taylorsilva I've opened PRs for packaging stuff:

@taylorsilva

Copy link
Copy Markdown
Member

You da bestttt 🙏 👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Vault secret read makes two Vault API calls per secret (KV version preflight + secret read)

3 participants