Авторизация в GitHub Actions через Workload Identities
В старых примерах использования экшенов, я для авторизации предлагал складывать в секреты авторизованный ключ сервисного аккаунта. На тот момент это было единственным способом авторизоваться. Однако в 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.
Полный пример можно найти в репозитории.