rustd-resolved 0.2.1

A compatibility-oriented reimplementation of systemd-resolved
name: Replacement security proof
run-name: Replacement security proof ${{ inputs.source_sha || github.sha }}

on:
  workflow_dispatch:
    inputs:
      source_sha:
        description: Full Git commit to prove; blank selects the dispatch ref
        required: false
        type: string

permissions:
  actions: read
  contents: read
  statuses: write

jobs:
  prove:
    runs-on: ubuntu-24.04
    timeout-minutes: 20
    steps:
      - name: Check out exact source
        uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
        with:
          ref: ${{ inputs.source_sha || github.sha }}
          fetch-depth: 1

      - name: Verify exact source identity
        shell: bash
        env:
          REQUESTED_SHA: ${{ inputs.source_sha || github.sha }}
        run: |
          set -euo pipefail
          [[ $REQUESTED_SHA =~ ^[0-9a-f]{40}$ ]]
          test "$(git rev-parse HEAD)" = "$REQUESTED_SHA"

      - name: Collect successful security evidence for this SHA
        shell: bash
        env:
          GH_TOKEN: ${{ github.token }}
          SOURCE_SHA: ${{ inputs.source_sha || github.sha }}
        run: |
          set -euo pipefail
          python3 - <<'PY'
          from __future__ import annotations

          import json
          import os
          from pathlib import Path
          import re
          import urllib.parse
          import urllib.request

          repository = os.environ["GITHUB_REPOSITORY"]
          sha = os.environ["SOURCE_SHA"]
          token = os.environ["GH_TOKEN"]
          api = os.environ["GITHUB_API_URL"]
          server = os.environ["GITHUB_SERVER_URL"]

          def request(path: str) -> dict:
              req = urllib.request.Request(
                  api + path,
                  headers={
                      "Accept": "application/vnd.github+json",
                      "Authorization": f"Bearer {token}",
                      "X-GitHub-Api-Version": "2022-11-28",
                  },
              )
              with urllib.request.urlopen(req, timeout=30) as response:
                  return json.load(response)

          status_payload = request(
              f"/repos/{repository}/commits/{sha}/status"
          )
          status_repository = status_payload.get("repository")
          if (
              status_payload.get("sha") != sha
              or not isinstance(status_repository, dict)
              or status_repository.get("full_name") != repository
          ):
              raise SystemExit("replacement/security status source identity differs")
          matching_security = [
              item
              for item in status_payload.get("statuses", [])
              if item.get("context") == "replacement/security"
          ]
          security_status = max(
              matching_security,
              key=lambda item: (item.get("created_at", ""), item.get("id", 0)),
              default={},
          )
          if not isinstance(security_status, dict) or security_status.get("state") != "success":
              raise SystemExit("replacement/security is not successful for this exact source SHA")
          target_url = security_status.get("target_url")
          if not isinstance(target_url, str):
              raise SystemExit("replacement/security has no workflow target URL")
          parsed_target = urllib.parse.urlsplit(target_url)
          expected_prefix = f"/{repository}/actions/runs/"
          if (
              parsed_target.scheme != urllib.parse.urlsplit(server).scheme
              or parsed_target.netloc != urllib.parse.urlsplit(server).netloc
              or parsed_target.query
              or parsed_target.fragment
              or not parsed_target.path.startswith(expected_prefix)
              or not re.fullmatch(
                  r"[1-9][0-9]*", parsed_target.path[len(expected_prefix):]
              )
          ):
              raise SystemExit("replacement/security target URL has no workflow run id")
          run_id = int(parsed_target.path[len(expected_prefix):])
          workflow = request(
              f"/repos/{repository}/actions/workflows/replacement-security-gates.yml"
          )
          if (
              not isinstance(workflow.get("id"), int)
              or workflow["id"] <= 0
              or workflow.get("name") != "Replacement security gates"
              or workflow.get("path")
              != ".github/workflows/replacement-security-gates.yml"
              or workflow.get("state") != "active"
          ):
              raise SystemExit("replacement security workflow identity differs")
          run = request(f"/repos/{repository}/actions/runs/{run_id}")
          run_repository = run.get("repository")
          head_repository = run.get("head_repository")
          if (
              run.get("id") != run_id
              or run.get("workflow_id") != workflow["id"]
              or run.get("event") != "workflow_dispatch"
              or run.get("status") != "completed"
              or run.get("conclusion") != "success"
              or not isinstance(run.get("run_attempt"), int)
              or run["run_attempt"] <= 0
              or not isinstance(run_repository, dict)
              or run_repository.get("full_name") != repository
              or not isinstance(head_repository, dict)
              or head_repository.get("full_name") != repository
              or head_repository.get("id") != run_repository.get("id")
              or run.get("head_sha") != sha
              or run.get("head_branch") != "main"
              or run.get("path")
              != ".github/workflows/replacement-security-gates.yml"
              or run.get("name") != f"Replacement security gates {sha}"
              or run.get("html_url") != target_url
              or run.get("display_title") != f"Replacement security gates {sha}"
          ):
              raise SystemExit("the source-bound replacement/security workflow did not pass")
          jobs_payload = request(
              f"/repos/{repository}/actions/runs/{run_id}"
              f"/attempts/{run['run_attempt']}/jobs?per_page=100"
          )
          jobs = jobs_payload.get("jobs", [])
          if (
              not isinstance(jobs, list)
              or jobs_payload.get("total_count") != len(jobs)
              or any(not isinstance(job, dict) for job in jobs)
          ):
              raise SystemExit("replacement security job listing is incomplete")
          expected_jobs = {
              "fuzz": "libFuzzer corpus and smoke",
              "asan": "Address Sanitizer ASan",
              "ubsan": "Undefined Behavior Sanitizer UBSan",
              "miri": "Miri strict provenance",
              "tsan": "Thread Sanitizer TSan",
              "valgrind": "Valgrind NSS Varlink and DNS fallback",
          }
          evidence = []
          for job in jobs:
              if job.get("conclusion") != "success":
                  continue
              successful_steps = [
                  step.get("name", "")
                  for step in job.get("steps", [])
                  if step.get("conclusion") == "success"
              ]
              if job.get("name") not in expected_jobs.values():
                  continue
              if (
                  job.get("run_id") != run_id
                  or job.get("run_attempt") != run["run_attempt"]
                  or job.get("head_sha") != sha
                  or job.get("head_branch") != "main"
                  or job.get("workflow_name") != f"Replacement security gates {sha}"
              ):
                  raise SystemExit(
                      f"security job run identity differs: {job.get('name')}"
                  )
              if "Verify exact source identity" not in successful_steps:
                  raise SystemExit(
                      f"security job did not prove the requested checkout: {job.get('name')}"
                  )
              evidence.append(
                  {
                      "repository": run_repository["full_name"],
                      "requested_source_commit": sha,
                      "workflow_id": workflow["id"],
                      "workflow_name": workflow["name"],
                      "workflow_path": workflow["path"],
                      "run_id": run["id"],
                      "run_attempt": run["run_attempt"],
                      "html_url": run["html_url"],
                      "event": run["event"],
                      "workflow_head_sha": run["head_sha"],
                      "workflow_head_branch": run["head_branch"],
                      "workflow_head_repository": head_repository["full_name"],
                      "workflow_display_title": run.get("display_title"),
                      "created_at": run["created_at"],
                      "updated_at": run["updated_at"],
                      "job_id": job["id"],
                      "job_name": job["name"],
                      "job_conclusion": job["conclusion"],
                      "job_run_id": job["run_id"],
                      "job_run_attempt": job["run_attempt"],
                      "job_head_sha": job["head_sha"],
                      "job_head_branch": job["head_branch"],
                      "job_workflow_name": job["workflow_name"],
                      "steps": successful_steps,
                  }
              )

          matched = {
              category: [
                  item for item in evidence if item["job_name"] == expected_name
              ]
              for category, expected_name in expected_jobs.items()
          }
          missing = [
              name for name, values in matched.items() if len(values) != 1
          ]
          payload = {
              "schema": 2,
              "repository": repository,
              "source_commit": sha,
              "workflow": {
                  "id": workflow["id"],
                  "name": workflow["name"],
                  "path": workflow["path"],
              },
              "run": {
                  "id": run["id"],
                  "attempt": run["run_attempt"],
                  "event": run["event"],
                  "conclusion": run["conclusion"],
                  "repository": run_repository["full_name"],
                  "head_repository": head_repository["full_name"],
                  "workflow_head_sha": run["head_sha"],
                  "head_branch": run["head_branch"],
                  "workflow_path": run["path"],
                  "workflow_name": run["name"],
                  "display_title": run.get("display_title"),
              },
              "required_categories": sorted(expected_jobs),
              "matched": matched,
              "all_successful_job_evidence": evidence,
              "missing": missing,
          }
          Path("security-evidence.json").write_text(
              json.dumps(payload, indent=2, sort_keys=True) + "\n",
              encoding="utf-8",
          )
          if missing:
              raise SystemExit(
                  "missing successful security evidence for: " + ", ".join(missing)
              )
          PY

      - name: Write bound proof
        shell: bash
        run: |
          set -euo pipefail
          mkdir -p proof
          cp security-evidence.json proof/security-evidence.json
          python3 scripts/write-replacement-proof.py \
            --gate security-suite \
            --result pass \
            --output proof/security-suite.json \
            --artifact proof/security-evidence.json \
            --metadata profiles=fuzz,asan,ubsan,miri,tsan,valgrind \
            --summary 'All required security profiles passed on this exact Git tree.'

      - name: Upload security proof
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        with:
          name: replacement-security-proof-${{ inputs.source_sha || github.sha }}
          path: proof
          if-no-files-found: error
          retention-days: 30

  report:
    name: Publish security proof status
    if: ${{ always() }}
    needs:
      - prove
    runs-on: ubuntu-24.04
    steps:
      - name: Publish exact-source status
        env:
          GH_TOKEN: ${{ github.token }}
          SOURCE_SHA: ${{ inputs.source_sha || github.sha }}
          RESULT: ${{ needs.prove.result }}
        run: |
          set -euo pipefail
          state=failure
          if [[ "$RESULT" == success ]]; then
            state=success
          fi
          payload=$(printf '{"state":"%s","context":"replacement/security-proof","description":"Bound security proof %s","target_url":"%s"}' "$state" "$state" "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}")
          curl --fail-with-body --silent --show-error -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: Bearer $GH_TOKEN" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/statuses/${SOURCE_SHA}" \
            --data "$payload" >/dev/null