Методы аутентификации GitHub Actions для Azure


Обзор

Когда вы работаете с GitHub Actions и начинаете писать и разрабатывать рабочие процессы автоматизации, вам иногда потребуется подключить ваши рабочие процессы к различным платформам, таким как, например, облачный провайдер, чтобы предоставить вашим рабочим процессам доступ и разрешения на выполнение действий на облачном провайдере. Таким образом, вам потребуется каким-то образом подключить и аутентифицировать ваши рабочие процессы GitHub Actions к облачному провайдеру.

Сегодня мы рассмотрим два способа, как это можно сделать с помощью Azure.

В обоих способах мы создадим так называемую регистрацию приложения/принципал службы, назначим разрешения принципалу и свяжем его с GitHub, чтобы ваши рабочие процессы действий могли аутентифицироваться и выполнять соответствующие задачи в Azure.

ПРИМЕЧАНИЕ: Если вы знакомы с использованием Azure DevOps и конвейеров Azure, это синоним создания подключения к службе для ваших конвейеров. Рабочие процессы GitHub Actions являются синонимом многоступенчатых YAML-конвейеров Azure.

Метод 1 — Клиент и секрет (Legacy)

Первый метод, который мы рассмотрим, — это старый унаследованный метод, который использует 'Client' и 'Secret' для аутентификации.

1. Создание учетных данных принципала службы

Для этого метода я буду использовать следующий сценарий PowerShell; ‘Create-SP.ps1’ для создания Azure AD App & Service Principal.

### Create-SP.ps1 ###
# Log into Azure
Az login

# Show current subscription (use 'Az account set' to change subscription)
Az account show

# variables
$subscriptionId=$(az account show --query id -o tsv)
$appName="GitHub-projectName-Actions"
$RBACRole="Contributor"

