Skip to content

Commit

Permalink
feat(zizmor): add a reusable workflow for zizmor GitHub Actions stati…
Browse files Browse the repository at this point in the history
…c analysis

This is a [reusable workflow] which runs the [`zizmor`][zizmor] static
analysis tool on a repo's GitHub Actions workflow files. This will
report things such as whether there is potential for untrusted code to
be injected via a template. See a full list of checks in [the
documentation][zizmor-checks].

This workflow will run zizmor, upload results to GitHub's code scanning
service (requires an Advanced Security subscription for private
repositories), and comment on the pull request with the results. The
comment will be re-posted on each run - and previous comments hidden -
so the most recent comment will always show the current results.

[reusable workflow]: https://docs.github.com/en/actions/using-workflows/reusing-workflows
[zizmor]: https://woodruffw.github.io/zizmor/
[zizmor-checks]: https://woodruffw.github.io/zizmor/audits/
  • Loading branch information
iainlane committed Dec 2, 2024
1 parent 1025215 commit 9488aad
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 1 deletion.
8 changes: 7 additions & 1 deletion .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@

This folder contains some workflows that can be re-used from other repositories:

- [publish-techdocs](./publish-techdocs.md): Publish your project's documentation to EngHub
- [`publish-techdocs`](./publish-techdocs.md): Publish your project's
documentation to EngHub

- [`reusable-zizmor`](./reusable-zizmor.md): Run [zizmor] static analysis on
your GitHub Actions workflow files.

[zizmor]: https://woodruffw.github.io/zizmor/
86 changes: 86 additions & 0 deletions .github/workflows/reusable-zizmor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Reusable workflow: zizmor

This is a [reusable workflow] which runs the [`zizmor`][zizmor] static analysis
tool on a repo's GitHub Actions workflow files. This will report things such as
whether there is potential for untrusted code to be injected via a template. See
a full list of checks in [the documentation][zizmor-checks].

This workflow will run zizmor, upload results to GitHub's code scanning service
(requires an Advanced Security subscription for private repositories), and
comment on the pull request with the results. The comment will be re-posted on
each run - and previous comments hidden - so the most recent comment will always
show the current results.

[reusable workflow]: https://docs.github.com/en/actions/using-workflows/reusing-workflows
[zizmor]: https://woodruffw.github.io/zizmor/
[zizmor-checks]: https://woodruffw.github.io/zizmor/audits/

```yaml
name: Zizmor GitHub Actions static analysis
on:
pull_request:

push:
branches:
- main

jobs:
scorecard:
name: Analyse

permissions:
actions: read
contents: read

# required to comment on pull requests with the results of the check
pull-requests: write
# required to upload the results to GitHub's code scanning service
security-events: write

uses: grafana/shared-workflows/.github/workflows/reusable-zizmor.yml@<some sha>
with:
# example: fail if there are any findings
fail-severity: any
```
## Inputs
| Name | Type | Description | Default Value | Required |
| -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- | ------------- | -------- |
| min-severity | string | Only show results at or above this severity [possible values: unknown, informational, low, medium, high] | medium | false |
| min-confidence | string | Only show results at or above this confidence level [possible values: unknown, low, medium, high] | low | false |
| fail-severity | string | Fail the build if any result is at or above this severity [possible values: never, any, informational, low, medium, high] | high | false |
| runs-on | string | The runner to use for jobs. Configure this to use self-hosted runners. | ubuntu-latest | false |
## Getting started
This workflow uses quite strict settings by default. It isn't always practical
to introduce this workflow and fix all of the issues at once. There are a few
ways to get started if this is the case:
1. Set `fail-severity: never` to run the check without failing the build.
Results will still be posted to pull requests but they won't be blocking.
2. Adopt an incremental approach to fixing issues. For example, start with
`min-severity: high`. Once all high severity issues are resolved, lower the
severity to `medium` and then onwards to `low`.

After the initial setup, we recommend running with the default settings.

## Ignore findings

Findings can be ignored by [adding a comment to the line with the finding][zizmor-ignore-comment].

```yaml
uses: actions/checkout@v3 # zizmor: ignore[artipacked]
```

[zizmor-ignore-comment]: https://woodruffw.github.io/zizmor/usage/#with-comments

## Configuration

zizmor [can be configured][zizmor-config] with a `zizmor.yml` or
`.github/zizmor.yml` file in the repository. With this, [findings or entire
files can be ignored][zizmor-ignore-config].

[zizmor-config]: https://woodruffw.github.io/zizmor/configuration/
[zizmor-ignore-config]: https://woodruffw.github.io/zizmor/usage/#with-zizmoryml
190 changes: 190 additions & 0 deletions .github/workflows/reusable-zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
name: zizmor (reusable)

on:
workflow_call:
inputs:
min-severity:
description: "Only show results at or above this severity [possible values: unknown, informational, low, medium, high]"
required: false
type: string
default: "low"

min-confidence:
description: "Only show results at or above this confidence level [possible values: unknown, low, medium, high]"
required: false
type: string
default: "low"

fail-severity:
description: "Fail the build if any result is at or above this severity [possible values: never, any, informational, low, medium, high]"
required: false
type: string
default: "high"

runs-on:
description: "The runner to use for jobs"
required: false
type: string
default: "ubuntu-latest"

permissions: {}

# TODO:
# - [ ] Write a README. (Include some FAQs.)
# - [ ] Set up release-please, and make sure the linter catches reusable workflows.

