diff --git a/packages/attest/__tests__/__snapshots__/provenance.test.ts.snap b/packages/attest/__tests__/__snapshots__/provenance.test.ts.snap index f4b22123..409d9f91 100644 --- a/packages/attest/__tests__/__snapshots__/provenance.test.ts.snap +++ b/packages/attest/__tests__/__snapshots__/provenance.test.ts.snap @@ -1,6 +1,48 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`provenance functions buildSLSAProvenancePredicate returns a provenance hydrated from an OIDC token 1`] = ` +exports[`provenance functions buildSLSAProvenancePredicate returns a provenance from an org required workflow: provenance from org required workflow 1`] = ` +{ + "params": { + "buildDefinition": { + "buildType": "https://actions.github.io/buildtypes/workflow/v1", + "externalParameters": { + "workflow": { + "path": ".github/workflows/enforce.yml", + "ref": "refs/heads/vetted", + "repository": "https://foo.ghe.com/enterprise/org-workflows", + }, + }, + "internalParameters": { + "github": { + "event_name": "push", + "repository_id": "repo-id", + "repository_owner_id": "owner-id", + "runner_environment": "github-hosted", + }, + }, + "resolvedDependencies": [ + { + "digest": { + "gitCommit": "babca52ab0c93ae16539e5923cb0d7403b9a093b", + }, + "uri": "git+https://foo.ghe.com/owner/repo@refs/heads/main", + }, + ], + }, + "runDetails": { + "builder": { + "id": "https://foo.ghe.com/enterprise/org-workflows/.github/workflows/enforce.yml@refs/heads/vetted", + }, + "metadata": { + "invocationId": "https://foo.ghe.com/owner/repo/actions/runs/run-id/attempts/run-attempt", + }, + }, + }, + "type": "https://slsa.dev/provenance/v1", +} +`; + +exports[`provenance functions buildSLSAProvenancePredicate returns a provenance hydrated from an OIDC token: provenance with OIDC token 1`] = ` { "params": { "buildDefinition": { @@ -31,7 +73,7 @@ exports[`provenance functions buildSLSAProvenancePredicate returns a provenance }, "runDetails": { "builder": { - "id": "https://foo.ghe.com/owner/workflows/.github/workflows/publish.yml@main", + "id": "https://foo.ghe.com/owner/workflows/.github/workflows/publish.yml@refs/heads/main", }, "metadata": { "invocationId": "https://foo.ghe.com/owner/repo/actions/runs/run-id/attempts/run-attempt", diff --git a/packages/attest/__tests__/provenance.test.ts b/packages/attest/__tests__/provenance.test.ts index 2b533053..ca2f4f4d 100644 --- a/packages/attest/__tests__/provenance.test.ts +++ b/packages/attest/__tests__/provenance.test.ts @@ -23,8 +23,27 @@ describe('provenance functions', () => { repository: 'owner/repo', ref: 'refs/heads/main', sha: 'babca52ab0c93ae16539e5923cb0d7403b9a093b', - job_workflow_ref: 'owner/workflows/.github/workflows/publish.yml@main', - workflow_ref: 'owner/repo/.github/workflows/main.yml@main', + job_workflow_ref: + 'owner/workflows/.github/workflows/publish.yml@refs/heads/main', + workflow_ref: 'owner/repo/.github/workflows/main.yml@refs/heads/main', + event_name: 'push', + repository_id: 'repo-id', + repository_owner_id: 'owner-id', + run_id: 'run-id', + run_attempt: 'run-attempt', + runner_environment: 'github-hosted' + } + + const orgEnforcedclaims = { + iss: issuer, + aud: 'nobody', + repository: 'owner/repo', + ref: 'refs/heads/main', + sha: 'babca52ab0c93ae16539e5923cb0d7403b9a093b', + job_workflow_ref: + 'enterprise/org-workflows/.github/workflows/enforce.yml@refs/heads/vetted', + workflow_ref: + 'enterprise/org-workflows/.github/workflows/enforce.yml@refs/heads/vetted', event_name: 'push', repository_id: 'repo-id', repository_owner_id: 'owner-id', @@ -73,7 +92,14 @@ describe('provenance functions', () => { describe('buildSLSAProvenancePredicate', () => { it('returns a provenance hydrated from an OIDC token', async () => { const predicate = await buildSLSAProvenancePredicate() - expect(predicate).toMatchSnapshot() + expect(predicate).toMatchSnapshot('provenance with OIDC token') + }) + + it('returns a provenance from an org required workflow', async () => { + nock.cleanAll() + await mockIssuer(orgEnforcedclaims) + const predicate = await buildSLSAProvenancePredicate() + expect(predicate).toMatchSnapshot('provenance from org required workflow') }) }) diff --git a/packages/attest/src/provenance.ts b/packages/attest/src/provenance.ts index 1bd1e5c9..267b5d0e 100644 --- a/packages/attest/src/provenance.ts +++ b/packages/attest/src/provenance.ts @@ -27,12 +27,15 @@ export const buildSLSAProvenancePredicate = async ( const serverURL = process.env.GITHUB_SERVER_URL const claims = await getIDTokenClaims(issuer) - // Split just the path and ref from the workflow string. - // owner/repo/.github/workflows/main.yml@main => - // .github/workflows/main.yml, main - const [workflowPath] = claims.workflow_ref - .replace(`${claims.repository}/`, '') - .split('@') + // Split up the repo, path and ref from the workflow string. + // owner/repo/.github/workflows/main.yml@refs/heads/main => + // owner/repo, .github/workflows/main.yml, main + const workflowRef = claims.workflow_ref + const pathStart = workflowRef.indexOf('/.github/') + const refStart = workflowRef.lastIndexOf('@') + const workflowRepo = workflowRef.substring(0, pathStart) + const workflowPath = workflowRef.substring(pathStart + 1, refStart) + const workflowGitRef = workflowRef.substring(refStart + 1) return { type: SLSA_PREDICATE_V1_TYPE, @@ -41,8 +44,8 @@ export const buildSLSAProvenancePredicate = async ( buildType: GITHUB_BUILD_TYPE, externalParameters: { workflow: { - ref: claims.ref, - repository: `${serverURL}/${claims.repository}`, + ref: workflowGitRef, + repository: `${serverURL}/${workflowRepo}`, path: workflowPath } },