From 201548b75afb6f521ee7449ff6b68cf75ee2bbda Mon Sep 17 00:00:00 2001 From: Jason Hall Date: Fri, 23 Jun 2023 09:19:09 -0400 Subject: [PATCH] also set up Chainguard puller identity Signed-off-by: Jason Hall --- .github/workflows/workflow.yaml | 5 +++- image-workflow/README.md | 21 +++++++++++++++-- image-workflow/iac/main.tf | 42 +++++++++++++++++++++++++++++++++ image-workflow/iac/outputs.tf | 5 ++++ 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 507c124..22739c7 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -9,5 +9,8 @@ jobs: test-image: runs-on: ubuntu-latest steps: + - uses: chainguard-dev/actions/setup-chainctl@main + with: + identity: 7bf08061e47a927f78ffa39cd6393f4a83ec6eb7/aa8f8890af6747f9 - run: | - echo ding ding testing ${{ github.event.inputs.image }} + docker pull ${{ github.event.inputs.image }} diff --git a/image-workflow/README.md b/image-workflow/README.md index 9afafe0..cc16586 100644 --- a/image-workflow/README.md +++ b/image-workflow/README.md @@ -2,6 +2,10 @@ This sets up a Cloud Run app to listen for `registry.push` events to a private Chainguard Registry group, and triggers a GitHub Actions workflow with that image ref as an input. +This lets you define GitHub Actions workflows to pull and test images in response to pushes. + +# Usage + To start, create a GitHub workflow at `.github/workflows/workflow.yaml`, with an input named `image`: ``` @@ -16,12 +20,17 @@ jobs: test-image: runs-on: ubuntu-latest steps: + # This sets up auth with the registry to be able to pull the image. + - uses: chainguard-dev/actions/setup-chainctl@main + with: + identity: TODO # We'll fill this in later. + - run: | # Your tests go here. - echo ding ding testing ${{ github.event.inputs.image }} + docker pull ${{ github.event.inputs.image }} ``` -Then Terraform apply the module (e.g., from the root of this repo): +Then `terraform apply` the module (e.g., from the root of this repo): ``` module "image-workflow" { @@ -52,6 +61,8 @@ module "image-workflow" { } ``` +## Setting your GitHub Personal Access Token + Once things have been provisioned, this module outputs a `secret-command` containing the command to run to upload your Github "personal access token" to the Google Secret Manager secret the application will use, looking something @@ -63,3 +74,9 @@ echo -n YOUR GITHUB PAT | \ ``` The personal access token needs `actions:write` to trigger workflows. + +## Setting your puller identity + +The module also outputs the identity that was created, which can be assumed by the +GitHub Actions workflow. This is the value that goes in the `setup-chainctl` step +of your workflow above. diff --git a/image-workflow/iac/main.tf b/image-workflow/iac/main.tf index 6fe9ff6..318dd33 100644 --- a/image-workflow/iac/main.tf +++ b/image-workflow/iac/main.tf @@ -7,14 +7,20 @@ terraform { } } +provider "ko" { + repo = "gcr.io/${var.project_id}/${var.name}-image-workflow" +} + provider "google" { project = var.project_id } +# Create a service account to run the service, with access to the GitHub PAT secret. resource "google_service_account" "image-workflow" { account_id = "${var.name}-image-workflow" } +# Create a secret to hold the GitHub personal access token. resource "google_secret_manager_secret" "gh-pat" { project = var.project_id secret_id = "${var.name}-github-pat" @@ -23,6 +29,9 @@ resource "google_secret_manager_secret" "gh-pat" { } } +# Create the initial secret version, which will let the service start up. +# After the infrastructure is provisioned, the secret-command output will +# show you how to populate the secret. resource "google_secret_manager_secret_version" "initial-secret-version" { secret = google_secret_manager_secret.gh-pat.id @@ -36,12 +45,14 @@ resource "google_secret_manager_secret_version" "initial-secret-version" { } } +# Grant the service account access to read the secret. resource "google_secret_manager_secret_iam_member" "grant-secret-access" { secret_id = google_secret_manager_secret.gh-pat.id role = "roles/secretmanager.secretAccessor" member = "serviceAccount:${google_service_account.image-workflow.email}" } +# Verify the base image is signed by the expected identity. data "cosign_verify" "base-image" { image = "cgr.dev/chainguard/static:latest-glibc" @@ -71,11 +82,13 @@ data "cosign_verify" "base-image" { }) } +# Build the app into a container image. resource "ko_build" "image" { importpath = "github.com/imjasonh/terraform-playground/image-workflow/cmd/app" working_dir = path.module } +# Deploy the service, running as the Service Account, with the GitHub PAT as a secret env var. resource "google_cloud_run_service" "image-workflow" { name = "${var.name}-image-workflow" location = var.location @@ -119,6 +132,7 @@ resource "google_cloud_run_service" "image-workflow" { } } +# Look up the IAM policy for "allUsers" to allow anyone to invoke the service. data "google_iam_policy" "noauth" { binding { role = "roles/run.invoker" @@ -128,6 +142,7 @@ data "google_iam_policy" "noauth" { } } +# Allow anyone to invoke the service. resource "google_cloud_run_service_iam_policy" "noauth" { location = google_cloud_run_service.image-workflow.location service = google_cloud_run_service.image-workflow.name @@ -140,3 +155,30 @@ resource "chainguard_subscription" "subscription" { parent_id = var.group sink = google_cloud_run_service.image-workflow.status[0].url } + +# Create an identity that can be assumed by the GitHub workflow. +resource "chainguard_identity" "puller" { + parent_id = var.group + name = "${var.name}-image-workflow image puller" + description = <