Compare commits

..

1 Commits

Author SHA1 Message Date
Brian DeHamer fde0a052cc test jwks with proxy
Signed-off-by: Brian DeHamer <bdehamer@github.com>
2024-07-29 10:51:10 -07:00
14 changed files with 70692 additions and 47506 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ updates:
- minor - minor
- patch - patch
ignore: ignore:
- dependency-name: 'actions/attest-build-provenance' - dependency-name: "actions/attest-build-provenance"
- package-ecosystem: npm - package-ecosystem: npm
directory: / directory: /
+1
View File
@@ -69,3 +69,4 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Dump output - name: Dump output
run: jq < ${{ steps.attest-provenance.outputs.bundle-path }} run: jq < ${{ steps.attest-provenance.outputs.bundle-path }}
+1 -3
View File
@@ -38,7 +38,7 @@ jobs:
- name: Lint Codebase - name: Lint Codebase
id: super-linter id: super-linter
uses: super-linter/super-linter/slim@v7 uses: super-linter/super-linter/slim@v6
env: env:
DEFAULT_BRANCH: main DEFAULT_BRANCH: main
FILTER_REGEX_EXCLUDE: dist/**/* FILTER_REGEX_EXCLUDE: dist/**/*
@@ -46,6 +46,4 @@ jobs:
TYPESCRIPT_DEFAULT_STYLE: prettier TYPESCRIPT_DEFAULT_STYLE: prettier
VALIDATE_ALL_CODEBASE: true VALIDATE_ALL_CODEBASE: true
VALIDATE_JAVASCRIPT_STANDARD: false VALIDATE_JAVASCRIPT_STANDARD: false
VALIDATE_TYPESCRIPT_STANDARD: false
VALIDATE_JSCPD: false VALIDATE_JSCPD: false
VALIDATE_YAML_PRETTIER: false
-17
View File
@@ -1,17 +0,0 @@
name: GitHub Sigstore Prober
on:
workflow_dispatch:
schedule:
# run every 5 minutes, as often as Github Actions allows
- cron: '*/5 * * * *'
jobs:
prober:
permissions:
attestations: write
id-token: write
secrets: inherit
uses: ./.github/workflows/prober.yml
with:
sigstore: github
-17
View File
@@ -1,17 +0,0 @@
name: Public-Good Sigstore Prober
on:
workflow_dispatch:
schedule:
# run every 5 minutes, as often as Github Actions allows
- cron: '*/5 * * * *'
jobs:
prober:
permissions:
attestations: write
id-token: write
secrets: inherit
uses: ./.github/workflows/prober.yml
with:
sigstore: public-good
-84
View File
@@ -1,84 +0,0 @@
name: Prober Workflow
on:
workflow_call:
inputs:
sigstore:
description: 'Which Sigstore instance to use for signing'
required: true
type: string
jobs:
probe:
runs-on: ubuntu-latest
permissions:
attestations: write
id-token: write
steps:
- name: Request OIDC Token
run: |
curl "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=nobody" \
-H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \
-H "Accept: application/json; api-version=2.0" \
-H "Content-Type: application/json" \
--silent | jq -r '.value' | jq -R 'split(".") | .[0],.[1] | @base64d | fromjson'
- name: Create artifact
run: |
date > artifact
- name: Attest build provenance
uses: actions/attest-build-provenance@v1
env:
INPUT_PRIVATE-SIGNING: ${{ inputs.sigstore == 'github' && 'true' || 'false' }}
with:
subject-path: artifact
- name: Verify build artifact
env:
GH_TOKEN: ${{ github.token }}
run: |
gh attestation verify ./artifact --owner "$GITHUB_REPOSITORY_OWNER"
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
path: "artifact"
- name: Report attestation prober success
if: ${{ success() }}
uses: masci/datadog@a5d283e78e33a688ed08a96ba64440505e645a8c # v1.7.1
with:
api-key: "${{ secrets.DATADOG_API_KEY }}"
service-checks: |
- check: "attestation-integration.actions.prober"
status: 0
host_name: github.com
tags:
- "catalog_service:${{ secrets.CATALOG_SERVICE }}"
- "service:${{ secrets.CATALOG_SERVICE }}"
- "deployed_to:production"
- "env:production"
- "repo:${{ github.repository }}"
- "team:${{ secrets.TEAM }}"
- "sigstore:${{ inputs.sigstore }}"
- name: Report attestation prober failure
if: ${{ failure() }}
uses: masci/datadog@a5d283e78e33a688ed08a96ba64440505e645a8c # v1.7.1
with:
api-key: "${{ secrets.DATADOG_API_KEY }}"
service-checks: |
- check: "attestation-integration.actions.prober"
message: "${{ github.repository_owner }} failed prober check"
status: 2
host_name: github.com
tags:
- "catalog_service:${{ secrets.CATALOG_SERVICE }}"
- "service:${{ secrets.CATALOG_SERVICE }}"
- "deployed_to:production"
- "env:production"
- "repo:${{ github.repository }}"
- "team:${{ secrets.TEAM }}"
- "sigstore:${{ inputs.sigstore }}"
-4
View File
@@ -77,10 +77,6 @@ See [action.yml](action.yml)
# the "subject-digest" parameter be specified. Defaults to false. # the "subject-digest" parameter be specified. Defaults to false.
push-to-registry: push-to-registry:
# Whether to attach a list of generated attestations to the workflow run
# summary page. Defaults to true.
show-summary:
# The GitHub token used to make authenticated API requests. Default is # The GitHub token used to make authenticated API requests. Default is
# ${{ github.token }} # ${{ github.token }}
github-token: github-token:
+1 -40
View File
@@ -1,45 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`main when a non-default OIDC issuer is used successfully run main 1`] = ` exports[`main successfully run main 1`] = `
{
"buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1",
"externalParameters": {
"workflow": {
"path": ".github/workflows/main.yml",
"ref": "main",
"repository": "https://example-01.ghe.com/owner/repo",
},
},
"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://example-01.ghe.com/owner/repo@refs/heads/main",
},
],
},
"runDetails": {
"builder": {
"id": "https://example-01.ghe.com/owner/shared/.github/workflows/build.yml@main",
},
"metadata": {
"invocationId": "https://example-01.ghe.com/owner/repo/actions/runs/run-id/attempts/run-attempt",
},
},
}
`;
exports[`main when the default OIDC issuer is used successfully run main 1`] = `
{ {
"buildDefinition": { "buildDefinition": {
"buildType": "https://actions.github.io/buildtypes/workflow/v1", "buildType": "https://actions.github.io/buildtypes/workflow/v1",
+56 -125
View File
@@ -13,13 +13,61 @@ setFailedMock.mockImplementation(() => {})
describe('main', () => { describe('main', () => {
let outputs = {} as Record<string, string> let outputs = {} as Record<string, string>
const originalEnv = process.env const originalEnv = process.env
const issuer = 'https://token.actions.githubusercontent.com'
const audience = 'nobody'
const jwksPath = '/.well-known/jwks.json'
const tokenPath = '/token'
beforeEach(() => { const claims = {
iss: issuer,
aud: 'nobody',
repository: 'owner/repo',
ref: 'refs/heads/main',
sha: 'babca52ab0c93ae16539e5923cb0d7403b9a093b',
workflow_ref: 'owner/repo/.github/workflows/main.yml@main',
job_workflow_ref: 'owner/shared/.github/workflows/build.yml@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'
}
beforeEach(async () => {
jest.resetAllMocks() jest.resetAllMocks()
setOutputMock.mockImplementation((key, value) => { setOutputMock.mockImplementation((key, value) => {
outputs[key] = value outputs[key] = value
}) })
process.env = {
...originalEnv,
ACTIONS_ID_TOKEN_REQUEST_URL: `${issuer}${tokenPath}?`,
ACTIONS_ID_TOKEN_REQUEST_TOKEN: 'token',
GITHUB_SERVER_URL: 'https://github.com',
GITHUB_REPOSITORY: claims.repository
}
// Generate JWT signing key
const key = await jose.generateKeyPair('PS256')
// Create JWK, JWKS, and JWT
const kid = '12345'
const jwk = await jose.exportJWK(key.publicKey)
const jwks = { keys: [{ ...jwk, kid }] }
const jwt = await new jose.SignJWT(claims)
.setProtectedHeader({ alg: 'PS256', kid })
.sign(key.privateKey)
// Mock OpenID configuration and JWKS endpoints
nock(issuer)
.get('/.well-known/openid-configuration')
.reply(200, { jwks_uri: `${issuer}${jwksPath}` })
nock(issuer).get(jwksPath).reply(200, jwks)
// Mock OIDC token endpoint for populating the provenance
nock(issuer).get(tokenPath).query({ audience }).reply(200, { value: jwt })
}) })
afterEach(() => { afterEach(() => {
@@ -27,131 +75,14 @@ describe('main', () => {
process.env = originalEnv process.env = originalEnv
}) })
describe('when the default OIDC issuer is used', () => { it('successfully run main', async () => {
const issuer = 'https://token.actions.githubusercontent.com' // Run the main function
const audience = 'nobody' await main.run()
const jwksPath = '/.well-known/jwks.json'
const tokenPath = '/token'
const claims = { // Verify that outputs were set correctly
iss: issuer, expect(setOutputMock).toHaveBeenCalledTimes(2)
aud: 'nobody',
repository: 'owner/repo',
ref: 'refs/heads/main',
sha: 'babca52ab0c93ae16539e5923cb0d7403b9a093b',
workflow_ref: 'owner/repo/.github/workflows/main.yml@main',
job_workflow_ref: 'owner/shared/.github/workflows/build.yml@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'
}
beforeEach(async () => { expect(outputs['predicate']).toMatchSnapshot()
process.env = { expect(outputs['predicate-type']).toBe('https://slsa.dev/provenance/v1')
...originalEnv,
ACTIONS_ID_TOKEN_REQUEST_URL: `${issuer}${tokenPath}?`,
ACTIONS_ID_TOKEN_REQUEST_TOKEN: 'token',
GITHUB_SERVER_URL: 'https://github.com',
GITHUB_REPOSITORY: claims.repository
}
// Generate JWT signing key
const key = await jose.generateKeyPair('PS256')
// Create JWK, JWKS, and JWT
const kid = '12345'
const jwk = await jose.exportJWK(key.publicKey)
const jwks = { keys: [{ ...jwk, kid }] }
const jwt = await new jose.SignJWT(claims)
.setProtectedHeader({ alg: 'PS256', kid })
.sign(key.privateKey)
// Mock OpenID configuration and JWKS endpoints
nock(issuer)
.get('/.well-known/openid-configuration')
.reply(200, { jwks_uri: `${issuer}${jwksPath}` })
nock(issuer).get(jwksPath).reply(200, jwks)
// Mock OIDC token endpoint for populating the provenance
nock(issuer).get(tokenPath).query({ audience }).reply(200, { value: jwt })
})
it('successfully run main', async () => {
// Run the main function
await main.run()
// Verify that outputs were set correctly
expect(setOutputMock).toHaveBeenCalledTimes(2)
expect(outputs['predicate']).toMatchSnapshot()
expect(outputs['predicate-type']).toBe('https://slsa.dev/provenance/v1')
})
})
describe('when a non-default OIDC issuer is used', () => {
const issuer = 'https://token.actions.example-01.ghe.com'
const audience = 'nobody'
const jwksPath = '/.well-known/jwks.json'
const tokenPath = '/token'
const claims = {
iss: issuer,
aud: 'nobody',
repository: 'owner/repo',
ref: 'refs/heads/main',
sha: 'babca52ab0c93ae16539e5923cb0d7403b9a093b',
workflow_ref: 'owner/repo/.github/workflows/main.yml@main',
job_workflow_ref: 'owner/shared/.github/workflows/build.yml@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'
}
beforeEach(async () => {
process.env = {
...originalEnv,
ACTIONS_ID_TOKEN_REQUEST_URL: `${issuer}${tokenPath}?`,
ACTIONS_ID_TOKEN_REQUEST_TOKEN: 'token',
GITHUB_SERVER_URL: 'https://example-01.ghe.com',
GITHUB_REPOSITORY: claims.repository
}
// Generate JWT signing key
const key = await jose.generateKeyPair('PS256')
// Create JWK, JWKS, and JWT
const kid = '12345'
const jwk = await jose.exportJWK(key.publicKey)
const jwks = { keys: [{ ...jwk, kid }] }
const jwt = await new jose.SignJWT(claims)
.setProtectedHeader({ alg: 'PS256', kid })
.sign(key.privateKey)
// Mock OpenID configuration and JWKS endpoints
nock(issuer)
.get('/.well-known/openid-configuration')
.reply(200, { jwks_uri: `${issuer}${jwksPath}` })
nock(issuer).get(jwksPath).reply(200, jwks)
// Mock OIDC token endpoint for populating the provenance
nock(issuer).get(tokenPath).query({ audience }).reply(200, { value: jwt })
})
it('successfully run main', async () => {
// Run the main function
await main.run()
// Verify that outputs were set correctly
expect(setOutputMock).toHaveBeenCalledTimes(2)
expect(outputs['predicate']).toMatchSnapshot()
expect(outputs['predicate-type']).toBe('https://slsa.dev/provenance/v1')
})
}) })
}) })
+2 -9
View File
@@ -30,12 +30,6 @@ inputs:
and that the "subject-digest" parameter be specified. Defaults to false. and that the "subject-digest" parameter be specified. Defaults to false.
default: false default: false
required: false required: false
show-summary:
description: >
Whether to attach a list of generated attestations to the workflow run
summary page. Defaults to true.
default: true
required: false
github-token: github-token:
description: > description: >
The GitHub token used to make authenticated API requests. The GitHub token used to make authenticated API requests.
@@ -50,9 +44,9 @@ outputs:
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- uses: actions/attest-build-provenance/predicate@f1185f1959cdaeda41a7f5a7b43cbe6b58a7a793 # predicate@1.1.3 - uses: actions/attest-build-provenance/predicate@test
id: generate-build-provenance-predicate id: generate-build-provenance-predicate
- uses: actions/attest@67422f5511b7ff725f4dbd6fb9bd2cd925c65a8d # v1.4.1 - uses: actions/attest@7305951e905fb742188aa16c1d23409b13565e26 # v1.3.3
id: attest id: attest
with: with:
subject-path: ${{ inputs.subject-path }} subject-path: ${{ inputs.subject-path }}
@@ -61,5 +55,4 @@ runs:
predicate-type: ${{ steps.generate-build-provenance-predicate.outputs.predicate-type }} predicate-type: ${{ steps.generate-build-provenance-predicate.outputs.predicate-type }}
predicate: ${{ steps.generate-build-provenance-predicate.outputs.predicate }} predicate: ${{ steps.generate-build-provenance-predicate.outputs.predicate }}
push-to-registry: ${{ inputs.push-to-registry }} push-to-registry: ${{ inputs.push-to-registry }}
show-summary: ${{ inputs.show-summary }}
github-token: ${{ inputs.github-token }} github-token: ${{ inputs.github-token }}
Generated Vendored
+70469 -46259
View File
File diff suppressed because one or more lines are too long
Generated Vendored
+21 -2
View File
@@ -1798,7 +1798,7 @@ lru-cache
ISC ISC
The ISC License The ISC License
Copyright (c) 2010-2023 Isaac Z. Schlueter and Contributors Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@@ -2389,7 +2389,7 @@ supports-color
MIT MIT
MIT License MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com) Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -2517,3 +2517,22 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
yallist
ISC
The ISC License
Copyright (c) Isaac Z. Schlueter and Contributors
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+132 -937
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -1,7 +1,7 @@
{ {
"name": "actions/attest-build-provenance", "name": "actions/attest-build-provenance",
"description": "Generate signed build provenance attestations", "description": "Generate signed build provenance attestations",
"version": "1.1.3", "version": "1.1.0",
"author": "", "author": "",
"private": true, "private": true,
"homepage": "https://github.com/actions/attest-build-provenance", "homepage": "https://github.com/actions/attest-build-provenance",
@@ -70,27 +70,27 @@
] ]
}, },
"dependencies": { "dependencies": {
"@actions/attest": "^1.4.2", "@actions/attest": "file:../toolkit/packages/attest",
"@actions/core": "^1.10.1" "@actions/core": "^1.10.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/node": "^22.5.2", "@types/node": "^22.0.0",
"@typescript-eslint/eslint-plugin": "^7.17.0", "@typescript-eslint/eslint-plugin": "^7.17.0",
"@typescript-eslint/parser": "^7.18.0", "@typescript-eslint/parser": "^7.17.0",
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-plugin-github": "^5.0.1", "eslint-plugin-github": "^5.0.1",
"eslint-plugin-jest": "^28.8.1", "eslint-plugin-jest": "^28.6.0",
"eslint-plugin-jsonc": "^2.16.0", "eslint-plugin-jsonc": "^2.16.0",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"jest": "^29.7.0", "jest": "^29.7.0",
"jose": "^5.8.0", "jose": "^5.6.3",
"markdownlint-cli": "^0.41.0", "markdownlint-cli": "^0.41.0",
"nock": "^13.5.5", "nock": "^13.5.4",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"prettier-eslint": "^16.3.0", "prettier-eslint": "^16.3.0",
"ts-jest": "^29.2.5", "ts-jest": "^29.2.3",
"typescript": "^5.5.4" "typescript": "^5.5.4"
} }
} }