| 1 | #!/usr/bin/env bash |
| 2 | # SPDX-License-Identifier: AGPL-3.0-or-later |
| 3 | |
| 4 | set -eu |
| 5 | |
| 6 | ROOT="$(git rev-parse --show-toplevel)" |
| 7 | cd "$ROOT" |
| 8 | |
| 9 | fail() { |
| 10 | printf 'audit-actions-public-runners: %s\n' "$*" >&2 |
| 11 | exit 1 |
| 12 | } |
| 13 | |
| 14 | ok() { |
| 15 | printf 'ok: %s\n' "$*" |
| 16 | } |
| 17 | |
| 18 | require_file() { |
| 19 | [ -f "$1" ] || fail "missing required file: $1" |
| 20 | ok "found $1" |
| 21 | } |
| 22 | |
| 23 | require_grep() { |
| 24 | pattern="$1" |
| 25 | file="$2" |
| 26 | desc="$3" |
| 27 | rg -q -- "$pattern" "$file" || fail "$desc not found in $file" |
| 28 | ok "$desc" |
| 29 | } |
| 30 | |
| 31 | require_file "docs/internal/actions-public-runners.md" |
| 32 | require_file "docs/internal/runbooks/actions-runner.md" |
| 33 | require_file "docs/internal/runbooks/runner-deploy.md" |
| 34 | require_file "deploy/doctl/provision-actions-runner-pool.sh" |
| 35 | require_file "deploy/doctl/generate-actions-runner-inventory.sh" |
| 36 | require_file "deploy/runner-config/firewall.sh.j2" |
| 37 | require_file "deploy/runner-config/dnsmasq.conf.j2" |
| 38 | require_file "deploy/runner-config/seccomp.json" |
| 39 | |
| 40 | require_grep 'WHEN COALESCE\(sp\.actions_enabled, true\) = false THEN false' \ |
| 41 | "internal/actions/queries/actions_policy.sql" \ |
| 42 | "site kill switch in effective policy" |
| 43 | require_grep 'WHEN COALESCE\(sp\.actions_enabled, true\) = false THEN false' \ |
| 44 | "internal/actions/queries/workflow_jobs.sql" \ |
| 45 | "site kill switch in runner claim" |
| 46 | require_grep 'TestEvaluateTrigger_SiteDisableOverridesRepoEnable' \ |
| 47 | "internal/actions/policy/policy_test.go" \ |
| 48 | "enqueue-time site kill switch test" |
| 49 | require_grep 'TestRunnerHeartbeatSiteDisableOverridesRepoEnable' \ |
| 50 | "internal/web/handlers/api/runners_test.go" \ |
| 51 | "claim-time site kill switch test" |
| 52 | require_grep 'TestRunnerHeartbeatRespectsRepoConcurrencyCap' \ |
| 53 | "internal/web/handlers/api/runners_test.go" \ |
| 54 | "repo concurrency claim test" |
| 55 | require_grep 'TestRunnerHeartbeatRespectsOwnerConcurrencyCap' \ |
| 56 | "internal/web/handlers/api/runners_test.go" \ |
| 57 | "owner concurrency claim test" |
| 58 | |
| 59 | require_grep '--cap-drop=ALL' "internal/runner/engine/docker.go" "cap drop in Docker engine" |
| 60 | require_grep '--read-only' "internal/runner/engine/docker.go" "read-only rootfs in Docker engine" |
| 61 | require_grep '--security-opt=no-new-privileges' "internal/runner/engine/docker.go" "no-new-privileges in Docker engine" |
| 62 | require_grep 'seccomp=' "internal/runner/engine/docker.go" "seccomp profile in Docker engine" |
| 63 | require_grep '--user' "internal/runner/engine/docker.go" "non-root container user in Docker engine" |
| 64 | require_grep 'rejects direct-IP' "docs/internal/runbooks/runner-deploy.md" "direct-IP egress runbook note" |
| 65 | require_grep '-j REJECT' "deploy/runner-config/firewall.sh.j2" "runner firewall default reject" |
| 66 | require_grep 'Do not put runner tokens' "deploy/doctl/actions-runner-cloud-init.yaml" "no-secret cloud-init warning" |
| 67 | |
| 68 | require_grep 'FeatureOrgActionsMinutesQuota' "internal/entitlements/entitlements.go" "actions minutes entitlement key" |
| 69 | require_grep 'LimitOrgActionsMinutesQuota' "internal/entitlements/entitlements.go" "actions minutes limit key" |
| 70 | require_grep 'no concrete number until' "docs/internal/actions-public-runners.md" "billing-metering caveat" |
| 71 | require_grep 'controlled dogfood, not broad public GA' "docs/internal/actions-public-runners.md" "public runner rollout status" |
| 72 | |
| 73 | ok "S41j-6 public runner readiness static audit complete" |