Octo STS
GitHub App
Octo STS
GitHub App
A "Security Token Service" for GitHub
tl;dr
Octo STS is a GitHub App that acts as a "Security Token Service" (aka
STS) for the GitHub API.
Octo STS enables workloads running anywhere to exchange short-lived OIDC tokens
for short-lived GitHub credentials thereby eliminating the need for those
workloads to manage long-lived GitHub credentials.
Leveraging Octo STS, Chainguard has been able to eliminate a small horde of
assorted long-lived GitHub credentials including:
- Dozens of Classic and Fine-grained "Personal Access Tokens" (aka PATs),
- A handful of dedicated GitHub App private keys,
- A handful of "deploy keys".
Chainguard does not currently offer any level of support for Octo STS, but if you are interested then please reach out to us.
Setting up workload trust
For the App to produce credentials that work with resources in your-org
it must be installed into your-org
and have access to any repositories (e.g. your-repo
)
that you will want workloads to be able to interact with.
Due to the way Github Apps work, the App must ask for a superset of the
permissions that any user might ask for in a token, so the full set of
permissions the App requests is large, but the only permissions the
App itself uses is contents: read
for reading trust policies, and checks: write
for validating trust policies.
All of the remaining permissions are requested exclusively for producing
tokens as specified in trust policies.
The Trust Policy
Trust policies are checked into .github/chainguard/{name}.sts.yaml
, and
consist of a few key parts:
- The claim matching criteria for federation,
- The permissions to grant the identity, and
- (for Org-level policies) The list of repositories to grant access.
Here is a simple example that allows the Github actions workflows in
chainguard-dev/foo
running on the main
branch to read the repo contents and
interact with issues:
issuer: https://token.actions.githubusercontent.com
subject: repo:chainguard-dev/foo:ref:refs/heads/main
permissions:
contents: read
issues: write
The Trust Policy can also match the issuer, subject, and even custom claims with
regular expressions. For example:
issuer: https://accounts.google.com
subject_pattern: '[0-9]+'
claim_pattern:
email: '.*@chainguard\.dev'
permissions:
contents: read
This policy will allow OIDC tokens from Google accounts of folks with a
Chainguard email address to federate and read the repo contents.
Federating a token (GitHub Actions)
To support federation from GitHub Actions, we provide
octo-sts/action
here, which can be used like so:
permissions:
id-token: write # Needed to federate tokens.
steps:
- uses: octo-sts/action@6177b4481c00308b3839969c3eca88c96a91775f # v1.0.0
id: octo-sts
with:
scope: your-org/your-repo
identity: foo
- env:
GITHUB_TOKEN: ${{ steps.octo-sts.outputs.token }}
run: |
gh repo list
The App will attempt to load the trust policy from
.github/chainguard/foo.sts.yaml
from your-org/your-repo
and if the
workflow's identity token satisfies the trust policy, it will return a token
with the enclosed permissions.
Federating a token (Go)
The Github App implements a subset of the Chainguard SecurityTokenService
GRPC
service definition here, and we have some higher-level libraries
around this.
Here is an example program that takes in an input token via -token
, performs
the federation, and prints the resulting token to STDOUT
:
package main
import (
"context"
"flag"
"log"
"os"
"chainguard.dev/sdk/sts"
)
var token = flag.String("token", "", "Bot token")
func main() {
flag.Parse()
xchg := sts.New(
"https://octo-sts.dev",
"does-not-matter",
sts.WithScope("your-org/your-repo"),
sts.WithIdentity("foo"),
)
res, err := xchg.Exchange(context.Background(), *token)
if err != nil {
log.Fatalf("exchange failed: %v", err)
}
os.Stdout.WriteString(res)
}
The App will attempt to load the trust policy from
.github/chainguard/foo.sts.yaml
from your-org/your-repo
and if the
workflow's identity token satisfies the trust policy, it will return a token
with the enclosed permissions.
Federating a token (low-level)
If you would like to try this out on the command-line with curl
, here is how.
If a ${TOKEN}
suitable for federation is sent like so:
curl -H "Authorization: Bearer ${TOKEN}" \
"https://octo-sts.dev/sts/exchange?scope=your-org/your-repo&identity=foo"
The App will attempt to load the trust policy from
.github/chainguard/foo.sts.yaml
from your-org/your-repo
and if the
workflow's identity token satisfies the trust policy, it will return a token
with the enclosed permissions.
Developer
Octo STS is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.
Report abuse