From 345fe37c1fb36a2ae5c461a4e8b7968c8d94498d Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Mon, 25 Mar 2024 08:25:42 -0700 Subject: [PATCH] update conformance cli to support sigstore staging (#1084) Signed-off-by: Brian DeHamer --- .changeset/polite-crabs-perform.md | 2 ++ .github/workflows/conformance.yml | 4 ++++ .../conformance/src/commands/sign-bundle.ts | 10 ++++++++++ packages/conformance/src/commands/sign.ts | 10 ++++++++++ .../conformance/src/commands/verify-bundle.ts | 17 +++++++++++++++++ packages/conformance/src/commands/verify.ts | 17 +++++++++++++++++ packages/conformance/src/staging.ts | 6 ++++++ 7 files changed, 66 insertions(+) create mode 100644 .changeset/polite-crabs-perform.md create mode 100644 packages/conformance/src/staging.ts diff --git a/.changeset/polite-crabs-perform.md b/.changeset/polite-crabs-perform.md new file mode 100644 index 00000000..a845151c --- /dev/null +++ b/.changeset/polite-crabs-perform.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml index 8b2f4b9f..b59e508d 100644 --- a/.github/workflows/conformance.yml +++ b/.github/workflows/conformance.yml @@ -29,3 +29,7 @@ jobs: with: entrypoint: ${{ github.workspace }}/packages/conformance/bin/run xfail: "test_verify_with_trust_root" + - uses: sigstore/sigstore-conformance@ee4de0e602873beed74cf9e49d5332529fe69bf6 # v0.0.11 + with: + entrypoint: ${{ github.workspace }}/packages/conformance/bin/run + environment: staging diff --git a/packages/conformance/src/commands/sign-bundle.ts b/packages/conformance/src/commands/sign-bundle.ts index 07c66d72..3c5093d2 100644 --- a/packages/conformance/src/commands/sign-bundle.ts +++ b/packages/conformance/src/commands/sign-bundle.ts @@ -1,6 +1,7 @@ import { Args, Command, Flags } from '@oclif/core'; import fs from 'fs/promises'; import * as sigstore from 'sigstore'; +import { FULCIO_STAGING_URL, REKOR_STAGING_URL } from '../staging'; export default class SignBundle extends Command { static override flags = { @@ -12,6 +13,10 @@ export default class SignBundle extends Command { description: 'path to which the bundle will be written', required: true, }), + staging: Flags.boolean({ + description: 'whether to use the staging environment', + default: false, + }), }; static override args = { @@ -29,6 +34,11 @@ export default class SignBundle extends Command { identityToken: flags['identity-token'], }; + if (flags['staging']) { + options.fulcioURL = FULCIO_STAGING_URL; + options.rekorURL = REKOR_STAGING_URL; + } + const artifact = await fs.readFile(args.artifact); const bundle = await sigstore.sign(artifact, options); diff --git a/packages/conformance/src/commands/sign.ts b/packages/conformance/src/commands/sign.ts index 3323e866..cb537ee2 100644 --- a/packages/conformance/src/commands/sign.ts +++ b/packages/conformance/src/commands/sign.ts @@ -1,6 +1,7 @@ import { Args, Command, Flags } from '@oclif/core'; import fs from 'fs/promises'; import * as sigstore from 'sigstore'; +import { FULCIO_STAGING_URL, REKOR_STAGING_URL } from '../staging'; export default class Sign extends Command { static override flags = { @@ -16,6 +17,10 @@ export default class Sign extends Command { description: 'path to which the certificate will be written', required: true, }), + staging: Flags.boolean({ + description: 'whether to use the staging environment', + default: false, + }), }; static override args = { @@ -33,6 +38,11 @@ export default class Sign extends Command { identityToken: flags['identity-token'], }; + if (flags['staging']) { + options.fulcioURL = FULCIO_STAGING_URL; + options.rekorURL = REKOR_STAGING_URL; + } + const artifact = await fs.readFile(args.artifact); const bundle = await sigstore.sign(artifact, options); diff --git a/packages/conformance/src/commands/verify-bundle.ts b/packages/conformance/src/commands/verify-bundle.ts index e9bce1e6..75c6bf91 100644 --- a/packages/conformance/src/commands/verify-bundle.ts +++ b/packages/conformance/src/commands/verify-bundle.ts @@ -3,7 +3,10 @@ import { bundleFromJSON } from '@sigstore/bundle'; import { TrustedRoot } from '@sigstore/protobuf-specs'; import { Verifier, toSignedEntity, toTrustMaterial } from '@sigstore/verify'; import fs from 'fs/promises'; +import os from 'os'; +import path from 'path'; import * as sigstore from 'sigstore'; +import { TUF_STAGING_ROOT, TUF_STAGING_URL } from '../staging'; export default class VerifyBundle extends Command { static override flags = { @@ -24,6 +27,10 @@ export default class VerifyBundle extends Command { description: 'path to trusted root', required: false, }), + staging: Flags.boolean({ + description: 'whether to use the staging environment', + default: false, + }), }; static override args = { @@ -49,6 +56,16 @@ export default class VerifyBundle extends Command { certificateIssuer: flags['certificate-oidc-issuer'], }; + if (flags['staging']) { + // Write the initial root.json to a temporary directory + const tmpPath = await fs.mkdtemp(path.join(os.tmpdir(), 'sigstore-')); + const rootPath = path.join(tmpPath, 'root.json'); + await fs.writeFile(rootPath, Buffer.from(TUF_STAGING_ROOT, 'base64')); + + options.tufMirrorURL = TUF_STAGING_URL; + options.tufRootPath = rootPath; + } + sigstore.verify(bundle, artifact, options); } else { // Need to assemble the Verifier manually to pass in the trusted root diff --git a/packages/conformance/src/commands/verify.ts b/packages/conformance/src/commands/verify.ts index 275b3e92..f8cce508 100644 --- a/packages/conformance/src/commands/verify.ts +++ b/packages/conformance/src/commands/verify.ts @@ -1,7 +1,10 @@ import { Args, Command, Flags } from '@oclif/core'; import crypto, { BinaryLike } from 'crypto'; import fs from 'fs/promises'; +import os from 'os'; +import path from 'path'; import * as sigstore from 'sigstore'; +import { TUF_STAGING_ROOT, TUF_STAGING_URL } from '../staging'; export default class Verify extends Command { static override flags = { @@ -22,6 +25,10 @@ export default class Verify extends Command { description: 'the expected OIDC issuer for the signing certificate', required: true, }), + staging: Flags.boolean({ + description: 'whether to use the staging environment', + default: false, + }), }; static override args = { @@ -51,6 +58,16 @@ export default class Verify extends Command { tlogThreshold: 0, }; + if (flags['staging']) { + // Write the initial root.json to a temporary directory + const tmpPath = await fs.mkdtemp(path.join(os.tmpdir(), 'sigstore-')); + const rootPath = path.join(tmpPath, 'root.json'); + await fs.writeFile(rootPath, Buffer.from(TUF_STAGING_ROOT, 'base64')); + + options.tufMirrorURL = TUF_STAGING_URL; + options.tufRootPath = rootPath; + } + sigstore.verify(bundle, artifact, options); } } diff --git a/packages/conformance/src/staging.ts b/packages/conformance/src/staging.ts new file mode 100644 index 00000000..ab45ff57 --- /dev/null +++ b/packages/conformance/src/staging.ts @@ -0,0 +1,6 @@ +export const FULCIO_STAGING_URL = 'https://fulcio.sigstage.dev'; +export const REKOR_STAGING_URL = 'https://rekor.sigstage.dev'; + +export const TUF_STAGING_URL = 'https://tuf-repo-cdn.sigstage.dev'; +export const TUF_STAGING_ROOT = + 'ewoJInNpZ25lZCI6IHsKCQkiX3R5cGUiOiAicm9vdCIsCgkJInNwZWNfdmVyc2lvbiI6ICIxLjAiLAoJCSJ2ZXJzaW9uIjogNCwKCQkiZXhwaXJlcyI6ICIyMDI5LTAzLTA1VDIyOjUwOjIxWiIsCgkJImtleXMiOiB7CgkJCSIzMTRhZTczYWJkMzAxMmZjNzNiZmNjMzc4M2UzMWQwMzg1MjcxNjU5NzY0MmI4OTFkNmEzMzE1NWM0YmFmNjAwIjogewoJCQkJImtleXR5cGUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAoJCQkJImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKCQkJCQkic2hhMjU2IiwKCQkJCQkic2hhNTEyIgoJCQkJXSwKCQkJCSJrZXl2YWwiOiB7CgkJCQkJInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFWE1aN3JEOHRXREU0bEsvK25hSk43SU5NeE5DN1xuYk1NQU5EcVRRRTdXcHp5emZmV09nNTloYy9Nd2J2SnR2dXhoTzltRXUzR0QzQ24wSGZmRmxtVlJpQT09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKCQkJCX0KCQkJfSwKCQkJImM4ZTA5YTY4YjU4MjFiNzU0NjJhZTBkZjUyMTUxYzgxZGViN2YxODM4MjQ2ZGMxZGE4YzM0Y2M5MWVjMTJiZGEiOiB7CgkJCQkia2V5dHlwZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKCQkJCSJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCgkJCQkia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwoJCQkJCSJzaGEyNTYiLAoJCQkJCSJzaGE1MTIiCgkJCQldLAoJCQkJImtleXZhbCI6IHsKCQkJCQkicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVMM3ZML1ZlYUg2bkJibzRyZWt5TzRjYy9RdGhTXG4rbmx5SlhDWFNueUlNQXRMbVZUYThQZjBxRzZZSVZhUjBUbUxreWs5WW9TVnNaYWt4dU1UdWFFd3JnPT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgoJCQkJfQoJCQl9CgkJfSwKCQkicm9sZXMiOiB7CgkJCSJyb290IjogewoJCQkJImtleWlkcyI6IFsKCQkJCQkiYzhlMDlhNjhiNTgyMWI3NTQ2MmFlMGRmNTIxNTFjODFkZWI3ZjE4MzgyNDZkYzFkYThjMzRjYzkxZWMxMmJkYSIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMQoJCQl9LAoJCQkic25hcHNob3QiOiB7CgkJCQkia2V5aWRzIjogWwoJCQkJCSIzMTRhZTczYWJkMzAxMmZjNzNiZmNjMzc4M2UzMWQwMzg1MjcxNjU5NzY0MmI4OTFkNmEzMzE1NWM0YmFmNjAwIgoJCQkJXSwKCQkJCSJ0aHJlc2hvbGQiOiAxCgkJCX0sCgkJCSJ0YXJnZXRzIjogewoJCQkJImtleWlkcyI6IFsKCQkJCQkiYzhlMDlhNjhiNTgyMWI3NTQ2MmFlMGRmNTIxNTFjODFkZWI3ZjE4MzgyNDZkYzFkYThjMzRjYzkxZWMxMmJkYSIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMQoJCQl9LAoJCQkidGltZXN0YW1wIjogewoJCQkJImtleWlkcyI6IFsKCQkJCQkiMzE0YWU3M2FiZDMwMTJmYzczYmZjYzM3ODNlMzFkMDM4NTI3MTY1OTc2NDJiODkxZDZhMzMxNTVjNGJhZjYwMCIKCQkJCV0sCgkJCQkidGhyZXNob2xkIjogMQoJCQl9CgkJfSwKCQkiY29uc2lzdGVudF9zbmFwc2hvdCI6IHRydWUKCX0sCgkic2lnbmF0dXJlcyI6IFsKCQl7CgkJCSJrZXlpZCI6ICJjOGUwOWE2OGI1ODIxYjc1NDYyYWUwZGY1MjE1MWM4MWRlYjdmMTgzODI0NmRjMWRhOGMzNGNjOTFlYzEyYmRhIiwKCQkJInNpZyI6ICIzMDQ0MDIyMDA2ZmU4ZmZmNTFkMTg3NTNhZWZmMTQxZjgxYTk2MmI4YWMzM2Y0OTgzMWJiYmVjMTMzNGIyNzMzZWE5Njg5MDAwMjIwNmU2ZjM0M2M5YzdiOThhMmViZDFmMGI1MWFhNTI4NmVkM2E0ZDQ4ZTI3MWM3N2Q4OGVhNzc0OTkyMzFiZmY1YyIKCQl9CgldCn0=';