Skip to content

Python library for using HashiCorp Vault to manage a GitHub App's private key.

License

Notifications You must be signed in to change notification settings

andreaso/hv4gha

Repository files navigation

HashiCorp Vault for GitHub Apps

Python library for using HashiCorp Vault's Transit Engine to manage a GitHub App's private RSA key. More precisely, the library provides the following pieces of functionality.

  • Perform initial one-way import of the App's private key into Vault
  • Issue (short-lived) GitHub Access Token
    • Have Vault sign a JWT using the App's private key
    • Exchange that JWT for a GitHub Access Token

Conceptually Vault here fills the role of an HSM or a Cloud KMS.

See Authenticating as a GitHub App installation (GitHub Docs) for context.

Installation

pip install hv4gha

Usage

In addition to the examples below see also the hv4gha/entry.py docstrings.

Import App key

from hv4gha import import_app_key

with open("/path/to/github-app.private-key.pem", "r") as akh:
    my_app_key = akh.read()

import_app_key(
    pem_key=my_app_key,
    key_name="my-github-app",
    vault_addr="https://vault.example.com:8200",
    vault_token="...",
)

Issue Access Token

from hv4gha import issue_access_token

response = issue_access_token(
    key_name="my-github-app",
    vault_addr="https://vault.example.com:8200",
    vault_token="...",
    app_id=368468,
    account="andreaso",
)

access_token = response["access_token"]
token_expiry = response["expires_at"]

Issue scoped Access Token

from hv4gha import issue_access_token

response = issue_access_token(
    key_name="my-github-app",
    vault_addr="https://vault.example.com:8200",
    vault_token="...",
    app_id=368468,
    account="andreaso",
    permissions={"contents": "read"},
    repositories=["world-domination"],
)

access_token = response["access_token"]
token_expiry = response["expires_at"]

Vault requirements

Somewhat simplified, this is what's required Vault wise.

Transit secrets engine

First of all, the Transit Engine needs to be enabled.

vault secrets enable transit

Here we are sticking to the default transit/ mount point.

Import policy

path "transit/wrapping_key" {
  capabilities = ["read"]
}

path "transit/keys/my-github-app/import" {
  capabilities = ["update"]
}

Issue policy

path "transit/sign/my-github-app" {
  capabilities = ["update"]
}

Vault Token

For obtaining the initial Vault Token, see the hvac Python library and its Auth Methods documentation.