mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-22 15:11:07 +02:00
* Update README Let contributors know that docs will now be located in UDR * Add comments to each mdx doc Comment has been added to all mdx docs that are not partials * chore: added changelog changelog check failure * wip: removed changelog * Fix content errors * Doc spacing * Update website/content/docs/deploy/kubernetes/vso/helm.mdx Co-authored-by: Tu Nguyen <im2nguyen@users.noreply.github.com> --------- Co-authored-by: jonathanfrappier <92055993+jonathanfrappier@users.noreply.github.com> Co-authored-by: Tu Nguyen <im2nguyen@users.noreply.github.com>
304 lines
15 KiB
Plaintext
304 lines
15 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Secrets sync
|
|
description: >-
|
|
Use secrets sync feature to automatically sync Vault-managed secrets with external destinations to centralize secrets lifecycle management.
|
|
---
|
|
|
|
> [!IMPORTANT]
|
|
> **Documentation Update:** Product documentation, which were located in this repository under `/website`, are now located in [`hashicorp/web-unified-docs`](https://github.com/hashicorp/web-unified-docs), colocated with all other product documentation. Contributions to this content should be done in the `web-unified-docs` repo, and not this one. Changes made to `/website` content in this repo will not be reflected on the developer.hashicorp.com website.
|
|
|
|
# Secrets sync
|
|
|
|
@include 'alerts/enterprise-and-hcp.mdx'
|
|
|
|
In certain circumstances, fetching secrets directly from Vault is impossible or impractical. To help with this challenge,
|
|
Vault can maintain a one-way sync for KVv2 secrets into various destinations that are easier to access for some clients.
|
|
With this, Vault remains the system of records but can cache a subset of secrets on various external systems acting as
|
|
trusted last-mile delivery systems.
|
|
|
|
A secret that is associated from a Vault KVv2 Secrets Engine into an external destination is actively managed by a continuous
|
|
process. If the secret value is updated in Vault, the secret is updated in the destination as well. If the secret is deleted
|
|
from Vault, it is deleted on the external system as well. This process is asynchronous and event-based. Vault propagates
|
|
modifications into the proper destinations automatically in a handful of seconds.
|
|
|
|
## Activating the feature
|
|
|
|
The secrets sync feature requires manual activation through a one-time trigger. If a sync-related endpoint is called prior to
|
|
activation, an error response will be received indicating that the feature has not been activated yet. Be sure to understand the
|
|
potential [client count impacts](#client-counts) of using secrets sync before proceeding.
|
|
|
|
Activating the feature can be done through one of several methods:
|
|
|
|
1. Activation directly through the UI.
|
|
|
|
1. Activation through the CLI:
|
|
|
|
```shell-session
|
|
$ vault write -f sys/activation-flags/secrets-sync/activate
|
|
```
|
|
|
|
1. Activation through a POST or PUT request:
|
|
|
|
```shell-session
|
|
$ curl \
|
|
--request PUT \
|
|
--header "X-Vault-Token: ..." \
|
|
http://127.0.0.1:8200/v1/sys/activation-flags/secrets-sync/activate
|
|
```
|
|
|
|
## Destinations
|
|
|
|
Secrets can be synced into various external systems, called destinations. The supported destinations are:
|
|
* [AWS Secrets Manager](/vault/docs/sync/awssm)
|
|
* [Azure Key Vault](/vault/docs/sync/azurekv)
|
|
* [GCP Secret Manager](/vault/docs/sync/gcpsm)
|
|
* [GitHub Repository Actions](/vault/docs/sync/github)
|
|
* [Vercel Projects](/vault/docs/sync/vercelproject)
|
|
|
|
## Associations
|
|
|
|
Syncing a secret into one of the external systems is done by creating a connection between it and a destination, which is
|
|
called an association. These associations are created via Vault's API by adding a KVv2 secret target to one of the configured
|
|
destinations. Each association keeps track of that secret's current sync status, the timestamp of its last status change, and
|
|
the error code of the last sync or unsync operation if it failed. Each destination can have any number of secret associations.
|
|
|
|
## Sync statuses
|
|
|
|
There are several sync statuses which relay information about the outcome of the latest sync
|
|
operation to have occurred on that secret. The status information is stored inside each
|
|
association object returned by the endpoint and, upon failure, includes an error code describing the cause of the failure.
|
|
|
|
| Status | Description |
|
|
|:-------------------------|:------------------------------------------------------------------------------------------------|
|
|
| `UNKNOWN` | Vault is unable to determine the current state of the secret in regard to the external service. |
|
|
| `PENDING` | An operation is queued for that secret and has not been processed yet. |
|
|
| `SYNCED` | The sync operation was successful and sent the secret to the external destination. |
|
|
| `UNSYNCED` | The unsync operation was successful and removed the secret from the external destination. |
|
|
| `INTERNAL_VAULT_ERROR` | The operation failed due to an issue internal to Vault. |
|
|
| `CLIENT_SIDE_ERROR` | The operation failed due to a configuration error such as invalid privileges. |
|
|
| `EXTERNAL_SERVICE_ERROR` | The operation failed due to an issue with the external service such as a temporary downtime. |
|
|
|
|
## Name template
|
|
|
|
By default, the name of synced secrets follows this format: `vault/<accessor>/<secret-path>`. The casing and delimiters
|
|
may change as they are normalized according to the valid character set of each destination type. This pattern was chosen to
|
|
prevent accidental name collisions and to clearly identify where the secret is coming from.
|
|
|
|
Every destination allows you to customize this name pattern by configuring a `secret_name_template` field to best suit
|
|
individual use cases. The templates use a subset of the go-template syntax for extra flexibility.
|
|
|
|
The following placeholders are available:
|
|
|
|
| Placeholder | Description |
|
|
|:--------------------|:------------------------------------------------------------------------------------------------------------|
|
|
| `DestinationType` | The type of the destination, e.g. "aws-sm" |
|
|
| `DestinationName` | The name of the destination |
|
|
| `NamespacePath` | The full namespace path where the secret being synced is located |
|
|
| `NamespaceBaseName` | The segment following the last `/` character from the full path |
|
|
| `NamespaceID` | The internal unique ID identifying the namespace, e.g. `RQegM` |
|
|
| `MountPath` | The full mount path where the secret being synced is located |
|
|
| `MountBaseName` | The segment following the last `/` character from the full path |
|
|
| `MountAccessor` | The internal unique ID identifying the mount, e.g. `kv_1234` |
|
|
| `SecretPath` | The full secret path |
|
|
| `SecretBaseName` | The segment following the last `/` character from the full path |
|
|
| `SecretKey` | The individual secret key being synced, only available if the destination uses the `secret-key` granularity |
|
|
|
|
The following example syncs the KV secrets.
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ VAULT_NAMESPACE=ns1/ns2 vault kv get -mount=path/to/kv1 path/to/secret1
|
|
|
|
========== Secret Path ==========
|
|
path/to/kv1/data/path/to/secret1
|
|
|
|
======= Metadata =======
|
|
(...)
|
|
|
|
=== Data ===
|
|
Key Value
|
|
--- -----
|
|
foo bar
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
The table below shows some name template examples and the resulting secret name at the sync destination.
|
|
|
|
| Name template | Result |
|
|
|:-----------------------------------------|:-----------------------|
|
|
| prefix-{{ .SecretPath }} | prefix-path/to/secret1 |
|
|
| {{ .SecretBaseName \| uppercase }} | SECRET1 |
|
|
| {{ .MountAccessor }}_{{ .SecretKey }} | kv_1234_foo |
|
|
| {{ .SecretPath \| replace \"/\" \"_\" }} | path_to_secret1 |
|
|
|
|
Name templates can be updated. The new template is only effective for new secrets associated with the destination and does
|
|
not affect the secrets synced with the previous template. It is possible to update an association to force a recreate operation.
|
|
The secret synced with the old template will be deleted and a new secret using the new template version will be synced.
|
|
|
|
## Custom tags
|
|
|
|
A destination can also have custom tags so that every secret associated to it that is synced will share that same set of tags.
|
|
Additionally, a default tag value of `hashicorp:vault` is used to denote any secret that is synced via Vault Enterprise. Similar
|
|
to secret names, tag keys and values are normalized according to the valid character set of each destination type.
|
|
|
|
## Granularity
|
|
|
|
Vault KV-v2 secrets are multi-value and their data is represented in JSON. Multi-value secrets are useful to bundle closely
|
|
related information together like a username & password pair. However, most secret management systems only support single-value
|
|
entries. Secrets sync allows you to choose the granularity that best suits your use case for each destination by specifying a `granularity`
|
|
field.
|
|
|
|
The `secret-path` granularity syncs the entire JSON content of the Vault secret as a single entry at the destination. If
|
|
the destination does not support multi-value secret the JSON is encoded as a single-value JSON-string.
|
|
|
|
The `secret-key` granularity syncs each Vault key-value pair as a distinct entry at the destination. If the value itself is a list or map
|
|
it is encoded as a JSON blob.
|
|
|
|
Granularity can be updated. The new granularity only affects secrets newly associated with the destination and does
|
|
not modify the previously synced secrets. It is possible to update an association to force a recreate operation.
|
|
The secret synced with the old granularity will be deleted and new secrets will be synced according to the new granularity.
|
|
|
|
## Security
|
|
|
|
Vault does not control the permissions at the destination. It is the responsibility
|
|
of the operator to configure and maintain proper access controls on the external system so synced
|
|
secrets are not accessed unintentionally.
|
|
|
|
### Vault access requirements
|
|
|
|
Vault verifies the client has read access on the secret before syncing it with any destination. This additional check is
|
|
there to prevent users from maliciously or unintentionally leveraging elevated permissions on an external system to access
|
|
secrets they normally wouldn't be able to.
|
|
|
|
The following example assumes you have a secret located at `path/to/data/secret1` and a user with write access to the sync feature, but no read access to that secret. This scenario is equivalent to this ACL policy:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```hcl
|
|
# Allow full access to the sync feature
|
|
path "sys/sync/*" {
|
|
capabilities = ["read", "list", "create", "update", "delete"]
|
|
}
|
|
|
|
# Allow read access to the secret mount path/to
|
|
path "path/to/*" {
|
|
capabilities = ["read"]
|
|
}
|
|
|
|
# Deny access to a specific secret
|
|
path "path/to/data/my-secret-1" {
|
|
capabilities = ["deny"]
|
|
}
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
If a client with this policy tries to read this secret they will receive an unauthorized error:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault kv get -mount=path/to my-secret-1
|
|
|
|
Error reading path/to/data/my-secret-1: Error making API request.
|
|
|
|
URL: GET http://127.0.0.1:8200/v1/path/to/data/my-secret-1
|
|
Code: 403. Errors:
|
|
|
|
* 1 error occurred:
|
|
* permission denied
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
Likewise, if the client tries to sync this secret to any destination they will receive a similar unauthorized error:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/destinations/$TYPE/$NAME/associations/set \
|
|
mount="path/to" \
|
|
secret_name="my-secret-1"
|
|
|
|
Error writing data to sys/sync/destinations/$TYPE/$NAME/associations/set: Error making API request.
|
|
|
|
URL: PUT http://127.0.0.1:8200/v1/sys/sync/destinations/$TYPE/$NAME/associations/set
|
|
Code: 403. Errors:
|
|
|
|
* permission denied to read the content of the secret my-secret-1 in mount path/to
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
This read access verification is only done when creating or updating an association. Once the association is created, revoking
|
|
read access to the policy that was used to sync the secret has no effect.
|
|
|
|
### Collisions and overwrites
|
|
|
|
Secrets Sync operates with a last-write-wins strategy. If a secret with the same name already exists at the destination,
|
|
Vault overwrites it when syncing a secret. There are also no automatic mechanisms to prevent a principal with sufficient
|
|
privileges at the destination from overwriting a secret synced by Vault.
|
|
|
|
To prevent Vault from accidentally overwriting existing secrets, it is recommended to use either a name pattern or
|
|
built-in tags as an extra policy condition on the role used to configure a Vault sync destination. A negative condition on other
|
|
policies may be used to prevent out-of-band overwrites to Vault secrets from non-Vault roles.
|
|
|
|
To see examples of policies that provide this type of restriction, refer to the access management section of the documentation
|
|
for each destination type below:
|
|
|
|
* [AWS Access Management](/vault/docs/sync/awssm#access-management)
|
|
* [GCP Access Management](/vault/docs/sync/gcpsm#access-management)
|
|
|
|
### Endpoint security
|
|
|
|
By default, Vault restricts the allowed IP addresses and port numbers used by the sync clients to safeguard against
|
|
server-side request forgery (SSRF). All special purpose IPs defined at the IANA special-purpose registry for
|
|
[IPv4](https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml) and
|
|
[IPv6](https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml) are blocked, while the only
|
|
two allowed ports are 80 and 443.
|
|
|
|
Both IP addresses and port numbers can be customized to fit the specific needs of the environment. This is useful in environments
|
|
where the destination service is behind things such as a private endpoint, a load balancer, or a proxy. This strict networking policy
|
|
can also be entirely disabled in environments where IP addresses or port numbers are not static values.
|
|
Refer to the [API](#api) section for more information on these parameters.
|
|
|
|
|
|
## Reconciliation
|
|
|
|
Vault Secrets Sync is designed to automatically recover from transient failures
|
|
in two ways: operation retries and reconciliation scans.
|
|
|
|
Operation retries happen when a sync operation fails. Vault automatically
|
|
retries the operation with exponential backoff. Operation retries help in
|
|
situations where your network becomes unreliable or overwhelmed.
|
|
|
|
Reconciliation scans happen periodically in a background thread. Vault scans all
|
|
secrets currently managed by the sync system to identify and update out-of-date
|
|
secrets, and to ensure that any configured destinations are up-to-date.
|
|
Reconciliation scans help in situations where there are external service downtimes
|
|
that are outside of your control and provide a way to automatically recover and self-heal.
|
|
|
|
Operation retries and reconciliation scans are both enabled by default.
|
|
|
|
Note that reconciliation process do not protect from out-of-band updates
|
|
that occur directly in the external service. The secrets sync system is designed to be
|
|
one-way and does not support bidirectional sync at this time.
|
|
|
|
## Client counts
|
|
|
|
Each secret that is synced with one or more destinations is counted as a
|
|
distinct client in Vault's client counting. See [entity assignments with secret
|
|
sync](/vault/docs/concepts/client-count#secret-sync-clients)
|
|
for more information.
|
|
|
|
## Tutorial
|
|
|
|
Refer to the [Synchronize cloud native secrets](/vault/tutorials/enterprise/enable-secrets-sync) tutorial for an end-to-end example.
|
|
|
|
|
|
## API
|
|
|
|
Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. |