Skip to content

feat(security): add Python (Ruff) and IaC (Checkov) reusable workflows#14

Open
NORSAIN-AI wants to merge 1 commit intomainfrom
feat/security-python-iac
Open

feat(security): add Python (Ruff) and IaC (Checkov) reusable workflows#14
NORSAIN-AI wants to merge 1 commit intomainfrom
feat/security-python-iac

Conversation

@NORSAIN-AI
Copy link
Copy Markdown
Owner

Summary

Batch 2 of the shared NORSAIN-AI security baseline under NORSAIN-AI/.github. Introduces two reusable workflow_call workflows, each self-gating on file presence so callers can wire them in unconditionally.

  • security-python.yml - uv + Ruff (latest) with a broad lint (S,E,F,B,I,N,UP,SIM,TID,RUF) piped through reviewdog for inline PR comments, plus a strict --select S enforcement pass that fails the job on any security finding regardless of reviewdog outcome. Inputs: python-version (default 3.14), paths (default .), fail-on (default error).
  • security-iac.yml - Checkov with soft_fail: true (so reviewdog can post inline comments) plus a deterministic severity gate that fails the job on findings at or above fail-on (default HIGH). Sets up Terraform so Checkov resolves provider schemas. Inputs: directory (default .), fail-on (default HIGH), terraform-version (default 1.7.0).

Both inherit secrets (GITHUB_TOKEN for reviewdog) and upload JSON findings as workflow artifacts. Follows the graceful-degradation pattern established by batch 1 (security-sast.yml, security-secrets.yml).

README gets a new 3a. Security Workflows section with the caller snippet from the plan at ~/.claude/plans/hvordan-kan-vi-bygge-magical-hinton.md.

Caller snippet

jobs:
  python-lint:
    if: ${{ hashFiles('**/pyproject.toml') != '' }}
    uses: NORSAIN-AI/.github/.github/workflows/security-python.yml@v1
    secrets: inherit
  iac:
    if: ${{ hashFiles('**/*.tf') != '' }}
    uses: NORSAIN-AI/.github/.github/workflows/security-iac.yml@v1
    secrets: inherit

Test plan

  • actionlint passes (verified locally via rhysd/actionlint container)
  • yamllint clean bar the repo-wide document-start warning (matches existing files)
  • Require-labels / semantic-pr / actionlint workflow checks green on this PR
  • Pilot call from a Python repo: add a known S-rule violation (e.g. subprocess.run(user_input, shell=True)); verify job fails and reviewdog posts an inline comment
  • Pilot call from a Terraform repo: add a google_storage_bucket with public read; verify Checkov gate fails and reviewdog posts an inline comment
  • Call from a repo with neither *.py/pyproject.toml nor *.tf: verify both workflows short-circuit and exit green

Notes

Adds batch 2 of the shared security baseline under NORSAIN-AI/.github:

- security-python.yml: uv + Ruff (latest) with a broad lint piped through
  reviewdog for inline PR comments, plus a strict --select S enforcement
  pass that fails the job on any security finding. Self-guards on
  pyproject/py presence.
- security-iac.yml: Checkov with soft_fail so reviewdog posts inline
  comments on PRs; a deterministic severity gate then fails the job on
  any finding at or above fail-on (default HIGH). Self-guards on .tf
  presence. Sets up Terraform so Checkov can resolve provider schemas.

Both workflows inherit secrets (GITHUB_TOKEN for reviewdog), upload JSON
findings as artifacts, and follow the graceful-degradation pattern
established by batch 1 (security-sast.yml, security-secrets.yml).

README gets a new Security Workflows section (3a) with a caller snippet
matching the plan in
/home/hs/.claude/plans/hvordan-kan-vi-bygge-magical-hinton.md.
Copilot AI review requested due to automatic review settings April 22, 2026 14:54
@NORSAIN-AI NORSAIN-AI added security Security-related issues or improvements ci-cd CI/CD and automation changes triage Needs triage labels Apr 22, 2026
@github-actions
Copy link
Copy Markdown

⚠️ This PR must have a milestone assigned before it can be merged/closed. Please assign an appropriate milestone.

@NORSAIN-AI NORSAIN-AI changed the title feat(security): Python (Ruff) and IaC (Checkov) reusable workflows feat(security): add Python (Ruff) and IaC (Checkov) reusable workflows Apr 22, 2026
@github-actions
Copy link
Copy Markdown

⚠️ This PR must have a milestone assigned before it can be merged/closed. Please assign an appropriate milestone.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Denne PR-en introduserer to nye gjenbrukbare sikkerhets-workflows i organisasjonsrepoet .github, slik at downstream-repoer kan koble på en felles baseline for Python (Ruff) og Terraform/IaC (Checkov). I tillegg oppdateres README med dokumentasjon og caller-eksempel for å gjøre adopsjon enkel på tvers av NORSAIN-AI.

Changes:

  • Legger til reusable workflow for Python security lint med uv + Ruff + reviewdog.
  • Legger til reusable workflow for Terraform IaC scanning med Checkov + reviewdog + severity-gate.
  • Dokumenterer de nye workflowene og caller-snippet i README.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
