Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ updates:
- dependencies
- github-actions

- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
commit-message:
prefix: "chore(deps)"
labels:
- dependencies
- go

- package-ecosystem: npm
directory: /docs
schedule:
Expand Down
47 changes: 47 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CodeQL

on:
push:
branches:
- master
pull_request:
branches:
- master
schedule:
- cron: "27 6 * * 1"

permissions: {}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze Go
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
cache: false

- name: Initialize CodeQL
uses: github/codeql-action/init@6f7376048dd6be43ea34c6bd4a3ecef7d7abd847 # v4.31.4
with:
languages: go
build-mode: autobuild

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@6f7376048dd6be43ea34c6bd4a3ecef7d7abd847 # v4.31.4
with:
category: "/language:go"
54 changes: 54 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Release

on:
push:
tags:
- "v*"

permissions: {}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
verify-draft-release:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Wait for draft release handoff
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./scripts/wait-for-draft-release.sh

release:
needs: verify-draft-release
uses: ./.github/workflows/reusable-release.yml
permissions:
contents: write
id-token: write
attestations: write
with:
tag: ${{ github.ref_name }}

publish-draft-release:
needs: release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Publish draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./scripts/publish-draft-release.sh
87 changes: 87 additions & 0 deletions .github/workflows/reusable-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Reusable Release

on:
workflow_call:
inputs:
tag:
description: "Release tag (e.g. v1.2.3)"
required: true
type: string

permissions: {}

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: go.mod
cache: false

- name: Build Lambda zip
shell: bash
env:
GOOS: linux
GOARCH: arm64
CGO_ENABLED: "0"
run: |
set -euo pipefail
rm -rf build dist
mkdir -p build dist
go build \
-buildvcs=false \
-tags lambda.norpc \
-trimpath \
-ldflags="-s -w" \
-o build/bootstrap \
./cmd/github-token-broker
(cd build && zip -X ../dist/github-token-broker.zip bootstrap)

- name: Generate checksums
shell: bash
run: |
set -euo pipefail
cd dist
sha256sum github-token-broker.zip > checksums.txt
cat checksums.txt

- name: Generate SBOM
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
path: dist/github-token-broker.zip
format: spdx-json
output-file: dist/github-token-broker.zip.spdx.json
upload-artifact: false
upload-release-assets: false

- name: Attest build provenance
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-checksums: dist/checksums.txt

- name: Attest SBOM
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-path: dist/github-token-broker.zip
predicate-type: https://spdx.dev/Document
predicate-path: dist/github-token-broker.zip.spdx.json

- name: Upload Lambda zip to draft release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
gh release upload "${TAG}" dist/github-token-broker.zip --clobber
39 changes: 39 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: OpenSSF Scorecard

on:
push:
branches:
- master
schedule:
- cron: "43 5 * * 2"

permissions: {}

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
analysis:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
security-events: write
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Run Scorecard
uses: ossf/scorecard-action@99c09fe975337306107572b4fdf4db224cf8e2f2 # v2.4.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true

- name: Upload SARIF results to code scanning
uses: github/codeql-action/upload-sarif@6f7376048dd6be43ea34c6bd4a3ecef7d7abd847 # v4.31.4
with:
sarif_file: results.sarif
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,45 @@ Successful responses have this shape:

The token is intentionally logged nowhere. Callers should treat it as a secret and discard it after the task completes.

## Verification

Releases ship only the Lambda zip. Build provenance and an SBOM are persisted to GitHub's Attestations API; verify them with [`gh attestation verify`](https://cli.github.com/manual/gh_attestation_verify) rather than downloading signature or SBOM files from the release page.

```sh
TAG=v1.0.0
gh release download "$TAG" -R meigma/github-token-broker -p 'github-token-broker.zip'

gh release verify "$TAG" -R meigma/github-token-broker
gh release verify-asset "$TAG" ./github-token-broker.zip -R meigma/github-token-broker

gh attestation verify ./github-token-broker.zip \
--repo meigma/github-token-broker \
--signer-workflow meigma/github-token-broker/.github/workflows/reusable-release.yml \
--source-ref "refs/tags/$TAG" \
--deny-self-hosted-runners
```

The attestation call above validates the SLSA build provenance by default. To validate the SBOM attestation specifically, add a predicate filter:

```sh
gh attestation verify ./github-token-broker.zip \
--repo meigma/github-token-broker \
--predicate-type https://spdx.dev/Document
```

For air-gapped or offline verification, download the attestation bundle first and pass it explicitly:

```sh
gh attestation download ./github-token-broker.zip -R meigma/github-token-broker
gh attestation verify ./github-token-broker.zip \
--bundle github-token-broker.zip.bundle.jsonl \
--signer-workflow meigma/github-token-broker/.github/workflows/reusable-release.yml \
--source-ref "refs/tags/$TAG" \
--deny-self-hosted-runners
```

See [docs/explanation/release-architecture.md](docs/docs/explanation/release-architecture.md) for the full pipeline design and the rationale behind the attestation-only verification channel.

## Documentation

The Docusaurus site under [`docs/`](docs/) is the canonical location for configuration, deployment, and operational guidance. Published versions will be linked here once the site is deployed.
Expand Down
Loading