Erica Thompson 0660ea6fac
Update README (#31244)
* 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>
2025-07-22 08:12:22 -07:00

340 lines
13 KiB
Plaintext

---
layout: docs
page_title: Sync secrets from Vault to GCP Secret Manager
description: >-
Automatically sync and unsync the secrets from Vault to GCP Secret Manager to centralize visibility and control of 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.
# Sync secrets from Vault to GCP Secret Manager
The Google Cloud Platform (GCP) Secret Manager sync destination allows Vault to safely synchronize secrets to your GCP projects.
This is a low footprint option that enables your applications to benefit from Vault-managed secrets without requiring them
to connect directly with Vault. This guide walks you through the configuration process.
Prerequisites:
* Ability to read or create KVv2 secrets
* Ability to create GCP Service Account credentials with access to the Secret Manager
* Ability to create sync destinations and associations on your Vault server
## Setup
1. If you do not already have a Service Account, navigate to the IAM & Admin page in the Google Cloud console to
[create a new Service Account](https://cloud.google.com/iam/docs/service-accounts-create) with the
[necessary permissions](/vault/docs/sync/gcpsm#permissions). [Instructions](/vault/docs/sync/gcpsm#provision-service-account)
to provision this Service Account via Terraform can be found below.
1. Configure a sync destination with the Service Account JSON credentials created in the previous step. See docs for
[alternative ways](/vault/docs/secrets/gcp#authentication) to pass in the `credentials` parameter.
```shell-session
$ vault write sys/sync/destinations/gcp-sm/my-dest \
credentials='@path/to/credentials.json'
replication_locations='us-east1,us-west1'
```
**Output:**
<CodeBlockConfig hideClipboard>
```plaintext
Key Value
--- -----
connection_details map[credentials:***** replication_locations:us-east1,us-west1]
name my-dest
type gcp-sm
```
</CodeBlockConfig>
## Usage
1. If you do not already have a KVv2 secret to sync, mount a new KVv2 secrets engine.
```shell-session
$ vault secrets enable -path=my-kv kv-v2
```
**Output**:
<CodeBlockConfig hideClipboard>
```plaintext
Success! Enabled the kv-v2 secrets engine at: my-kv/
```
</CodeBlockConfig>
1. Create secrets you wish to sync with a target GCP Secret Manager.
```shell-session
$ vault kv put -mount=my-kv my-secret foo='bar'
```
**Output**:
<CodeBlockConfig hideClipboard>
```plaintext
==== Secret Path ====
my-kv/data/my-secret
======= Metadata =======
Key Value
--- -----
created_time <timestamp>
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
```
</CodeBlockConfig>
1. Create an association between the destination and a secret to synchronize.
```shell-session
$ vault write sys/sync/destinations/gcp-sm/my-dest/associations/set \
mount='my-kv' \
secret_name='my-secret'
```
**Output:**
<CodeBlockConfig hideClipboard>
```plaintext
Key Value
--- -----
associated_secrets map[kv_1234/my-secret:map[accessor:kv_1234 secret_name:my-secret sync_status:SYNCED updated_at:<timestamp>]]
store_name my-dest
store_type gcp-sm
```
</CodeBlockConfig>
1. Navigate to the [Secret Manager](https://console.cloud.google.com/security/secret-manager) in the Google Cloud console
to confirm your secret was successfully created in your GCP project.
Moving forward, any modification on the Vault secret will be propagated in near real time to its GCP Secret Manager
counterpart. Creating a new secret version in Vault will create a new version in GCP Secret Manager. Deleting the secret
or the association in Vault will delete the secret in your GCP project as well.
## Replication policy
GCP can target specific geographic regions to provide strict control on where
your applications store data and sync secrets. You can target specific GCP
regions for each sync destinations during creation which will limit where Vault writes
secrets.
Regardless of the region limits on writes, synced secrets are always readable
globally when the client has the required permissions.
### Encryption keys
Vault can leverage customer-managed encryption keys (CMEK) instead of Google-managed keys to encrypt secrets in GCP Secret Manager
as part of the replication policy. To use CMEK, you must first create key ring(s) and key(s) as desired, ensuring that the key quantity
corresponds with the planned replication policy. The key rings and keys must be created before configuring the sync destination.
When using a global KMS key, it must be the only key set on the destination and the replication locations must remain unset, meaning
it can only be used with using GCP's automatic replication. When specifying regional keys, a key must be set for each region in the
replication location list. GCP key names are expected in the format of the entire resource ID, e.g. `projects/<project_id>/locations/<location_name>/keyRings/<key_ring_name>/cryptoKeys/<key_name>`. See the [API](#api) section for more details.
## Permissions
Enabling the Secret Manager API and the Cloud Resource Manager API's are prerequisites to using secrets sync with
GCP Secret Manager. Once both APIs are enabled, it may take several minutes for the changes to take effect within
the GCP project.
After the necessary APIs are active, the credentials given to Vault must have the following permissions to synchronize secrets:
```shell-session
secretmanager.secrets.create
secretmanager.secrets.delete
secretmanager.secrets.update
secretmanager.versions.add
secretmanager.versions.destroy
```
## Provision service account
Vault needs to be configured with credentials to establish a trust relationship with your GCP project so it can manage
Secret Manager secrets on your behalf. The IAM & Admin page in the Google Cloud console can be used to
[create a new Service Account](https://cloud.google.com/iam/docs/service-accounts-create) with access to the Secret Manager.
You can equally use the [Terraform Google provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs#authentication-and-configuration)
to provision a GCP Service Account with the appropriate policies.
1. Copy-paste this HCL snippet into a `secrets-sync-setup.tf` file.
```hcl
provider "google" {
// See https://registry.terraform.io/providers/hashicorp/google/latest/docs#authentication-and-configuration to setup the Google Provider
// for options on how to configure this provider. The following parameters or environment
// variables are typically used.
// Parameters
// region = "" (Optional)
// project = ""
// credentials = ""
// Environment Variables
// GOOGLE_REGION (optional)
// GOOGLE_PROJECT
// GOOGLE_CREDENTIALS (The path to a service account key file with the
// "Service Account Admin", "Service Account Key Admin",
// "Secret Manager Admin", and "Project IAM Admin" roles
// attached)
}
data "google_client_config" "config" {}
resource "google_service_account" "vault_secrets_sync_account" {
account_id = "gcp-sm-vault-secrets-sync"
description = "service account for Vault Secrets Sync feature"
}
// Production environments should use a more restricted role.
// The built-in secret manager admin role is used as an example for simplicity.
data "google_iam_policy" "vault_secrets_sync_iam_policy" {
binding {
role = "roles/secretmanager.admin"
members = [
google_service_account.vault_secrets_sync_account.email,
]
}
}
resource "google_project_iam_member" "vault_secrets_sync_iam_member" {
project = data.google_client_config.config.project
role = "roles/secretmanager.admin"
member = google_service_account.vault_secrets_sync_account.member
}
resource "google_service_account_key" "vault_secrets_sync_account_key" {
service_account_id = google_service_account.vault_secrets_sync_account.name
public_key_type = "TYPE_X509_PEM_FILE"
}
resource "local_file" "vault_secrets_sync_credentials_file" {
content = base64decode(google_service_account_key.vault_secrets_sync_account_key.private_key)
filename = "gcp-sm-sync-service-account-credentials.json"
}
output "vault_secrets_sync_credentials_file_path" {
value = abspath("${path.module}/${local_file.sync_service_account_credentials_file.filename}")
}
```
1. Execute a plan to validate the Terraform Google provider is properly configured.
```shell-session
$ terraform init && terraform plan
```
**Output:**
<CodeBlockConfig hideClipboard>
```plaintext
(...)
Plan: 4 to add, 0 to change, 0 to destroy.
```
</CodeBlockConfig>
1. Execute an apply to provision the Service Account.
```shell-session
$ terraform apply
```
**Output:**
<CodeBlockConfig hideClipboard>
```plaintext
(...)
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Outputs:
sync_service_account_credentials_file = "/path/to/credentials/file/gcp-sm-sync-service-account-credentials.json"
```
</CodeBlockConfig>
The generated Service Account credentials file can then be used to configure the Vault GCP Secret Manager destination
following the [setup](/vault/docs/sync/gcpsm#setup) steps.
## Targeting specific GCP projects
By default, the target GCP project to sync secrets with is derived from the service
account JSON [credentials](/vault/api-docs/system/secrets-sync#credentials) or application
default credentials for a particular GCP sync destination. This means secrets will be synced
within the parent project of the configured service account.
In some cases, it's desirable to use a single service account or [workload identity](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances)
to sync secrets with any number of GCP projects within an organization. To achieve this,
you can set the `project_id` parameter to the target project to sync secrets with:
```shell-session
$ vault write sys/sync/destinations/gcp-sm/my-dest \
project_id='target-project-id'
```
This overrides the project ID derived from the service account JSON credentials or application
default credentials. The service account must be [authorized](https://cloud.google.com/iam/docs/service-account-overview#locations)
to perform Secret Manager actions in the target project.
## Access management
You can allow or restrict access to secrets based on
[IAM conditions](https://cloud.google.com/iam/docs/conditions-resource-attributes#resource-name)
against the fully-qualified resource name. For secrets in Secret Manager, a fully-qualified resource name must have the following
format:
`projects/<project_number>/secrets/<secret_name>`
<Tip title="Use the project number, not the project ID">
The project **number** is not the same as the project **ID**. Project numbers
are **numeric** while project IDs are **alphanumeric**. They can be found on
the Project info panel in the web dashboard or on the Welcome screen.
</Tip>
For example, the default secret name template prepends the word `vault` to the
beginning of secret names. To prevent Vault from modifying secrets that were not
created by a sync operation, you can use a role binding against the resource
name with the `startsWith` condition:
```
resource.name.startsWith("projects/<project_number>/secrets/vault")
```
To prevent out-of-band overwrites, simply add a negative condition with `!` on any
write-access role bindings not being used by Vault that contain Secret Manager permissions:
```
!(resource.name.startsWith("projects/<project_number>/secrets/vault"))
```
To add conditions to IAM principles in GCP, click "+ADD IAM CONDITION" on the **Assign Roles** screen.
![Assign Roles screen in GCP with the "+ADD IAM CONDITION" link circled in red](/img/gcp-add-iam-conditions_light.png#light-theme-only)
![Assign Roles screen in GCP with the "+ADD IAM CONDITION" link circled in red](/img/gcp-add-iam-conditions_dark.png#dark-theme-only)
<Tip title="Refer to Google's Overview of IAM Conditions documentation">
[Google's documentation](https://cloud.google.com/iam/docs/conditions-overview) on IAM Conditions provides
further information on how they work and how they should be used, as well as their limits.
</Tip>
## API
Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details.