Skip to content

Commit

Permalink
fix: provenance build type v2 (#6228)
Browse files Browse the repository at this point in the history
Signed-off-by: Brian DeHamer <bdehamer@github.com>
Co-authored-by: Philip Harrison <philip@mailharrison.com>
  • Loading branch information
bdehamer and feelepxyz authored Mar 14, 2023
1 parent 618c1ba commit 17adfb7
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 10 deletions.
19 changes: 10 additions & 9 deletions workspaces/libnpmpublish/lib/provenance.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,40 @@ const INTOTO_PAYLOAD_TYPE = 'application/vnd.in-toto+json'
const INTOTO_STATEMENT_TYPE = 'https://in-toto.io/Statement/v0.1'
const SLSA_PREDICATE_TYPE = 'https://slsa.dev/provenance/v0.2'

const BUILDER_ID_PREFIX = 'https://github.com/npm/cli'
const BUILDER_ID = 'https://github.com/actions/runner'
const BUILD_TYPE_PREFIX = 'https://github.com/npm/cli/gha'
const BUILD_TYPE_VERSION = 'v1'
const BUILD_TYPE_VERSION = 'v2'

const generateProvenance = async (subject, opts) => {
const { env } = process
/* istanbul ignore next - not covering missing env var case */
const [workflowPath] = (env.GITHUB_WORKFLOW_REF || '')
.replace(env.GITHUB_REPOSITORY + '/', '')
.split('@')
const payload = {
_type: INTOTO_STATEMENT_TYPE,
subject,
predicateType: SLSA_PREDICATE_TYPE,
predicate: {
buildType: `${BUILD_TYPE_PREFIX}@${BUILD_TYPE_VERSION}`,
builder: { id: `${BUILDER_ID_PREFIX}@${opts.npmVersion}` },
buildType: `${BUILD_TYPE_PREFIX}/${BUILD_TYPE_VERSION}`,
builder: { id: BUILDER_ID },
invocation: {
configSource: {
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
digest: {
sha1: env.GITHUB_SHA,
},
entryPoint: env.GITHUB_WORKFLOW_REF,
entryPoint: workflowPath,
},
parameters: {},
environment: {
GITHUB_ACTOR_ID: env.GITHUB_ACTOR_ID,
GITHUB_EVENT_NAME: env.GITHUB_EVENT_NAME,
GITHUB_REF: env.GITHUB_REF,
GITHUB_REF_TYPE: env.GITHUB_REF_TYPE,
GITHUB_REPOSITORY: env.GITHUB_REPOSITORY,
GITHUB_REPOSITORY_ID: env.GITHUB_REPOSITORY_ID,
GITHUB_REPOSITORY_OWNER_ID: env.GITHUB_REPOSITORY_OWNER_ID,
GITHUB_RUN_ATTEMPT: env.GITHUB_RUN_ATTEMPT,
GITHUB_RUN_ID: env.GITHUB_RUN_ID,
GITHUB_RUN_NUMBER: env.GITHUB_RUN_NUMBER,
GITHUB_SHA: env.GITHUB_SHA,
GITHUB_WORKFLOW_REF: env.GITHUB_WORKFLOW_REF,
GITHUB_WORKFLOW_SHA: env.GITHUB_WORKFLOW_SHA,
Expand All @@ -53,7 +54,7 @@ const generateProvenance = async (subject, opts) => {
},
materials: [
{
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}`,
uri: `git+${env.GITHUB_SERVER_URL}/${env.GITHUB_REPOSITORY}@${env.GITHUB_REF}`,
digest: {
sha1: env.GITHUB_SHA,
},
Expand Down
49 changes: 48 additions & 1 deletion workspaces/libnpmpublish/test/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -599,17 +599,47 @@ t.test('other error code', async t => {
})

t.test('publish existing package with provenance in gha', async t => {
// Environment variables
const oidcURL = 'https://mock.oidc'
const requestToken = 'decafbad'
const workflowPath = '.github/workflows/publish.yml'
const repository = 'github/foo'
const serverUrl = 'https://github.com'
const ref = 'refs/heads/main'
const sha = 'deadbeef'
const runID = '123456'
const runAttempt = '1'

// Set-up GHA environment variables
mockGlobals(t, {
'process.env': {
CI: true,
GITHUB_ACTIONS: true,
ACTIONS_ID_TOKEN_REQUEST_URL: oidcURL,
ACTIONS_ID_TOKEN_REQUEST_TOKEN: requestToken,
GITHUB_WORKFLOW_REF: `${repository}/${workflowPath}@${ref}`,
GITHUB_REPOSITORY: repository,
GITHUB_SERVER_URL: serverUrl,
GITHUB_REF: ref,
GITHUB_SHA: sha,
GITHUB_RUN_ID: runID,
GITHUB_RUN_ATTEMPT: runAttempt,
},
})

const expectedSubject = {
name: 'pkg:npm/%40npmcli/libnpmpublish-test@1.0.0',
digest: {
sha512: integrity.sha512[0].hexDigest(),
},
}

const expectedConfigSource = {
uri: `git+${serverUrl}/${repository}@${ref}`,
digest: { sha1: sha },
entryPoint: workflowPath,
}

const { publish } = t.mock('..', { 'ci-info': t.mock('ci-info') })
const registry = new MockRegistry({
tap: t,
Expand Down Expand Up @@ -732,7 +762,24 @@ t.test('publish existing package with provenance in gha', async t => {

registry.getVisibility({ spec, visibility: { public: true } })
registry.nock.put(`/${spec.escapedName}`, body => {
return t.match(body, packument, 'posted packument matches expectations')
const bundleAttachment = body._attachments['@npmcli/libnpmpublish-test-1.0.0.sigstore']
const bundle = JSON.parse(bundleAttachment.data)
const provenance = JSON.parse(Buffer.from(bundle.dsseEnvelope.payload, 'base64').toString())

t.hasStrict(body, packument, 'posted packument matches expectations')
t.hasStrict(provenance.subject[0],
expectedSubject,
'provenance subject matches expectations')
t.hasStrict(provenance.predicate.buildType,
'https://github.com/npm/cli/gha/v2',
'buildType matches expectations')
t.hasStrict(provenance.predicate.builder.id,
'https://github.com/actions/runner',
'builder id matches expectations')
t.hasStrict(provenance.predicate.invocation.configSource,
expectedConfigSource,
'configSource matches expectations')
return true
}).reply(201, {})

const ret = await publish(manifest, tarData, {
Expand Down

0 comments on commit 17adfb7

Please sign in to comment.