# Create AAD App and Service Principal and assign RBAC Role
az ad sp create-for-rbac --name $appName `
    --role $RBACRole `
    --scopes /subscriptions/$subscriptionId `
    --sdk-auth
Вход в полноэкранный режим Выход из полноэкранного режима

В приведенном выше сценарии команда 'az ad sp create-for-rbac' создаст AAD app & service principal и выведет JSON объект, содержащий учетные данные service principal:

ПРИМЕЧАНИЕ: Принципал службы предоставит вашему рабочему процессу GitHub Actions, Contributor доступ к подписке. Не стесняйтесь изменять RBAC 'role' и 'scopes' по мере необходимости в предоставленном скрипте.

Скопируйте объект JSON, поскольку мы будем добавлять его в качестве секрета GitHub. Вам понадобятся только секции со значениями "clientId", "clientSecret", "subscriptionId" и "tenantId":

{
  "clientId": "<GUID>",
  "clientSecret": "<PrincipalSecret>",
  "subscriptionId": "<GUID>",
  "tenantId": "<GUID>"
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Основной недостаток использования этого метода для создания принципала службы для GitHub заключается в том, что секрет клиента принципала действителен только в течение 1 года, и в целях безопасности должен часто управляться и ротироваться, а также обновляться в вашем аккаунте GitHub вручную, что может стать громоздкой задачей администрирования.

Вы можете изменить секрет принципала службы, перейдя к ‘App registrations’ в ‘Azure Active Directory (AAD)’ и найдя приложение, которое мы только что создали.

Позже мы обсудим, почему использование беспарольного подхода с Open ID Connect (OIDC) является гораздо лучшим вариантом.

2. Создайте секрет GitHub Actions Secret

Далее создайте GitHub Secret на вашем репозитории GitHub, используя скопированные учетные данные JSON-объекта Service Principal из предыдущего шага:

В пользовательском интерфейсе GitHub перейдите к своему репозиторию и выберите ‘Settings’ -> ‘Secrets’ -> ‘Actions’:

Выберите New repository secret, чтобы добавить следующие секреты:

Секрет Значение
AZURE_CREDENTIALS Весь вывод JSON с шага создания принципала службы

3. Аутентификация рабочих процессов GitHub Actions в Azure

Теперь, когда у нас есть секрет GitHub под названием 'AZURE_CREDENTIALS', который содержит наши учетные данные принципала службы Azure, мы можем использовать этот секрет в наших рабочих процессах для аутентификации и входа в Azure.

Вот пример рабочего процесса, который будет аутентифицироваться в Azure и показывать все группы ресурсов в подписке как часть выполнения рабочего процесса: authenticate-azure.yml.

name: Authenticate Azure
on:
  workflow_dispatch:
  pull_request:
    branches:
      - master

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repository
        uses: actions/checkout@v2

      - name: 'Log into Azure using github secret AZURE_CREDENTIALS'
        uses: Azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
          enable-AzPSSession: true

      - name: 'Run az commands'
        run: |
          az account show
          az group list
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание на шаг GitHub Actions, который мы используем для входа в Azure:

- name: 'Log into Azure using github secret AZURE_CREDENTIALS'
uses: Azure/login@v1
with:
    creds: ${{ secrets.AZURE_CREDENTIALS }}
    enable-AzPSSession: true
Войти в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: Шаг 'Run az commands' отобразит учетную запись Azure, а также список всех групп ресурсов.

Метод 2 — Open ID Connect(OIDC) (современный)

В этом разделе мы рассмотрим новый, более современный способ подключения GitHub Actions к Azure, при котором не нужны секреты клиента.

Мы будем использовать федеративные учетные данные с Open ID connect (OIDC). Одним из основных преимуществ использования OIDC является отсутствие паролей или клиентских секретов для управления или поддержки, а также использование подхода 'identity', основанного на аутентификации.

1. Создание принципала службы

Как и раньше, нам потребуется AAD App и Service Principal.

Вы можете использовать следующий сценарий PowerShell; ‘Create-SP-OIDC.ps1’ для создания Azure AD App & Service Principal с федеративными учетными данными GitHub Action.

### Create-SP-OIDC.ps1 ###
# Log into Azure
Az login

# Show current subscription (use 'Az account set' to change subscription)
Az account show

# variables
$subscriptionId = $(az account show --query id -o tsv)
$appName = "GitHub-projectName-Actions-OIDC"
$RBACRole = "Contributor"

$githubOrgName = "Pwd9000-ML"
$githubRepoName = "RandomStuff"
$githubBranch = "master"

# Create AAD App and Principal
$appId = $(az ad app create --display-name $appName --query appId -o tsv)
az ad sp create --id $appId

# Create federated GitHub credentials (Entity type 'Branch')
$githubBranchConfig = [PSCustomObject]@{
    name        = "GH-[$githubOrgName-$githubRepoName]-Branch-[$githubBranch]"
    issuer      = "https://token.actions.githubusercontent.com/"
    subject     = "repo:" + "$githubOrgName/$githubRepoName" + ":ref:refs/heads/$githubBranch"
    description = "Federated credential linked to GitHub [$githubBranch] branch @: [$githubOrgName/$githubRepoName]"
    audiences   = @("api://AzureADTokenExchange")
}
$githubBranchConfigJson = $githubBranchConfig | ConvertTo-Json
$githubBranchConfigJson | az ad app federated-credential create --id $appId --parameters "@-"

# Create federated GitHub credentials (Entity type 'Pull Request')
$githubPRConfig = [PSCustomObject]@{
    name        = "GH-[$githubOrgName-$githubRepoName]-PR"
    issuer      = "https://token.actions.githubusercontent.com/"
    subject     = "repo:" + "$githubOrgName/$githubRepoName" + ":pull_request"
    description = "Federated credential linked to GitHub Pull Requests @: [$githubOrgName/$githubRepoName]"
    audiences   = @("api://AzureADTokenExchange")
}
$githubPRConfigJson = $githubPRConfig | ConvertTo-Json
$githubPRConfigJson | az ad app federated-credential create --id $appId --parameters "@-"

### Additional federated GitHub credential entity types are 'Tag' and 'Environment' (see: https://docs.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azcli#github-actions-example) ###

# Assign RBAC permissions to Service Principal (Change as necessary)
$appId | foreach-object {

    # Permission 1 (Example)
    az role assignment create `
        --role $RBACRole `
        --assignee $_ `
        --subscription $subscriptionId

    # Permission 2 (Example)
    #az role assignment create `
    #    --role "Reader and Data Access" `
    #    --assignee "$_" `
    #    --scope "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Storage/storageAccounts/$storageName"
}
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что сценарий создает федеративные учетные данные GitHub Action на приложении AAD, вы можете просмотреть их или добавить новые, перейдя к ‘App registrations’ в ‘Azure Active Directory (AAD)’ и найдя приложение, которое мы только что создали.

Обратите внимание, что в приложении AAD нет секретов клиента.

Вместо этого сценарий создал два федеративных учетных данных GitHub Action, один с типом сущности 'Branch', связанный с моим репозиторием 'master; branch, и один с типом сущности 'pull request', связанный с моим репозиторием для любых действий, вызванных ‘Pull Request (PR)’.

Вы можете добавить больше, нажав на '+ Add credential'.

Выберите 'GitHub Actions deploying Azure resources' для сценария федеративных учетных данных.

Существует четыре типа сущностей для федеративных учетных данных действий Github. Это 'Environment', 'Branch', 'Pull Request' и 'Tag'.

В зависимости от того, какой тип сущности вы выбрали, будет автоматически создан 'Идентификатор субъекта', это значение используется для установления связи между рабочим процессом GitHub Actions и Azure Active Directory. Значение генерируется на основе введенных данных GitHub.

