diff --git a/.github/workflows/base-image.yml b/.github/workflows/base-image.yml index 066a8d2..ffb4740 100644 --- a/.github/workflows/base-image.yml +++ b/.github/workflows/base-image.yml @@ -8,22 +8,22 @@ permissions: env: PROJECT_ID: casecomp-495718 - IMAGE: gcr.io/casecomp-495718/casecomp-node24 + IMAGE: us-docker.pkg.dev/casecomp-495718/casecomp-node24/node24 jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: google-github-actions/auth@v3 + - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: workload_identity_provider: projects/129850122606/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: casecomp-deploy@casecomp-495718.iam.gserviceaccount.com - - uses: google-github-actions/setup-gcloud@v3 + - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 with: go-version: "1.24" @@ -34,7 +34,7 @@ jobs: run: apko build images/node24/apko.yaml ${{ env.IMAGE }}:latest image.tar - name: Configure Docker auth - run: gcloud auth configure-docker --quiet + run: gcloud auth configure-docker us-docker.pkg.dev --quiet - name: Load image run: docker load < image.tar diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e429664..3d0dea2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ name: CI on: push: - branches: [main, dev] + branches: [main] pull_request: branches: [main] @@ -13,8 +13,8 @@ jobs: unit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: node-version: 24 - run: npm install @@ -24,8 +24,8 @@ jobs: continue-on-error: true runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: node-version: 24 - run: npm install @@ -33,7 +33,7 @@ jobs: id: pw-version run: echo "version=$(npx playwright --version | awk '{print $2}')" >> $GITHUB_OUTPUT - name: Cache Playwright browsers - uses: actions/cache@v5 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 id: pw-cache with: path: ~/.cache/ms-playwright @@ -50,8 +50,8 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: node-version: 24 - run: npm install @@ -61,26 +61,26 @@ jobs: codeql: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: github/codeql-action/init@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: github/codeql-action/init@7c1e4cf0b20d7c1872b26569c00ba908797a59bf # v4 with: languages: javascript-typescript - - uses: github/codeql-action/analyze@v4 + - uses: github/codeql-action/analyze@7c1e4cf0b20d7c1872b26569c00ba908797a59bf # v4 scan: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Generate SBOM (Syft) - uses: anchore/sbom-action@v0 + uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 with: path: . format: spdx-json output-file: sbom.spdx.json - name: Vulnerability scan (Grype) - uses: anchore/scan-action@v7 + uses: anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2 # v7 id: grype with: sbom: sbom.spdx.json @@ -89,7 +89,7 @@ jobs: add-cpes-if-none: true - name: Upload SBOM - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: sbom-${{ github.sha }} path: sbom.spdx.json @@ -97,7 +97,7 @@ jobs: - name: Upload Grype report if: always() && steps.grype.outputs.sarif != '' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: grype-sarif-${{ github.sha }} path: ${{ steps.grype.outputs.sarif }} @@ -106,8 +106,8 @@ jobs: audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v5 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: node-version: 24 - run: npm install @@ -119,9 +119,9 @@ jobs: secrets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - - uses: gitleaks/gitleaks-action@v2 + - uses: gitleaks/gitleaks-action@dcedce43c6f43de0b836d1fe38946645c9c638dc # v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 553d32b..8a87fae 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -6,11 +6,12 @@ on: permissions: contents: read id-token: write + attestations: write env: PROJECT_ID: casecomp-495718 SERVICE: casecomp-api - IMAGE: gcr.io/casecomp-495718/casecomp-api + IMAGE: us-docker.pkg.dev/casecomp-495718/casecomp-api/app jobs: build: @@ -18,14 +19,14 @@ jobs: outputs: digest: ${{ steps.digest.outputs.digest }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: google-github-actions/auth@v3 + - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: workload_identity_provider: projects/129850122606/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: casecomp-deploy@casecomp-495718.iam.gserviceaccount.com - - uses: google-github-actions/setup-gcloud@v3 + - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3 - name: Build and push run: | @@ -48,16 +49,16 @@ jobs: - name: Get image digest id: digest run: | - DIGEST=$(gcloud container images describe ${{ env.IMAGE }}:latest \ + DIGEST=$(gcloud artifacts docker images describe ${{ env.IMAGE }}:latest \ --project ${{ env.PROJECT_ID }} \ --format='value(image_summary.digest)') echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" echo "Image digest: $DIGEST" - - name: Configure Docker auth for GCR - run: gcloud auth configure-docker --quiet + - name: Configure Docker auth for Artifact Registry + run: gcloud auth configure-docker us-docker.pkg.dev --quiet - - uses: sigstore/cosign-installer@v3 + - uses: sigstore/cosign-installer@f713795cb21599bc4e5c4b58cbad1da852d7eeb9 # v3 - name: Sign image (keyless) run: | @@ -70,10 +71,17 @@ jobs: cosign verify \ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \ --certificate-identity-regexp="github.com/Pyronewbic/casecomp" \ - "${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" || true + "${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" + + - name: Create Binary Auth attestation + run: | + gcloud beta container binauthz attestations sign-and-create \ + --artifact-url="${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" \ + --attestor="projects/${{ env.PROJECT_ID }}/attestors/deploy-attestor" \ + --keyversion="projects/${{ env.PROJECT_ID }}/locations/global/keyRings/binary-auth/cryptoKeys/attestor-key/cryptoKeyVersions/1" - name: Generate container SBOM (Syft) - uses: anchore/sbom-action@v0 + uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 with: image: "${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" format: spdx-json @@ -88,26 +96,12 @@ jobs: --type spdxjson \ "${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" - - name: Attest SLSA provenance - run: | - cat > /tmp/provenance.json << 'PROV' - { - "buildType": "https://slsa.dev/provenance/v1", - "builder": { "id": "https://github.com/Pyronewbic/casecomp/.github/workflows/deploy.yml" }, - "invocation": { - "configSource": { - "uri": "git+https://github.com/Pyronewbic/casecomp@refs/heads/main", - "digest": { "sha1": "${{ github.sha }}" }, - "entryPoint": ".github/workflows/deploy.yml" - } - } - } - PROV - cosign attest --yes \ - --oidc-issuer=https://token.actions.githubusercontent.com \ - --predicate /tmp/provenance.json \ - --type slsaprovenance \ - "${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}" + - name: Attest build provenance + uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2 + with: + subject-name: ${{ env.IMAGE }} + subject-digest: ${{ steps.digest.outputs.digest }} + push-to-registry: true deploy: needs: build @@ -117,12 +111,12 @@ jobs: region: [asia-south1, us-central1] fail-fast: false steps: - - uses: google-github-actions/auth@v3 + - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: workload_identity_provider: projects/129850122606/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: casecomp-deploy@casecomp-495718.iam.gserviceaccount.com - - uses: google-github-actions/setup-gcloud@v3 + - uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3 - name: Deploy to Cloud Run (${{ matrix.region }}) run: | @@ -156,9 +150,9 @@ jobs: needs: deploy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: ZAP API Scan - uses: zaproxy/action-api-scan@v0.9.0 + uses: zaproxy/action-api-scan@a9a916402665623ce9d37a6998d7b48e6b35dd6c # v0.9.0 with: target: https://api.casecomp.xyz/docs/spec.json format: openapi @@ -167,7 +161,7 @@ jobs: cmd_options: '-a' - name: Upload DAST report if: always() - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: zap-report-${{ github.sha }} path: report_html.html diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index 7e8fd91..d094270 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -21,14 +21,14 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: google-github-actions/auth@v3 + - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: workload_identity_provider: projects/129850122606/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: casecomp-deploy@casecomp-495718.iam.gserviceaccount.com - - uses: hashicorp/setup-terraform@v4 + - uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4 with: terraform_version: ${{ env.TF_VERSION }} @@ -56,7 +56,7 @@ jobs: working-directory: ${{ env.TF_DIR }} - name: Post plan to PR - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: script: | const fs = require('fs'); @@ -85,14 +85,14 @@ jobs: if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: google-github-actions/auth@v3 + - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3 with: workload_identity_provider: projects/129850122606/locations/global/workloadIdentityPools/github-pool/providers/github-provider service_account: casecomp-deploy@casecomp-495718.iam.gserviceaccount.com - - uses: hashicorp/setup-terraform@v4 + - uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4 with: terraform_version: ${{ env.TF_VERSION }} diff --git a/CLAUDE.md b/CLAUDE.md index d6edf5a..b4b167b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,10 +112,10 @@ Strict palette — no deviations: - GCP: Cloud Run in asia-south1 + us-central1, Firestore (asia-south1), HTTPS LB (global, geo-routes), Cloud CDN, Secret Manager, Cloud Scheduler - Terraform: GCS state, 8 files by resource type, CI plan/apply, `for_each` over regions - **CI (ci.yml):** single workflow. Jobs: unit, api (demo-based, continue-on-error), smoke (non-blocking), codeql, scan (SBOM+Grype), audit (npm+lockfile-lint), secrets (gitleaks). Required: unit + codeql. -- **Deploy:** Kaniko v1.23.2 --reproducible → cosign sign → SBOM attest (Syft SPDX from container) → SLSA provenance attest → deploy by digest → both regions → health check → OWASP ZAP DAST -- **Custom Wolfi base image:** gcr.io/casecomp-495718/casecomp-node24. Built with apko. 9 smoke tests. 0 CVEs. -- **Supply chain:** SBOM + SLSA attestations on image digest, Dependabot, lockfile-lint, Socket.dev, pre-commit hook (blocks .env, secrets, large files) -- **Binary Authorization:** ENFORCED on both Cloud Run services +- **Deploy:** Kaniko v1.23.2 --reproducible → cosign sign → Binary Auth attestation (KMS) → SBOM attest (Syft SPDX from container) → build provenance (actions/attest-build-provenance) → deploy by digest → both regions → health check → OWASP ZAP DAST +- **Custom Wolfi base image:** us-docker.pkg.dev/casecomp-495718/casecomp-node24/node24. Built with apko. 9 smoke tests. 0 CVEs. +- **Supply chain:** SBOM + SLSA attestations on image digest, SHA-pinned GitHub Actions, Dependabot, lockfile-lint, Socket.dev, pre-commit hook (blocks .env, secrets, large files) +- **Binary Authorization:** ENFORCED on both Cloud Run services, KMS-backed attestor, deploy pipeline creates attestations - **Secret workflow:** Add to secrets.tf → CI creates → `gcloud secrets versions add` for value. Never `gcloud secrets create`. - Secrets: EBAY_CLIENT_ID/SECRET, ANTHROPIC_API_KEY, TOGETHER_API_KEY, PSA_AUTH_TOKEN, CASECOMP_API_KEY, CASECOMP_SANDBOX_KEY, RESEND_API_KEY, CASECOMP_JWT_SECRET, GOOGLE_OAUTH_CLIENT_ID, CASECOMP_ADMIN_SUB diff --git a/Dockerfile b/Dockerfile index 0bf1495..8ca14c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN npm install --production COPY . . -FROM gcr.io/casecomp-495718/casecomp-node24:latest +FROM us-docker.pkg.dev/casecomp-495718/casecomp-node24/node24:latest WORKDIR /app COPY --from=build /app /app diff --git a/cloudbuild.yml b/cloudbuild.yml index 9ef6fc9..9d5ac0e 100644 --- a/cloudbuild.yml +++ b/cloudbuild.yml @@ -1,8 +1,8 @@ steps: - name: gcr.io/kaniko-project/executor:v1.23.2 args: - - --destination=gcr.io/$PROJECT_ID/casecomp-api:latest - - --destination=gcr.io/$PROJECT_ID/casecomp-api:$SHORT_SHA + - --destination=us-docker.pkg.dev/$PROJECT_ID/casecomp-api/app:latest + - --destination=us-docker.pkg.dev/$PROJECT_ID/casecomp-api/app:$SHORT_SHA - --cache=true - --cache-ttl=168h - --reproducible diff --git a/docs/internals.md b/docs/internals.md index 481d77d..07d01f2 100644 --- a/docs/internals.md +++ b/docs/internals.md @@ -80,7 +80,7 @@ Both `casecomp-api` and `casecomp-site` run in asia-south1 (Mumbai) and us-centr | Cloud Scheduler | asia-south1 | Hits LB domain, auto-routes | | HTTPS LB | Global | Backend services have NEGs in both regions | | Artifact Registry (frontend) | us (multi-region) | `us-docker.pkg.dev`, accessible from both regions | -| GCR (API) | us (multi-region) | `gcr.io`, accessible globally | +| Artifact Registry (API) | us (multi-region) | `us-docker.pkg.dev`, accessible globally | Deploy workflow: build once → cosign sign → SBOM attest → SLSA attest → deploy to both regions via GitHub Actions matrix (parallel, fail-fast: false) → health check → ZAP DAST. diff --git a/package.json b/package.json index 52a597d..45e97ce 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test:smoke": "node test/smoke-test.js", "scan": "node scan.js", "psa": "node scripts/psa-report.js", - "deploy": "gcloud builds submit --config=cloudbuild.yml --project casecomp-495718 && gcloud run deploy casecomp-api --image gcr.io/casecomp-495718/casecomp-api --region asia-south1 --project casecomp-495718 --port 3000 --allow-unauthenticated", + "deploy": "gcloud builds submit --config=cloudbuild.yml --project casecomp-495718 && gcloud run deploy casecomp-api --image us-docker.pkg.dev/casecomp-495718/casecomp-api/app --region asia-south1 --project casecomp-495718 --port 3000 --allow-unauthenticated", "playwright-install": "npx playwright install chromium" }, "dependencies": { diff --git a/terraform/README.md b/terraform/README.md index dc29bfa..bbe7116 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -38,7 +38,7 @@ Both backends have NEGs in asia-south1 and us-central1. LB routes to nearest. | `regions` | `["asia-south1", "us-central1"]` | Cloud Run deploy regions | | `api_domain` | `api.casecomp.xyz` | API SSL cert domain | | `site_domain` | `casecomp.xyz` | Frontend SSL cert domain | -| `container_image` | `gcr.io/casecomp-495718/casecomp-api` | API Docker image | +| `container_image` | `us-docker.pkg.dev/casecomp-495718/casecomp-api/app` | API Docker image | | `alert_email` | *(sensitive, in terraform.tfvars / GitHub secret)* | Monitoring alert recipient | ## Usage diff --git a/terraform/artifact-registry.tf b/terraform/artifact-registry.tf new file mode 100644 index 0000000..125a6f1 --- /dev/null +++ b/terraform/artifact-registry.tf @@ -0,0 +1,54 @@ +resource "google_artifact_registry_repository" "casecomp_api" { + location = "us" + repository_id = "casecomp-api" + format = "DOCKER" + description = "casecomp API container images" + + cleanup_policies { + id = "keep-recent" + action = "KEEP" + most_recent_versions { + keep_count = 20 + } + } + + depends_on = [google_project_service.artifactregistry] +} + +resource "google_artifact_registry_repository" "casecomp_node24" { + location = "us" + repository_id = "casecomp-node24" + format = "DOCKER" + description = "casecomp Node.js 24 base image" + + cleanup_policies { + id = "keep-recent" + action = "KEEP" + most_recent_versions { + keep_count = 5 + } + } + + depends_on = [google_project_service.artifactregistry] +} + +resource "google_artifact_registry_repository_iam_member" "api_deploy" { + repository = google_artifact_registry_repository.casecomp_api.name + location = google_artifact_registry_repository.casecomp_api.location + role = "roles/artifactregistry.writer" + member = "serviceAccount:casecomp-deploy@${var.project_id}.iam.gserviceaccount.com" +} + +resource "google_artifact_registry_repository_iam_member" "api_cloudbuild" { + repository = google_artifact_registry_repository.casecomp_api.name + location = google_artifact_registry_repository.casecomp_api.location + role = "roles/artifactregistry.writer" + member = "serviceAccount:${data.google_project.current.number}@cloudbuild.gserviceaccount.com" +} + +resource "google_artifact_registry_repository_iam_member" "node24_deploy" { + repository = google_artifact_registry_repository.casecomp_node24.name + location = google_artifact_registry_repository.casecomp_node24.location + role = "roles/artifactregistry.writer" + member = "serviceAccount:casecomp-deploy@${var.project_id}.iam.gserviceaccount.com" +} diff --git a/terraform/binary-auth.tf b/terraform/binary-auth.tf new file mode 100644 index 0000000..bb28f62 --- /dev/null +++ b/terraform/binary-auth.tf @@ -0,0 +1,81 @@ +resource "google_kms_key_ring" "binary_auth" { + name = "binary-auth" + location = "global" + + depends_on = [google_project_service.cloudkms] +} + +resource "google_kms_crypto_key" "attestor_key" { + name = "attestor-key" + key_ring = google_kms_key_ring.binary_auth.id + purpose = "ASYMMETRIC_SIGN" + + version_template { + algorithm = "EC_SIGN_P256_SHA256" + protection_level = "SOFTWARE" + } +} + +data "google_kms_crypto_key_version" "attestor" { + crypto_key = google_kms_crypto_key.attestor_key.id +} + +resource "google_container_analysis_note" "deploy_attestor" { + name = "deploy-attestor" + + attestation_authority { + hint { + human_readable_name = "Deploy pipeline attestor" + } + } + + depends_on = [google_project_service.containeranalysis] +} + +resource "google_binary_authorization_attestor" "deploy" { + name = "deploy-attestor" + + attestation_authority_note { + note_reference = google_container_analysis_note.deploy_attestor.name + + public_keys { + id = data.google_kms_crypto_key_version.attestor.id + + pkix_public_key { + public_key_pem = data.google_kms_crypto_key_version.attestor.public_key[0].pem + signature_algorithm = "ECDSA_P256_SHA256" + } + } + } + + depends_on = [google_project_service.binaryauthorization] +} + +resource "google_binary_authorization_policy" "default" { + global_policy_evaluation_mode = "ENABLE" + + default_admission_rule { + evaluation_mode = "ALWAYS_ALLOW" + enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG" + } + + depends_on = [google_project_service.binaryauthorization] +} + +resource "google_kms_crypto_key_iam_member" "deploy_sa_signer" { + crypto_key_id = google_kms_crypto_key.attestor_key.id + role = "roles/cloudkms.signerVerifier" + member = "serviceAccount:casecomp-deploy@${var.project_id}.iam.gserviceaccount.com" +} + +resource "google_project_iam_member" "deploy_sa_note_attacher" { + project = var.project_id + role = "roles/containeranalysis.notes.attacher" + member = "serviceAccount:casecomp-deploy@${var.project_id}.iam.gserviceaccount.com" +} + +resource "google_project_iam_member" "deploy_sa_occurrence_editor" { + project = var.project_id + role = "roles/containeranalysis.occurrences.editor" + member = "serviceAccount:casecomp-deploy@${var.project_id}.iam.gserviceaccount.com" +} diff --git a/terraform/main.tf b/terraform/main.tf index 5873022..be2c609 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -68,15 +68,13 @@ resource "google_project_service" "monitoring" { disable_on_destroy = false } -# ── Binary Authorization ────────────────────────────────────── - -resource "google_binary_authorization_policy" "default" { - global_policy_evaluation_mode = "ENABLE" - - default_admission_rule { - evaluation_mode = "ALWAYS_ALLOW" - enforcement_mode = "ENFORCED_BLOCK_AND_AUDIT_LOG" - } +resource "google_project_service" "artifactregistry" { + service = "artifactregistry.googleapis.com" + disable_on_destroy = false +} - depends_on = [google_project_service.binaryauthorization] +resource "google_project_service" "cloudkms" { + service = "cloudkms.googleapis.com" + disable_on_destroy = false } + diff --git a/terraform/variables.tf b/terraform/variables.tf index dbd67a4..e92cdc4 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -15,7 +15,7 @@ variable "site_domain" { } variable "container_image" { - default = "gcr.io/casecomp-495718/casecomp-api" + default = "us-docker.pkg.dev/casecomp-495718/casecomp-api/app" } variable "regions" {