diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cd79dc0..553844f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "args": { "DOCKER_GID": "${env:DOCKER_GID:}", "IMAGE_NAME": "node_24_python_3_10", - "IMAGE_VERSION": "v1.2.0", + "IMAGE_VERSION": "v1.4.7", "USER_UID": "${localEnv:USER_ID:}", "USER_GID": "${localEnv:GROUP_ID:}" } diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..5ca94d5 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# restrict access to approving workflow changes +.github/workflows/ @NHSDigital/eps-administrators diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 950c164..8d272d2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -4,17 +4,26 @@ on: push: branches: - main +permissions: {} jobs: get_config_values: uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + attestations: read + contents: read + packages: read with: verify_published_from_main_image: true quality_checks: name: Quality Checks needs: get_config_values - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} secrets: diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index fe9900f..710f40e 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -6,6 +6,7 @@ on: - main workflow_dispatch: +permissions: {} jobs: pr_title_format_check: name: PR Title Format Check @@ -14,6 +15,10 @@ jobs: pull-requests: write get_config_values: uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + attestations: read + contents: read + packages: read with: verify_published_from_main_image: false @@ -23,11 +28,14 @@ jobs: runs-on: ubuntu-22.04 permissions: id-token: write + contents: read outputs: pypi_token: ${{ steps.get_pypi_token.outputs.pypi_token }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd name: Checkout source code + with: + persist-credentials: false - name: Get PyPI token id: get_pypi_token @@ -36,7 +44,11 @@ jobs: quality_checks: name: Quality Checks needs: get_config_values - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} secrets: @@ -45,7 +57,7 @@ jobs: tag_release: name: Tag Release (Dry Run) needs: [get_config_values, get_pypi_token] - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} branch_name: ${{ github.event.pull_request.head.ref }} @@ -56,6 +68,7 @@ jobs: permissions: id-token: write contents: write + packages: write dependabot_auto_approve_and_merge: name: Dependabot Auto Approve and Merge diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c5ecfc2..8ca621d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -2,6 +2,7 @@ name: Release on: workflow_dispatch: +permissions: {} jobs: get_pypi_token: @@ -9,23 +10,34 @@ jobs: runs-on: ubuntu-22.04 permissions: id-token: write + contents: read outputs: pypi_token: ${{ steps.get_pypi_token.outputs.pypi_token }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd name: Checkout source code + with: + persist-credentials: false - name: Get PyPI token id: get_pypi_token uses: ./.github/actions/get_pypi_token get_config_values: uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + attestations: read + contents: read + packages: read with: verify_published_from_main_image: false quality_checks: name: Quality Checks needs: get_config_values - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} secrets: @@ -33,8 +45,12 @@ jobs: get_next_version: name: Get Next Version Number for Poetry - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 needs: [get_config_values, quality_checks] + permissions: + id-token: write + contents: write + packages: write with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} branch_name: main @@ -43,6 +59,8 @@ jobs: build: name: Build Package and Upload as Artifact runs-on: ubuntu-22.04 + permissions: + contents: read container: image: ${{ needs.get_config_values.outputs.pinned_image }} options: --user 1001:1001 --group-add 128 @@ -57,7 +75,9 @@ jobs: run: | cp /home/vscode/.tool-versions "$HOME/.tool-versions" - name: Git checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + with: + persist-credentials: false - name: make install run: | make install @@ -80,7 +100,7 @@ jobs: tag_release: name: Tag Release - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@5ac2707dd9cd60ad127275179495b9c890d74711 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@e798d5aee897de6f7dc387dd5623fcd9ba4c8929 needs: [build, get_config_values, get_pypi_token] with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} @@ -94,6 +114,6 @@ jobs: secrets: PYPI_TOKEN: ${{ needs.get_pypi_token.outputs.pypi_token }} permissions: - actions: write - contents: write id-token: write + contents: write + packages: write diff --git a/.github/workflows/sync_copilot.yml b/.github/workflows/sync_copilot.yml index d9921bc..4ac462a 100644 --- a/.github/workflows/sync_copilot.yml +++ b/.github/workflows/sync_copilot.yml @@ -4,6 +4,7 @@ on: workflow_dispatch: schedule: - cron: '0 6 * * 1' +permissions: {} jobs: sync-copilot-instructions: diff --git a/.gitignore b/.gitignore index 108ef9d..557e261 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ __pycache__/ # Temp agents.md +.sbom/ diff --git a/.grype.yaml b/.grype.yaml new file mode 100644 index 0000000..b053560 --- /dev/null +++ b/.grype.yaml @@ -0,0 +1,5 @@ +ignore: + # urllib3 - fixed to older version to match spine + - vulnerability: GHSA-gm62-xv2j-4w53 + - vulnerability: GHSA-2xpw-w6gg-jr37 + - vulnerability: GHSA-38jv-5279-wg99 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f9c85f..9db284a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,6 +18,14 @@ repos: - repo: local hooks: + - id: grype-scan-local + name: Grype scan local changes + entry: make + args: ["grype-scan-local"] + language: system + pass_filenames: false + always_run: true + - id: check-commit-signing name: Check commit signing description: Ensures that commits are GPG signed diff --git a/.trivyignore.yaml b/.trivyignore.yaml deleted file mode 100644 index 7d70c48..0000000 --- a/.trivyignore.yaml +++ /dev/null @@ -1,12 +0,0 @@ -vulnerabilities: - - id: CVE-2025-66418 - statement: urllib3 - can't upgrade due to spine version restraints - - id: CVE-2025-66471 - statement: urllib3 - can't upgrade due to spine version restraints - - id: CVE-2026-21441 - statement: urllib3 - can't upgrade due to spine version restraints - - id: CVE-2025-50181 - statement: urllib3 - can't upgrade due to spine version restraints - - id: CVE-2026-26007 - statement: cryptography (moto dependency) - will eventually update via dependabot - expired_at: 2027-01-01 diff --git a/trivy.yaml b/trivy.yaml deleted file mode 100644 index eb24337..0000000 --- a/trivy.yaml +++ /dev/null @@ -1 +0,0 @@ -ignorefile: ".trivyignore.yaml" diff --git a/zizmor.yml b/zizmor.yml new file mode 100644 index 0000000..ab01bad --- /dev/null +++ b/zizmor.yml @@ -0,0 +1,5 @@ +rules: + unpinned-images: + # these workflows use unpinned images because they are using a full image passed in that contains the tag + ignore: + - release.yaml:65:7