README.md Dokumenterer de nye security-workflowene og viser eksempel på hvordan de kalles fra andre repoer.
.github/workflows/security-python.yml Ny reusable Python (Ruff) workflow med guard, reviewdog-rapportering og S-rule enforcement.
.github/workflows/security-iac.yml Ny reusable IaC (Checkov) workflow med guard, reviewdog-rapportering og severity-basert gate.

Comment on lines +68 to +77
- name: Run Checkov
id: checkov
if: steps.guard.outputs.has-tf == 'true'
uses: bridgecrewio/checkov-action@master
with:
directory: ${{ inputs.directory }}
framework: terraform
soft_fail: true
output_format: json
output_file_path: checkov.json
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uses: bridgecrewio/checkov-action@master kjører fra en flytende branch og er en supply-chain risiko (plutselige endringer uten review) i en delt, organisasjonsnivå baseline. Pin actionen til en tag eller (helst) en commit-SHA for å få deterministiske og auditerbare kjøringer.

Copilot uses AI. Check for mistakes.
Comment on lines +93 to +96
# Fall back to empty report so downstream steps stay green on
# repos with no scannable IaC.
echo '{"results": {"failed_checks": []}}' > checkov.normalized.json
echo "path=checkov.normalized.json" >> "$GITHUB_OUTPUT"
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Locate Checkov JSON report faller workflowen tilbake til en tom rapport hvis checkov.json ikke finnes. Siden jobben allerede har gated på at repoet har *.tf, kan dette maskere reelle kjøre-/action-feil (Checkov kjørte ikke, krasjet, eller skrev et annet sted) og dermed gi falsk grønn status. I stedet bør dette steget feile tydelig når has-tf=true men ingen rapport kan lokaliseres (evt. med en eksplisitt melding om forventet output-path).

Suggested change
# Fall back to empty report so downstream steps stay green on
# repos with no scannable IaC.
echo '{"results": {"failed_checks": []}}' > checkov.normalized.json
echo "path=checkov.normalized.json" >> "$GITHUB_OUTPUT"
echo "::error title=Missing Checkov JSON report::Expected Checkov output at 'checkov.json' or 'checkov.json/results_json.json', but neither file was found. This usually means the Checkov action failed, crashed, or wrote output to an unexpected location."
exit 1

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +74 to +76
Callers must use `secrets: inherit` so `GITHUB_TOKEN` reaches reviewdog for
inline PR comments. Each workflow also self-gates on file presence so it is
a safe no-op when called from an unrelated repo.
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README sier at kallere må bruke secrets: inherit for at GITHUB_TOKEN skal nå reviewdog. GITHUB_TOKEN er allerede tilgjengelig i Actions-konteksten, mens secrets: inherit videresender alle repo-secrets og øker eksponeringsflaten unødvendig. Oppdater teksten og caller-snippet til å ikke kreve secrets: inherit, og dokumenter heller nødvendige permissions (minst pull-requests: write) for at reviewdog skal kunne poste inline PR-kommentarer.

Suggested change
Callers must use `secrets: inherit` so `GITHUB_TOKEN` reaches reviewdog for
inline PR comments. Each workflow also self-gates on file presence so it is
a safe no-op when called from an unrelated repo.
`GITHUB_TOKEN` is already available in the Actions context, so callers do
not need `secrets: inherit` for reviewdog. Instead, caller workflows should
grant the required `permissions` for PR annotations, at minimum
`pull-requests: write` for inline PR comments. Each workflow also self-gates
on file presence so it is a safe no-op when called from an unrelated repo.

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +70 to +91
## 3a. Security Workflows

Reusable security workflows in `.github/workflows/` provide a shared baseline
for Python linting and Terraform scanning across all NORSAIN-AI repos.
Callers must use `secrets: inherit` so `GITHUB_TOKEN` reaches reviewdog for
inline PR comments. Each workflow also self-gates on file presence so it is
a safe no-op when called from an unrelated repo.

- `security-python.yml` — Installs `uv` and Ruff (latest), runs a broad lint
(`S,E,F,B,I,N,UP,SIM,TID,RUF`) whose JSON output is converted to rdjson
and posted via reviewdog, then runs a strict enforcement pass on `--select
S` that fails the job on any security finding. Uploads `ruff.json` as an
artifact. Inputs: `python-version` (default `3.14`), `paths` (default
`.`), `fail-on` (default `error`).
- `security-iac.yml` — Sets up Terraform for Checkov's provider schema
resolution, runs Checkov with `soft_fail: true`, converts JSON findings
to rdjson for reviewdog inline PR comments, then runs a severity gate
that fails the job when any finding is at or above `fail-on`. Uploads
`checkov.json` as an artifact. Inputs: `directory` (default `.`),
`fail-on` (default `HIGH`), `terraform-version` (default `1.7.0`).

