vault-plugin-secrets-github icon indicating copy to clipboard operation
vault-plugin-secrets-github copied to clipboard

Create ephemeral, finely-scoped @github access tokens using @hashicorp Vault.

[[https://github.com/martinbaillie/vault-plugin-secrets-github/actions][https://github.com/martinbaillie/vault-plugin-secrets-github/workflows/build/badge.svg]] [[https://codecov.io/gh/martinbaillie/vault-plugin-secrets-github][https://codecov.io/gh/martinbaillie/vault-plugin-secrets-github/branch/master/graph/badge.svg]] [[https://godoc.org/github.com/martinbaillie/vault-plugin-secrets-github][https://godoc.org/github.com/martinbaillie/vault-plugin-secrets-github?status.svg]] [[https://goreportcard.com/report/github.com/martinbaillie/vault-plugin-secrets-github][https://goreportcard.com/badge/github.com/martinbaillie/vault-plugin-secrets-github?status.svg]] [[https://github.com/martinbaillie/vault-plugin-secrets-github/releases/latest][https://img.shields.io/github/release/martinbaillie/vault-plugin-secrets-github.svg]]

  • Vault Plugin Secrets GitHub :TOC_2_gh:noexport:
  • [[#about][About]]
    • [[#why][Why?]]
    • [[#what][What?]]
    • [[#how][How?]]
  • [[#installation][Installation]]
    • [[#from-release][From release]]
    • [[#from-source][From source]]
    • [[#setup-github][Setup (GitHub)]]
    • [[#setup-vault][Setup (Vault)]]
  • [[#api][API]]
    • [[#token][Token]]
    • [[#permission-sets][Permission sets]]
    • [[#config][Config]]
    • [[#metrics][Metrics]]
    • [[#info][Info]]
  • [[#development][Development]]
    • [[#tests][Tests]]
  • [[#security][Security]]
  • About Are you using HashiCorp Vault and GitHub in your organisation? Do you want ephemeral, finely-scoped GitHub tokens? If so, this plugin might be for you.

#+begin_quote UPDATE: The plugin was recently demoed at HashiCorp's [[https://www.youtube.com/watch?v=JuzBolDyGdg&t=17308s][Hashitalks 2021]]. #+end_quote

** Why? Performing automation against GitHub APIs often neccessitates the creation of [[https://help.github.com/en/github/extending-github/git-automation-with-oauth-tokens][OAuth Tokens]]. These tokens are tied to a user account, have /very/ [[https://developer.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/#available-scopes][coarsely-scoped permissions]] and do not expire.

As an organisation owner this likely means your automation-savvy users have created personal access tokens with powerful permissions which are being neither rotated nor deleted.

You will also commonly have wasted at least one of your GitHub seats on a [[https://help.github.com/en/github/getting-started-with-github/types-of-github-accounts#personal-user-accounts][robot/machine user]] for CI/CD purposes. These users share a similar access token and SSH key story as your human users do, and additonally need their credentials managed and rotated for them (arguably made more awkward when authenticating through an IdP).

[[https://developer.github.com/apps/building-github-apps/][GitHub Apps]] offer a better approach to this automation problem:

  • They do not consume a seat (license) nor need credential management.
  • They have /much/ finer-grained [[https://developer.github.com/v3/apps/permissions/][permissions]] available to the access tokens.
  • The tokens they issue expire after one hour.

However, GitHub Apps require the management of at least one private key which is needed to mint the JWTs used for the [[https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation][App installation authentication]] token request flow.

** What? This plugin allows you to take advantage of your existing Vault deployment's durable storage backend to protect the GitHub App private key, and your enabled Vault authN/Z mechanisms and highly-available API to perform the GitHub App token request flow on behalf of your users.

** How? The Vault plugin acts as an intermediary for a GitHub App that you install into your organisation:

#+ATTR_ORG: :width 1024 #+CAPTION: Logical Architecture [[file:vault_github_plugin.png]]

Users login using your existing Vault auth backend(s) and, Vault RBAC permitting, can request GitHub tokens from the plugin. The plugin, in turn, authenticates with the GitHub App and requests a token on behalf of the user. This flow is better explained in the sequence diagram below:

#+CAPTION: Sequence Diagram [[https://mermaid-js.github.io/mermaid-live-editor/#/view/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gICAgcGFydGljaXBhbnQgVSBhcyBVc2VyXG4gICAgcGFydGljaXBhbnQgViBhcyBWYXVsdFxuICAgIHBhcnRpY2lwYW50IEcgYXMgR2l0SHViXG4gICAgTm90ZSBvdmVyIFU6IEh1bWFuLCBDSS9DRCBhZ2VudCBldGMuXG4gICAgVS0+PlY6IFBPU1QgeW91ci52YXVsdC5vcmcvdjEvYXV0aFxuICAgIGFjdGl2YXRlIFZcbiAgICBOb3RlIG92ZXIgVjogU1NPLCBBRCwgQ2xvdWQgSUFNIGV0Yy5cbiAgICBWLS0+PlU6IE9LXG4gICAgZGVhY3RpdmF0ZSBWXG4gICAgTm90ZSByaWdodCBvZiBVOiBSZXF1ZXN0IGEgR2l0SHViIHRva2VuXG4gICAgYWx0XG4gICAgVS0+PlY6IFBPU1QgeW91ci52YXVsdC5vcmcvdjEvZ2l0aHViL3Rva2VuXG4gICAgZWxzZSByZXBvczogWzEyMyw0NTZdLCBwZXJtczogXCJpc3N1ZXM6d3JpdGVcIlxuICAgIFUtPj5WOiBQT1NUIHlvdXIudmF1bHQub3JnL3YxL2dpdGh1Yi90b2tlblxuICAgIGVuZFxuICAgIGFjdGl2YXRlIFZcbiAgICBOb3RlIG92ZXIgVjogTWludCBKV1QgdXNpbmcgUHJpdmF0ZSBLZXlcbiAgICBWLT4+VjogR2l0SHViIEpXVCAoZXhwOiAxMG0pXG4gICAgVi0+Pkc6IFBPU1QgYXBpLmdpdGh1Yi5jb20vLi4uL2FjY2Vzc190b2tlbnNcbiAgICBHLS0+PlY6IHRva2VuOiBbIFwidjEuMTIzNDU2Nzg5Li4uXCIgZXhwOiBcIjFoXCIgXVxuICAgIFYtPj5WOiBSZWNvcmQgbWV0cmljcywgbG9nc1xuICAgIFYtLT4+VTogWyB0b2tlbjogXCJ2MS4xMjM0NTY3ODkuLi5cIiBleHA6IFwiMWhcIiBdXG4gICAgZGVhY3RpdmF0ZSBWXG4gICAgTm90ZSBvdmVyIFU6IFVzZSBhY2Nlc3MgdG9rZW4gb24gR2l0SHViXG4gICAgYWx0IE9wZXJhdGUgb24gcmVwb3N0b3JpZXMgYWNjZXNzIHRva2VuIGhhcyBwZXJtaXNzaW9ucyBvblxuICAgIFUtPj5HOiAkIGdpdCBjbG9uZSBodHRwczovL3gtYWNjZXNzLXRva2VuOnYxLjEyMzQ1Njc4OS4uLkBnaXRodWIuY29tL29yZy9yZXBvLmdpdFxuICAgIGVsc2UgUGVyZm9ybSBBUEkgcmVxdWVzdHMgYWdhaW5zdCByZXNvdXJjZXMgYWNjZXNzIHRva2VuIGhhcyBwZXJtaXNzaW9ucyBvblxuICAgIFUtPj5HOiAkIGN1cmwgLUggXCJBdXRob3JpemF0aW9uOiBCZWFyZXIgdjEuMTIzNDU2Nzg5Li4uXCIgaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXNvdXJjZVxuICAgIGVuZCIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0Iiwic2VxdWVuY2UiOnsibWlycm9yQWN0b3JzIjpmYWxzZSwiYWN0b3JNYXJnaW4iOjEyMCwibm90ZU1hcmdpbiI6MTAsIm1lc3NhZ2VNYXJnaW4iOjMwLCJib3hUZXh0TWFyZ2luIjoxLCJoZWlnaHQiOjMwLCJ3aWR0aCI6MjAwfX19][https://mermaid.ink/img/eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG4gICAgcGFydGljaXBhbnQgVSBhcyBVc2VyXG4gICAgcGFydGljaXBhbnQgViBhcyBWYXVsdFxuICAgIHBhcnRpY2lwYW50IEcgYXMgR2l0SHViXG4gICAgTm90ZSBvdmVyIFU6IEh1bWFuLCBDSS9DRCBhZ2VudCBldGMuXG4gICAgVS0+PlY6IFBPU1QgeW91ci52YXVsdC5vcmcvdjEvYXV0aFxuICAgIGFjdGl2YXRlIFZcbiAgICBOb3RlIG92ZXIgVjogU1NPLCBBRCwgQ2xvdWQgSUFNIGV0Yy5cbiAgICBWLS0+PlU6IE9LXG4gICAgZGVhY3RpdmF0ZSBWXG4gICAgTm90ZSByaWdodCBvZiBVOiBSZXF1ZXN0IGEgR2l0SHViIHRva2VuXG4gICAgYWx0XG4gICAgVS0+PlY6IFBPU1QgeW91ci52YXVsdC5vcmcvdjEvZ2l0aHViL3Rva2VuXG4gICAgZWxzZSByZXBvczogWzEyMyw0NTZdLCBwZXJtczogXCJpc3N1ZXM6d3JpdGVcIlxuICAgIFUtPj5WOiBQT1NUIHlvdXIudmF1bHQub3JnL3YxL2dpdGh1Yi90b2tlblxuICAgIGVuZFxuICAgIGFjdGl2YXRlIFZcbiAgICBOb3RlIG92ZXIgVjogTWludCBKV1QgdXNpbmcgUHJpdmF0ZSBLZXlcbiAgICBWLT4+VjogR2l0SHViIEpXVCAoZXhwOiAxMG0pXG4gICAgVi0+Pkc6IFBPU1QgYXBpLmdpdGh1Yi5jb20vLi4uL2FjY2Vzc190b2tlbnNcbiAgICBHLS0+PlY6IHRva2VuOiBbIFwidjEuMTIzNDU2Nzg5Li4uXCIgZXhwOiBcIjFoXCIgXVxuICAgIFYtPj5WOiBSZWNvcmQgbWV0cmljcywgbG9nc1xuICAgIFYtLT4+VTogWyB0b2tlbjogXCJ2MS4xMjM0NTY3ODkuLi5cIiBleHA6IFwiMWhcIiBdXG4gICAgZGVhY3RpdmF0ZSBWXG4gICAgTm90ZSBvdmVyIFU6IFVzZSBhY2Nlc3MgdG9rZW4gb24gR2l0SHViXG4gICAgYWx0IE9wZXJhdGUgb24gcmVwb3N0b3JpZXMgYWNjZXNzIHRva2VuIGhhcyBwZXJtaXNzaW9ucyBvblxuICAgIFUtPj5HOiAkIGdpdCBjbG9uZSBodHRwczovL3gtYWNjZXNzLXRva2VuOnYxLjEyMzQ1Njc4OS4uLkBnaXRodWIuY29tL29yZy9yZXBvLmdpdFxuICAgIGVsc2UgUGVyZm9ybSBBUEkgcmVxdWVzdHMgYWdhaW5zdCByZXNvdXJjZXMgYWNjZXNzIHRva2VuIGhhcyBwZXJtaXNzaW9ucyBvblxuICAgIFUtPj5HOiAkIGN1cmwgLUggXCJBdXRob3JpemF0aW9uOiBCZWFyZXIgdjEuMTIzNDU2Nzg5Li4uXCIgaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXNvdXJjZVxuICAgIGVuZCIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0Iiwic2VxdWVuY2UiOnsibWlycm9yQWN0b3JzIjpmYWxzZSwiYWN0b3JNYXJnaW4iOjEyMCwibm90ZU1hcmdpbiI6MTAsIm1lc3NhZ2VNYXJnaW4iOjMwLCJib3hUZXh0TWFyZ2luIjoxLCJoZWlnaHQiOjMwLCJ3aWR0aCI6MjAwfX19?nothing.svg]]

#+BEGIN_COMMENT Mermaid source sequenceDiagram participant U as User participant V as Vault participant G as GitHub Note over U: Human, CI/CD agent etc. U->>V: POST your.vault.org/v1/auth activate V Note over V: SSO, AD, Cloud IAM etc. V-->>U: OK deactivate V Note right of U: Request a GitHub token alt U->>V: POST your.vault.org/v1/github/token else repos: [123,456], perms: "issues:write" U->>V: POST your.vault.org/v1/github/token end activate V Note over V: Mint JWT using Private Key V->>V: GitHub JWT (exp: 10m) V->>G: POST api.github.com/.../access_tokens G-->>V: token: [ "v1.123456789..." exp: "1h" ] V->>V: Record metrics, logs V-->>U: [ token: "v1.123456789..." exp: "1h" ] deactivate V Note over U: Use access token on GitHub alt Operate on repostories access token has permissions on U->>G: $ git clone https://x-access-token:[email protected]/org/repo.git else Perform API requests against resources access token has permissions on U->>G: $ curl -H "Authorization: Bearer v1.123456789..." https://api.github.com/resource end #+END_COMMENT #+BEGIN_COMMENT Mermaid style { "theme": "default", "sequence": { "mirrorActors": false, "actorMargin": 120, "noteMargin": 10, "messageMargin": 30, "boxTextMargin": 1, "height": 30, "width": 200 } } #+END_COMMENT

  • Installation To begin plugin installation, either download a [[./releases][release]] or build from source for your chosen OS and architecture.

** From release Always download the latest stable release from the [[./releases][releases]] section.

*** Verify

You can and should verify the authenticity and integrity of the plugin you downloaded. All released binaries are hashed and the resulting sums are signed by my GPG key.

#+BEGIN_SRC shell

Import my key.

curl -sS https://github.com/martinbaillie.gpg | gpg --import -

Verify the authenticity.

gpg --verify SHA256SUMS.sig SHA256SUMS

Verify the integrity.

shasum -a 256 -c SHA256SUMS #+END_SRC

** From source #+BEGIN_QUOTE NOTE: You will need a [[https://golang.org/dl/][Go 1.13+ toolchain]] to build this plugin from source. #+END_QUOTE

  1. Either download the source zip/tar.gz of the latest release from the [[./releases][releases]] section and uncompress, or shallow clone to the target release tag as in below:

    #+BEGIN_SRC shell git clone --depth 1 -b <target_release_tag>
    https://github.com/martinbaillie/vault-plugin-secrets-github.git #+END_SRC

  2. Build for your target OS and architecture. The [[./Makefile][Makefile]] has auto-generated targets for each supported combination (see: =make help=). Examples:

    #+BEGIN_SRC shell

    Build for Linux/AMD64.

    make vault-plugin-secrets-github-linux-amd64

    Build for OpenBSD/ARM.

    make vault-plugin-secrets-github-openbsd-arm

    Build every supported OS and architecture combination.

    make build #+END_SRC

** Setup (GitHub) #+BEGIN_QUOTE NOTE: You will need access to admin of your GitHub or GitHub Enterprise organisation to continue with the one-time setup. You can of course use this plugin on your personal account if so desired. #+END_QUOTE

  1. Sign in as an org admin and begin creating a new [[https://github.com/settings/apps/new][GitHub App.]]

  2. Choose any unique name, and homepage / webhook URLs (these can be anything; they are not required by the plugin). #+BEGIN_QUOTE NOTE: You may wish to take advantage of having GitHub call a webhook URL you own each time the App is used for auditing purposes. #+END_QUOTE

  3. Carefully choose the permissions the App will have access to. This is the superset of permissions. You will have the option of further restricting access to all or some repositories when you install an instance of the App, and users of this plugin will be able to even further restrict access in their individual token requests.

  4. Decide if you want the app to be installable to other accounts. Usually you just want the one you are signed into.

  5. Create the App. On the next screen GitHub will prompt you to create a Private Key. Do so, and save it somewhere safe (this is the key that will be ultimately lodged into the plugin configuration).

  6. Note the App ID at the top of this page as well. #+BEGIN_QUOTE NOTE: Get the App ID anytime: Settings > Developer > settings > GitHub App > About item. #+END_QUOTE

  7. Click Install App from the LHS. You will be taken to the account installation pages where you can confirm the app was installed.

  8. (OPTIONAL as of v1.3.0) Note the Installation ID from the URL of this page (usually: https://github.com/settings/installations/) if you wish to configure using the installation ID directly. #+BEGIN_QUOTE NOTE: Get the Installation ID anytime: Settings > Developer > settings > GitHub Apps > Advanced > Payload in Request tab. #+END_QUOTE

** Setup (Vault) Using the information noted from the previous step (Private Key, App ID and optionally the Installation ID), you are ready to move on to setting up the Vault plugin.

  1. Move the desired plugin binary into your Vault's configured =plugin_directory=.

    #+BEGIN_SRC shell mv vault-plugin-secrets-github-- <plugin_directory>/vault-plugin-secrets-github #+END_SRC

  2. (OPTIONAL) Allow [[https://linux.die.net/man/2/mlock][ =mlock()= ]] capabilities for the plugin binary. Memory locking is available to most UNIX-like OSes; the example below is for Linux.

    #+BEGIN_SRC shell setcap cap_ipc_lock=+ep <plugin_directory>/vault-plugin-secrets-github #+END_SRC

  3. (OPTIONAL) Calculate the SHA256 sum of the plugin and register it in Vault's plugin catalog. If you are downloading the pre-compiled binary, it is highly recommended that you use the published SHA256SUMS file.

    #+BEGIN_QUOTE NOTE: The rest of these commands assume you have a valid VAULT_TOKEN and VAULT_API environment variables. #+END_QUOTE

    #+BEGIN_SRC shell

    If using a pre-compiled binary:

    SHA256SUM=$(grep <downloaded_binary> SHA256SUMS | cut -d' ' -f1)

    If building from source:

    SHA256SUM=$(shasum -a 256 <compiled_binary> | cut -d' ' -f1)

    vault write sys/plugins/catalog/secret/vault-plugin-secrets-github
    sha_256=${SHA256SUM} command=vault-plugin-secrets-github #+END_SRC

  4. Mount the secrets engine, choosing a prefix path (recommendation: =github=).

    #+BEGIN_SRC shell vault secrets enable -path=github -plugin-name=vault-plugin-secrets-github plugin #+END_SRC

  5. Configure the plugin with the details noted from the previous section.

    #+BEGIN_SRC shell

    Write the configuration

    vault write /github/config app_id=<app_id> prv_key=@<private_key_file>

    (OPTIONAL) Confirm the configuration landed as you expected.

    vault read /github/config

    (OPTIONAL) Test a token creation.

    vault read /github/token #+END_SRC

  6. (OPTIONAL) Use Vault policy to constrain user capabilities on the GitHub endpoints. Example:

    #+BEGIN_SRC shell

Create a restrictive policy that only permits GitHub tokens that can write

pull requests to a single repository.

vault policy write github-only-prs -<<EOF path "github/token" { capabilities = ["update"] required_parameters = ["installation_id","permissions","repository_ids"] allowed_parameters = { "installation_id" = ["987654"] "repository_ids" = ["69857131"] "permissions"= ["pull_requests=write"] } } EOF

Create and login as an example user with the policy attached.

vault auth enable userpass vault write auth/userpass/users/martin password=baillie policies="github-only-prs" vault login -method=userpass username=martin password=baillie

Test the efficacy of the policy.

Successfully creates token:

vault write /github/token installation_id=987654 repository_ids=69857131 permissions=pull_requests=write

Permission denied:

vault write -f /github/token vault write /github/token installation_id=987654 permissions=pull_requests=write vault write /github/token installation_id=987654 repository_ids=69857131 permissions=pull_requests=read vault write /github/token installation_id=987654 repository_ids=69857131 permissions=metadata=read vault write /github/token installation_id=987654 repository_ids=123 permissions=pull_requests=write vault write /github/token installation_id=987654 repository_ids=69857131 vault write /github/token installation_id=123456 repository_ids=69857131 #+END_SRC

  • API Each plugin path is documented using Vault's own help framework. To find out more information about any path, use =vault path-help=. For brevity, the API is also documented below.

** Token Instruct the plugin to create an installation access token against the configured GitHub App.

| Method | Path | Produces | |--------+--------+------------------| | GET | /token | application/json | | POST | /token | application/json | | PUT | /token | application/json |

*** Parameters #+begin_quote NOTE: All parameters are optional. Omitting them results in a token that has access to all of the repositories and permissions that the GitHub App has.

When crafting Vault policy, hyper security sensitive organisations may wish to favour =repository_ids= (GitHub repository IDs are immutable) instead of =repositories= (GitHub repository names are mutable). #+end_quote

  • =installation_id= (int64) — the ID of the app installation.
  • =repositories= ([]string) — a list of the names of the repositories within the organisation that the installation token can access.
  • =repository_ids= ([]int64) — a list of the IDs of the repositories that the installation token can access. See this [[https://stackoverflow.com/a/47223479][StackOverflow post]] for the quickest way to find a repository ID.
  • =permissions= (map[string]string) — a key value map of permission names to their access type (read or write). See [[https://developer.github.com/v3/apps/permissions][GitHub's documentation]] on permission names and access types.

*** Examples #+BEGIN_SRC shell

Create a token with all the superset of all permissions and repositories that

the GitHub App installation has access to.

vault read /github/token

Create a token with read permissions on the packages and write permissions on

the pull requests of repositories named "demo-repo" and ID 123.

vault write /github/token
installation_id=456
repository_ids=123
repositories=demo-repo
permissions=packages=read
permissions=pull_requests=write

Create a token with all permissions but only on the "demo-repo" repository.

vault write /github/token installation_id=456 repository_ids=123 repository_ids=456

Create a token with all permissions but only on repositories 123 and 456.

vault write /github/token installation_id=456 repository_ids=123 repository_ids=456

Create a token with write access to pull requests using read / GET.

vault write /github/token permissions=pull_requests=write

Create a token with read access to metadata and write access to pull requests

on repositories "demo-repo", 123 and 456 only.

NOTE: Uses a Vault CLI JSON heredoc to submit the complex map type.

vault write /github/token - <<EOF { "installation_id": 456, "repositories": ["demo-repo"], "repository_ids": [123,456], "permissions": {"metadata": "read", "pull_requests": "write"} } EOF #+END_SRC

#+BEGIN_QUOTE NOTE: a 422 response usually indicates you have requested repositories IDs or permissions that your GitHub App install does not have access to. #+END_QUOTE *** Revocation It is possible to revoke tokens in your configured GitHub using Vault constructs. For example: #+begin_src shell

Revoke an individual token with just the lease ID.

vault lease revoke <lease_id previously received from token endpoint>

List currently active lease IDs.

vault list sys/leases/lookup/github/token

Revoke all tokens currently leased by Vault.

vault lease revoke -prefix github/token #+end_src

#+begin_quote NOTE: the previous commands presume your plugin is mounted at =/github=. #+end_quote

Alternatively, you can go directly to your GitHub with the token in hand: #+begin_src shell curl -H "Authorization: Bearer ${GITHUB_TOKEN}"
-X DELETE https://api.mygithub.com/installation/token #+end_src

** Permission sets Instruct the plugin to create a specific permission set.

| Method | Path | Produces | |--------+---------------------------+------------------| | GET | /permissionset/ | application/json | | POST | /permissionset/ | application/json | | PUT | /permissionset/ | application/json | | DELETE | /permissionset/ | application/json | | GET | /permissionsets?list=true | application/json |

*** Parameters #+begin_quote NOTE: All parameters are optional. Omitting them results in a token that has access to all of the repositories and permissions that the GitHub App has.

When crafting Vault policy, hyper security sensitive organisations may wish to favour =repository_ids= (GitHub repository IDs are immutable) instead of =repositories= (GitHub repository names are mutable). #+end_quote

  • =installation_id= (int64) — the ID of the app installation.
  • =repositories= ([]string) — a list of the names of the repositories within the organisation that the installation token can access.
  • =repository_ids= ([]int64) — a list of the IDs of the repositories that the installation token can access. See this [[https://stackoverflow.com/a/47223479][StackOverflow post]] for the quickest way to find a repository ID.
  • =permissions= (map[string]string) — a key value map of permission names to their access type (read or write). See [[https://developer.github.com/v3/apps/permissions][GitHub's documentation]] on permission names and access types.

*** Request a token from a permission set Similar to the [[#token][token]] flow in the previous section, you can instruct the plugin to create an installation access token by using a permission set name. The token returned will be constrained by that pre-configured permission set.

| Method | Path | Produces | |--------+---------------+------------------| | GET | /token/ | application/json | | POST | /token/ | application/json | | PUT | /token/ | application/json |

*** Examples #+BEGIN_SRC shell

Configure a permission set that only allows metadata reads and PR writes

against three repositories.

vault write /github/permissionset/demo-set - <<EOF { "installation_id": 987, "repositories": ["demo-repo"], "repository_ids": [123,456], "permissions": {"metadata": "read", "pull_requests": "write"} } EOF

Or

vault write /github/permissionset/demo-set
installation_id=987
repositories=demo-repo
repository_ids=123
repository_ids=456
permissions=pull_requests=read
permissions=metadata=read

Read the permission set configuration.

vault read /github/permissionset/demo-set

List all permission sets.

vault list /github/permissionsets

Create a token automatically constrained by the permission set.

vault read /github/token/demo-set

Delete an existing permission set.

vault delete /github/token/demo-set #+END_SRC

** Config General CRUD operations against the configuration of the plugin.

| Method | Path | Produces | |--------+---------+------------------| | POST | /config | application/json | | GET | /config | application/json | | PUT | /config | application/json | | DELETE | /config | application/json |

*** Parameters

  • =app_id= (int64) — the Application ID of the GitHub App.
  • =prv_key= (string) — a private key configured in the GitHub App. This private key must be in PEM PKCS#1 RSAPrivateKey format. It is not returned with read requests for security reasons but its presence or lack thereof is indicated.
  • =base_url= (string) — the base URL for API requests (defaults to the public GitHub API).

*** Examples #+BEGIN_SRC shell

Write the plugin configuration using the default base URL, and reading the key from a file.

vault write /github/config app_id=123 [email protected]

Read the plugin configuration.

vault read /github/config

Update the plugin configuration to a GitHub Enterprise base URL.

vault write /github/config base_url="https://api.mygithub.org"

Delete the plugin configuration.

vault delete /github/config #+END_SRC

** Metrics Prometheus/OpenMetrics formatted metrics exposition.

| Method | Path | Produces | |--------+----------+-------------| | GET | /metrics | text/plain |

*** Metrics In addition to standard Go metrics, the following custom metrics are exposed:

  • =vault_github_token_request_duration_seconds= — a summary of token request latency and status.
  • =vault_github_token_revocation_request_duration_seconds= — a summary of token revocation request latency and status.
  • =vault_github_token_build_info= — a constant with useful build information.

*** Sample Dashboard A sample dashboard is [[dashboard.json][provided]]. #+CAPTION: Sample Dashboard [[dashboard.png][dashboard.png]]

** Info Information about the GitHub secrets plugin, such as the plugin version, VCS detail and where to get help.

| Method | Path | Produces | |--------+-------+------------------| | GET | /info | application/json |

  • Development This plugin is written using modern [[https://golang.org/dl/][Go]]. You will need a Go 1.13+ toolchain and some common userspace tools like GNU/BSD =make=, =curl= and =git=.

The [[./Makefile][Makefile]] endeavours to install more atypical tooling when needed.

#+BEGIN_QUOTE NOTE: It is also possible to run any target inside Docker by prefixing the target name, e.g. =make docker-test=. #+END_QUOTE

There is also a =shell.nix= if Nix is more your bag. ** Tests This plugin is comprehensively tested by both unit and acceptance tests. Pull requests that do not maintain an [[https://codecov.io/gh/martinbaillie/vault-plugin-secrets-github][>90% coverage]] will not be accepted.

#+BEGIN_SRC shell

Run linting and unit tests.

make test

Run CI-grade linting and unit tests.

make test CI=true

Run unit and acceptance tests, integrating against a local Vault and stubbed

GitHub API.

make integration test

Run unit and acceptance tests, integrating against a local Vault and the real

GitHub API against your own GitHub App installation (you can also run these

tests against a GitHub Enterprise deployment). Setting BASE_URL causes the

tests to call against a real API.

NOTE: Keep in mind this test configuration will create real tokens.

make integration test
BASE_URL=https://api.github.com
ORG_NAME=<org_name>
APP_ID=<app_id>
PRV_KEY="$(cat <private_key_file>)" #+END_SRC

  • Security HashiCorp and GitHub take their security seriously. If you believe you have found a security issue with either through using this plugin, do not open an issue here. Responsibly disclose by getting in touch with [[mailto:[email protected]][HashiCorp]] or [[https://hackerone.com/github][GitHub]] security teams respectively.