Аутентификация с использованием Azure CLI поддерживается только для пользователя (а не для субъекта-службы)

Я настраиваю конвейер CI/CD через Azure DevOps для тестирования моего кода Terraform. Моя организация планирует перейти на CI/CD для нашей инфраструктуры. Я пытаюсь проверить Terraform в своем клиенте Azure через подключение к службе в конвейере YAML:

name: Azure Infrastructure CI/CD

trigger:
  branches:
    include:
      - main

pool:
  vmImage: ubuntu-latest

variables:
  - name: public_key
    value: $(public_key)
  - name: terraformSecret
    value: $(client_secret)

steps:
  - checkout: self
    submodules: true

  - task: TerraformInstaller@0
    inputs:
      terraformVersion: 'latest'

  - script: az login --service-principal -u "$(client_id)" -p $(client_secret) --tenant "$(tenant_id)"
    displayName: 'Azure CLI Login'

  - script: az account set --subscription "$(subscription_id)"
    displayName: 'Azure Subscription Set'
  
  - script: |
      terraform init
      terraform plan -out=tfplan \
        -var = "public_key=${public_key}" \
        -var = "client_secret=${terraformSecret}"
    displayName: 'Terraform Init and Plan'
    workingDirectory: .

  - script: |
      terraform apply -auto-approve tfplan
    displayName: 'Terraform Apply'
    workingDirectory: .

Вот мой файл провайдера Terraform:

provider "azurerm" {
    features {}

    client_id       = "xxxxx"
    client_secret   = var.client_secret
    tenant_id       = "xxxxx"
    subscription_id = "xxxxx"
}

И выдержка из моего файла переменных Terraform:

variable "client_secret" {
  type        = string
}

И у меня правильно установлены все переменные среды в конвейере Azure DevOps. Я получаю эту ошибку:

Planning failed. Terraform encountered an error while generating this plan.

╷
│ Error: building AzureRM Client: Authenticating using the Azure CLI is only supported as a User (not a Service Principal).
│ 
│ To authenticate to Azure using a Service Principal, you can use the separate 'Authenticate using a Service Principal'
│ auth method - instructions for which can be found here: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret
│ 
│ Alternatively you can authenticate using the Azure CLI by using a User Account.
│ 
│   with provider["registry.terraform.io/hashicorp/azurerm"],
│   on providers.tf line 10, in provider "azurerm":
│   10: provider "azurerm" {
│ 
╵

##[error]Bash exited with code '1'.

Я проверил документацию Terraform, и они не показывают, как я могу аутентифицировать соединение terraform с помощью сценария, и я хочу максимально защитить секрет клиента, а не сделать его доступным для всех, кто обращается к этому коду. Я также использовал несколько курсов LLM, и эта информация оказалась минимально полезной, как и в большинстве проектов, связанных с terraform.

Как мне аутентифицировать свой код terraform через субъект-службу в конвейере YAML?

Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
Как установить LAMP Stack 1/2 на Azure Linux VM
Как установить LAMP Stack 1/2 на Azure Linux VM
В дополнение к нашему предыдущему сообщению о намерении Azure прекратить поддержку Azure Database для MySQL в качестве единого сервера после 16...
0
0
166
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Согласно Настройка участника службы в Terraform , вы можете использовать переменные среды для аутентификации у поставщика Azurerm:

export ARM_CLIENT_ID = "00000000-0000-0000-0000-000000000000"
export ARM_CLIENT_SECRET = "12345678-0000-0000-0000-000000000000"
export ARM_TENANT_ID = "10000000-0000-0000-0000-000000000000"
export ARM_SUBSCRIPTION_ID = "20000000-0000-0000-0000-000000000000"

В конвейере Azure вы можете установить эти переменные среды на уровне задачи для всех задач, которые запускают команды terraform, такие как init, plan и apply — пример:

  - script: |
      terraform ...
    displayName: 'Run Terraform command'
    workingDirectory: .
    env:
      ARM_CLIENT_ID: $(my_client_id)
      ARM_CLIENT_SECRET: $(my_client_secret)
      ARM_SUBSCRIPTION_ID: $(my_subscription_id)
      ARM_TENANT_ID: $(my_tenant_id)

Касательно:

Я хочу максимально защитить секрет клиента и не делать его доступным для всех, кто имеет доступ к этому коду.

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

В качестве альтернативы используйте подключение к службе Azure Resource Manager с задачей Azure CLI v2 или задачами Terraform Azure Pipelines , как указано в ответе Шамрая.

Решение помогло, спасибо за совет!

Gabe Dillin 27.06.2024 06:08

Вы можете:

Используя ваш образец, я могу воспроизвести ту же ошибку.

Это потому, что вы использовали incorrect variable syntax ${var} в команде terraform plan, правильный формат — $(var).

Пожалуйста, исправьте это, как показано нижеL

  - script: |
      terraform init
      terraform plan -out=tfplan \
        -var = "public_key=$(public_key)" \
        -var = "client_secret=$(terraformSecret)"
    displayName: 'Terraform Init and Plan'
    workingDirectory: .

Тогда задача будет выполнена:

Другие вопросы по теме