Перейти к основному содержимому

Авторизация в GitHub Actions через Workload Identities

· 4 мин. чтения

В старых примерах использования экшенов, я для авторизации предлагал складывать в секреты авторизованный ключ сервисного аккаунта. На тот момент это было единственным способом авторизоваться. Однако в IAM появился новый способ. Я дописал экшены. А теперь давайте разберем, как работает это механизм, как его настроить и как использовать.

Принцип работы

Workload Identities Federation позволяет вам обмениваться токены выпущенные другими провайдерами идентификации, такими как GitHub, на IAM-токены. Это позволяет вам использовать IAM для авторизации в Yandex Cloud без необходимости хранить секреты или ключи доступа в вашем репозитории. Вместо этого вы можете использовать временные токены, которые выдаются GitHub при каждом запуске вашего экшена. Это позволяет вам безопасно управлять доступом к ресурсам Yandex Cloud, не беспокоясь о компрометации ваших секретов.

Настройка

Для начала вам нужно создать сервисный аккаунт, который будет использоваться для авторизации в Yandex Cloud. Затем вам нужно создать федерацию сервисных аккаунтов, которая будет использоваться для обмена токенами между GitHub и Yandex Cloud.

Создание федерации сервисных аккаунтов

  • Значение Issuer (iss) https://token.actions.githubusercontent.com
  • Допустимые значения Audience (aud) — ваш адрес на GitHub. У меня это https://github.com/nikolaymatrosov
  • Адрес JWKS https://token.actions.githubusercontent.com/.well-known/jwks

Теперь нужно на странице «Привязанные сервисные аккаунты» привязать сервисный аккаунт к федерации.

Привязка сервисного аккаунта к федерации

В поле «Значение Subject (sub)» укажите repo:%user%/%repo%:ref:refs/heads/main, где %user% и %repo% — это ваш логин и репозиторий на GitHub. Это значение указывает, что токен будет действителен только для вашего репозитория и ветки. Таким образом если кто-то попробует использовать те же настройки в своем репозитории, то он не сможет получить доступ к вашему сервисному аккаунту.

Использование

Теперь вы можете использовать этот сервисный аккаунт в своих экшенах. Для этого вам нужно указать ID сервисного аккаунта в вашем экшене. Например, если вы используете экшен yc-actions/yc-coi-deploy, то вам нужно указать ID сервисного аккаунта в параметре yc-sa-id:

name: Push To Yandex Cloud CR

permissions:
id-token: write # Нужно для получения JWT токена

# Описание, когда запускать этот workflow
on:
push:
branches: [ main ]
release:
types: [ created ]

# Позволяет запускать workflow вручную
workflow_dispatch:

jobs:
# Этот workflow содержит две задачи, называемые "build" и "deploy"
build:
# Тип runner, на котором будет выполняться задача
runs-on: ubuntu-latest

# Шаги представляют собой последовательность этапов, которые будут выполнены в рамках задачи
steps:
# Важно первым шагом выполнить checkout, чтобы получить доступ к коду
- uses: actions/checkout@v4

# Теперь мы можем используя ID сервисного аккаунта, который мы создали ранее, выпустить IAM токен для него,
# путем обмена GitHub токена на IAM токен.
- name: Get Yandex Cloud IAM token
id: get-iam-token
uses: docker://ghcr.io/yc-actions/yc-iam-token-fed:1.0.0
with:
yc-sa-id: ajep6pdp79imlp76gidn

# Используем полученный IAM токен для авторизации в Yandex Cloud Container Registry
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: cr.yandex
username: iam
password: ${{ steps.get-iam-token.outputs.token }}

# После того как мы авторизовались в Yandex Cloud Container Registry, мы можем собрать и запушить образ
- name: Build, tag, and push image to Yandex Cloud Container Registry
env:
CR_REGISTRY: crpk28lsfu91rns28316
CR_REPOSITORY: yc-coi-github-action
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t cr.yandex/$CR_REGISTRY/$CR_REPOSITORY:$IMAGE_TAG .
docker push cr.yandex/$CR_REGISTRY/$CR_REPOSITORY:$IMAGE_TAG
# Вторая задача, которая будет выполняться после завершения первой
# Задача "deploy" зависит от задачи "build"
deploy:
needs:
- build
runs-on: ubuntu-latest
steps:
# В новом job'е нам нужно снова выполнить checkout, чтобы получить доступ к коду
- uses: actions/checkout@v4

# Теперь мы можем использовать полученный IAM токен для авторизации в Yandex Cloud Container Registry
# передав его в `yc-iam-token`. Или же передав `yc-sa-id`, как в примере ниже, снова обменять GitHub токен на IAM токен.
- name: Deploy COI VM
id: deploy-coi
uses: yc-actions/yc-coi-deploy@v3
env:
IMAGE_URL: cr.yandex/crpk28lsfu91rns28316/yc-coi-github-action:${{ github.sha }}
SSH_KEY: ${{ secrets.SSH_KEY }}
with:
yc-sa-id: ajep6pdp79imlp76gidn
folder-id: b1gbmkj63hnlfu8877sn
vm-name: yc-action-demo
vm-service-account-id: ajepa75j7t2ki57l5i9m
vm-cores: 2
vm-memory: 2 GB
vm-core-fraction: 100
vm-zone-id: ru-central1-a
vm-subnet-id: e9bobc1ueq7aue8csi6m
vm-disk-type: network-hdd
vm-disk-size: 64GB
user-data-path: './user-data.yaml'
docker-compose-path: './docker-compose.yaml'

Отдельно стоит отметить, что чтобы в экшене был доступ GitHub токену, нужно указать permissions как на строках 3 и 4.

Полный пример можно найти в репозитории.