Skip to content

Commit 5baf6a2

Browse files
authored
feat: SLSA 1.0 provenance statement (#6613)
Generates a SLSA 1.0 compliant provenance statement for packages published from GitHub Actions. Signed-off-by: Brian DeHamer <[email protected]>
1 parent 89b2741 commit 5baf6a2

File tree

2 files changed

+49
-55
lines changed

2 files changed

+49
-55
lines changed

workspaces/libnpmpublish/lib/provenance.js

Lines changed: 37 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ const ci = require('ci-info')
44
const { env } = process
55

66
const INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json'
7-
const INTOTO_STATEMENT_TYPE = 'https://in-toto.io/Statement/v0.1'
8-
const SLSA_PREDICATE_TYPE = 'https://slsa.dev/provenance/v0.2'
7+
const INTOTO_STATEMENT_V01_TYPE = 'https://in-toto.io/Statement/v0.1'
8+
const INTOTO_STATEMENT_V1_TYPE = 'https://in-toto.io/Statement/v1'
9+
const SLSA_PREDICATE_V02_TYPE = 'https://slsa.dev/provenance/v0.2'
10+
const SLSA_PREDICATE_V1_TYPE = 'https://slsa.dev/provenance/v1'
911

10-
const GITHUB_BUILDER_ID = 'https://github.com/actions/runner'
11-
const GITHUB_BUILD_TYPE_PREFIX = 'https://github.com/npm/cli/gha'
12-
const GITHUB_BUILD_TYPE_VERSION = 'v2'
12+
const GITHUB_BUILDER_ID_PREFIX = 'https://github.com/actions/runner'
13+
const GITHUB_BUILD_TYPE = 'https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1'
1314

1415
const GITLAB_BUILD_TYPE_PREFIX = 'https://github.com/npm/cli/gitlab'
1516
const GITLAB_BUILD_TYPE_VERSION = 'v0alpha1'
@@ -18,63 +19,54 @@ const generateProvenance = async (subject, opts) => {
1819
let payload
1920
if (ci.GITHUB_ACTIONS) {
2021
/* istanbul ignore next - not covering missing env var case */
21-
const [workflowPath] = (env.GITHUB_WORKFLOW_REF || '')
22+
const [workflowPath, workflowRef] = (env.GITHUB_WORKFLOW_REF || '')
2223
.replace(env.GITHUB_REPOSITORY + '/', '')
2324
.split('@')
2425
payload = {
25-
_type: INTOTO_STATEMENT_TYPE,
26+
_type: INTOTO_STATEMENT_V1_TYPE,
2627
subject,
27-
predicateType: SLSA_PREDICATE_TYPE,
28+
predicateType: SLSA_PREDICATE_V1_TYPE,
2829
predicate: {
29-
buildType: `${GITHUB_BUILD_TYPE_PREFIX}/${GITHUB_BUILD_TYPE_VERSION}`,
30-
builder: { id: GITHUB_BUILDER_ID },
31-
invocation: {
32-
configSource: {
33-
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
34-
digest: {
35-
sha1: env.GITHUB_SHA,
30+
buildDefinition: {
31+
buildType: GITHUB_BUILD_TYPE,
32+
externalParameters: {
33+
workflow: {
34+
ref: workflowRef,
35+
repository: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}`,
36+
path: workflowPath,
3637
},
37-
entryPoint: workflowPath,
3838
},
39-
parameters: {},
40-
environment: {
41-
GITHUB_EVENT_NAME: env.GITHUB_EVENT_NAME,
42-
GITHUB_REF: env.GITHUB_REF,
43-
GITHUB_REPOSITORY: env.GITHUB_REPOSITORY,
44-
GITHUB_REPOSITORY_ID: env.GITHUB_REPOSITORY_ID,
45-
GITHUB_REPOSITORY_OWNER_ID: env.GITHUB_REPOSITORY_OWNER_ID,
46-
GITHUB_RUN_ATTEMPT: env.GITHUB_RUN_ATTEMPT,
47-
GITHUB_RUN_ID: env.GITHUB_RUN_ID,
48-
GITHUB_SHA: env.GITHUB_SHA,
49-
GITHUB_WORKFLOW_REF: env.GITHUB_WORKFLOW_REF,
50-
GITHUB_WORKFLOW_SHA: env.GITHUB_WORKFLOW_SHA,
39+
internalParameters: {
40+
github: {
41+
event_name: env.GITHUB_EVENT_NAME,
42+
repository_id: env.GITHUB_REPOSITORY_ID,
43+
repository_owner_id: env.GITHUB_REPOSITORY_OWNER_ID,
44+
},
5145
},
46+
resolvedDependencies: [
47+
{
48+
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
49+
digest: {
50+
gitCommit: env.GITHUB_SHA,
51+
},
52+
},
53+
],
5254
},
53-
metadata: {
54-
buildInvocationId: `${env.GITHUB_RUN_ID}-${env.GITHUB_RUN_ATTEMPT}`,
55-
completeness: {
56-
parameters: false,
57-
environment: false,
58-
materials: false,
55+
runDetails: {
56+
builder: { id: `${GITHUB_BUILDER_ID_PREFIX}/${env.RUNNER_ENVIRONMENT}` },
57+
metadata: {
58+
/* eslint-disable-next-line max-len */
59+
invocationId: `${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}/attempts/${env.GITHUB_RUN_ATTEMPT}`,
5960
},
60-
reproducible: false,
6161
},
62-
materials: [
63-
{
64-
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
65-
digest: {
66-
sha1: env.GITHUB_SHA,
67-
},
68-
},
69-
],
7062
},
7163
}
7264
}
7365
if (ci.GITLAB) {
7466
payload = {
75-
_type: INTOTO_STATEMENT_TYPE,
67+
_type: INTOTO_STATEMENT_V01_TYPE,
7668
subject,
77-
predicateType: SLSA_PREDICATE_TYPE,
69+
predicateType: SLSA_PREDICATE_V02_TYPE,
7870
predicate: {
7971
buildType: `${GITLAB_BUILD_TYPE_PREFIX}/${GITLAB_BUILD_TYPE_VERSION}`,
8072
builder: { id: `${env.CI_PROJECT_URL}/-/runners/${env.CI_RUNNER_ID}` },

workspaces/libnpmpublish/test/publish.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ t.test('publish existing package with provenance in gha', async t => {
610610
const sha = 'deadbeef'
611611
const runID = '123456'
612612
const runAttempt = '1'
613+
const runnerEnv = 'github-hosted'
613614

614615
// Set-up GHA environment variables
615616
mockGlobals(t, {
@@ -625,6 +626,7 @@ t.test('publish existing package with provenance in gha', async t => {
625626
GITHUB_SHA: sha,
626627
GITHUB_RUN_ID: runID,
627628
GITHUB_RUN_ATTEMPT: runAttempt,
629+
RUNNER_ENVIRONMENT: runnerEnv,
628630
},
629631
})
630632

@@ -635,10 +637,10 @@ t.test('publish existing package with provenance in gha', async t => {
635637
},
636638
}
637639

638-
const expectedConfigSource = {
639-
uri: `git+${serverUrl}/${repository}@${ref}`,
640-
digest: { sha1: sha },
641-
entryPoint: workflowPath,
640+
const expectedWorkflow = {
641+
ref: ref,
642+
repository: `${serverUrl}/${repository}`,
643+
path: workflowPath,
642644
}
643645

644646
const log = []
@@ -785,14 +787,14 @@ t.test('publish existing package with provenance in gha', async t => {
785787
t.hasStrict(provenance.subject[0],
786788
expectedSubject,
787789
'provenance subject matches expectations')
788-
t.hasStrict(provenance.predicate.buildType,
789-
'https://github.com/npm/cli/gha/v2',
790+
t.hasStrict(provenance.predicate.buildDefinition.buildType,
791+
'https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1',
790792
'buildType matches expectations')
791-
t.hasStrict(provenance.predicate.builder.id,
792-
'https://github.com/actions/runner',
793+
t.hasStrict(provenance.predicate.runDetails.builder.id,
794+
`https://github.com/actions/runner/${runnerEnv}`,
793795
'builder id matches expectations')
794-
t.hasStrict(provenance.predicate.invocation.configSource,
795-
expectedConfigSource,
796+
t.hasStrict(provenance.predicate.buildDefinition.externalParameters.workflow,
797+
expectedWorkflow,
796798
'configSource matches expectations')
797799
return true
798800
}).reply(201, {})

0 commit comments

Comments
 (0)