Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

limit attestation subject count #53

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 for the attestation. Must be in the form
Expand Down
50 changes: 49 additions & 1 deletion __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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: >
Expand Down
6 changes: 5 additions & 1 deletion dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)

Expand Down
Loading