Inject secrets from Vault into Buildkite
Secret data used in Expeditor is stored in our Hashicorp Vault instance, which is only accessible to private pipelines. There are two methods of access secrets from Vault:
- Using the
vaultCLI to directly fetch secrets as part of a Bash script. - Injecting secrets as environment variables using the secrets DSL when the
vaultCLI is not accessible.
This guide will cover the latter.
The secrets DSL is available in the following contexts:
- General purpose Buildkite pipelines. The secrets DSL is available under the steps.#.expeditor.secrets or expeditor.secrets keyspace in your pipeline definition file..
- Chef Habitat Buildkite build pipelines. The secrets DSL is available under the studio_secrets keyspace in your shim pipeline definition file.
The structure of the secrets DSL is a hash where the key is the name of your environment variable and the value is another hash containing secret location data.
---
ENV_VAR_NAME:
... # secret location dataThere are three categories of secret location data that the secrets DSL supports:
- account. Secret data associated with dynamically generated account credentials for things like AWS and GitHub.
- path. Referencing static secret data stored at a specific path in Vault.
- value. A way to inject “plain text secrets” into an environment. This is commonly used with the studio_secrets implementation to take advantage of the automatic injection (and prefixing with
HAB_STUDIO_SECRET_) of environment variables into the Chef Habitat studio.
In this document we will refer to actions that Expeditor takes, however the implementation within the Buildkite pipelines themselves is handled by the vault-util helper. This helper utility is installed by default on the Core, Core Docker and Chef Habitat Build pipeline images. Rather than injecting the environment variables and their secrets as plain text into the Buildkite environment, Expeditor passes the content of the secrets DSL as the VAULT_UTIL_SECRETS environment variable to the Buildkite build. Inside the appropriate Buildkite step, the vault-util fetch-secret-env helper runs as part of the Buildkite environment hook to fetch and inject the secrets at runtime, helping ensure that no secrets are stored in plain text in the logs.
account
An account secret is one associated with dynamically generated credentials for one of the following services:
awsazuregithubgoogle
What differentiates account secrets from path or value secrets is that Expeditor ensures that multiple secrets from the same account work together. For example, let’s take a look at a pretty standard usage of the aws account type in the secrets DSL.
AWS_ACCESS_KEY_ID:
account: aws/chef-example
field: access_key_id
AWS_SECRET_ACCESS_KEY:
account: aws/chef-example
field: secret_access_key
AWS_SESSION_TOKEN:
account: aws/chef-example
field: session_token
AWS_REGION:
account: aws/chef-example
field: regionIn the code block above you can see we have four individual secrets: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, and AWS_REGION. All of those secrets are pulling specific fields for the fictional aws/chef-example account. What Expeditor does is ensure that all of those individual secrets are actually related to a single temporary STS credential set.
Expeditor does not enforce any special naming requirements for environment variables. The intent of the account secrets functionality is to provide a mechanism by which to easily inject environment variables into execution environments so that native tooling can detect their presence (e.g. AWS_ACCESS_KEY_ID). You are free to name the environment variables whatever you please.
aws
When you specify an AWS account, you’ll need to provide the name of the account for which you want to generate the temporary STS credentials. To determine which account is best for your situation, please consult the Release Engineering team.
- Available Fields
- The following fields are available for an AWS account secret.
Field Description access_key_idThe Access Key ID for the temporary IAM credentials secret_access_keyThe Secret Access Key for the temporary IAM credentials session_tokenThe Session Token for the temporary IAM credentials regionThe AWS region for which the temporary credentials have access. - Sample Usage
- Inject the three environment variables required by the AWS to communicate with AWS API using temporary STS credentials for the fictional
chef-exampleaccount.AWS_ACCESS_KEY_ID: account: aws/chef-example field: access_key_id AWS_SECRET_ACCESS_KEY: account: aws/chef-example field: secret_access_key AWS_SESSION_TOKEN: account: aws/chef-example field: session_tokenLet’s take a moment to walk through how this code block is processed.
- AWS_ACCESS_KEY_ID. Expeditor generates a temporary STS credentials, fetches the
access_key_idfield from the Vault secret, and assigns it to theAWS_ACCESS_KEY_IDenvironment variable. - AWS_SECRET_ACCESS_KEY. Expeditor sees that is has already generated temporary STS credentials for the
chef-exampleAWS account, so it fetches thesecret_access_keyfrom that cached Vault secret and assigns it to theAWS_SECRET_ACCESS_KEYenvironment variable. - AWS_SESSION_TOKEN. Expeditor repeats the same process again, fetching the
session_tokenfrom the cached Vault secret and assigning it to theAWS_SESSION_TOKENenvironment variable.
- AWS_ACCESS_KEY_ID. Expeditor generates a temporary STS credentials, fetches the
azure
When you specify an Azure account, you’ll need to provide the nickname for the tenant for which you want to generate temporary credentials. To determine which tenant is best for your situation, please consult the Release Engineering team.
- Available Fields
- The following fields are available for an Azure account secret.
Field Description tenant_idThe unique identifier for the Azure Tenant subscription_idThe unique identifier for the subscription within the Azure Tenant client_idThe ID for the Azure Application client_secretThe secret associated with the Azure Application - Sample Usage
- Inject the three environment variables required by Azure to communicate with the Azure API using temporary service principal credentials for the fictional
exampleAzure subscription.AZURE_TENANT_ID: account: azure/example field: tenant_id AZURE_CLIENT_ID: account: azure/example field: client_id AZURE_CLIENT_SECRET: account: azure/example field: client_secretLet’s take a moment to walk through how this code block is processed.
- AZURE_TENANT_ID. Expeditor generates temporary service principal credentials for the
examplesubscription, fetches thetenant_idfield from the Vault secret, and assigns it to theAZURE_TENANT_IDenvironment variable. - AZURE_CLIENT_ID. Expeditor sees that is has already generated the temporary service principal credentials for the
exampleAzure subscription, so it fetches theclient_idfrom that cached Vault secret and assigns it to theAZURE_CLIENT_IDenvironment variable. - AZURE_CLIENT_SECRET. Expeditor repeats the same process again, fetching the
session_tokenfrom the cached Vault secret and assigning it to theAZURE_CLIENT_SECRETenvironment variable.
- AZURE_TENANT_ID. Expeditor generates temporary service principal credentials for the
github
Generate a temporary access token for one our our GitHub organizations. See our projects page for a list of supported organizations. If no organization is specified, Expeditor will default to the chef organization.
- Available Fields
- The following fields are available for a GitHub account secret.
Field Description tokenA temporary access token for the specified GitHub organization. - Sample Usage
- Inject the
GITHUB_TOKENenvironment variable that can be used for interactions with the GitHub API for the inspec GitHub organization.GITHUB_TOKEN: account: github/inspec field: token
Generate a temporary Google Cloud Principal with access to the specified Application. To determine which application is best for your situation, please reach out to Release Engineering.
- Available Fields
- The following fields are available to your Google Cloud account secret.
Field Description tokenThe API KEY that can be used for communicating with the Google Cloud API. jsonThe service account keys JSON document that can be used for authenticating server applications. - Sample Usage: API Key
- Inject the
GOOGLE_API_KEYenvironment variable with access to the fictionalexampleapplication to use with the Google Cloud API.GOOGLE_API_KEY: account: google/example field: token - Sample Usage: Service Account Key
- Inject the
GOOGLE_APPLICATION_CREDENTIALSenvironment variable to access the fictionalexampleapplication using the Google Cloud SDK.GOOGLE_APPLICATION_CREDENTIALS: account: google/example field: json
path
A path secret is one associated with a specific secret stored in Vault. Path secrets have their path and field values fed directly into the vault read API. Expeditor does not do any additional processing like it does with account secrets. If you need assistance in accessing a specific secret, please reach out to the Release Engineering team.
- Sample Usage
- Inject the
MY_ENVIRONMENT_VARIABLEenvironment variable with the value of thefoobarfield of the secret located atsecret/myapp/custom_secretin Chef’s Hashicorp Vault instance.MY_ENVIRONMENT_VARIABLE: path: secret/myapp/custom_secret field: foobar
value
There are some situations, like specifying studio_secrets in the Habitat pipeline definition file, where you simply want to pass in a plain text value into the DSL. To do this, you can simply provide a value.
- Sample Usage
- Inject the
PLAINTEXT_SECRETenvironment variable with the plaintext value of “foo”.PLAINTEXT_SECRET: value: foo