From 68b0e7980375de2040e7c0be53adfa6de5bc70cb Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 17:45:55 -0800 Subject: [PATCH 1/9] Add zizmor and frizbee CI checks Add caller workflows for zizmor (security scanning) and frizbee (action pinning verification). Fix zizmor findings where applicable and add suppression config for intentional patterns. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/frizbee.yml | 16 ++++++ .github/workflows/publish-packages.yml | 77 ++++++++++++++++++++++++++ .github/workflows/release.yml | 4 +- .github/workflows/zizmor.yml | 16 ++++++ .github/zizmor.yml | 54 ++++++++++++++++++ 5 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/frizbee.yml create mode 100644 .github/workflows/publish-packages.yml create mode 100644 .github/workflows/zizmor.yml create mode 100644 .github/zizmor.yml diff --git a/.github/workflows/frizbee.yml b/.github/workflows/frizbee.yml new file mode 100644 index 0000000..642f692 --- /dev/null +++ b/.github/workflows/frizbee.yml @@ -0,0 +1,16 @@ +name: Frizbee pinning check +on: + push: + workflow_call: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + frizbee: + uses: smallstep/workflows/.github/workflows/frizbee.yml@main + secrets: inherit diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml new file mode 100644 index 0000000..d76346b --- /dev/null +++ b/.github/workflows/publish-packages.yml @@ -0,0 +1,77 @@ +name: Publish to packages.smallstep.com + +# Independently publish packages to Red Hat (RPM) and Debian (DEB) repositories +# without running a full release. Downloads packages from GitHub releases, +# uploads to GCS, and imports to Artifact Registry. +# +# Usage (CLI): +# gh workflow run publish-packages.yml -f tag=v0.28.0 + +on: + workflow_dispatch: + inputs: + tag: + description: 'Git tag to publish (e.g., v0.28.0)' + required: true + type: string + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ inputs.tag }} + fetch-depth: 0 + + - name: Extract version + id: version + run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + env: + TAG: ${{ inputs.tag }} + + - name: Is Pre-release + id: is_prerelease + run: | + if [[ "$TAG" == *"-rc"* ]]; then + echo "is_prerelease=true" >> "$GITHUB_OUTPUT" + else + echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + fi + env: + TAG: ${{ inputs.tag }} + + - name: Authenticate to Google Cloud + uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 + with: + workload_identity_provider: ${{ secrets.GOOGLE_CLOUD_WORKLOAD_IDENTITY_PROVIDER }} + service_account: ${{ secrets.GOOGLE_CLOUD_GITHUB_SERVICE_ACCOUNT }} + + - name: Set up Cloud SDK + uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 + with: + project_id: ${{ secrets.GOOGLE_CLOUD_PACKAGES_PROJECT_ID }} + + - name: Download packages from GitHub release + run: | + mkdir -p dist + gh release download "$TAG" --pattern "*${VERSION}*.deb" --pattern "*${VERSION}*.rpm" --dir dist + env: + TAG: ${{ inputs.tag }} + VERSION: ${{ steps.version.outputs.version }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload packages to GCS + run: | + for pkg in dist/*.deb dist/*.rpm; do + ./scripts/package-upload.sh "$pkg" step-kms-plugin ${{ steps.version.outputs.version }} + done + + - name: Import packages to Artifact Registry + run: ./scripts/package-repo-import.sh step-kms-plugin ${{ steps.version.outputs.version }} + env: + IS_PRERELEASE: ${{ steps.is_prerelease.outputs.is_prerelease }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 72481a6..557a0eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,9 +30,11 @@ jobs: steps: - name: Is Pre-release id: is_prerelease + env: + REF: ${{ github.ref }} run: | set +e - echo ${{ github.ref }} | grep "\-rc.*" + echo "${REF}" | grep "\-rc.*" OUT=$? if [ $OUT -eq 0 ]; then IS_PRERELEASE=true; else IS_PRERELEASE=false; fi echo "IS_PRERELEASE=${IS_PRERELEASE}" >> "${GITHUB_OUTPUT}" diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..3270953 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,16 @@ +name: Zizmor security scan +on: + push: + workflow_call: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + zizmor: + uses: smallstep/workflows/.github/workflows/zizmor.yml@main + secrets: inherit diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000..4045c8e --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,54 @@ +rules: + # Internal reusable workflows (smallstep/*@main) intentionally track + # the main branch for centralized CI management. Pinning to a SHA + # would defeat the purpose of the shared workflows repo. + unpinned-uses: + ignore: + - actionlint.yml:16 + - ci.yml:18 + - code-scan-cron.yml:7 + - dependabot-auto-merge.yml:10 + - frizbee.yml:15 + - release.yml:11 + - release.yml:115 + - release.yml:123 + - release.yml:136 + - release.yml:164 + - release.yml:178 + - release.yml:192 + - release.yml:206 + - triage.yml:19 + - zizmor.yml:15 + # Reusable workflow callers require `secrets: inherit` to pass + # credentials needed by the shared workflows (e.g. SSH keys, PATs). + secrets-inherit: + ignore: + - actionlint.yml:16 + - ci.yml:18 + - dependabot-auto-merge.yml:10 + - frizbee.yml:15 + - release.yml:11 + - release.yml:164 + - release.yml:178 + - release.yml:192 + - release.yml:206 + - triage.yml:19 + - zizmor.yml:15 + # These workflows either lack a top-level `permissions:` block + # (using GitHub defaults) or delegate to reusable workflows that + # declare their own minimal permissions internally. + excessive-permissions: + ignore: + - ci.yml:17 + - code-scan-cron.yml:6 + - release.yml:1 + - release.yml:10 + - release.yml:14 + # The triage workflow uses `pull_request_target` to label PRs + # from forks. This is safe because the called reusable workflow + # does not checkout or execute code from the PR. + dangerous-triggers: + ignore: + - triage.yml:3 + + From 8a6903d8d16b42a4020ee14f31eeb14cb35ca202 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 17:56:16 -0800 Subject: [PATCH 2/9] Add explicit permissions blocks, remove excessive-permissions ignores Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 5 +++++ .github/workflows/code-scan-cron.yml | 5 +++++ .github/workflows/release.yml | 5 +++++ .github/zizmor.yml | 10 ---------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9006cb..6573831 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,11 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + actions: read + contents: read + security-events: write + jobs: ci: uses: smallstep/workflows/.github/workflows/goCI.yml@main diff --git a/.github/workflows/code-scan-cron.yml b/.github/workflows/code-scan-cron.yml index e235db3..3905f02 100644 --- a/.github/workflows/code-scan-cron.yml +++ b/.github/workflows/code-scan-cron.yml @@ -2,6 +2,11 @@ on: schedule: - cron: '0 0 * * SUN' +permissions: + actions: read + contents: read + security-events: write + jobs: code-scan: uses: smallstep/workflows/.github/workflows/code-scan.yml@main diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 557a0eb..d10b284 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,9 @@ on: tags: - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 +permissions: + contents: read + jobs: ci: uses: smallstep/step-kms-plugin/.github/workflows/ci.yml@main @@ -14,6 +17,8 @@ jobs: create_release: name: Create Release needs: ci + permissions: + contents: write runs-on: ubuntu-latest env: DOCKER_IMAGE: smallstep/step-kms-plugin diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 4045c8e..9a5dd49 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -34,16 +34,6 @@ rules: - release.yml:206 - triage.yml:19 - zizmor.yml:15 - # These workflows either lack a top-level `permissions:` block - # (using GitHub defaults) or delegate to reusable workflows that - # declare their own minimal permissions internally. - excessive-permissions: - ignore: - - ci.yml:17 - - code-scan-cron.yml:6 - - release.yml:1 - - release.yml:10 - - release.yml:14 # The triage workflow uses `pull_request_target` to label PRs # from forks. This is safe because the called reusable workflow # does not checkout or execute code from the PR. From 2e752d2422b4475e474b605d99efe52606d4d15e Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 18:02:53 -0800 Subject: [PATCH 3/9] Replace zizmor line-number ignores with policies Use unpinned-uses config.policies with org-level wildcard and secrets-inherit disable instead of brittle per-line ignores that break whenever workflow files change. Co-Authored-By: Claude Opus 4.6 --- .github/zizmor.yml | 44 +++++--------------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 9a5dd49..b8ff071 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -1,44 +1,10 @@ rules: - # Internal reusable workflows (smallstep/*@main) intentionally track - # the main branch for centralized CI management. Pinning to a SHA - # would defeat the purpose of the shared workflows repo. unpinned-uses: - ignore: - - actionlint.yml:16 - - ci.yml:18 - - code-scan-cron.yml:7 - - dependabot-auto-merge.yml:10 - - frizbee.yml:15 - - release.yml:11 - - release.yml:115 - - release.yml:123 - - release.yml:136 - - release.yml:164 - - release.yml:178 - - release.yml:192 - - release.yml:206 - - triage.yml:19 - - zizmor.yml:15 - # Reusable workflow callers require `secrets: inherit` to pass - # credentials needed by the shared workflows (e.g. SSH keys, PATs). + config: + policies: + "smallstep/*": ref-pin secrets-inherit: - ignore: - - actionlint.yml:16 - - ci.yml:18 - - dependabot-auto-merge.yml:10 - - frizbee.yml:15 - - release.yml:11 - - release.yml:164 - - release.yml:178 - - release.yml:192 - - release.yml:206 - - triage.yml:19 - - zizmor.yml:15 - # The triage workflow uses `pull_request_target` to label PRs - # from forks. This is safe because the called reusable workflow - # does not checkout or execute code from the PR. + disable: true dangerous-triggers: ignore: - - triage.yml:3 - - + - triage.yml From 7328630e05080b79dd935d7eb26f49976114b7f1 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 18:29:12 -0800 Subject: [PATCH 4/9] Disable ref-confusion audit The ref-confusion audit crashes when workflows reference private repos (e.g. internal-workflows, robot) because the GITHUB_TOKEN lacks cross-repo access. Disable until zizmor supports scoping this audit or we provide a broader token. Co-Authored-By: Claude Opus 4.6 --- .github/zizmor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/zizmor.yml b/.github/zizmor.yml index b8ff071..92a6146 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -5,6 +5,8 @@ rules: "smallstep/*": ref-pin secrets-inherit: disable: true + ref-confusion: + disable: true dangerous-triggers: ignore: - triage.yml From 800f5b80f89978322979850cf32ee2f8e6d3cb51 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 18:43:22 -0800 Subject: [PATCH 5/9] Add security-events: write to zizmor caller workflow The caller workflow's permissions are the ceiling for reusable workflows. The zizmor-action needs security-events: write to upload SARIF results to GitHub Advanced Security. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/zizmor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 3270953..0057146 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -9,6 +9,7 @@ concurrency: permissions: contents: read + security-events: write jobs: zizmor: From 0a78fb1d30693d37c820539359814021ebb0dcdc Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 19:52:26 -0800 Subject: [PATCH 6/9] ci: Replace separate actionlint/zizmor/frizbee with actionci.yml Consolidate the three separate workflow files into a single actionci.yml that calls the shared workflow from smallstep/workflows. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/actionci.yml | 22 ++++++++++++++++++++++ .github/workflows/actionlint.yml | 17 ----------------- .github/workflows/frizbee.yml | 16 ---------------- .github/workflows/zizmor.yml | 17 ----------------- 4 files changed, 22 insertions(+), 50 deletions(-) create mode 100644 .github/workflows/actionci.yml delete mode 100644 .github/workflows/actionlint.yml delete mode 100644 .github/workflows/frizbee.yml delete mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/actionci.yml b/.github/workflows/actionci.yml new file mode 100644 index 0000000..6086cd4 --- /dev/null +++ b/.github/workflows/actionci.yml @@ -0,0 +1,22 @@ +name: Action CI + +on: + push: + tags-ignore: + - 'v*' + branches: + - "main" + pull_request: + workflow_call: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + actionci: + permissions: + contents: read + security-events: write + uses: smallstep/workflows/.github/workflows/actionci.yml@main + secrets: inherit diff --git a/.github/workflows/actionlint.yml b/.github/workflows/actionlint.yml deleted file mode 100644 index 8e9248e..0000000 --- a/.github/workflows/actionlint.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Lint GitHub Actions workflows -on: - push: - workflow_call: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -permissions: - contents: write - pull-requests: write - -jobs: - actionlint: - uses: smallstep/workflows/.github/workflows/actionlint.yml@main - secrets: inherit diff --git a/.github/workflows/frizbee.yml b/.github/workflows/frizbee.yml deleted file mode 100644 index 642f692..0000000 --- a/.github/workflows/frizbee.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Frizbee pinning check -on: - push: - workflow_call: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - -jobs: - frizbee: - uses: smallstep/workflows/.github/workflows/frizbee.yml@main - secrets: inherit diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml deleted file mode 100644 index 0057146..0000000 --- a/.github/workflows/zizmor.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Zizmor security scan -on: - push: - workflow_call: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - security-events: write - -jobs: - zizmor: - uses: smallstep/workflows/.github/workflows/zizmor.yml@main - secrets: inherit From c17f8aa6567056abadda4cce23c246e943b29b07 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 19:54:08 -0800 Subject: [PATCH 7/9] ci: Pin unpinned actions in release.yml Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d10b284..86c97ab 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -117,7 +117,7 @@ jobs: - name: Authenticate to Google Cloud if: ${{ needs.create_release.outputs.is_prerelease == 'false' }} id: gcloud-auth - uses: google-github-actions/auth@v3 + uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: token_format: access_token workload_identity_provider: ${{ secrets.GOOGLE_CLOUD_WORKLOAD_IDENTITY_PROVIDER }} @@ -125,7 +125,7 @@ jobs: - name: Set up Google Cloud SDK if: ${{ needs.create_release.outputs.is_prerelease == 'false' }} - uses: google-github-actions/setup-gcloud@v3 + uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3 with: project_id: ${{ secrets.GOOGLE_CLOUD_PACKAGES_PROJECT_ID }} @@ -138,7 +138,7 @@ jobs: echo 'IS_PRERELEASE=${{ needs.create_release.outputs.is_prerelease }}' >> "${GITHUB_ENV}" - name: Run GoReleaser Pro - uses: goreleaser/goreleaser-action@v7.0.0 + uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0 with: distribution: goreleaser-pro version: v2.8.1 From 8beeb04ab9b86dee2c64ba2bc25f530ef2cf6744 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Mon, 2 Mar 2026 20:11:56 -0800 Subject: [PATCH 8/9] ci: Remove accidentally included publish-packages.yml Co-Authored-By: Claude Opus 4.6 --- .github/workflows/publish-packages.yml | 77 -------------------------- 1 file changed, 77 deletions(-) delete mode 100644 .github/workflows/publish-packages.yml diff --git a/.github/workflows/publish-packages.yml b/.github/workflows/publish-packages.yml deleted file mode 100644 index d76346b..0000000 --- a/.github/workflows/publish-packages.yml +++ /dev/null @@ -1,77 +0,0 @@ -name: Publish to packages.smallstep.com - -# Independently publish packages to Red Hat (RPM) and Debian (DEB) repositories -# without running a full release. Downloads packages from GitHub releases, -# uploads to GCS, and imports to Artifact Registry. -# -# Usage (CLI): -# gh workflow run publish-packages.yml -f tag=v0.28.0 - -on: - workflow_dispatch: - inputs: - tag: - description: 'Git tag to publish (e.g., v0.28.0)' - required: true - type: string - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ inputs.tag }} - fetch-depth: 0 - - - name: Extract version - id: version - run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" - env: - TAG: ${{ inputs.tag }} - - - name: Is Pre-release - id: is_prerelease - run: | - if [[ "$TAG" == *"-rc"* ]]; then - echo "is_prerelease=true" >> "$GITHUB_OUTPUT" - else - echo "is_prerelease=false" >> "$GITHUB_OUTPUT" - fi - env: - TAG: ${{ inputs.tag }} - - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0 - with: - workload_identity_provider: ${{ secrets.GOOGLE_CLOUD_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ secrets.GOOGLE_CLOUD_GITHUB_SERVICE_ACCOUNT }} - - - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1 - with: - project_id: ${{ secrets.GOOGLE_CLOUD_PACKAGES_PROJECT_ID }} - - - name: Download packages from GitHub release - run: | - mkdir -p dist - gh release download "$TAG" --pattern "*${VERSION}*.deb" --pattern "*${VERSION}*.rpm" --dir dist - env: - TAG: ${{ inputs.tag }} - VERSION: ${{ steps.version.outputs.version }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload packages to GCS - run: | - for pkg in dist/*.deb dist/*.rpm; do - ./scripts/package-upload.sh "$pkg" step-kms-plugin ${{ steps.version.outputs.version }} - done - - - name: Import packages to Artifact Registry - run: ./scripts/package-repo-import.sh step-kms-plugin ${{ steps.version.outputs.version }} - env: - IS_PRERELEASE: ${{ steps.is_prerelease.outputs.is_prerelease }} From 532acef5db772d3abfd69cc59efbb35af5cec699 Mon Sep 17 00:00:00 2001 From: Carl Tashian Date: Tue, 3 Mar 2026 06:12:40 -0800 Subject: [PATCH 9/9] Move codeql permissions to job level to satisfy zizmor Co-Authored-By: Claude Opus 4.6 --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6573831..78451da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,12 +14,14 @@ concurrency: cancel-in-progress: true permissions: - actions: read contents: read - security-events: write jobs: ci: + permissions: + actions: read + contents: read + security-events: write uses: smallstep/workflows/.github/workflows/goCI.yml@main with: only-latest-golang: false