diff --git a/.github/workflows/README.md b/.github/workflows/README.md index ff0fe447e..880aad949 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -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/ diff --git a/.github/workflows/reusable-zizmor.md b/.github/workflows/reusable-zizmor.md new file mode 100644 index 000000000..333f653e6 --- /dev/null +++ b/.github/workflows/reusable-zizmor.md @@ -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@ + 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 diff --git a/.github/workflows/reusable-zizmor.yml b/.github/workflows/reusable-zizmor.yml new file mode 100644 index 000000000..9b752cd9a --- /dev/null +++ b/.github/workflows/reusable-zizmor.yml @@ -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<> "${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: "" + + - 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 }}. + +
+ Expand for full output + + ``` + ${{ steps.zizmor-plain.outputs.zizmor-results }} + ``` +
+ ${{ 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 diff --git a/.github/workflows/self-zizmor.yml b/.github/workflows/self-zizmor.yml new file mode 100644 index 000000000..fd525e31a --- /dev/null +++ b/.github/workflows/self-zizmor.yml @@ -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 diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 000000000..a7a2be673 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/v0.36.1/schema/markdownlint-config-schema.json", + "line-length": { + "tables": false + } +} diff --git a/README.md b/README.md index 5b769b4e5..d7d73fc84 100644 --- a/README.md +++ b/README.md @@ -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