diff --git a/.gitignore b/.gitignore index 8c7c498183..95e675edf5 100644 --- a/.gitignore +++ b/.gitignore @@ -72,6 +72,9 @@ enos/**/kubeconfig .idea .vscode +# VSCode debugger executable +__debug_bin* + dist/* # ignore ctags diff --git a/website/content/api-docs/system/secrets-sync.mdx b/website/content/api-docs/system/secrets-sync.mdx new file mode 100644 index 0000000000..f7fcf30eb2 --- /dev/null +++ b/website/content/api-docs/system/secrets-sync.mdx @@ -0,0 +1,538 @@ +--- +layout: api +page_title: /sys/sync - HTTP API +description: The `/sys/sync` endpoints are used to configure destinations and associate secrets to sync with these destinations. +--- + +# `/sys/sync` + +The `/sys/sync` endpoints are used to configure destinations and associate secrets to sync with these destinations. + +Each destination type has its own endpoint for creation & update operations, but share the same endpoints for read & +delete operations. + +## List destinations + +This endpoint lists all configured sync destination names regrouped by destination type. + +| Method | Path | +|:-------|:-------------------------| +| `LIST` | `/sys/sync/destinations` | + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request LIST + http://127.0.0.1:8200/v1/sys/sync/destinations +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "key_info": { + "aws-sm": [ + "my-dest-1" + ], + "gh": [ + "my-dest-1" + ] + }, + "keys": [ + "aws-sm", + "gh" + ] + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +## Read destination + +This endpoint retrieves information about the destination of a given type and name. Sensitive information from the +connection details are obfuscated. + +| Method | Path | +|:-------|:-------------------------------------| +| `GET` | `/sys/sync/destinations/:type/:name` | + +### Parameters + +- `type` `(string: )` - Specifies the destination type. This is specified as part of the URL. + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --reuquest GET + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1 +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "connection_details": { + "access_key_id": "*****", + "secret_access_key": "*****", + "region": "us-west-1" + }, + "name": "my-store-1", + "type": "aws-sm" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +## Delete destination + +This endpoint deletes information about the destination of a given type and name if it exists. Destinations still managing +associations cannot be deleted. + +| Method | Path | +|:---------|:-------------------------------------| +| `DELETE` | `/sys/sync/destinations/:type/:name` | + +### Parameters + +- `type` `(string: )` - Specifies the destination type. This is specified as part of the URL. + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request DELETE + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1 +``` + +## Create|Update AWS Secrets Manager destination + +This endpoint creates a destination to synchronize secrets with the AWS Secrets manager. + +| Method | Path | +|:-------|:--------------------------------------| +| `POST` | `/sys/sync/destinations/aws-sm/:name` | + +### Parameters + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `access_key_id` `(string: "")` - Access key id to authenticate against the AWS secrets manager. If omitted, authentication +fallbacks on the AWS credentials provider chain and tries to infer authentication from the environment. + +- `secret_access_key` `(string: "")` - Secret access key to authenticate against the AWS secrets manager. If omitted, +authentication fallbacks on the AWS credentials provider chain and tries to infer authentication from the environment. + +- `region` `(string: "")` - Region where to manage the secrets manager entries. If omitted, configuration fallbacks on +the AWS credentials provider chain and tries to infer region from the environment. + +### Sample payload +```json +{ + "access_key_id": "AKI***", + "secret_access_key": "ktri****", + "region": "us-west-1" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1 +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "connection_details": { + "access_key_id": "*****", + "secret_access_key": "*****", + "region": "us-west-1" + }, + "name": "my-store-1", + "type": "aws-sm" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +## Create|Update Azure Key Vault destination + +This endpoint creates a destination to synchronize secrets with an Azure Key Vault instance. + +| Method | Path | +|:-------|:----------------------------------------| +| `POST` | `/sys/sync/destinations/azure-kv/:name` | + +### Parameters + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `key_vault_uri` `(string: )` - URI of an existing Azure Key Vault instance. + +- `client_id` `(string: )` - Client ID of an Azure app registration. + +- `client_secret` `(string: )` - Client secret of an Azure app registration. + +- `tenant_id` `(string: )` - ID of the target Azure tenant. + +- `cloud` `(string: "cloud")` - Specifies a cloud for the client. The default is Azure Public Cloud. + + +### Sample payload +```json +{ + "key_vault_uri": "https://keyvault-1234abcd.vault.azure.net", + "subscription_id": "uuid", + "tenant_id": "uuid", + "client_id": "uuid", + "client_secret": "90y8Q***" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1 +``` + +## Create|Update GCP Secret Manager destination + +This endpoint creates a destination to synchronize secrets with the GCP Secret Manager. + +| Method | Path | +|:-------|:--------------------------------------| +| `POST` | `/sys/sync/destinations/gcp-sm/:name` | + +### Parameters + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `credentials` `(string: )` - JSON credentials (either file contents or '@path/to/file') +See docs for [alternative ways](/vault/docs/secrets/gcp#authentication) to pass in to this parameter + +### Sample payload +```json +{ + "credentials": "" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/gcp-sm/my-store-1 +``` + +## Create|Update GitHub Repository Action destination + +This endpoint creates a destination to synchronize action secrets with a GitHub repository. + +| Method | Path | +|:-------|:----------------------------------| +| `POST` | `/sys/sync/destinations/gh/:name` | + +### Parameters + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `access_token` `(string: )` - Fine-grained or personal access token. + +- `repository_owner` `(string: )` - GitHub organization or username that owns the repository. For example, if a repository is located at https://github.com/hashicorp/vault.git the owner is hashicorp. + +- `repisitory_name` `(string: )` - Name of the repository. For example, if a repository is located at https://github.com/hashicorp/vault.git the name is vault. + +### Sample payload +```json +{ + "access_token": "github_pat_12345", + "repository_owner": "my-organization-or-username", + "repository_name": "my-repository" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/gh/my-store-1 +``` + +## Create|Update Vercel Project destination + +This endpoint creates a destination to synchronize secrets with the GCP Secret Manager. + +| Method | Path | +|:-------|:----------------------------------------------| +| `POST` | `/sys/sync/destinations/vercel-project/:name` | + +### Parameters + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `access_token` `(string: )` - Vercel API access token with the permissions to manage environment variables. + +- `project_id` `(string: )` - Project ID where to manage environment variables. + +- `team_id` `(string: "")` - Team ID the project belongs to. Optional. + +- `deployment_environments` `(string: )` - Deployment environments where the environment variables are available. Accepts 'development', 'preview' & 'production'. + +### Sample payload +```json +{ + "access_token": ">", + "project_id": "prj_12345", + "deployment_environments": ["development", "preview", "production"] +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/vercel-project/my-store-1 +``` + + +## Read Associations + +This endpoint returns all existing associations for a given destination. An association references the mount via its accessor. +Associations also contain the latest sync status for the secret they represent. + + + + In the event a synchronisation operation does not succeed, the sync status will indicate the cause + of the error and is a useful tool when troubleshooting. + + + +| Method | Path | +|:-------|:--------------------------------------------------| +| `GET` | `/sys/sync/destinations/:type/:name/associations` | + +### Parameters + +- `type` `(string: )` - Specifies the destination type. This is specified as part of the URL. + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request GET + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1/associations +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "associated_secrets": { + "kv_eb4acbae/my-secret-1": { + "accessor": "kv_eb4acbae", + "secret_name": "my-secret-1", + "sync_status": "SYNCED", + "updated_at": "2023-09-20T10:51:53.961861096-04:00" + } + }, + "store_name": "my-store-1", + "store_type": "aws-sm" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +## Set Association + +This endpoint sets a new association for a given destination. If an equivalent association already exists, this request +does not create a duplicate but will trigger a sync operation and refresh the secret value on the external system. + + + + Only KV-v2 secrets are supported at the moment. + + + +| Method | Path | +|:-------|:------------------------------------------------------| +| `POST` | `/sys/sync/destinations/:type/:name/associations/set` | + +### Parameters + +- `type` `(string: )` - Specifies the destination type. This is specified as part of the URL. + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `mount` `(string: )` - Specifies the mount where the secret is located. For example, if you can read a secret +with `vault kv get -mount=my-kv my-secret-1`, the mount name is `my-kv`. + +- `secret_name` `(string: )` - Specifies the name of the secret to synchronize. For example, if you can read a secret +with `vault kv get -mount=my-kv my-secret-1`, the secret name is `my-secret-1`. + +### Sample payload +```json +{ + "mount": "my-kv", + "secret_name": "my-secret-1" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1/associations/set +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "associated_secrets": { + "kv_eb4acbae/my-secret-1": { + "accessor": "kv_eb4acbae", + "secret_name": "my-secret-1", + "sync_status": "SYNCED", + "updated_at": "2023-09-20T10:51:53.961861096-04:00" + } + }, + "store_name": "my-store-1", + "store_type": "aws-sm" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +## Remove Association + +This endpoint removes an existing association for a given destination. If an equivalent association already exists, this request +does not create a duplicate but will trigger a sync operation and refresh the secret value on the external system. + +| Method | Path | +|:-------|:------------------------------------------------------| +| `POST` | `/sys/sync/destinations/:type/:name/associations/set` | + +### Parameters + +- `type` `(string: )` - Specifies the destination type. This is specified as part of the URL. + +- `name` `(string: )` - Specifies the name for this destination. This is specified as part of the URL. + +- `mount` `(string: )` - Specifies the mount where the secret is located. For example, if you can read a secret +with `vault kv get -mount=my-kv my-secret-1`, the mount name is `my-kv`. + +- `name` `(string: )` - Specifies the name of the secret to synchronize. For example, if you can read a secret +with `vault kv get -mount=my-kv my-secret-1`, the secret name is `my-secret-1`. + +### Sample payload +```json +{ + "mount": "my-kv", + "secret_name": "my-secret-1" +} +``` + +### Sample request + +```shell-session +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST + --data @payload.json + http://127.0.0.1:8200/v1/sys/sync/destinations/aws-sm/my-store-1/associations/remove +``` + +### Sample response + +```json +{ + "request_id": "uuid", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "associated_secrets": { + "kv_eb4acbae/my-secret-1": { + "accessor": "kv_eb4acbae", + "secret_name": "my-secret-1", + "sync_status": "UNSYNCED", + "updated_at": "2023-09-20T10:51:53.961861096-04:00" + } + }, + "store_name": "my-store-1", + "store_type": "aws-sm" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` diff --git a/website/content/docs/sync/awssm.mdx b/website/content/docs/sync/awssm.mdx new file mode 100644 index 0000000000..10902e2251 --- /dev/null +++ b/website/content/docs/sync/awssm.mdx @@ -0,0 +1,147 @@ +--- +layout: docs +page_title: AWS Secrets Manager - Secrets Sync Destination +description: The AWS Secrets Manager destination syncs secrets from Vault to AWS. +--- + +# AWS Secrets Manager + +The AWS Secrets Manager destination enables Vault to sync and unsync secrets of your choosing into +an external AWS account. When configured, Vault will actively maintain the state of each externally-synced +secret in near-realtime. This includes sending new secrets, updating existing secret values, and removing +secrets when they either get dissociated from the destination or deleted from Vault. This enables the +ability to keep control of all your secrets localized while leveraging the benefits of the AWS Secrets Manager. + +Prerequisites: +* Ability to read or create KVv2 secrets +* Ability to create AWS IAM user and access keys with access to the Secrets Manager +* Ability to create sync destinations and associations on your Vault server + +## Setup + +1. Navigate to the [AWS Identity and Access Management (IAM) console](https://us-east-1.console.aws.amazon.com/iamv2/home#/home) + to configure a IAM user with access to the Secrets Manager. The following is an example policy outlining the required + permissions to use secrets syncing. + + ```json + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "secretsmanager:Create*", + "secretsmanager:Update*", + "secretsmanager:Delete*", + "secretsmanager:TagResource" + ], + "Resource": "arn:aws:secretsmanager:*:*:secret:vault*" + } + ] + } + ``` + +1. Configure a sync destination with the IAM user credentials created in the previous step. + + ```shell-session + $ vault write sys/sync/destinations/aws-sm/my-awssm-1 \ + access_key_id="$ACCESS_KEY_ID" \ + secret_access_key="$SECRET_ACCESS_KEY" \ + region='us-east-1' + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + connection_details map[access_key_id:***** region:us-east-1 secret_access_key:*****] + name my-awssm-1 + type aws-sm + ``` + + + +## 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:** + + + + ```plaintext + Success! Enabled the kv-v2 secrets engine at: my-kv/ + ``` + + + +1. Create secrets you wish to sync with a target AWS Secrets Manager. + + ```shell-session + $ vault kv put -mount=my-kv my-secret foo='bar' + ``` + + **Output:** + + + + ```plaintext + ==== Secret Path ==== + my-kv/data/my-secret + + ======= Metadata ======= + Key Value + --- ----- + created_time 2023-09-19T13:17:23.395109Z + custom_metadata + deletion_time n/a + destroyed false + version 1 + ``` + + + +1. Create an association between the destination and a secret to synchronize. + + ```shell-session + $ vault write sys/sync/destinations/aws-sm/my-awssm-1/associations/set \ + mount='my-kv' \ + secret_name='my-secret' + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + associated_secrets map[kv_37993f8a/my-secret:map[accessor:kv_37993f8a secret_name:my-secret sync_status:SYNCED updated_at:2023-09-19T13:17:35.085581-05:00]] + store_name aws1 + store_type aws-sm + ``` + + + +1. Navigate to the [Secrets Manager](https://console.aws.amazon.com/secretsmanager/) in the AWS console + to confirm your secret was successfully synced. + +Moving forward, any modification on the Vault secret will be propagated to its AWS Secrets Manager +counterpart. Creating a new secret version in Vault will update the one in AWS to the new version. Deleting either +the secret or the association in Vault will delete the secret in your AWS account as well. + +## Tutorial + +Refer to the [Vault Enterprise Secrets Sync tutorial](/vault/tutorials/enterprise/secrets-sync) +to learn how to configure the secrets sync between Vault and AWS Secrets Manager. + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/content/docs/sync/azurekv.mdx b/website/content/docs/sync/azurekv.mdx new file mode 100644 index 0000000000..8266420d01 --- /dev/null +++ b/website/content/docs/sync/azurekv.mdx @@ -0,0 +1,132 @@ +--- +layout: docs +page_title: Azure Key Vault - Secrets Sync Destination +description: The Azure Key Vault destination syncs secrets from Vault to Azure. +--- + +# Azure Key Vault + +The Azure Key Vault destination enables Vault to sync and unsync secrets of your choosing into +an external Azure account. When configured, Vault will actively maintain the state of each externally-synced +secret in realtime. This includes sending new secrets, updating existing secret values, and removing +secrets when they either get dissociated from the destination or deleted from Vault. + +Prerequisites: +* Ability to read or create KVv2 secrets +* Ability to create Azure AD user credentials with access to an Azure Key Vault +* Ability to create sync destinations and associations on your Vault server + +## Setup + +1. If you do not already have an Azure Key Vault instance, navigate to the Azure Portal to create a new + [Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/general/quick-create-portal). + +1. A service principal with a client id and client secret will be needed to configure Azure Key Vault as a + sync destination. This [guide](https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal) + will walk you through creating the service principal. + +1. Once the service principal is created, the next step is to + [grant the service principal](https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-guide?tabs=azure-cli) + access to Azure Key Vault. We recommend using the "Key Vault Secrets Officer" built-in role, + which gives sufficient access to manage secrets. + +1. Configure a sync destination with the service principal credentials and Key Vault URI created in the previous steps. + + ```shell-session + $ vault write sys/sync/stores/azure-kv/my-azure-1 \ + key_vault_uri="$KEY_VAULT_URI" \ + client_id="$CLIENT_ID" \ + client_secret="$CLIENT_SECRET" \ + tenant_id="$TENANT_ID" + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + connection_details map[client_id:123 client_secret:***** key_vault_uri:***** tenant_id:123] + name my-azure-1 + type azure-kv + ``` + + + +## 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:** + + + + ```plaintext + Success! Enabled the kv-v2 secrets engine at: my-kv/ + ``` + + + +1. Create secrets you wish to sync with a target Azure Key Vault. + + ```shell-session + $ vault kv put -mount='my-kv' my-secret foo='bar' + ``` + + **Output:** + + + + ```plaintext + ==== Secret Path ==== + my-kv/data/my-secret + + ======= Metadata ======= + Key Value + --- ----- + created_time 2023-09-19T13:17:23.395109Z + custom_metadata + deletion_time n/a + destroyed false + version 1 + ``` + + + +1. Create an association between the destination and a secret to synchronize. + + ```shell-session + $ vault write sys/sync/destinations/azure-kv/my-azure-1/associations/set \ + mount='my-kv' \ + secret_name='my-secret' + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + associated_secrets map[kv_7532a8b4/my-secret:map[accessor:kv_7532a8b4 secret_name:my-secret sync_status:SYNCED updated_at:2023-09-21T13:53:24.839885-07:00]] + store_name my-azure-1 + store_type azure-kv + ``` + + + +1. Navigate to [Azure Key Vault](https://portal.azure.com/#view/HubsExtension/BrowseResource/resourceType/Microsoft.KeyVault%2Fvaults) + in the Azure portal to confirm your secret was successfully created. + +Moving forward, any modification on the Vault secret will be propagated in near real time to its Azure Key Vault +counterpart. Creating a new secret version in Vault will create a new version in Azure Key Vault. Deleting the secret +or the association in Vault will delete the secret in your Azure Key Vault as well. + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/content/docs/sync/gcpsm.mdx b/website/content/docs/sync/gcpsm.mdx new file mode 100644 index 0000000000..aea1a149a4 --- /dev/null +++ b/website/content/docs/sync/gcpsm.mdx @@ -0,0 +1,249 @@ +--- +layout: docs +page_title: Google Cloud Platform Secret Manager - Secrets Sync Destination +description: The Google Cloud Platform Secret Manager destination syncs secrets from Vault to GCP. +--- + +# Google Cloud Platform 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' + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + connection_details map[credentials:*****] + name my-dest + type gcp-sm + ``` + + + +## 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**: + + + + ```plaintext + Success! Enabled the kv-v2 secrets engine at: my-kv/ + ``` + + + +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**: + + + + ```plaintext + ==== Secret Path ==== + my-kv/data/my-secret + + ======= Metadata ======= + Key Value + --- ----- + created_time + custom_metadata + deletion_time n/a + destroyed false + version 1 + ``` + + + +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:** + + + + ```plaintext + Key Value + --- ----- + associated_secrets map[kv_1234/my-secret:map[accessor:kv_1234 secret_name:my-secret sync_status:SYNCED updated_at:]] + store_name my-dest + store_type gcp-sm + ``` + + + +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. + +## Permissions + +The credentials given to Vault must have the following permissions to synchronize secrets: + +```shell-session +secretmanager.secrets.create +secretmanager.secrets.delete +secretmanager.secrets.get +secretmanager.secrets.list +secretmanager.secrets.update +secretmanager.versions.access +secretmanager.versions.add +secretmanager.versions.destroy +secretmanager.versions.get +secretmanager.versions.list +``` + +## 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", and "Security 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:** + + + + ```plaintext + (...) + Plan: 4 to add, 0 to change, 0 to destroy. + ``` + + + +1. Execute an apply to provision the Service Account. + + ```shell-session + $ terraform apply + ``` + + **Output:** + + + + ```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" + ``` + + + +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. + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/content/docs/sync/github.mdx b/website/content/docs/sync/github.mdx new file mode 100644 index 0000000000..5a774b2489 --- /dev/null +++ b/website/content/docs/sync/github.mdx @@ -0,0 +1,129 @@ +--- +layout: docs +page_title: GitHub - Secrets Sync Destination +description: The GitHub destination syncs secrets from Vault to GitHub. +--- + +# GitHub repository secrets + +The GitHub repository sync destination allows Vault to safely synchronize secrets as GitHub repository action secrets. +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 GitHub fine-grained or personal tokens with access to modify repository secrets +* Ability to create sync destinations and associations on your Vault server + +## Setup + +1. To get started with syncing Vault secrets to your GitHub repository, you will need an + [access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) + which has access to the repository you want to manage secrets for and write permissions on the repository's actions secrets. + In the list of GitHub permissions, this is simply called "Secrets". Choosing this will automatically include read-only Metadata. + +1. Configure a sync destination with the access token created in the previous step. + + ```shell-session + $ vault write sys/sync/destinations/gh/my-dest \ + access_token="$ACCESS_TOKEN" \ + repository_owner="$OWNER" \ + repository_name="$NAME" + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + connection_details map[access_token:***** repository_owner: repository_name:] + name my-dest + type gh + ``` + + + +## 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:** + + + + ``` + Success! Enabled the kv-v2 secrets engine at: my-kv/ + ``` + + + +1. Create secrets you wish to sync with a target GitHub repository for Actions. + + ```shell-session + $ vault kv put -mount='my-kv' my-secret foo='bar' + ``` + + **Output:** + + + + ```plaintext + ==== Secret Path ==== + my-kv/data/my-secret + + ======= Metadata ======= + Key Value + --- ----- + created_time + custom_metadata + deletion_time n/a + destroyed false + version 1 + ``` + + + +1. Create an association between the destination and a secret to synchronize. + + ```shell-session + $ vault write sys/sync/destinations/gh/my-dest/associations/set \ + mount=my-kv \ + secret_name=my-secret + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + associated_secrets map[kv_1234/my-secret:map[accessor:kv_1234 secret_name:my-secret sync_status:SYNCED updated_at:>]] + store_name my-dest + store_type gh + ``` + + + +1. Navigate to your GitHub repository settings to confirm your secret was successfully created. + +Moving forward, any modification on the Vault secret will be propagated in near real time to its GitHub repository secrets +counterpart. Creating a new secret version in Vault will create a new version in GitHub. Deleting the secret +or the association in Vault will delete the secret in GitHub as well. + + + +GitHub only supports single value secrets, so KVv2 secrets from Vault will be stored as a JSON string. +In the example above, the value for secret "my-secret" will be synced to GitHub as the JSON string `{"foo":"bar"}`. + + + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/content/docs/sync/index.mdx b/website/content/docs/sync/index.mdx new file mode 100644 index 0000000000..8bcbbfc213 --- /dev/null +++ b/website/content/docs/sync/index.mdx @@ -0,0 +1,57 @@ +--- +layout: docs +page_title: Secrets Sync +description: Secrets sync allows you to safely sync Vault-managed secrets with external destinations. +--- + + + +# Secrets Sync + +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. + +## 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. + +* `SYNCING` - The sync operation for the secret is currently in-progress. +* `SYNCED` - The sync operation was successful and sent the secret to the external destination. +* `UNSYNCING` - The unsync operation for the secret is currently in-progress. +* `UNSYNCED` - The unsync operation was successful and removed the secret from the external destination. + This is returned when a secret itself is deleted but the association is not. +* `INTERNAL_VAULT_ERROR` - The sync or unsync operation failed due to an issue internal to Vault. +* `CLIENT_SIDE_ERROR` - The sync or unsync operation failed due to a configuration error. + For example, the credentials used to configure the destination expired or were revoked. +* `EXTERNAL_SERVICE_ERROR` - The sync or unsync operation failed due to an issue with the + external service provider's side. +* `UNKNOWN` - Vault is unable to determine the current state of the secret in regards to the external service. + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/content/docs/sync/vercelproject.mdx b/website/content/docs/sync/vercelproject.mdx new file mode 100644 index 0000000000..c7fb61340f --- /dev/null +++ b/website/content/docs/sync/vercelproject.mdx @@ -0,0 +1,132 @@ +--- +layout: docs +page_title: Vercel Project - Secrets Sync Destination +description: The Vercel Project destination syncs secrets from Vault to Vercel. +--- + +# Vercel Project environment variables + +The Vercel Project sync destination allows Vault to safely synchronize secrets as Vercel environment variables. +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 Vercel tokens with access to modify project environment variables +* Ability to create sync destinations and associations on your Vault server + +## Setup + +1. If you do not already have a Vercel token, navigate [your account settings](https://vercel.com/account/tokens) to + generate credentials with the necessary permissions to manage your project's environment variables. + +1. Next you need to locate your project ID. It can be found under the `Settings` tab in your project's overview page. + +1. Configure a sync destination with the access token and project ID obtained in the previous steps. + + ```shell-session + $ vault write sys/sync/destinations/vercel-project/my-dest \ + access_token="$TOKEN" \ + project_id="$PROJECT_ID" \ + deployment_environments=development \ + deployment_environments=preview \ + deployment_environments=production + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + connection_details map[access_token:***** deployment_environments:[development preview production] project_id:] + name my-dest + type vercel-project + ``` + + + +## 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:** + + + + ```plaintext + Success! Enabled the kv-v2 secrets engine at: my-kv/ + ``` + + + +1. Create secrets you wish to sync with a target Vercel project. + + ```shell-session + $ vault kv put -mount='my-kv' my-secret foo='bar' + ``` + + **Output:** + + + + ```plaintext + ==== Secret Path ==== + my-kv/data/my-secret + + ======= Metadata ======= + Key Value + --- ----- + created_time + custom_metadata + deletion_time n/a + destroyed false + version 1 + ``` + + + +1. Create an association between the destination and a secret to synchronize. + + ```shell-session + $ vault write sys/sync/destinations/vercel-project/my-dest/associations/set \ + mount='my-kv' \ + secret_name='my-secret' + ``` + + **Output:** + + + + ```plaintext + Key Value + --- ----- + associated_secrets map[kv_1234/my-secret:map[accessor:kv_1234 secret_name:my-secret sync_status:SYNCED updated_at:]] + store_name my-dest + store_type vercel-project + ``` + + + +1. Navigate to your project's settings under the `Environment Variables` section to confirm your secret was successfully + created in your Vercel project. + +Moving forward, any modification on the Vault secret will be propagated in near real time to its Vercel environment variable +counterpart. Creating a new secret version in Vault will overwrite the value in your Vercel Project. Deleting the secret +or the association in Vault will delete the secret on Vercel as well. + + + +Vercel Project environment variables only support single value secrets, so KVv2 secrets from Vault will be stored as a JSON string. +In the example above, the value for secret "my-secret" will be synced to Vercel as the JSON string `{"foo":"bar"}`. + + + +## API + +Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details. diff --git a/website/data/api-docs-nav-data.json b/website/data/api-docs-nav-data.json index 20bc2f9587..cedccaed77 100644 --- a/website/data/api-docs-nav-data.json +++ b/website/data/api-docs-nav-data.json @@ -715,6 +715,15 @@ } ] }, + { + "title": "/sys/sync", + "path": "system/secrets-sync", + "badge": { + "text": "ENT", + "type": "outlined", + "color": "neutral" + } + }, { "title": "/sys/tools", "path": "system/tools" diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index bc237de684..d3e151123b 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -1509,6 +1509,45 @@ } ] }, + { + "title": "Secrets Sync", + "badge": { + "text": "ENT", + "type": "outlined", + "color": "neutral" + }, + "routes": [ + { + "title": "Overview", + "path": "sync", + "badge": { + "text": "BETA", + "type": "outlined", + "color": "neutral" + } + }, + { + "title": "AWS Secrets Manager", + "path": "sync/awssm" + }, + { + "title": "Azure Key Vault", + "path": "sync/azurekv" + }, + { + "title": "GCP Secret Manager", + "path": "sync/gcpsm" + }, + { + "title": "GitHub", + "path": "sync/github" + }, + { + "title": "Vercel Project", + "path": "sync/vercelproject" + } + ] + }, { "title": "Auth Methods", "routes": [