limit attestation subject count (#53)

Signed-off-by: Brian DeHamer <bdehamer@github.com>
This commit is contained in:
Brian DeHamer
2024-05-06 11:51:42 -07:00
committed by GitHub
parent 9a8c43656a
commit c58d52c41d
5 changed files with 65 additions and 5 deletions

View File

@@ -65,7 +65,7 @@ See [action.yml](action.yml)
with:
# Path to the artifact serving as the subject of the attestation. Must
# specify exactly one of "subject-path" or "subject-digest". May contain
# a glob pattern or list of paths.
# a glob pattern or list of paths (total subject count cannot exceed 64).
subject-path:
# SHA256 digest of the subject for the attestation. Must be in the form

View File

@@ -5,12 +5,14 @@
* Specifically, the inputs listed in `action.yml` should be set as environment
* variables following the pattern `INPUT_<INPUT_NAME>`.
*/
import * as core from '@actions/core'
import * as github from '@actions/github'
import { mockFulcio, mockRekor, mockTSA } from '@sigstore/mock'
import * as oci from '@sigstore/oci'
import fs from 'fs/promises'
import nock from 'nock'
import os from 'os'
import path from 'path'
import { MockAgent, setGlobalDispatcher } from 'undici'
import { SEARCH_PUBLIC_GOOD_URL } from '../src/endpoints'
import * as main from '../src/main'
@@ -286,6 +288,52 @@ describe('action', () => {
expect(setFailedMock).not.toHaveBeenCalled()
})
})
describe('when too many subjects are specified', () => {
let dir = ''
beforeEach(async () => {
const filename = 'subject'
const content = 'file content'
// Set-up temp directory
const tmpDir = await fs.realpath(os.tmpdir())
dir = await fs.mkdtemp(tmpDir + path.sep)
// Add files for glob testing
for (let i = 0; i < 65; i++) {
await fs.writeFile(path.join(dir, `${filename}-${i}`), content)
}
// Set the GH context with private repository visibility and a repo owner.
setGHContext({
payload: { repository: { visibility: 'private' } },
repo: { owner: 'foo', repo: 'bar' }
})
// Mock the action's inputs
getInputMock.mockImplementation(
mockInput({
predicate: '{}',
'subject-path': path.join(dir, `${filename}-*`)
})
)
})
afterEach(async () => {
// Clean-up temp directory
await fs.rm(dir, { recursive: true })
})
it('sets a failed status', async () => {
await main.run()
expect(runMock).toHaveReturned()
expect(setFailedMock).toHaveBeenCalledWith(
'Too many subjects specified. The maximum number of subjects is 64.'
)
})
})
})
function mockInput(inputs: Record<string, string>): typeof core.getInput {

View File

@@ -10,7 +10,7 @@ inputs:
description: >
Path to the artifact serving as the subject of the attestation. Must
specify exactly one of "subject-path" or "subject-digest". May contain a
glob pattern or list of paths.
glob pattern or list of paths (total subject count cannot exceed 64).
required: false
subject-digest:
description: >

6
dist/index.js generated vendored
View File

@@ -79644,6 +79644,7 @@ const subject_1 = __nccwpck_require__(95206);
const COLOR_CYAN = '\x1B[36m';
const COLOR_DEFAULT = '\x1B[39m';
const ATTESTATION_FILE_NAME = 'attestation.jsonl';
const MAX_SUBJECT_COUNT = 64;
/**
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
@@ -79661,8 +79662,11 @@ async function run() {
if (!process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
throw new Error('missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.');
}
// Calculate subject from inputs and generate provenance
// Gather list of subjets
const subjects = await (0, subject_1.subjectFromInputs)();
if (subjects.length > MAX_SUBJECT_COUNT) {
throw new Error(`Too many subjects specified. The maximum number of subjects is ${MAX_SUBJECT_COUNT}.`);
}
const predicate = (0, predicate_1.predicateFromInputs)();
const outputPath = path_1.default.join(tempDir(), ATTESTATION_FILE_NAME);
// Generate attestations for each subject serially

View File

@@ -16,6 +16,8 @@ const COLOR_CYAN = '\x1B[36m'
const COLOR_DEFAULT = '\x1B[39m'
const ATTESTATION_FILE_NAME = 'attestation.jsonl'
const MAX_SUBJECT_COUNT = 64
/**
* The main function for the action.
* @returns {Promise<void>} Resolves when the action is complete.
@@ -38,8 +40,14 @@ export async function run(): Promise<void> {
)
}
// Calculate subject from inputs and generate provenance
// Gather list of subjets
const subjects = await subjectFromInputs()
if (subjects.length > MAX_SUBJECT_COUNT) {
throw new Error(
`Too many subjects specified. The maximum number of subjects is ${MAX_SUBJECT_COUNT}.`
)
}
const predicate = predicateFromInputs()
const outputPath = path.join(tempDir(), ATTESTATION_FILE_NAME)