mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-06 22:57:02 +02:00
355 lines
12 KiB
Plaintext
355 lines
12 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Sync secrets from Vault to GitHub
|
|
description: >-
|
|
Automatically sync and unsync the secrets from Vault to GitHub to centralize visibility and control of secrets lifecycle management.
|
|
---
|
|
|
|
# Sync secrets from Vault to GitHub
|
|
|
|
The GitHub actions sync destination allows Vault to safely synchronize secrets as GitHub organization, repository, or environment 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 (or a GitHub application) with access to modify organization and/or 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, you will need a configured [GitHub application](#github-application) or an
|
|
[access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
|
|
that has write permission on the target sync location in GitHub for "Secrets". The "Secrets" permissions in GitHub automatically includes read-only "Metadata" access.
|
|
|
|
|
|
<Warning title="Pitfalls of using an access token">
|
|
|
|
Access tokens are tied to a user account and can be revoked at any time, causing disruptions to the sync process.
|
|
GitHub applications are long-lived and do not expire. Using a GitHub application for authentication is preferred over using a personal access token.
|
|
|
|
</Warning>
|
|
|
|
### Repositories
|
|
|
|
Use `vault write` to configure a repository sync destination with an access token:
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/destinations/gh/DESTINATION_NAME \
|
|
access_token="GITHUB_ACCESS_TOKEN" \
|
|
secrets_location="GITHUB_SECRETS_LOCATION" \
|
|
repository_owner="GITHUB_OWNER_NAME" \
|
|
repository_name="GITHUB_REPO_NAME"
|
|
```
|
|
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```
|
|
$ vault write sys/sync/destinations/gh/hcrepo-sandbox \
|
|
access_token="github_pat_11ABC000000000000000000000DEF" \
|
|
secrets_location="repository" \
|
|
repository_owner="hashicorp" \
|
|
repository_name="hcrepo"
|
|
|
|
Key Value
|
|
--- -----
|
|
connection_details map[access_token:***** secrets_location:repository repository_owner:hashicorp repository_name:hcrepo]
|
|
name hcrepo-sandbox
|
|
type gh
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
### Environments
|
|
|
|
Use `vault write` to configure an environment sync destination:
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/destinations/gh/DESTINATION_NAME \
|
|
access_token="GITHUB_ACCESS_TOKEN" \
|
|
secrets_location="GITHUB_SECRETS_LOCATION" \
|
|
repository_owner="GITHUB_OWNER_NAME" \
|
|
repository_name="GITHUB_REPO_NAME" \
|
|
environment_name="GITHUB_ENVIRONMENT_NAME"
|
|
```
|
|
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```
|
|
$ vault write sys/sync/destinations/gh/hcrepo-sandbox \
|
|
access_token="github_pat_11ABC000000000000000000000DEF" \
|
|
secrets_location="repository" \
|
|
repository_owner="hashicorp" \
|
|
repository_name="hcrepo" \
|
|
environment_name="sandbox"
|
|
|
|
Key Value
|
|
--- -----
|
|
connection_details map[access_token:***** secrets_location:repository environment_name:sandbox repository_owner:hashicorp repository_name:hcrepo]
|
|
name hcrepo-sandbox
|
|
type gh
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
### Organizations
|
|
|
|
@include 'alerts/beta.mdx'
|
|
|
|
|
|
Beta limitations:
|
|
|
|
- You cannot update visibility (`organization_visibility`) after creating a
|
|
secrets sync destination.
|
|
- You cannot update the list of repositories with access to synced secrets
|
|
(`selected_repository_names`) after creating a secrets sync destination.
|
|
|
|
Sync secrets to GitHub organization to share those secrets across repositories
|
|
in the organizations. You choose to make secrets global to the organization,
|
|
limited to private/internal repos, or limited to specifically named repositories.
|
|
|
|
Refer to the [Secrets sync API docs](/vault/docs/sync/github#api) for detailed
|
|
configuration information.
|
|
|
|
<Warning>
|
|
|
|
Organization secrets are
|
|
[not visible to private repositories for GitHub Free accounts](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-an-organization).
|
|
|
|
</Warning>
|
|
|
|
Use `vault write` to configure an organization sync destination:
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/destinations/gh/DESTINATION_NAME \
|
|
access_token="GITHUB_ACCESS_TOKEN" \
|
|
secrets_location="GITHUB_SECRETS_LOCATION" \
|
|
organization_name="ORGANIZATION_NAME" \
|
|
organization_visibility="ORGANIZATION_VISIBILITY"
|
|
```
|
|
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```
|
|
$ vault write sys/sync/destinations/gh/hcrepo-sandbox \
|
|
access_token="github_pat_11ABC000000000000000000000DEF" \
|
|
secrets_location="organization" \
|
|
organization_name="hashicorp" \
|
|
organization_visibility="selected" \
|
|
selected_repository_names="hcrepo-1,hcrepo-2"
|
|
|
|
Key Value
|
|
--- -----
|
|
connection_details map[access_token:***** secrets_location:organization organization_name:hashicorp organization_visibility:all selected_repository_names:[hcrepo-1 hcrepo-2]]
|
|
name hcrepo-sandbox
|
|
type gh
|
|
```
|
|
|
|
</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>
|
|
|
|
```
|
|
Success! Enabled the kv-v2 secrets engine at: my-kv/
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
1. Create secrets you wish to sync with a target GitHub repository for Actions.
|
|
|
|
```shell-session
|
|
$ vault kv put -mount='my-kv' my-secret key1='val1' key2='val2'
|
|
```
|
|
|
|
**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/gh/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 gh
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
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 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.
|
|
|
|
## Security
|
|
|
|
<Note>
|
|
|
|
Vault syncs secrets differently depending on whether you have configured
|
|
`secret-key` or `secret-path` [granularity](/vault/docs/sync#granularity):
|
|
|
|
- `secret-key` granularity splits KVv2 secrets from Vault into key-value pairs
|
|
and stores the pairs as distinct entries in GitHub. For example,
|
|
`secrets.key1="val1"` and `secrets.key2="val2"`.
|
|
|
|
- `secret-path` granularity stores secrets as a single JSON string that contains
|
|
all the associated key-value pairs. For example, `{"key1":"val1", "key2":"val2"}`.
|
|
|
|
Since GitHub limits secrets to single-value secrets, the sync granularity defaults to `secret-key`.
|
|
|
|
</Note>
|
|
|
|
If using the secret-path granularity, it is strongly advised to mask individual values for each sub-key to prevent the
|
|
unintended disclosure of secrets in any GitHub Action outputs. The following snippet illustrates how to mask each secret values:
|
|
|
|
```yaml
|
|
name: Mask synced secret values
|
|
|
|
on:
|
|
workflow_dispatch
|
|
|
|
jobs:
|
|
synced-secret-examples:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: ✓ Mask synced secret values
|
|
run: |
|
|
for v in $(echo '${{ secrets.VAULT_KV_1234_MY_SECRET }}' | jq -r '.[]'); do
|
|
echo "::add-mask::$v"
|
|
done
|
|
```
|
|
|
|
If the GitHub destination uses the default `secret-key` granularity, the values are masked by GitHub automatically.
|
|
|
|
## GitHub application
|
|
|
|
Instead of authenticating with a personal access token, you can choose to
|
|
authenticate with a
|
|
[custom GitHub application](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app).
|
|
|
|
Start by following the GitHub instructions for
|
|
[installing a GitHub app](https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app).
|
|
to install your GitHub application on a specified repository and note the
|
|
assigned installation ID.
|
|
|
|
<Tip title="Your installation ID is in the app URL">
|
|
|
|
You can find your assigned installation ID in the URL path parameter:
|
|
`https://github.com/settings/installations/<INSTALLATION_ID>`
|
|
|
|
</Tip>
|
|
|
|
Then add your GitHub application to your Vault instance.
|
|
|
|
To use your GitHub application with Vault:
|
|
|
|
- The application must have permission to read and write secrets.
|
|
- You must generate a private key for the application on GitHub.
|
|
- The application must be installed on the repository you want to sync secrets with.
|
|
- You must know the application ID assigned by GitHub.
|
|
- You must know the installation ID assigned by GitHub.
|
|
|
|
Callback, redirect URLs, and webhooks are not required at this time.
|
|
|
|
To configure the application in Vault, use `vault write` with the
|
|
`sys/sync/github-apps` endpoint to assign a unique name and set the relevant
|
|
information:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/github-apps/<APP_NAME> \
|
|
app_id=<APP_ID> \
|
|
private_key=@/path/to/private/key
|
|
|
|
Key Value
|
|
--- -----
|
|
app_id <app-id>
|
|
fingerprint <fingerprint>
|
|
name <app-name>
|
|
private_key *****
|
|
```
|
|
</CodeBlockConfig>
|
|
|
|
<Tip title="Fingerprint verification">
|
|
|
|
Vault returns the fingerprint of the private_key provided to ensure that the
|
|
correct private key was configured and that it was not tampered with along the way.
|
|
You can compare the fingerprint to the one provided by GitHub.
|
|
For more information, see [Verifying private keys](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#verifying-private-keys).
|
|
|
|
</Tip>
|
|
|
|
|
|
Next, use `vault write` with the `sys/sync/destinations/gh` endpoint to
|
|
configure a GitHub destination that references your new GitHub application:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault write sys/sync/destinations/gh/<DESTINATION_NAME> \
|
|
installation_id=<INSTALLATION_ID> \
|
|
repository_owner=<GITHUB_USER> \
|
|
repository_name=<MY_REPO_NAME> \
|
|
app_name=<APP_NAME>
|
|
|
|
Key Value
|
|
--- -----
|
|
connection_details map[app_config:map[app_name:<app-name>] installation_id:<installation-id> repository_name:<repo-name> repository_owner:<repo-owner>]
|
|
name my-dest
|
|
options map[custom_tags:map[] granularity_level:secret-key secret_name_template:VAULT_{{ .MountAccessor | uppercase }}_{{ .SecretPath | uppercase }}_{{ .SecretKey | uppercase }}]
|
|
type gh
|
|
```
|
|
</CodeBlockConfig>
|
|
|
|
You can now [use your GitHub application to sync secrets with your GitHub repository](#usage).
|
|
|
|
## API
|
|
|
|
Please see the [secrets sync API](/vault/api-docs/system/secrets-sync) for more details.
|