Skip to content

Commit d16f8fe

Browse files
Fix gh identity flag compatibility and verify before publishing
1 parent b66e59e commit d16f8fe

4 files changed

Lines changed: 13 additions & 2 deletions

File tree

‎.github/workflows/publish-rules.yml‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ jobs:
4343
with:
4444
subject-path: dist/node2shell-rules.json
4545
create-storage-record: false
46+
- name: Independently verify the attested publication
47+
env:
48+
BUNDLE_PATH: ${{ steps.attest.outputs.bundle-path }}
49+
run: |
50+
gh attestation trusted-root > "$RUNNER_TEMP/sigstore-roots.jsonl"
51+
python tools/signed_rules/keyless_rules.py verify --artifact dist/node2shell-rules.json --bundle "$BUNDLE_PATH" --trusted-root "$RUNNER_TEMP/sigstore-roots.jsonl" --state "$RUNNER_TEMP/rule-state.json" --output "$RUNNER_TEMP/rule-review.json"
4652
- name: Publish immutable-named release assets
4753
env:
4854
GH_TOKEN: ${{ github.token }}

‎docs/KEYLESS_RULES.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ reviewed workflow and the trusted local GitHub CLI.
3838

3939
An authorized maintainer explicitly dispatches **Publish authenticated rule
4040
snapshot** on `main`. The job runs local-only tests, packages the existing
41-
embedded snapshot, attests those exact bytes and creates a new release with
41+
embedded snapshot, attests those exact bytes, verifies them with independently
42+
obtained Sigstore roots using the client policy, and creates a new release with
4243
`node2shell-rules.json` and `node2shell-rules.sigstore.json`. Tags have the form
4344
`rules-v1-RUN_NUMBER-ATTEMPT`; no existing release/asset is overwritten and no
4445
unrelated software release is marked latest. There is no recurring schedule.

‎test_keyless_rules.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ def test_gh_policy_checks_cert_numeric_ids_and_exact_source_identity(self):
123123
def run(command, **kwargs):
124124
self.assertIn("--custom-trusted-root", command)
125125
self.assertIn("--bundle", command)
126+
# gh makes these four policy flags mutually exclusive. Exact
127+
# certificate identity includes the workflow path AND main ref.
128+
identity_flags = {"--cert-identity", "--cert-identity-regex", "--signer-repo", "--signer-workflow"}
129+
self.assertEqual({"--cert-identity"}, set(command) & identity_flags)
126130
for expected in (k.IDENTITY, k.ISSUER, "--deny-self-hosted-runners", "--source-digest", "--signer-digest", "refs/heads/main"):
127131
self.assertIn(expected, command)
128132
self.assertNotIn("shell", kwargs)

‎tools/signed_rules/keyless_rules.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def verify_provenance(artifact, bundle, root, commit):
116116
raise ValueError("Install a trusted GitHub CLI with attestation support")
117117
command = [gh, "attestation", "verify", str(artifact), "--repo", REPOSITORY,
118118
"--bundle", str(bundle), "--custom-trusted-root", str(root),
119-
"--signer-workflow", WORKFLOW, "--cert-identity", IDENTITY,
119+
"--cert-identity", IDENTITY,
120120
"--cert-oidc-issuer", ISSUER, "--source-ref", "refs/heads/main",
121121
"--source-digest", commit, "--signer-digest", commit,
122122
"--deny-self-hosted-runners", "--hostname", "github.com", "--format", "json"]

0 commit comments

Comments
 (0)