SCITT OIDC Auth
-
References
- https://github.com/scitt-community/scitt-api-emulator/pull/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
Dependencies
Install the SCITT API Emulator with the oidc
extra.
$ pip install -e .[oidc]
Usage example with GitHub Actions
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
Share this recording
Link
Append ?t=30
to start the playback at 30s, ?t=3:20
to start the playback at 3m 20s.
Embed image link
Use snippets below to display a screenshot linking to this recording.
Useful in places where scripts are not allowed (e.g. in a project's README file).
HTML:
Markdown:
Embed the player
If you're embedding on your own page or on a site which permits script tags, you can use the full player widget:
Paste the above script tag where you want the player to be displayed on your page.
See embedding docs for additional options.
Download this recording
You can download this recording in asciicast v2 format, as a .cast file.
DownloadReplay in terminal
You can replay the downloaded recording in your terminal using the
asciinema play
command:
asciinema play 607600.cast
If you don't have asciinema CLI installed then see installation instructions.
Use with stand-alone player on your website
Download asciinema player from
the releases page
(you only need .js
and .css
file), then use it like this:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="asciinema-player.css" />
</head>
<body>
<div id="player"></div>
<script src="asciinema-player.min.js"></script>
<script>
AsciinemaPlayer.create(
'/assets/607600.cast',
document.getElementById('player'),
{ cols: 115, rows: 36 }
);
</script>
</body>
</html>
See asciinema player quick-start guide for full usage instructions.
Generate GIF from this recording
While this site doesn't provide GIF conversion at the moment, you can still do it yourself with the help of asciinema GIF generator utility - agg.
Once you have it installed, generate a GIF with the following command:
agg https://asciinema.org/a/607600 demo.gif
Or, if you already downloaded the recording file:
agg demo.cast demo.gif
Check agg --help
for all available options. You can change font
family and size, select color theme, adjust speed and more.
See agg manual for full usage instructions.