Skip to content

Vault OIDC SSH client certs

Actions
Use OIDC authentication to get SSH client certificates from Vault alt. OpenBao
v2.0
Latest
Star (4)

Vault OIDC SSH Certificate Action

This action uses GitHub's OIDC support to authenticate towards a HashiCorp Vault instance or an OpenBao instance, and to request a (short-lived) SSH client certificate from it.

Example Usage

jobs:
  deploy:
    permissions:
      contents: read
      id-token: write
    # ...
    steps:
      # ...
      - name: Generate SSH client certificate
        if: github.ref == 'refs/heads/main'
        id: ssh_cert
        uses: andreaso/[email protected]
        with:
          vault_server: https://vault.example.com:8200
          jwt_audience: vault.example.com
          jwt_oidc_backend_path: github-oidc
          jwt_oidc_role: example-user
          ssh_backend_path: ssh-client-ca
          ssh_role: github-actions-example

      - name: Deploy site
        if: github.ref == 'refs/heads/main'
        run: >
          rsync -e "ssh -i '$SSH_KEY_PATH'"
          --verbose --recursive --delete-after --perms --chmod=D755,F644
          build/ [email protected]:/var/www/site/
        env:
          SSH_KEY_PATH: ${{ steps.ssh_cert.outputs.key_path }}

Do note that all client certification configuration is expected to happen on the Vault end, given that that is where all the limitations can be enforced.

Automated cleanup

All the action's writes are to the ${{ runner.temp }} directory. Hence as soon as the job is completed both the SSH certificate and its private key will be automatically removed, even in the case of a non-ephemeral runner.

Corresponding Configuration

HashiCorp Vault

resource "vault_jwt_auth_backend" "github" {
  path               = "github-oidc"
  oidc_discovery_url = "https://token.actions.githubusercontent.com"
  bound_issuer       = "https://token.actions.githubusercontent.com"
}

resource "vault_mount" "ssh_ca" {
  path        = "ssh-client-ca"
  type        = "ssh"
}

resource "vault_ssh_secret_backend_ca" "ssh_ca" {
  backend              = vault_mount.ssh_ca.path
  key_type             = "ed25519"
  generate_signing_key = true
}
resource "vault_ssh_secret_backend_role" "example" {
  name                    = "github-actions-example"
  backend                 = vault_mount.ssh_ca.path
  max_ttl                 = "900"
  key_type                = "ca"
  allow_user_certificates = true
  allow_host_certificates = false
  allowed_users           = "[email protected]"
  default_user            = "[email protected]"
  default_extensions      = {}

  allowed_user_key_config {
    type    = "ed25519"
    lengths = [0]
  }
}

data "vault_policy_document" "example" {
  rule {
    path         = "${vault_mount.ssh_ca.path}/sign/${vault_ssh_secret_backend_role.example.name}"
    capabilities = ["update"]
  }
}

resource "vault_policy" "example" {
  name   = "example-policy"
  policy = data.vault_policy_document.example.hcl
}

resource "vault_jwt_auth_backend_role" "example" {
  backend         = vault_jwt_auth_backend.github.path
  role_type       = "jwt"
  role_name       = "example-user"
  token_max_ttl   = "300"
  token_policies  = [vault_policy.example.name]
  user_claim      = "actor"
  bound_audiences = ["vault.example.com"]
  bound_claims    = {
    repository = "OWNER/REPO-NAME",
    ref        = "refs/heads/main",
  }
}
output "ssh_ca" {
  value = vault_ssh_secret_backend_ca.ssh_ca.public_key
}

OpenSSH

# /etc/ssh/sshd_config
# ...
TrustedUserCAKeys /etc/ssh/sshd_user_ca.pub
AuthorizedPrincipalsFile /etc/ssh/user_principals/%u
# /etc/ssh/sshd_user_ca.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
# /etc/ssh/user_principals/deployer
[email protected]

Immutable releases

As of version v2.0 all further releases are intended to take advantage of GitHub's Immutable releases.

To verify that a new version tag is indeed immutable you can either check the Releases page for the Immutable marker or you can use the GitHub CLI to check the tag's release attestation.

gh release verify --repo andreaso/vault-oidc-ssh-cert-action v2.0

Vault OIDC SSH client certs is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.

About

Use OIDC authentication to get SSH client certificates from Vault alt. OpenBao
v2.0
Latest

Vault OIDC SSH client certs is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.