- References
- scitt-community/scitt-api-emulator#31
- 5.1.1.1.1.
- https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/using-openid-connect-with-reusable-workflows
- https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
Install the SCITT API Emulator with the oidc
extra.
$ pip install -e .[oidc]
Expose the server to the internet. localhost.run or ngrok are common options if you need to exposed a NAT'd machine.
$ ssh -nT -R 80:localhost:8080 nokey@localhost.run 2>/dev/null | grep --line-buffered 'tunneled with tls' | python -c 'import sys; print(sys.stdin.readline().split()[-1])' | tee public-url.txt &
$ export SCITT_URL=$(cat public-url.txt)
Create the middleware config file. Set config audience
to the publicly accessible URL of the SCITT instance.
oidc-middleware-config.yaml
audience: $SCITT_URL
issuers:
- https://token.actions.githubusercontent.com
claim_schema:
https://token.actions.githubusercontent.com:
$schema: https://json-schema.org/draft/2020-12/schema
properties:
job_workflow_ref:
enum:
- ${WORKFLOW_REF}
type: string
job_workflow_sha:
enum:
- ${JOB_WORKFLOW_SHA}
type: string
repository_id:
enum:
- ${REPOSITORY_ID}
type: string
repository_owner_id:
enum:
- ${REPOSITORY_OWNER_ID}
type: string
required:
- job_workflow_ref
- job_workflow_sha
- repository_owner_id
- repository_id
Start the SCITT instance using the OIDCAuthMiddleware
and associated config.
$ scitt-emulator server --port 8080 --workspace workspace/ --tree-alg CCF \
--middleware scitt_emulator.oidc:OIDCAuthMiddleware \
--middleware-config-path oidc-middleware-config.json
Create GitHub Actions Workflow.
name: "SCITT Notary"
on:
push:
branches:
- main
paths-ignore:
- '**.md'
workflow_dispatch:
inputs:
scitt-url:
description: 'URL of SCITT instance'
type: string
payload:
description: 'Payload for claim'
default: ''
type: string
workflow_call:
inputs:
scitt-url:
description: 'URL of SCITT instance'
type: string
payload:
description: 'Payload for claim'
type: string
jobs:
notarize:
runs-on: ubuntu-latest
permissions:
id-token: write
env:
SCITT_URL: '${{ inputs.scitt-url || github.event.inputs.scitt-url }}'
PAYLOAD: '${{ inputs.payload || github.event.inputs.payload }}'
steps:
- name: Set defaults if env vars not set (as happens with on.push trigger)
run: |
if [[ "x${SCITT_URL}" = "x" ]]; then
echo "SCITT_URL=http://localhost:8080" >> "${GITHUB_ENV}"
fi
if [[ "x${PAYLOAD}" = "x" ]]; then
echo 'PAYLOAD={"key": "value"}' >> "${GITHUB_ENV}"
fi
- uses: actions/checkout@v4
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install SCITT API Emulator
run: |
pip install -U pip setuptools wheel
pip install .[oidc]
- name: Install github-script dependencies
run: |
npm install @actions/core
- name: Get OIDC token to use as bearer token for auth to SCITT
uses: actions/github-script@v6
id: github-oidc
with:
script: |
const {SCITT_URL} = process.env;
core.setOutput('token', await core.getIDToken(SCITT_URL));
- name: Create claim
run: |
scitt-emulator client create-claim --issuer did:web:example.org --content-type application/json --payload "${PAYLOAD}" --out claim.cose
- name: Submit claim
env:
OIDC_TOKEN: '${{ steps.github-oidc.outputs.token }}'
WORKFLOW_REF: '${{ github.workflow_ref }}'
# Use of job_workflow_sha blocked by
# https://github.com/actions/runner/issues/2417#issuecomment-1718369460
JOB_WORKFLOW_SHA: '${{ github.sha }}'
REPOSITORY_OWNER_ID: '${{ github.repository_owner_id }}'
REPOSITORY_ID: '${{ github.repository_id }}'
run: |
# Create the middleware config file
tee oidc-middleware-config.json <<EOF
{
"issuers": ["https://token.actions.githubusercontent.com"],
"claim_schema": {
"https://token.actions.githubusercontent.com": {
"\$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"job_workflow_ref",
"job_workflow_sha",
"repository_owner_id",
"repository_id"
],
"properties": {
"job_workflow_ref": {
"type": "string",
"enum": [
"${WORKFLOW_REF}"
]
},
"job_workflow_sha": {
"type": "string",
"enum": [
"${JOB_WORKFLOW_SHA}"
]
},
"repository_owner_id": {
"type": "string",
"enum": [
"${REPOSITORY_OWNER_ID}"
]
},
"repository_id": {
"type": "string",
"enum": [
"${REPOSITORY_ID}"
]
}
}
}
},
"audience": "${SCITT_URL}"
}
EOF
# Start SCITT using the `OIDCAuthMiddleware` and associated config.
if [[ "x${SCITT_URL}" = "xhttp://localhost:8080" ]]; then
scitt-emulator server --port 8080 --workspace workspace/ --tree-alg CCF \
--middleware scitt_emulator.oidc:OIDCAuthMiddleware \
--middleware-config-path oidc-middleware-config.json &
sleep 1s
fi
# Submit the claim using OIDC token as auth
scitt-emulator client submit-claim --token "${OIDC_TOKEN}" --url "${SCITT_URL}" --claim claim.cose --out claim.receipt.cbor
Dispatch GitHub Actions Workflow.
$ gh -R scitt-community/scitt-api-emulator workflow run notarize.yml -F scitt-url=$(cat public-url.txt)
Check SCITT instance logs
Leaf hash: 2c58c822a8344b9fa14d247987977eaa3719dbe02df74169d3893ed6365bb181
Root: 0d5ae584ce5c9aac751d6b6ad79e1d61fd7c51933c45b127409e6147abdab4e2
Receipt written to workspace/storage/2.receipt.cbor
Claim written to workspace/storage/2.cose
127.0.0.1 - - [12/Sep/2023 22:31:08] "POST /entries HTTP/1.1" 201 -
127.0.0.1 - - [12/Sep/2023 22:31:09] "GET /entries/2/receipt HTTP/1.1" 200 -
Basic GitHub Action Reusable Workflow OIDC validation support as used by slsa generator TS submission and others requires validating claims to do workload based identity where the workload is identified by job_workflow_ref
, job_workflow_sha
, repository_owner_id
, and repository_id
claims.
audience: http://localhost:8080
issuers:
- https://token.actions.githubusercontent.com
claim_schema:
https://token.actions.githubusercontent.com:
required:
- job_workflow_ref
- job_workflow_sha
- repository_owner_id
- repository_id
properties:
job_workflow_ref:
enum:
- 'pdxjohnny/scitt-api-emulator/.github/workflows/notarize.yml@refs/heads/auth'
type: string
job_workflow_sha:
enum:
- '215777b7ea418f1e0bd54f39cc70467e1fb76b8e'
type: string
repository_id:
enum:
- '621131680'
type: string
repository_owner_id:
enum:
- '5950433'
type: string