Skip to content
ps-pufferfishPublic
forked from PortSwigger/idcat

About

The github app identity service

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

idcat

idcat is a small Axum service that hides the GitHub App authentication dance behind one internal endpoint.

It reads a GitHub App RSA private key from the filesystem, signs a short-lived GitHub App JWT, and exchanges that JWT for a GitHub installation access token.

Configuration

private-key-directory = "/var/run/secrets/idcat"

[[role]]
name = "kubernetes-default"
audience = "idcat"
issuer = "https://kubernetes.default.svc"

[role.claims]
sub = "system:serviceaccount:default:default"

[[role]]
name = "github-workflow"
audience = "idcat"
issuer = "https://token.actions.githubusercontent.com"

[[github-app]]
name = "deployments"
app-id = 123456
secret-key = "deployments-private-key.pem"
allowed-roles = ["kubernetes-default"]

[[installation-policy]]
github-app = "deployments"
repository = "myorg/alfa"
role = "github-workflow"

[installation-policy.required-claims]
repository = "myorg/gamma"

See idcat.toml.example for a fuller configuration with multiple roles and GitHub Apps. List multiple entries in allowed-roles to allow alternative authentication methods or role trust requirements for the same GitHub App. Use [[installation-policy]] to grant a role only for one installed app/repository combination, with additional required token claims. For example, a request for deployments on myorg/alfa can require the token to satisfy github-workflow and also carry repository = "myorg/gamma". App-level allowed-roles still grant access to every repository installation for that GitHub App.

Mount the private keys as files. For example, in Kubernetes this could be a Secret volume mounted at private-key-directory, but idcat only reads files from the filesystem.

kubectl create secret generic idcat \
  --from-file=private-key.pem=/path/to/github-app-private-key.pem

The application does not need Kubernetes API permissions to read private keys.

When built with the kms feature, key-source may be set to kms. In that mode, secret-key selects an AWS KMS alias instead of a filesystem path. Values without the alias/ prefix are treated as alias names, so secret-key = "deployments" uses alias/deployments. AWS credentials and region are loaded from the ambient AWS SDK configuration.

API

curl -X POST \
  -H "Authorization: Bearer $KUBERNETES_JWT" \
  http://localhost:8080/installation-token/deployments/github_user/repo_name

The response body is the GitHub installation token:

ghs_...

To proxy a repository-scoped GitHub API request through an installation token, prefix the GitHub /repos/{owner}/{repo} path with /proxy/{github-app}. The GitHub app name selects the configured GitHub App and its allowed roles, while the owner/repo pair comes from the proxied GitHub API path:

curl -X GET \
  -H "Authorization: Bearer $KUBERNETES_JWT" \
  http://localhost:8080/proxy/deployments/repos/github_user/repo_name/contents/README.md

Running

cargo run -- --config-file idcat.toml

For local testing, authentication and role checks can be bypassed:

cargo run -- --config-file idcat.toml --disable-auth

Use --debug to log detailed installation-token flow steps:

cargo run -- --config-file idcat.toml --debug

GitHub App installation IDs are cached in memory after the first lookup. Installation tokens are cached in memory for 50 minutes per GitHub app and repo.

License

MIT

About

The github app identity service

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages