Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add provenance.jq #76

Merged
merged 6 commits into from
Sep 19, 2024
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
1 change: 1 addition & 0 deletions .test/provenance/in.json
271 changes: 271 additions & 0 deletions .test/provenance/out.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
[
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "pkg:docker/docker:24.0.7-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/docker:24.0-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/docker:24-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/docker:cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/docker:24.0.7-cli-alpine3.18?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/amd64/docker:24.0.7-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/amd64/docker:24.0-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/amd64/docker:24-cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/amd64/docker:cli?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/amd64/docker:24.0.7-cli-alpine3.18?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
},
{
"name": "pkg:docker/oisupport/staging-amd64:4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43?platform=linux%2Famd64",
"digest": {
"sha256": "153793dfbac130679ad1eebd9e88b3772c47d3903a3f299c49d5c3f23a6e35d2"
}
}
],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1",
"externalParameters": {
"workflow": {
"ref": "refs/heads/subset",
"repository": "https://github.com/docker-library/meta",
"path": ".github/workflows/build.yml",
"digest": {
"gitCommit": "0123456789abcdef0123456789abcdef01234567"
}
},
"inputs": {
"buildId": "4b199ac326c74b3058a147e14f553af9e8e1659abc29bd3e82c9c9807b66ee43",
"bashbrewArch": "amd64",
"firstTag": "docker:24.0.7-cli"
}
},
"internalParameters": {
"github": {
"event_name": "workflow_dispatch",
"repository_id": "1234",
"repository_owner_id": "5678",
"runner_environment": "github-hosted"
}
},
"resolvedDependencies": [
{
"uri": "git+https://github.com/docker-library/meta@refs/heads/subset",
"digest": {
"gitCommit": "0123456789abcdef0123456789abcdef01234567"
}
}
]
},
"runDetails": {
"builder": {
"id": "https://github.com/docker-library/meta/.github/workflows/build.yml@refs/heads/subset"
},
"metadata": {
"invocationId": "https://github.com/docker-library/meta/actions/runs/9001/attempts/2"
}
}
}
},
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "pkg:docker/docker:24.0.7-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:24.0-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:24-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:24.0.7-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:24.0-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:24-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/docker:windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24.0.7-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24.0-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24-windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:windowsservercore-ltsc2022?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24.0.7-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24.0-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:24-windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/winamd64/docker:windowsservercore?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
},
{
"name": "pkg:docker/oisupport/staging-windows-amd64:9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e?platform=windows%2Famd64",
"digest": {
"sha256": "69aba7120e3f4014bfa80f4eae2cfc9698dcb6b8a5d64daf06de4039a19846ce"
}
}
],
"predicateType": "https://slsa.dev/provenance/v1",
"predicate": {
"buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1",
"externalParameters": {
"workflow": {
"ref": "refs/heads/subset",
"repository": "https://github.com/docker-library/meta",
"path": ".github/workflows/build.yml",
"digest": {
"gitCommit": "0123456789abcdef0123456789abcdef01234567"
}
},
"inputs": {
"buildId": "9b405cfa5b88ba65121aabdb95ae90fd2e1fee7582174de82ae861613ae3072e",
"bashbrewArch": "windows-amd64",
"firstTag": "docker:24.0.7-windowsservercore-ltsc2022",
"windowsVersion": "2022"
}
},
"internalParameters": {
"github": {
"event_name": "workflow_dispatch",
"repository_id": "1234",
"repository_owner_id": "5678",
"runner_environment": "github-hosted"
}
},
"resolvedDependencies": [
{
"uri": "git+https://github.com/docker-library/meta@refs/heads/subset",
"digest": {
"gitCommit": "0123456789abcdef0123456789abcdef01234567"
}
}
]
},
"runDetails": {
"builder": {
"id": "https://github.com/docker-library/meta/.github/workflows/build.yml@refs/heads/subset"
},
"metadata": {
"invocationId": "https://github.com/docker-library/meta/actions/runs/9001/attempts/2"
}
}
}
}
]
32 changes: 32 additions & 0 deletions .test/provenance/test.jq
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
include "provenance";
include "jenkins";

[
first(.[] | select(.build.arch == "amd64" and .build.resolved)),
first(.[] | select(.build.arch == "windows-amd64" and .build.resolved)),
empty # trailing comma

| (.build.resolved.annotations["org.opencontainers.image.ref.name"] | split("@")[1]) as $digest

# some faked GitHub event data so we can ~test the provenance generation
| gha_payload as $payload
| {
event: $payload,
event_name: "workflow_dispatch",
ref: "refs/heads/\($payload.ref)",
repository: "docker-library/meta",
repository_id: "1234",
repository_owner_id: "5678",
run_attempt: "2",
run_id: "9001",
server_url: "https://github.com",
sha: "0123456789abcdef0123456789abcdef01234567",
workflow_ref: "docker-library/meta/.github/workflows/build.yml@refs/heads/\($payload.ref)",
workflow_sha: "0123456789abcdef0123456789abcdef01234567",
} as $github
| {
environment: "github-hosted",
} as $runner

| github_actions_provenance($github; $runner; $digest)
]
79 changes: 79 additions & 0 deletions provenance.jq
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# input: "build" object with platform and image digest
# $github: "github" context; CONTAINS SENSITIVE INFORMATION (https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context)
# $runner: "runner" context; https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#runner-context
# $digest: the OCI image digest for the just-built image (normally in .build.resolved.annotations["org.opencontainers.image.ref.name"] but only post-push/regeneration and we haven't pushed yet)
#
# output: in-toto provenance statement (https://slsa.dev/spec/v1.0/provenance)
# see also: https://github.com/actions/buildtypes/tree/main/workflow/v1
def github_actions_provenance($github; $runner; $digest):
if $github.event_name != "workflow_dispatch" then error("error: '\($github.event_name)' is not a supported event type for provenance generation") else
mrjoelkamp marked this conversation as resolved.
Show resolved Hide resolved
{
_type: "https://in-toto.io/Statement/v1",
subject: [
($digest | split(":")) as $splitDigest
| (.source.arches[.build.arch].platformString) as $platform
| (
.source.arches[.build.arch].tags[],
.source.arches[.build.arch].archTags[],
.build.img,
empty # trailing comma
)
| {
# https://github.com/package-url/purl-spec/blob/b33dda1cf4515efa8eabbbe8e9b140950805f845/PURL-TYPES.rst#docker (this matches what BuildKit generates as of 2024-09-18; "oci" would also be a reasonable choice, but would require signer and policy changes to support, and be more complex to generate accurately)
name: "pkg:docker/\(.)?platform=\($platform | @uri)",
digest: { ($splitDigest[0]): $splitDigest[1] },
}
],
predicateType: "https://slsa.dev/provenance/v1",
predicate: {
buildDefinition: {
buildType: "https://actions.github.io/buildtypes/workflow/v1",
externalParameters: {
workflow: {
# TODO this matches how this is documented/suggested in GitHub's buildType documentation, but does not account for the workflow file being in a separate repository at a separate ref from the "source" (which the "workflow_ref" field *does* account for), so that would/will change how we need to calculate these values if we ever do that (something like "^(?<repo>[^/]+/[^/]+)/(?<path>.*)@(?<ref>refs/.*)$" on $github.workflow_ref ?)
ref: $github.ref,
repository: ($github.server_url + "/" + $github.repository),
path: (
$github.workflow_ref
| ltrimstr($github.repository + "/")
| rtrimstr("@" + $github.ref)
| if contains("@") then error("parsing 'workflow_ref' failed: '\(.)'") else . end
),
# not required, but useful/important (and potentially but unlikely different from $github.sha used in resolvedDependencies below):
digest: { gitCommit: $github.workflow_sha },
},
inputs: $github.event.inputs, # https://docs.github.com/en/webhooks/webhook-events-and-payloads#workflow_dispatch
},
internalParameters: {
github: {
event_name: $github.event_name,
repository_id: $github.repository_id,
repository_owner_id: $github.repository_owner_id,
runner_environment: $runner.environment,
},
},
resolvedDependencies: [
{
uri: "git+\($github.server_url)/\($github.repository)@\($github.ref)",
mrjoelkamp marked this conversation as resolved.
Show resolved Hide resolved
digest: { "gitCommit": $github.sha },
},
# TODO figure out a way to include resolved action SHAs from "uses:" expressions
# TODO include more resolved dependencies
empty # tailing comma
],
},
runDetails: {
# builder.id identifies the transitive closure of the trusted build platform evalution.
# any changes that alter security properties or build level must update this ID and rotate the signing key.
# https://slsa.dev/spec/v1.0/provenance#builder
builder: {
id: ($github.server_url + "/" + $github.workflow_ref),
},
metadata: {
invocationId: ($github.server_url + "/" + $github.repository + "/actions/runs/" + $github.run_id + "/attempts/" + $github.run_attempt)
},
},
},
}
end
;