Когда рабочий процесс GitHub Actions запрашивает у платформы идентификации Microsoft обмен маркера GitHub на маркер доступа, значения в удостоверении федеративной идентификации сверяются с предоставленным маркером GitHub. Прежде чем Azure предоставит маркер доступа, запрос должен соответствовать условиям, определенным в 'Идентификатор субъекта'.

  • Для заданий, привязанных к окружению, используйте: repo:<Organization/Repository>:environment:<Name>.
  • Для заданий, не привязанных к окружению, включите ссылочный путь ветки/тега на основе ссылочного пути, используемого для запуска рабочего процесса: repo:<Organization/Repository>:ref:<ref path>. Например, repo:myOrg/myRepo:ref:refs/heads/myBranch или repo:myOrg/myRepo:ref:refs/tags/myTag.
  • Для рабочих процессов, запускаемых событием запроса на вытягивание, используйте: repo:<Organization/Repository>:pull-request.

Больше примеров вы можете посмотреть в официальной документации Microsoft.

Возьмите 'CLIENT_ID' приложения AAD, поскольку он понадобится нам в следующем шаге.

2. Создайте секреты действий GitHub

Далее создайте следующие секреты GitHub на вашем репозитории GitHub.

В пользовательском интерфейсе GitHub перейдите к вашему репозиторию и выберите ‘Settings’ -> ‘Secrets’ -> ‘Actions’:

Выберите New repository secret, чтобы добавить следующие секреты:

Секрет Значение
AZURE_CLIENT_ID Идентификатор приложения AAD (клиента), созданный в предыдущем шаге
AZURE_TENANT_ID Идентификатор каталога Azure (арендатор)
AZURE_SUBSCRIPTION_ID Идентификатор подписки Azure

ПРИМЕЧАНИЕ: Пароль/секрет не требуется.

3. Аутентификация рабочих процессов GitHub Actions в Azure (OIDC)

Теперь, когда у вас настроены федеративные учетные данные и секреты GitHub, вы можете настроить свои рабочие процессы на использование токенов OIDC для аутентификации и входа в Azure.

Чтобы обновить рабочие процессы для OIDC, вам нужно внести два изменения в YAML:

  • Добавить параметр permissions с id-token: write для токена.
  • Используйте действие azure/login для обмена токена OIDC (JWT) на токен доступа к облаку.

Вот пример рабочего процесса, который выполнит аутентификацию в Azure и покажет все группы ресурсов в подписке как часть выполнения рабочего процесса: authenticate-azure-oidc.yml.

name: Run Azure Login with OIDC
on:
  workflow_dispatch:
  pull_request:
    branches:
      - master

permissions:
  id-token: write
  contents: read

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: 'Az CLI login using OIDC'
        uses: azure/login@v1
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: 'Run az commands'
        run: |
          az account show
          az group list
Вход в полноэкранный режим Выход из полноэкранного режима

ПРИМЕЧАНИЕ: Шаг 'Run az commands' отобразит учетную запись Azure, а также список всех групп ресурсов.

Обратите внимание на шаг GitHub Actions, который мы используем для входа в Azure:

- name: 'Az CLI login'
uses: azure/login@v1
with:
    client-id: ${{ secrets.AZURE_CLIENT_ID }}
    tenant-id: ${{ secrets.AZURE_TENANT_ID }}
    subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
Войти в полноэкранный режим Выйти из полноэкранного режима

Также обратите внимание, что 'permissions' на рабочем процессе использует 'id-token: write'. Вы не сможете запросить идентификационный токен OIDC JWT, если в настройках разрешений для id-token установлено значение 'read' или 'none'.

permissions:
  id-token: write
  contents: read
Вход в полноэкранный режим Выход из полноэкранного режима

Если вам нужно получить токен OIDC только для одного задания, то это разрешение также может быть установлено внутри задания. Например:

jobs:
  job1:
    runs-on: ubuntu-latest

    permissions:
      id-token: write

    steps:
      - uses: actions/stale@v5
Войти в полноэкранный режим Выйти из полноэкранного режима

Заключение

Как вы можете видеть, довольно просто настроить аутентификацию между вашими GitHub Actions и Azure. Я бы настоятельно рекомендовал использовать более новый метод Open ID Connect (OIDC), если вы еще не используете его, поскольку это намного удобнее, чем вручную управлять и поддерживать пароли/секреты принципалов служб Azure и секреты GitHub.

OIDC — это лучший вариант безопасности, поскольку это метод аутентификации без пароля, основанный на идентификации, который не требует частой ротации или истечения срока действия паролей/секретов принципалов служб Azure.

Надеюсь, вам понравилась эта статья и вы узнали что-то новое. Вы также можете найти примеры кода, использованные в этой статье, на моей опубликованной странице GitHub. ❤️

Автор

Ставьте лайк, делитесь, следуйте за мной на: 🐙 GitHub | 🐧 Twitter | 👾 LinkedIn

Marcel.L

Microsoft DevOps MVP | Cloud Solutions & DevOps Architect | Технический спикер, специализирующийся на технологиях Microsoft, IaC и автоматизации в Azure. Найдите меня на GitHub: https://github.com/Pwd9000-ML

Оцените статью
devanswers.ru
Добавить комментарий