Azure DevOps Pipelines: TerraformTaskV4: инициализация с другой подпиской и Федерацией идентификаций рабочего процесса

Вопрос или проблема

У меня есть YAML-пайплайн Azure DevOps, и я хочу развернуть ресурсы с помощью Terraform в Azure. Первым шагом мне нужно выполнить terraform init. Для этого я хочу использовать TerraformTaskV4 (https://github.com/microsoft/azure-pipelines-terraform/blob/main/Tasks/TerraformTask/TerraformTaskV4/README.md):

- task: TerraformTaskV4@4
  displayName: Инициализация Terraform
  inputs:
    provider: 'azurerm'
    command: 'init'
    backendServiceArm: 'ваша-служба-подключения'
    backendAzureRmResourceGroupName: 'ваше-имя-rg'
    backendAzureRmStorageAccountName: 'ваше-имя-stg'
    backendAzureRmContainerName: 'ваше-имя-контейнера'
    backendAzureRmKey: 'state.tfstate'

Но есть две проблемы:

  1. Я хочу использовать другую подписку Azure, отличную от той, что связана со службой подключения. Служебная учётная запись службы подключения имеет доступ к нескольким подпискам
  2. Я использую службу подключения с учётной записью службы, использующей федерацию идентичности рабочего процесса

Как я могу выполнить terraform init соответствующим образом?

  1. Насколько я знаю, невозможно выбрать подписку с помощью TerraformTaskV4@4. Она всегда берёт подписку, связанную со службой подключения. Поэтому я переключился на использование AzureCLI@2 (https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/azure-cli-v2?view=azure-pipelines)
  2. На первом этапе необходимо получить доступ к учётной записи службы (через addSpnToEnvironment) в задаче AzureCLI@2 и добавить переменные окружения (https://developer.hashicorp.com/terraform/language/backend/azurerm#backend-azure-ad-service-principal-or-user-assigned-managed-identity-via-oidc-workload-identity-federation) в окружение. Это должно происходить в первой и отдельной задаче. Затем вы можете создать последующую задачу (в том же задании) для, например, terraform init

Пример:

...

- task: AzureCLI@2
  displayName: "Установить переменные окружения"
  inputs:
    azureSubscription: "${{ variables.service_connection_name }}"
    addSpnToEnvironment: true
    scriptType: pscore
    scriptLocation: inlineScript
    workingDirectory: $(System.DefaultWorkingDirectory)/terraform
    inlineScript: |
      Write-Host "##vso[task.setvariable variable=ARM_USE_OIDC]true"
      Write-Host "##vso[task.setvariable variable=ARM_OIDC_TOKEN]$env:idToken"
      Write-Host "##vso[task.setvariable variable=ARM_CLIENT_ID]$env:servicePrincipalId"
      Write-Host "##vso[task.setvariable variable=ARM_SUBSCRIPTION_ID]$(subscriptionId)"
      Write-Host "##vso[task.setvariable variable=ARM_TENANT_ID]$env:tenantId"
    
- task: TerraformInstaller@1
  displayName: Установка Terraform
  inputs:
    terraformVersion: ${{ variables.terraform_version }}

- task: AzureCLI@2
  displayName: "Terraform init"
  inputs:
    azureSubscription: "${{ variables.service_connection_name }}"
    addSpnToEnvironment: true
    scriptType: pscore
    scriptLocation: inlineScript
    workingDirectory: $(System.DefaultWorkingDirectory)/terraform
    inlineScript: |
      terraform init -backend-config="resource_group_name=$(terraformBackendResourceGroupName)" -backend-config="storage_account_name=$(terraformBackendStorageAccountName)" -backend-config="container_name=$(terraformBackendContainerName)" -backend-config="key=$(terraformBackendKey)"

...

Ответ или решение

Azure DevOps Pipelines: Инициализация Terraform с различной подпиской и федерацией идентификации рабочего процесса

При использовании Azure DevOps для развертывания ресурсов с помощью Terraform могут возникать сложности, особенно если вы хотите инициализировать Terraform с использованием другой подписки Azure, отличной от той, что указана в подключении службы. В этой статье мы подробно рассмотрим, как справиться с этой задачей, уделяя особое внимание использованию TerraformTaskV4 и AzureCLI@2, а также концепции федерации идентификации рабочего процесса.

Проблема: Инициализация Terraform с другой подпиской

Как вы правильно заметили, TerraformTaskV4 не предоставляет возможности выбора подписки, связанной с используемым подключением службы. Большинство операций происходит в контексте подписки, указанной в этом подключении. Однако можно обойти это ограничение, используя AzureCLI@2, что позволяет вручную управлять окружением и настраивать желаемое значение подписки для Terraform.

Решение: использование AzureCLI для настройки окружения

Чтобы управлять подписками и инициализировать Terraform с другими параметрами, выполните следующие шаги:

  1. Установите переменные окружения для идентификации:
    Используйте AzureCLI@2 для добавления переменных окружения с помощью команды addSpnToEnvironment. Это упростит использование идентификатора службы (Service Principal) для аутентификации Terraform.

  2. Инициализация Terraform:
    После того как окружение будет настроено, выполните команду terraform init, передав необходимые параметры для конфигурации бэкенда.

Пример конфигурации YAML для Azure DevOps Pipeline

Вот пример того, как может выглядеть ваша конфигурация YAML:

variables:
  service_connection_name: 'your-service-connection'
  terraform_version: '1.0.0'
  subscriptionId: 'your-target-subscription-id' 
  terraformBackendResourceGroupName: 'your-rg-name'
  terraformBackendStorageAccountName: 'your-stg-name'
  terraformBackendContainerName: 'your-container-name'
  terraformBackendKey: 'state.tfstate'

jobs:
- job: TerraformDeployment
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - task: AzureCLI@2
    displayName: "Настройка переменных окружения"
    inputs:
      azureSubscription: "$(service_connection_name)"
      addSpnToEnvironment: true
      scriptType: pscore
      scriptLocation: inlineScript
      workingDirectory: $(System.DefaultWorkingDirectory)/terraform
      inlineScript: |
        Write-Host "##vso[task.setvariable variable=ARM_USE_OIDC]true"
        Write-Host "##vso[task.setvariable variable=ARM_OIDC_TOKEN]$env:idToken"
        Write-Host "##vso[task.setvariable variable=ARM_CLIENT_ID]$env:servicePrincipalId"
        Write-Host "##vso[task.setvariable variable=ARM_SUBSCRIPTION_ID]$(subscriptionId)"
        Write-Host "##vso[task.setvariable variable=ARM_TENANT_ID]$env:tenantId"

  - task: TerraformInstaller@1
    displayName: Установка Terraform
    inputs:
      terraformVersion: "$(terraform_version)"

  - task: AzureCLI@2
    displayName: "Инициализация Terraform"
    inputs:
      azureSubscription: "$(service_connection_name)"
      addSpnToEnvironment: true
      scriptType: pscore
      scriptLocation: inlineScript
      workingDirectory: $(System.DefaultWorkingDirectory)/terraform
      inlineScript: |
        terraform init -backend-config="resource_group_name=$(terraformBackendResourceGroupName)" -backend-config="storage_account_name=$(terraformBackendStorageAccountName)" -backend-config="container_name=$(terraformBackendContainerName)" -backend-config="key=$(terraformBackendKey)"

Заключение

Использование Azure DevOps для работы с Terraform может быть простым и удобным, если вы правильно настроите ваше окружение и разберетесь с подключениями. Выбор AzureCLI@2 для управления переменными окружения и выбора подписки позволит вам эффективно использовать существующие сервисные подключения и упростить процесс развертывания ресурсов. Федерация идентификации рабочего процесса значительно улучшает безопасность и управление доступом для серверов, использующих идентификаторы служб. С помощью приведенного выше примера вы сможете успешно реализовать операцию инициализации Terraform, даже когда вам требуется работать с другой подпиской Azure.

Оцените материал
Добавить комментарий

Капча загружается...