5
0
Fork 0
mirror of https://github.com/hashicorp/vault-action.git synced 2025-11-07 07:06:56 +00:00
A GitHub Action that simplifies using HashiCorp Vault™ secrets as build variables.
Find a file
dependabot-preview[bot] 268a32f886
chore(deps-dev): bump @types/jest from 25.1.4 to 25.1.5 (#36)
Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 25.1.4 to 25.1.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-04-03 10:53:43 -05:00
.github chore: fix step output syntax 2020-02-20 11:38:11 -06:00
.vscode docs: add headers docs and toc 2020-03-11 14:11:13 -05:00
dist fix: fix got not being use correctly and path prefix 2020-03-31 12:15:30 -05:00
integrationTests chore: I really should PR changes 2020-03-31 12:20:05 -05:00
.gitignore Initial commit 2019-09-20 12:33:19 -05:00
action.js fix: fix got not being use correctly and path prefix 2020-03-31 12:15:30 -05:00
action.test.js chore: I really should PR changes 2020-03-31 12:20:05 -05:00
action.yml feat: add github auth and cleanup docs a little 2020-03-31 11:56:54 -05:00
docker-compose.yml feat(authenticate): add approle auth method (#10) 2020-01-28 19:10:19 -06:00
index.js feat: add initial code logic 2019-09-20 15:09:58 -05:00
jest.config.js chore(test): organize tests a bit better (#7) 2019-11-24 16:00:31 -06:00
jsconfig.json feat: add initial code logic 2019-09-20 15:09:58 -05:00
LICENSE Initial commit 2019-09-20 12:33:19 -05:00
package-lock.json chore(deps-dev): bump @types/jest from 25.1.4 to 25.1.5 (#36) 2020-04-03 10:53:43 -05:00
package.json feat: add github auth and cleanup docs a little 2020-03-31 11:56:54 -05:00
README.md docs: add note about exportEnv option 2020-04-03 10:52:40 -05:00

vault-action

A helper action for easily pulling secrets from HashiCorp Vault™.

By default, this action pulls from Version 2 of the K/V Engine. See examples below for how to use v1 as well as other non-K/V engines.

Example Usage

jobs:
    build:
        # ...
        steps:
            # ...
            - name: Import Secrets
              uses: RichiCoder1/vault-action
              with:
                url: https://vault.mycompany.com:8200
                token: ${{ secrets.VaultToken }}
                secrets: |
                    ci/aws accessKey | AWS_ACCESS_KEY_ID ;
                    ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
                    ci npm_token                    
            # ...

Authentication method

While most workflows will likely use a vault token, you can also use an approle to authenticate with vaule. You can configure which by using the method parameter:

  • token: (by default) you must provide a token parameter
...
with:
  url: https://vault.mycompany.com:8200
  token: ${{ secrets.VaultToken }}
  • approle: you must provide a roleId & secretId parameter
...
with:
  url: https://vault.mycompany.com:8200
  method: approle
  roleId: ${{ secrets.roleId }}
  secretId: ${{ secrets.secretId }}
  • github: you must provide the github token as githubToken
...
with:
  url: https://vault.mycompany.com:8200
  method: github
  githubToken: ${{ secrets.GITHUB_TOKEN }}

Key Syntax

The secrets parameter is a set of multiple secret requests separated by the ; character.

Each secret request is comprised of the path and the key of the desired secret, and optionally the desired Env Var output name.

{{ Secret Path }} {{ Secret Key }} | {{ Output Variable Name }}

Simple Key

To retrieve a key npmToken from path ci that has value somelongtoken from vault you could do:

with:
    secrets: ci npmToken

vault-action will automatically normalize the given secret selector key, and set the follow as environment variables for the following steps in the current job:

NPMTOKEN=somelongtoken

You can also access the secret via ouputs:

steps:
    # ...
    - name: Import Secrets
      id: secrets
      # Import config...
    - name: Sensitive Operation
      run: "my-cli --token '${{ steps.secrets.outputs.npmToken }}'"

Note: If you'd like to only use outputs and disable automatic environment variables, you can set the exportEnv option to false.

Set Output Variable Name

However, if you want to set it to a specific name, say NPM_TOKEN, you could do this instead:

with:
    secrets: ci npmToken | NPM_TOKEN

With that, vault-action will now use your requested name and output:

NPM_TOKEN=somelongtoken
steps:
  # ...
  - name: Import Secrets
    id: secrets
    # Import config...
  - name: Sensitive Operation
    run: "my-cli --token '${{ steps.secrets.outputs.NPM_TOKEN }}'"

Multiple Secrets

This action can take multi-line input, so say you had your AWS keys stored in a path and wanted to retrieve both of them. You can do:

with:
    secrets: |
        ci/aws accessKey | AWS_ACCESS_KEY_ID ;
        ci/aws secretKey | AWS_SECRET_ACCESS_KEY        

Using K/V version 1

By default, vault-action expects a K/V engine using version 2.

In order to work with a v1 engine, the kv-version parameter may be passed:

with:
    kv-version: 1

Custom K/V Engine Path

When you enable the K/V Engine, by default it's placed at the path secret, so a secret named ci will be accessed from secret/ci. However, if you enabled the secrets engine using a custom path, you can pass it as follows:

with:
    path: my-secrets
    secrets: ci npmToken

This way, the ci secret in the example above will be retrieved from my-secrets/ci.

Other Secret Engines

While this action primarily supports the K/V engine, it is possible to request secrets from other engines in Vault.

To do so when specifying the Secret Path, just append a leading formard slash (/) and specify the path as described in the Vault API documentation.

For example, to retrieve a stored secret from the cubbyhole engine, assuming you have a stored secret at the path foo with the contents:

{
  "foo": "bar",
  "zip": "zap"
}

You could request the contents like so:

with:
    secrets: |
        /cubbyhole/foo foo ;
        /cubbyhole/foo zip | MY_KEY ;        

Resulting in:

FOO=bar
MY_KEY=zap
steps:
  # ...
  - name: Import Secrets
    id: secrets
    # Import config...
  - name: Sensitive Operation
    run: "my-cli --token '${{ steps.secrets.outputs.foo }}'"
  - name: Another Sensitive Operation
    run: "my-cli --token '${{ steps.secrets.outputs.MY_KEY }}'"

Secrets pulled from the same Secret Path are cached by default. So if you, for example, are using the aws engine and retrieve a key, only a single key for a given path is returned.

e.g.:

with:
    secrets: |
        /aws/creds/ci access_key | AWS_ACCESS_KEY_ID ;
        /aws/creds/ci secret_key | AWS_SECRET_ACCESS_KEY        

would work fine.

NOTE: The Secret Key is pulled from the data property of the response.

Adding Extra Headers

If you ever need to add extra headers to the vault request, say if you need to authenticate with a firewall, all you need to do is set extraHeaders:

with:
    secrets: |
        ci/aws accessKey | AWS_ACCESS_KEY_ID ;
        ci/aws secretKey | AWS_SECRET_ACCESS_KEY        
    extraHeaders: |
      X-Secure-Id: ${{ secrets.SECURE_ID }}
      X-Secure-Secret: ${{ secrets.SECURE_SECRET }}      

This will automatically add the x-secure-id and x-secure-secret headers to every request to vault.

Vault Enterprise Features

Namespace

If you need to retrieve secrets from a specific vault namespace, all that's required is an additional parameter specifying the namespace.

steps:
    # ...
    - name: Import Secrets
      uses: RichiCoder1/vault-action
      with:
        url: https://vault-enterprise.mycompany.com:8200
        method: token
        token: ${{ secrets.VaultToken }}
        namespace: ns1
        secrets: |
            ci/aws accessKey | AWS_ACCESS_KEY_ID ;
            ci/aws secretKey | AWS_SECRET_ACCESS_KEY ;
            ci npm_token            

Masking - Hidding Secrets from Logs

This action uses GitHub Action's built-in masking, so all variables will automatically be masked (aka hidden) if printed to the console or to logs. This only obscures secrets from output logs. If someone has the ability to edit your workflows, then they are able to read and therefore write secrets to somewhere else just like normal GitHub Secrets.