Thumbnail image

GCP Artifact Registry Для GitHub Организации (Часть 1)

Сегодня я хотел бы описать как использовать GCP “Workload Identity Federation” чтобы безопасно пушить докер образы из GitHub Actions CI в GCP Artifact Registry

Этот пост что-то типа туториала для тех у кого есть организация в github.com, но по какой-то причине желающих хранить докер-образы в GCP Artifact Registry (например чтобы ускорить пул внутри GCP)

Итак, что у нас есть и чего мы хотим достичь?

Дано:

  • организация в github.com, скажем mnacharov-eu
  • GCP проект, скажем mnacharov-eu-docker

Цель:

  1. Иметь закрытый GCP Artifact Registry репозиторий для каждого GitHub.com репозитория в нашей организации
  2. Иметь возможность пушить докер образы из GitHub Actions CI в закрытый GCP Artifact Registry репозиторий без необходимости добавлять секреты в github репозиторий
  3. Простота управления доступами пользователей к GCP Artifact Registry репозиториям

Авторизуем GitHubCI джобы в GCP с короткоживущими токенами

Начнём с простых вещей: авторизации с помощью Workload Identity Federation. Эта возможность должна быть использована в ваших GitHub CI пайплайнах!

Если вы когда нибудь использовали достаточно популярный способ авторизации github actions CI в google cloud - экшен google google-github-actions/auth, вы должны были заметить что рекомендуемый способ использования это “Direct Workload Identity Federation”. Инструкции по его настройки там достаточно хорошие, но на случай если вам хочется иметь terraform описание, вот мой конфиг:

variable "github_organization" {
  description = "The GitHub organization for the attribute condition."
  default     = "mnacharov-eu"
}

resource "google_iam_workload_identity_pool" "github_pool" {
  project                   = var.project_id
  workload_identity_pool_id = "github-com"
  display_name              = "GitHub identity pool"
}

resource "google_iam_workload_identity_pool_provider" "github_mnacharov-eu_repos" {
  project      = var.project_id
  display_name = "GitHub for mnacharov-eu repos"

  workload_identity_pool_id          = google_iam_workload_identity_pool.github_pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "mnacharov-eu"

  attribute_mapping = {
    "google.subject"             = "assertion.sub"
    "attribute.repository"       = "assertion.repository"
    "attribute.repository_owner" = "assertion.repository_owner"
  }

  # Condition: specific github organization
  attribute_condition = <<EOT
  assertion.repository_owner == '${var.github_organization}'
  EOT

  oidc {
    issuer_uri = "https://token.actions.githubusercontent.com"
  }
}

после этого я могу авторизовать любой github actions пайплайн из моей гитхаб организации в google. Но как назначить пермишены на пуш образов в Artifact Registry? Это может выглядеть как-то так:

locals {
  github_repos = [
    "push-to-gcp",
  ]
}

resource "google_artifact_registry_repository" "registries" {
  for_each      = toset(local.github_repos)
  repository_id = each.value
  description   = "github.com/mnacharov-eu/${each.value} images"
  format        = "DOCKER"
  location      = var.region
  project       = var.project_id

  docker_config {
    immutable_tags = true
  }
  cleanup_policies {
    id     = "keep-release-images"
    action = "KEEP"
    condition {
      tag_state    = "TAGGED"
      tag_prefixes = ["v"]
    }
  }
  cleanup_policies {
    id     = "delete-untagged"
    action = "DELETE"
    condition {
      tag_state    = "UNTAGGED"
      older_than   = "86400s"    # 1 day
    }
  }
  cleanup_policies {
    id     = "delete after 30d"
    action = "DELETE"
    condition {
      older_than   = "2592000s"  # 30 days
    }
  }
}

resource "google_artifact_registry_repository_iam_member" "allow_to_push_from_github" {
  for_each   = toset(local.github_repos)
  project    = var.project_id
  location   = google_artifact_registry_repository.registries[each.value].location
  repository = google_artifact_registry_repository.registries[each.value].name
  role       = "roles/artifactregistry.writer"
  member     = "principalSet://iam.googleapis.com/projects/${var.project_number}/locations/global/workloadIdentityPools/github-com/attribute.repository/mnacharov-eu/${each.value}"
}

таким образом, для github actions пайплайна из репозитория mnacharov-eu/push-to-gcp будет доступен пуш докер образа в закрытый Artifact Registry europe-docker.pkg.dev/mnacharov-eu-docker/push-to-gcp. Давайте попробуем провеить его в простом пайплайне:

on:
  schedule:
  - cron: '26 4 * * 4'
  push:
    branches:
    - main
    tags:
    - 'v*'

env:
  REGISTRY: europe-docker.pkg.dev

jobs:
  docker-build:
    runs-on: ubuntu-latest
    permissions:
      contents: 'read'
      id-token: 'write'

    steps:
    - uses: 'actions/checkout@v4'
    - uses: 'google-github-actions/auth@v2'
      with:
        project_id: 'mnacharov-eu-docker'
        workload_identity_provider: 'projects/152460024713/locations/global/workloadIdentityPools/github-com/providers/mnacharov-eu'
    - name: Docker meta
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: europe-docker.pkg.dev/mnacharov-eu-docker/push-to-gcp/main
        flavor: |
          latest=false
        tags: |
          type=semver,pattern={{version}}
          type=sha,enable=${{ github.ref == format('refs/heads/{0}', 'main') && github.event.schedule == null }}
          type=raw,enable=${{ github.event.schedule != null }},value={{date 'cron-YY-MM-DD'}}
    - name: Configure GC docker
      run: |
        gcloud auth configure-docker europe-docker.pkg.dev
    - name: Build & Push Airflow
      uses: docker/build-push-action@v6
      with:
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}

и это работает, вот тут можно найти как выглядит лог билда https://github.com/mnacharov-eu/push-to-gcp/actions

Вот и всё на сегодня

Итак, у нас уже есть безопасный способ авторизоваться и запушить образы в Artifact Registry из GitHub Actions CI, но всего для одного репозитория

В следующий раз я расширю этот подход чтобы иметь Artifact Registry репозиторий со всеми необходимыми доступами сразу после создания нового GitHub.com репозитория! До скорого…