jobs:
analysis:
name: Generate and upload zizmor results 🌈

runs-on: ${{ inputs.runs-on }}

permissions:
actions: read
contents: read

# comment with the results
pull-requests: write
# upload the results to code-scanning dashboard.
security-events: write

env:
MIN_SEVERITY: ${{ inputs.min-severity }}
MIN_CONFIDENCE: ${{ inputs.min-confidence }}

steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Setup Rust
uses: actions-rust-lang/setup-rust-toolchain@11df97af8e8102fd60b60a77dfbf58d40cd843b8 # v1.10.1
with:
cache-on-failure: true

- name: Get zizmor
shell: sh
# This is a commit with the `unpinned-uses` action available, which is something we want.
env:
ZIZMOR_COMMIT: fc5683c0f457f5766c3f175fad705dc8b0515bd7
run: >-
RUSTFLAGS=-Awarnings
cargo
install
--git https://github.com/woodruffw/zizmor
--rev "${ZIZMOR_COMMIT}"
zizmor
- name: Run zizmor
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: sh
run: >-
zizmor
--format sarif
--min-severity "${MIN_SEVERITY}"
--min-confidence "${MIN_CONFIDENCE}"
"${RUNNER_DEBUG:+--verbose}"
.
> results.sarif
- name: Upload artifact
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: SARIF file
path: results.sarif
retention-days: 5

- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # v3.27.5
with:
sarif_file: results.sarif
category: zizmor

- name: Run zizmor with plain output
id: zizmor-plain
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -o pipefail
echo "zizmor-results<<EOF" >> "${GITHUB_OUTPUT}"
# don't fail the build if zizmor fails - we want to capture the output
# and the exit code
set +e
zizmor \
--format plain \
--min-severity "${MIN_SEVERITY}" \
--min-confidence "${MIN_CONFIDENCE}" \
"${RUNNER_DEBUG:+--verbose}" \
. \
| tee -a "${GITHUB_OUTPUT}"
zizmor_exit_code=$?
set -e
echo "EOF" >> "${GITHUB_OUTPUT}"
# Error 1 is a failure of zizmor itself
if [ "${zizmor_exit_code}" -eq 1 ]; then
echo "zizmor itself failed - check the above output. failing the workflow."
exit 1
fi
echo "zizmor-exit-code=${zizmor_exit_code}" | tee -a "${GITHUB_OUTPUT}"
- name: Hide any previous comments
id: hide-comments
uses: int128/hide-comment-action@dafbbede100206f5401d06fa852a1c6997984cb3 # v1.37.0
with:
ends-with: "<!-- comment-action/${{ github.workflow }}/${{ github.job }} -->"

- name: Comment with zizmor results
if: steps.zizmor-plain.outputs.zizmor-exit-code != 0
uses: int128/comment-action@a20dbdebd79ab886a1e7a20d16bfa7dbaa732e5a # v1.33.0
with:
post: |
:cry: zizmor failed with exit code ${{ steps.zizmor-plain.outputs.zizmor-exit-code }}.
<details>
<summary>Expand for full output</summary>
```
${{ steps.zizmor-plain.outputs.zizmor-results }}
```
</details>
${{ steps.hide-comments.outputs.ends-with }}
- name: Fail the build
if: inputs.fail-severity != 'never' && steps.zizmor-plain.outputs.zizmor-exit-code != 0
shell: sh
env:
FAIL_LEVEL: ${{ inputs.fail-severity }}
EXIT_CODE: ${{ steps.zizmor-plain.outputs.zizmor-exit-code }}
run: |
case "${FAIL_LEVEL}" in
any)
FAIL_EXIT_CODE=10
;;
informational)
FAIL_EXIT_CODE=11
;;
low)
FAIL_EXIT_CODE=12
;;
medium)
FAIL_EXIT_CODE=13
;;
high)
FAIL_EXIT_CODE=14
;;
*)
echo "Unknown fail level: ${FAIL_LEVEL}"
exit 1
;;
esac
if [ "${EXIT_CODE}" -ge "${FAIL_EXIT_CODE}" ]; then
echo "Failing the build due to findings at or above ${FAIL_LEVEL} severity."
exit 1
fi
26 changes: 26 additions & 0 deletions .github/workflows/self-zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: zizmor GitHub Actions static analysis
on:
push:
branches:
- main

pull_request:
paths:
- .github/workflows/reusable-zizmor.yml
- .github/workflows/self-zizmor.yml

jobs:
zizmor:
name: Generate

permissions:
actions: read
contents: read

pull-requests: write
security-events: write

uses: ./.github/workflows/reusable-zizmor.yml
with:
# Don't fail the build while we are working on fixing the results.
fail-severity: never
6 changes: 6 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/v0.36.1/schema/markdownlint-config-schema.json",
"line-length": {
"tables": false
}
}
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# shared-workflows

[![OpenSSF Scorecard][scorecard image]][scorecard]

A public-facing, centralized place to store reusable GitHub workflows and action
used by Grafana Labs. See the `actions/` directory for the individual actions
themselves.

[scorecard]: https://scorecard.dev/viewer/?uri=github.com/grafana/shared-workflows
[scorecard image]: https://api.scorecard.dev/projects/github.com/grafana/shared-workflows/badge

## Notes

### Configure your IDE to run Prettier
Expand Down

0 comments on commit 9488aad

Please sign in to comment.