After this repo is tagged `v1`, callers wire in the reusable workflows:
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seksjonen "3a. Security Workflows" er skrevet på engelsk, mens resten av README er på norsk bokmål. For konsistens og for å følge repoets dokumentasjonsstil bør denne seksjonen oversettes til norsk (eller alternativt gjøres hele README språklig konsistent).

Suggested change
## 3a. Security Workflows
Reusable security workflows in `.github/workflows/` provide a shared baseline
for Python linting and Terraform scanning across all NORSAIN-AI repos.
Callers must use `secrets: inherit` so `GITHUB_TOKEN` reaches reviewdog for
inline PR comments. Each workflow also self-gates on file presence so it is
a safe no-op when called from an unrelated repo.
- `security-python.yml` — Installs `uv` and Ruff (latest), runs a broad lint
(`S,E,F,B,I,N,UP,SIM,TID,RUF`) whose JSON output is converted to rdjson
and posted via reviewdog, then runs a strict enforcement pass on `--select
S` that fails the job on any security finding. Uploads `ruff.json` as an
artifact. Inputs: `python-version` (default `3.14`), `paths` (default
`.`), `fail-on` (default `error`).
- `security-iac.yml` — Sets up Terraform for Checkov's provider schema
resolution, runs Checkov with `soft_fail: true`, converts JSON findings
to rdjson for reviewdog inline PR comments, then runs a severity gate
that fails the job when any finding is at or above `fail-on`. Uploads
`checkov.json` as an artifact. Inputs: `directory` (default `.`),
`fail-on` (default `HIGH`), `terraform-version` (default `1.7.0`).
After this repo is tagged `v1`, callers wire in the reusable workflows:
## 3a. Sikkerhets-workflows
Gjenbrukbare sikkerhets-workflows i `.github/workflows/` gir et felles
grunnnivå for Python-linting og Terraform-skanning på tvers av alle
NORSAIN-AI-repoer. Kallende repoer må bruke `secrets: inherit` slik at
`GITHUB_TOKEN` blir tilgjengelig for reviewdog til inline PR-kommentarer.
Hver workflow har også egen kontroll på filtilstedeværelse, slik at den
trygt blir en no-op når den kalles fra et repo uten relevante filer.
- `security-python.yml` — Installerer `uv` og Ruff (siste versjon), kjører
en bred lint (`S,E,F,B,I,N,UP,SIM,TID,RUF`) der JSON-utdata konverteres
til rdjson og publiseres via reviewdog, og kjører deretter en streng
håndhevingsrunde med `--select S` som feiler jobben ved ethvert
sikkerhetsfunn. Laster opp `ruff.json` som artefakt. Inputs:
`python-version` (standard `3.14`), `paths` (standard `.`), `fail-on`
(standard `error`).
- `security-iac.yml` — Setter opp Terraform for Checkovs oppløsning av
provider-skjema, kjører Checkov med `soft_fail: true`, konverterer
JSON-funn til rdjson for inline PR-kommentarer via reviewdog, og kjører
deretter en alvorlighetsgrad-sperre som feiler jobben når et funn er på
eller over nivået angitt i `fail-on`. Laster opp `checkov.json` som
artefakt. Inputs: `directory` (standard `.`), `fail-on` (standard
`HIGH`), `terraform-version` (standard `1.7.0`).
Etter at dette repoet er tagget `v1`, kan kallende repoer koble inn de
gjenbrukbare workflowene:

Copilot uses AI. Check for mistakes.
Comment on lines +27 to +31
fail-on:
description: 'Ruff severity that fails the job (maps to enforcement pass).'
required: false
type: string
default: 'error'
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fail-on er definert som input, men brukes ikke noe sted i workflowen. Dette gjør API-et misvisende for kallere. Enten implementer inputen (f.eks. ved å styre hvilke Ruff-koder som skal feile enforcement-steget) eller fjern inputen og oppdater README/kommentarer tilsvarende.

Copilot uses AI. Check for mistakes.
Comment on lines +70 to +97
- name: Install Ruff (latest)
if: steps.guard.outputs.has-python == 'true'
shell: bash
run: |
set -euo pipefail
uv tool install ruff
echo "$HOME/.local/bin" >> "$GITHUB_PATH"

- name: Ruff full lint (JSON for reviewdog, non-blocking)
if: steps.guard.outputs.has-python == 'true'
shell: bash
env:
PATHS: ${{ inputs.paths }}
run: |
set -euo pipefail
# shellcheck disable=SC2086
ruff check \
--select S,E,F,B,I,N,UP,SIM,TID,RUF \
--output-format=json \
--exit-zero \
${PATHS} > ruff.json

- name: Setup reviewdog
if: steps.guard.outputs.has-python == 'true' && github.event_name == 'pull_request'
uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest

Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Å installere verktøy som "latest" (uv tool install ruff uten versjon og reviewdog_version: latest) gjør workflowen ikke-deterministisk og kan gi plutselige brudd/endret policy når nye releaser kommer. Vurder å pinne til eksplisitte versjoner (evt. via input med trygg default) slik at baseline blir stabil og oppgraderinger kan styres.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-cd CI/CD and automation changes needs-milestone security Security-related issues or improvements triage Needs triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants