Unit 6C — Secrets Sync
Enterprise. Expanded in 2.0.0 with workload identity federation. This is the capability that resolves “our applications can’t talk to Vault directly,” which is a more common blocker than it sounds.
Vault Enterprise helps organizations manage secrets sprawl by centralizing the governance and control of secrets stored within other secret managers.
First, some applications or services cannot communicate directly with Vault Enterprise. Cloud providers often support their own secrets management solutions. For example, AWS RDS Proxy and AWS Glue can only access database credentials provided by AWS Secrets Manager. This leads to secrets being spread across different cloud environments and CI/CD systems.
Second, organizations want full control over how their secrets are stored, organized, accessed, and protected, while also benefiting from cloud-native access. Secrets sync allows application owners to use their existing platform knowledge, reducing the effort needed to adopt Vault. By leveraging cloud provider tools, application owners can maintain their current workflows without learning new technologies.
The second point is the adoption argument. Sync lowers the barrier for teams who would otherwise resist Vault because it means learning a new API.
Sync destinations — five types: AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, GitHub organization/repository/environment secrets, and Vercel Project.
Secret associations — a single Vault secret can be linked to multiple destinations. Secret associations link an existing Vault K/V secret to a sync destination. Each secret has its own association, and many associations can share a destination.
Name templates — you can define the name format of synced secrets for each destination. The default name template is vault/<accessor>/<secret-path>. Name templates help prevent accidental name collisions at the destination and clearly identify the origin of the secrets.
Network path requirements: Vault requires network access to the secrets sync destinations, and this connectivity must be in place before using the feature. The same requirement applies to the disaster recovery cluster, which also needs outbound network access to the sync destinations. While the DR cluster may not use this connection during normal operations, having it ensures a successful transition in the event of a DR failover.
Same shape as the dynamic secrets network requirement in Unit 7.5 — secondaries need the same reachability as the primary.
Active node processing: Sync operations are only processed on the active node of a primary cluster. Write operations, such as writing an association or a K/V v2 secret, can only occur on the active node. This also means that secrets sync operations will not benefit from scaling the Vault cluster with either performance replication or adding performance standby nodes.
Secrets Sync does not scale horizontally. Put it beside tokenization (Unit 8B.5) in your mental model of primary-bound, non-scalable operations. If a customer expects sync throughput to grow by adding nodes, correct that early.
- Multiple secrets sync destinations: you can configure several within a single namespace, enabling you to associate secrets from different K/V mounts, as long as they reside within the same namespace as the destination.
- Name templates: each sync destination has its own name template. If you need different templates for secrets, you can define the same destination multiple times with different names.
- Per application configuration: configuring a secret sync destination for each application enables isolated management of secrets for different applications. This approach helps in managing policy requirements, templating, and rotation separately for each application.
- One destination per application: it is generally recommended to create one destination per application with multiple secret associations. This practice simplifies the access management via Vault policies, allows effective templating, adheres to rotation requirements for every application, while it can also help with secret segregation at the destination.
- DR considerations: the destinations might need to be DR-aware and have secret-specific configurations. For example, a primary application in AWS us-west-2 and a DR application in eu-west-1 might need different synced credentials, even if the same application is deployed.
Administrator roles. Only namespace administrators should configure sync destinations to avoid exposing high-privileged cloud service account credentials. They need high privileges, such as access to write capabilities for paths under /sys/sync.
User roles. Users need read access to the Vault secret itself before configuring a sync association. This ensures the Secret Sync feature cannot be used for privilege escalations.
That’s the security property to understand: without the read-first requirement, a user could sync a secret they can’t read to a destination they can read. Vault closes that path.
Security consideration — the one to state plainly to customers: Vault does not control permissions at the destination. It is the platform team’s responsibility to configure and maintain proper access controls on external systems to prevent unintentional access to synced secrets.
Syncing a secret out of Vault ends Vault’s authorization control over it.
Administrator policy:
# Allow full access to the secrets sync feature.
path "tenant-1/sys/sync/*" {
capabilities = ["read","create","update","delete","list"]
}
# List existing secret engines.
path "tenant-1/sys/mounts" {
capabilities = ["read", "list"]
}
# Manage secret engines.
path "tenant-1/sys/mounts/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
# Allow full access to the secret mount called 'secret'.
path "tenant-1/secret/*" {
capabilities = ["read","create","update","delete","list","patch"]
}
User policy:
# List existing destinations.
path "tenant-1/sys/sync/destinations*" {
capabilities = ["read", "list"]
}
# List existing associations.
path "tenant-1/sys/sync/associations*" {
capabilities = ["read", "list"]
}
# Create an association for destination type 'aws-sm' and destination name 'my-account'
path "tenant-1/sys/sync/destinations/aws-sm/my-account/associations/set" {
capabilities = ["create", "update"]
}
# Remove an association
path "tenant-1/sys/sync/destinations/aws-sm/my-account/associations/remove" {
capabilities = ["create", "update"]
}
# Allow full access to the secret mount called 'secret'.
path "tenant-1/secret/*" {
capabilities = ["read", "create", "update", "delete", "list", "patch"]
}
Admin configures a destination:
export VAULT_NAMESPACE=admin/tenant-1
vault write sys/sync/destinations/aws-sm/my-account \
access_key_id="$ACCESS_KEY_ID" \
secret_access_key="$SECRET_ACCESS_KEY" \
region="eu-north-1" \
secret_name_template="vault/{{ .NamespacePath }}{{ .MountPath }}/{{ .SecretPath }}"
User creates a secret and associates it:
export VAULT_NAMESPACE=admin/tenant-1
vault kv put secret/database/dev api_key="abc" key_id="123"
vault write sys/sync/destinations/aws-sm/my-account/associations/set \
mount="secret" \
secret_name="database/dev"
Unsync:
vault write sys/sync/destinations/aws-sm/my-account/associations/remove \
mount="secret" \
secret_name="database/dev"
- Update and removal: if a secret is updated or removed in Vault, the same changes will be reflected in the external systems. Applications should be rotation-aware to handle these updates seamlessly.
- Last-write-wins: Vault operates with a last-write-wins strategy. If a secret with the same name exists at the destination, Vault will overwrite it during synchronization.
- Use templates and tags to manage secret access at the destination effectively and to prevent accidental overwrites or exposure.
“Last-write-wins” plus “Vault doesn’t control destination permissions” is the combination that causes incidents. A name collision silently overwrites someone else’s secret. Name templates are the mitigation, not a nicety.
Scaling the secrets sync feature via automation can be effectively achieved using Terraform. Resource types: vault_secrets_sync_association, vault_secrets_sync_aws_destination, vault_secrets_sync_azure_destination, vault_secrets_sync_config, vault_secrets_sync_gcp_destination, vault_secrets_sync_gh_destination, vault_secrets_sync_github_apps, vault_secrets_sync_vercel_destination.
resource "vault_mount" "tenant_mount" {
path = "secret"
type = "kv"
options = {
version = "2"
}
}
resource "vault_kv_secret_v2" "tenant_secret" {
mount = vault_mount.tenant_mount.path
name = "database/dev"
data_json = jsonencode(
{}
)
lifecycle {
ignore_changes = [
data_json
]
}
}
resource "vault_secrets_sync_aws_destination" "aws" {
name = "my-account"
access_key_id = var.access_key_id
secret_access_key = var.secret_access_key
region = "eu-north-1"
secret_name_template = "vault/{{ .NamespacePath }}{{ .MountPath }}/{{ .SecretPath }}"
custom_tags = {
"ochestrator" = "terraform"
}
}
resource "vault_secrets_sync_association" "aws-test" {
name = vault_secrets_sync_aws_destination.aws.name
type = vault_secrets_sync_aws_destination.aws.type
mount = vault_mount.tenant_mount.path
secret_name = vault_kv_secret_v2.tenant_secret.name
}
Note the lifecycle { ignore_changes = [data_json] } block — it ignores changes that are done outside of Terraform, that means you can update this secret via Vault API, CLI or UI. That’s the pattern reconciling “policies as code” with “secrets not in the repo” from Unit 4.4.
AWS Secrets Manager. Define AWS IAM resource-based policies ensuring synced secrets are read-only in AWS Secrets Manager and are only readable by applications and services that need access. This prevents developers from reading or accidentally overwriting the secret values. Use AWS resource tags to allow or restrict access, and add a negative condition on all write-access policies not used by Vault to prevent out-of-band overwrites. Use IAM assume role instead of tying the secrets management policies directly to an IAM user for Vault — this also allows granting access to AWS Secrets Manager across AWS accounts.
Two AWS limitations that will surface in real engagements:
- AWS MSK can integrate with Secrets Manager using SASL/SCRAM, but requires a KMS encryption key different from the default. Vault secrets sync currently only supports the default KMS encryption key, so this integration will not work.
- AWS RDS Proxy — the current iteration of secrets sync does not support dynamic secrets (database secrets engine). Therefore, you would need to create database credentials manually in RDS and store them in Vault, which is not a best practice because AWS Secrets Manager has native support for rotating RDS credentials.
That second one is important: Secrets Sync syncs KV secrets, not dynamic secrets. If a customer expects to sync dynamic database credentials to RDS Proxy, that doesn’t work today.
GCP Secret Manager. Grant minimal permissions using roles like roles/secretmanager.viewer and roles/secretmanager.secretAccessor. Use role binding with conditions — the startsWith condition against resource names, combined with name templates. Separate environments using different projects or namespaces. Rotate secrets regularly — Google Secret Manager’s automatic rotation feature cannot be used with Vault, so you must manage rotation manually. Limitations: some IAM conditions are not currently supported for the Vault secrets sync service account, and customer-managed encryption keys cannot be used with Vault secrets sync.
Azure Key Vault. Create different Key Vaults for each application, environment, and region. This limits the blast radius of any security incident. Implement strict access controls using RBAC, private links, and firewalls. Limitation: Azure Key Vault supports secrets, keys, and certificates. Vault secrets sync only works with secrets. If you need to manage keys, consider using the Key Management Secrets Engine.
GitHub. Prefer GitHub applications over access tokens: access tokens are tied to user accounts and can be revoked at any time, which could disrupt the sync process. GitHub applications are long-lived and do not expire. Use environment-specific secrets for different deployment stages. Limitation: secrets sync currently only supports GitHub, not GitHub Enterprise.
Vercel. Separate environments for development, preview, and production. Limit variable size — keep each within the 64KB limit. Limitation: no shared environment variables across multiple projects, only per project.
HVD’s worked scenario, useful as a template for multi-team sync design:
- Root administrators — enable the secrets sync feature; set up tenant namespaces.
- Each application development team gets a tenant namespace, where namespace users can read and update K/V secrets and associate these secrets with a sync destination, and namespace admins have elevated admin rights and can set up and configure sync destinations.
This structure allows each development team to manage their secrets independently, while ensuring centralized auditing and control through Vault Enterprise.
For the consumer-side workflow, see the HVD User Guide page on Secrets Sync. Vault 2.0.0 added workload identity federation for Secrets Sync, allowing destinations to be configured without storing static cloud credentials — see /vault/docs/sync for current provider support.