Skip to content

Commit 17adfb7

Browse files
bdehamerfeelepxyz
andauthored
fix: provenance build type v2 (#6228)
Signed-off-by: Brian DeHamer <[email protected]> Co-authored-by: Philip Harrison <[email protected]>
1 parent 618c1ba commit 17adfb7

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

workspaces/libnpmpublish/lib/provenance.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,39 +4,40 @@ const INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json'
44
const INTOTO_STATEMENT_TYPE = 'https://in-toto.io/Statement/v0.1'
55
const SLSA_PREDICATE_TYPE = 'https://slsa.dev/provenance/v0.2'
66

7-
const BUILDER_ID_PREFIX = 'https://github.com/npm/cli'
7+
const BUILDER_ID = 'https://github.com/actions/runner'
88
const BUILD_TYPE_PREFIX = 'https://github.com/npm/cli/gha'
9-
const BUILD_TYPE_VERSION = 'v1'
9+
const BUILD_TYPE_VERSION = 'v2'
1010

1111
const generateProvenance = async (subject, opts) => {
1212
const { env } = process
13+
/* istanbul ignore next - not covering missing env var case */
14+
const [workflowPath] = (env.GITHUB_WORKFLOW_REF || '')
15+
.replace(env.GITHUB_REPOSITORY + '/', '')
16+
.split('@')
1317
const payload = {
1418
_type: INTOTO_STATEMENT_TYPE,
1519
subject,
1620
predicateType: SLSA_PREDICATE_TYPE,
1721
predicate: {
18-
buildType: `${BUILD_TYPE_PREFIX}@${BUILD_TYPE_VERSION}`,
19-
builder: { id: `${BUILDER_ID_PREFIX}@${opts.npmVersion}` },
22+
buildType: `${BUILD_TYPE_PREFIX}/${BUILD_TYPE_VERSION}`,
23+
builder: { id: BUILDER_ID },
2024
invocation: {
2125
configSource: {
2226
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
2327
digest: {
2428
sha1: env.GITHUB_SHA,
2529
},
26-
entryPoint: env.GITHUB_WORKFLOW_REF,
30+
entryPoint: workflowPath,
2731
},
2832
parameters: {},
2933
environment: {
30-
GITHUB_ACTOR_ID: env.GITHUB_ACTOR_ID,
3134
GITHUB_EVENT_NAME: env.GITHUB_EVENT_NAME,
3235
GITHUB_REF: env.GITHUB_REF,
33-
GITHUB_REF_TYPE: env.GITHUB_REF_TYPE,
3436
GITHUB_REPOSITORY: env.GITHUB_REPOSITORY,
3537
GITHUB_REPOSITORY_ID: env.GITHUB_REPOSITORY_ID,
3638
GITHUB_REPOSITORY_OWNER_ID: env.GITHUB_REPOSITORY_OWNER_ID,
3739
GITHUB_RUN_ATTEMPT: env.GITHUB_RUN_ATTEMPT,
3840
GITHUB_RUN_ID: env.GITHUB_RUN_ID,
39-
GITHUB_RUN_NUMBER: env.GITHUB_RUN_NUMBER,
4041
GITHUB_SHA: env.GITHUB_SHA,
4142
GITHUB_WORKFLOW_REF: env.GITHUB_WORKFLOW_REF,
4243
GITHUB_WORKFLOW_SHA: env.GITHUB_WORKFLOW_SHA,
@@ -53,7 +54,7 @@ const generateProvenance = async (subject, opts) => {
5354
},
5455
materials: [
5556
{
56-
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}`,
57+
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
5758
digest: {
5859
sha1: env.GITHUB_SHA,
5960
},

workspaces/libnpmpublish/test/publish.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,17 +599,47 @@ t.test('other error code', async t => {
599599
})
600600

601601
t.test('publish existing package with provenance in gha', async t => {
602+
// Environment variables
602603
const oidcURL = 'https://mock.oidc'
603604
const requestToken = 'decafbad'
605+
const workflowPath = '.github/workflows/publish.yml'
606+
const repository = 'github/foo'
607+
const serverUrl = 'https://github.com'
608+
const ref = 'refs/heads/main'
609+
const sha = 'deadbeef'
610+
const runID = '123456'
611+
const runAttempt = '1'
612+
604613
// Set-up GHA environment variables
605614
mockGlobals(t, {
606615
'process.env': {
607616
CI: true,
608617
GITHUB_ACTIONS: true,
609618
ACTIONS_ID_TOKEN_REQUEST_URL: oidcURL,
610619
ACTIONS_ID_TOKEN_REQUEST_TOKEN: requestToken,
620+
GITHUB_WORKFLOW_REF: `${repository}/${workflowPath}@${ref}`,
621+
GITHUB_REPOSITORY: repository,
622+
GITHUB_SERVER_URL: serverUrl,
623+
GITHUB_REF: ref,
624+
GITHUB_SHA: sha,
625+
GITHUB_RUN_ID: runID,
626+
GITHUB_RUN_ATTEMPT: runAttempt,
611627
},
612628
})
629+
630+
const expectedSubject = {
631+
name: 'pkg:npm/%40npmcli/[email protected]',
632+
digest: {
633+
sha512: integrity.sha512[0].hexDigest(),
634+
},
635+
}
636+
637+
const expectedConfigSource = {
638+
uri: `git+${serverUrl}/${repository}@${ref}`,
639+
digest: { sha1: sha },
640+
entryPoint: workflowPath,
641+
}
642+
613643
const { publish } = t.mock('..', { 'ci-info': t.mock('ci-info') })
614644
const registry = new MockRegistry({
615645
tap: t,
@@ -732,7 +762,24 @@ t.test('publish existing package with provenance in gha', async t => {
732762

733763
registry.getVisibility({ spec, visibility: { public: true } })
734764
registry.nock.put(`/${spec.escapedName}`, body => {
735-
return t.match(body, packument, 'posted packument matches expectations')
765+
const bundleAttachment = body._attachments['@npmcli/libnpmpublish-test-1.0.0.sigstore']
766+
const bundle = JSON.parse(bundleAttachment.data)
767+
const provenance = JSON.parse(Buffer.from(bundle.dsseEnvelope.payload, 'base64').toString())
768+
769+
t.hasStrict(body, packument, 'posted packument matches expectations')
770+
t.hasStrict(provenance.subject[0],
771+
expectedSubject,
772+
'provenance subject matches expectations')
773+
t.hasStrict(provenance.predicate.buildType,
774+
'https://github.com/npm/cli/gha/v2',
775+
'buildType matches expectations')
776+
t.hasStrict(provenance.predicate.builder.id,
777+
'https://github.com/actions/runner',
778+
'builder id matches expectations')
779+
t.hasStrict(provenance.predicate.invocation.configSource,
780+
expectedConfigSource,
781+
'configSource matches expectations')
782+
return true
736783
}).reply(201, {})
737784

738785
const ret = await publish(manifest, tarData, {

0 commit comments

Comments
 (0)