Vault
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 (or a GitHub application) with access to modify repository secrets
- Ability to create sync destinations and associations on your Vault server
Setup
- To get started with syncing Vault secrets to your GitHub repository, you will need a configured GitHub application or an access token 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.
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.If you decide to go with an access token, here's how you can configure a sync destination:
$ vault write sys/sync/destinations/gh/my-dest \
access_token="$ACCESS_TOKEN" \
repository_owner="$OWNER" \
repository_name="$NAME"
Output:
Key Value
--- -----
connection_details map[access_token:***** repository_owner:<owner> repository_name:<name>]
name my-dest
type gh
Usage
If you do not already have a KVv2 secret to sync, mount a new KVv2 secrets engine.
$ vault secrets enable -path=my-kv kv-v2
Output:
Success! Enabled the kv-v2 secrets engine at: my-kv/
Create secrets you wish to sync with a target GitHub repository for Actions.
$ vault kv put -mount='my-kv' my-secret foo='bar'
Output:
==== Secret Path ==== my-kv/data/my-secret ======= Metadata ======= Key Value --- ----- created_time <timestamp> custom_metadata <nil> deletion_time n/a destroyed false version 1
Create an association between the destination and a secret to synchronize.
$ vault write sys/sync/destinations/gh/my-dest/associations/set \ mount=my-kv \ secret_name=my-secret
Output:
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
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.
Security
Note
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"}
if the
destination is configured to use the secret-path
granularity level.
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:
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.
Start by following the GitHub instructions for installing a GitHub app. to install your GitHub application on a specified repository and note the assigned installation ID.
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>
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:
$ 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 *****
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.
Next, use vault write
with the sys/sync/destinations/gh
endpoint to
configure a GitHub destination that references your new GitHub application:
$ 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
You can now use your GitHub application to sync secrets with your GitHub repository.
API
Please see the secrets sync API for more details.