Я настраиваю конвейер 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?
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 , как указано в ответе Шамрая.
Вы можете:
Используя ваш образец, я могу воспроизвести ту же ошибку.
Это потому, что вы использовали 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: .
Тогда задача будет выполнена:
Решение помогло, спасибо за совет!