Terraform:构建 ARM Config 时出错 - 仅支持使用 Azure CLI 进行身份验证
Terraform: Error building ARM Config - Authenticating using the Azure CLI is only supported
由于 terraform azurerm 提供程序缺少对 azure webapp 访问限制的支持 (see github issue)。我们使用 null_resource
和 local-exec
来应用访问限制:
provisioner "local-exec" {
command = <<COMMAND
az webapp config access-restriction add --subscription ${self.triggers.subscription_id} --resource-group ${self.triggers.resource_group} \
--name ${self.triggers.web_app_name} --rule-name 'allow application gateway' --action Allow --vnet-name ${self.triggers.vnet_name} \
--subnet ${self.triggers.subnet_name} --priority 100
COMMAND
}
我们的 terraform 代码随后由 azure DevOps 管道 运行 执行,该管道使用服务连接(带有服务主体)向 Azure 进行身份验证。以下任务正在尝试应用 terraform 资源:
- task: TerraformCLI@0
displayName: "Terraform apply"
inputs:
command: 'apply'
commandOptions: '--var-file="./environments/${{ parameters.environment }}.tfvars"'
workingDirectory: '$(System.DefaultWorkingDirectory)/${{ parameters.projectFolder }}'
environmentServiceName: 'shared-${{ parameters.environment }}-001'
这会导致以下错误:
Error: Error running command ' az webapp config access-restriction remove --subscription shared-staging-001 --resource-group rg-hub-network-staging \
--name landing-webapp-hub --rule-name 'allow application gateway'
': exit status 1. Output: Subscription 'shared-staging-001' not recognized.
Command group 'webapp config access-restriction' is in preview. It may be changed/removed in a future release.
Please run 'az login' to setup account.
不,我们尝试用普通 bash 脚本或 AzureCLI@2 任务替换 TerraformCLI@0 任务。
由于缺少信息,我们无法让 az login 在普通 bash 脚本中工作。 here 描述的方法也不起作用。
运行 AzureCLI@2 任务中的 terraform 命令看起来很有希望,但会导致一些与服务主体登录相关的奇怪错误:
- task: AzureCLI@2
displayName: "Terraform init"
inputs:
azureSubscription: shared-${{ parameters.environment }}-001
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
terraform init --backend-config="./environments/${{ parameters.environment }}_backend.tfvars"
这会导致以下错误:
Initializing modules...
- app-gateway in modules/app-gateway
- dummy1 in modules/BRZ365-AppService
- dummy2 in modules/BRZ365-AppService
- hub-network in modules/hub-network
- landing_zone_app in modules/BRZ365-AppService
- squad-area in modules/squad-area
Initializing the backend...
Error: Error building ARM Config: 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:
Alternatively you can authenticate using the Azure CLI by using a User Account.
我用 local-exec
解决了这个问题。
provisioner "local-exec" {
command = <<COMMAND
az login --service-principal --username #{APP_ID}# --password #{SP_PASSWORD}# --tenant #{TENANT_ID}#
az webapp config access-restriction add --resource-group ${azurerm_resource_group.example.name} --name ${azurerm_app_service.example.name} --rule-name developers --action Allow --ip-address 130.220.0.0/27 --priority 200
COMMAND
interpreter = ["PowerShell", "-Command"]
}
不幸的是,我不得不为此创建另一个服务主体,因为我不想重置 Azure DevOps 使用的服务主体(但您可以尝试并重用这个)。
我使用了这些命令:
az ad sp create-for-rbac --name sp-for-cli
az role assignment create --assignee APP_ID --role Contributor
接下来,我在我的发布管道上声明了变量 APP_ID、SP_PASSWORD 和 TENANT_ID,其值由上面的命令给出。
作为最后一步,我添加了 token replace step:
steps:
- task: qetza.replacetokens.replacetokens-task.replacetokens@3
displayName: 'Replace tokens in main.tf'
inputs:
rootDirectory: '$(System.DefaultWorkingDirectory)/terraform/drop'
targetFiles: main.tf
现在当我 运行 az webapp config access-restriction show --resource-group example-resources --name example-app-service-for-cli
我得到:
"ipSecurityRestrictions": [
{
"action": "Allow",
"additional_properties": {},
"description": null,
"ip_address": "130.220.0.0/27",
"name": "developers",
"priority": 200,
"subnet_mask": null,
"subnet_traffic_tag": null,
"tag": "Default",
"vnet_subnet_resource_id": null,
"vnet_traffic_tag": null
},
您可以找到完整的代码 here。
我终于将它与我在第一个 post 中描述的 AzureCLI 方法一起使用。我使用 addSpnToEnvironment
(它将服务提供商凭证添加到环境中,如 the documentation) and set the required parameters as described by terraform 中所述。
- task: AzureCLI@2
displayName: "Terraform"
inputs:
azureSubscription: shared-${{ parameters.environment }}-001
scriptType: bash
addSpnToEnvironment: true
scriptLocation: inlineScript
inlineScript: |
export ARM_CLIENT_ID=$servicePrincipalId
export ARM_CLIENT_SECRET=$servicePrincipalKey
export ARM_TENANT_ID=$tenantId
terraform init .....
我在使用 Terraform 在 Azure 上设置资源时遇到了类似的问题。
当我 运行 terraform 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 main.tf line 18, in provider "azurerm":
│ 18: provider "azurerm" {
我是这样解决的:
问题是我以错误的方式使用 Terraform 对 Azure CLI 进行了身份验证。我使用下面的命令通过服务主体对其进行身份验证:
az login --service-principal --username $SERVICE_PRINCIPAL_APP_ID --password $SERVICE_PRINCIPAL_PASSWORD --tenant $SERVICE_PRINCIPAL_TENANT_ID
问题是上面的命令不会将您作为用户进行身份验证,而是作为服务主体进行身份验证,这不是 Terraform 使用服务主体进行身份验证的受支持方式。
[
{
"cloudName": "AzureCloud",
"homeTenantId": "f8256ac9-e164-4ac6-a487-0f6e3dc17532",
"id": "bec123cd-bead-43ba-90c6-5235cririe903",
"isDefault": true,
"managedByTenants": [],
"name": "my-subscription-1",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "r673reb62-bbf7-40e1-ab10-ry45640484",
"type": "servicePrincipal"
}
}
]
正确的方法是简单地运行下面的命令:
az login
然后 Azure CLI 将打开一个浏览器 window,我将在其中登录到我在门户上的 Azure 帐户并以用户身份进行身份验证。如果您有多个订阅,它将select您当前登录的订阅作为您的默认订阅。
[
{
"cloudName": "AzureCloud",
"homeTenantId": "f8256ac9-e164-4ac6-a487-0f6e3dc17532",
"id": "bec123cd-bead-43ba-90c6-5235cririe903",
"isDefault": true,
"managedByTenants": [],
"name": "my-subscription-1",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "john.doe@my-domain.com",
"type": "user"
}
},
{
"cloudName": "AzureCloud",
"homeTenantId": "ghfjg6ac9-e164-7466-a487-0f6e3dc17hjr",
"id": "rtkrt7f3d-51b2-7587-88b7-d29ftheruofw",
"isDefault": false,
"managedByTenants": [],
"name": "my-subscription-2",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "john.doe@my-domain.com",
"type": "user"
}
}
]
OR 如果您希望以服务主体身份进行身份验证,那么您将使用提供的变量名称导出以下变量:
export ARM_CLIENT_ID="your-service-principal-appid"
export ARM_CLIENT_SECRET="your-service-principal-password"
export ARM_SUBSCRIPTION_ID="your-current-subscription-id"
export ARM_TENANT_ID="your-tenant-id"
现在,您可以 运行 您的 terraform plan
一切都会正常进行。
资源:Configuring the Service Principal in Terraform
就这些了
由于 terraform azurerm 提供程序缺少对 azure webapp 访问限制的支持 (see github issue)。我们使用 null_resource
和 local-exec
来应用访问限制:
provisioner "local-exec" {
command = <<COMMAND
az webapp config access-restriction add --subscription ${self.triggers.subscription_id} --resource-group ${self.triggers.resource_group} \
--name ${self.triggers.web_app_name} --rule-name 'allow application gateway' --action Allow --vnet-name ${self.triggers.vnet_name} \
--subnet ${self.triggers.subnet_name} --priority 100
COMMAND
}
我们的 terraform 代码随后由 azure DevOps 管道 运行 执行,该管道使用服务连接(带有服务主体)向 Azure 进行身份验证。以下任务正在尝试应用 terraform 资源:
- task: TerraformCLI@0
displayName: "Terraform apply"
inputs:
command: 'apply'
commandOptions: '--var-file="./environments/${{ parameters.environment }}.tfvars"'
workingDirectory: '$(System.DefaultWorkingDirectory)/${{ parameters.projectFolder }}'
environmentServiceName: 'shared-${{ parameters.environment }}-001'
这会导致以下错误:
Error: Error running command ' az webapp config access-restriction remove --subscription shared-staging-001 --resource-group rg-hub-network-staging \
--name landing-webapp-hub --rule-name 'allow application gateway'
': exit status 1. Output: Subscription 'shared-staging-001' not recognized.
Command group 'webapp config access-restriction' is in preview. It may be changed/removed in a future release.
Please run 'az login' to setup account.
不,我们尝试用普通 bash 脚本或 AzureCLI@2 任务替换 TerraformCLI@0 任务。
由于缺少信息,我们无法让 az login 在普通 bash 脚本中工作。 here 描述的方法也不起作用。
运行 AzureCLI@2 任务中的 terraform 命令看起来很有希望,但会导致一些与服务主体登录相关的奇怪错误:
- task: AzureCLI@2
displayName: "Terraform init"
inputs:
azureSubscription: shared-${{ parameters.environment }}-001
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
terraform init --backend-config="./environments/${{ parameters.environment }}_backend.tfvars"
这会导致以下错误:
Initializing modules...
- app-gateway in modules/app-gateway
- dummy1 in modules/BRZ365-AppService
- dummy2 in modules/BRZ365-AppService
- hub-network in modules/hub-network
- landing_zone_app in modules/BRZ365-AppService
- squad-area in modules/squad-area
Initializing the backend...
Error: Error building ARM Config: 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:
Alternatively you can authenticate using the Azure CLI by using a User Account.
我用 local-exec
解决了这个问题。
provisioner "local-exec" {
command = <<COMMAND
az login --service-principal --username #{APP_ID}# --password #{SP_PASSWORD}# --tenant #{TENANT_ID}#
az webapp config access-restriction add --resource-group ${azurerm_resource_group.example.name} --name ${azurerm_app_service.example.name} --rule-name developers --action Allow --ip-address 130.220.0.0/27 --priority 200
COMMAND
interpreter = ["PowerShell", "-Command"]
}
不幸的是,我不得不为此创建另一个服务主体,因为我不想重置 Azure DevOps 使用的服务主体(但您可以尝试并重用这个)。
我使用了这些命令:
az ad sp create-for-rbac --name sp-for-cli
az role assignment create --assignee APP_ID --role Contributor
接下来,我在我的发布管道上声明了变量 APP_ID、SP_PASSWORD 和 TENANT_ID,其值由上面的命令给出。
作为最后一步,我添加了 token replace step:
steps:
- task: qetza.replacetokens.replacetokens-task.replacetokens@3
displayName: 'Replace tokens in main.tf'
inputs:
rootDirectory: '$(System.DefaultWorkingDirectory)/terraform/drop'
targetFiles: main.tf
现在当我 运行 az webapp config access-restriction show --resource-group example-resources --name example-app-service-for-cli
我得到:
"ipSecurityRestrictions": [
{
"action": "Allow",
"additional_properties": {},
"description": null,
"ip_address": "130.220.0.0/27",
"name": "developers",
"priority": 200,
"subnet_mask": null,
"subnet_traffic_tag": null,
"tag": "Default",
"vnet_subnet_resource_id": null,
"vnet_traffic_tag": null
},
您可以找到完整的代码 here。
我终于将它与我在第一个 post 中描述的 AzureCLI 方法一起使用。我使用 addSpnToEnvironment
(它将服务提供商凭证添加到环境中,如 the documentation) and set the required parameters as described by terraform 中所述。
- task: AzureCLI@2
displayName: "Terraform"
inputs:
azureSubscription: shared-${{ parameters.environment }}-001
scriptType: bash
addSpnToEnvironment: true
scriptLocation: inlineScript
inlineScript: |
export ARM_CLIENT_ID=$servicePrincipalId
export ARM_CLIENT_SECRET=$servicePrincipalKey
export ARM_TENANT_ID=$tenantId
terraform init .....
我在使用 Terraform 在 Azure 上设置资源时遇到了类似的问题。
当我 运行 terraform 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 main.tf line 18, in provider "azurerm":
│ 18: provider "azurerm" {
我是这样解决的:
问题是我以错误的方式使用 Terraform 对 Azure CLI 进行了身份验证。我使用下面的命令通过服务主体对其进行身份验证:
az login --service-principal --username $SERVICE_PRINCIPAL_APP_ID --password $SERVICE_PRINCIPAL_PASSWORD --tenant $SERVICE_PRINCIPAL_TENANT_ID
问题是上面的命令不会将您作为用户进行身份验证,而是作为服务主体进行身份验证,这不是 Terraform 使用服务主体进行身份验证的受支持方式。
[
{
"cloudName": "AzureCloud",
"homeTenantId": "f8256ac9-e164-4ac6-a487-0f6e3dc17532",
"id": "bec123cd-bead-43ba-90c6-5235cririe903",
"isDefault": true,
"managedByTenants": [],
"name": "my-subscription-1",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "r673reb62-bbf7-40e1-ab10-ry45640484",
"type": "servicePrincipal"
}
}
]
正确的方法是简单地运行下面的命令:
az login
然后 Azure CLI 将打开一个浏览器 window,我将在其中登录到我在门户上的 Azure 帐户并以用户身份进行身份验证。如果您有多个订阅,它将select您当前登录的订阅作为您的默认订阅。
[
{
"cloudName": "AzureCloud",
"homeTenantId": "f8256ac9-e164-4ac6-a487-0f6e3dc17532",
"id": "bec123cd-bead-43ba-90c6-5235cririe903",
"isDefault": true,
"managedByTenants": [],
"name": "my-subscription-1",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "john.doe@my-domain.com",
"type": "user"
}
},
{
"cloudName": "AzureCloud",
"homeTenantId": "ghfjg6ac9-e164-7466-a487-0f6e3dc17hjr",
"id": "rtkrt7f3d-51b2-7587-88b7-d29ftheruofw",
"isDefault": false,
"managedByTenants": [],
"name": "my-subscription-2",
"state": "Enabled",
"tenantId": "f8556ac9-e159-4ac6-a487-8r9erhwjw",
"user": {
"name": "john.doe@my-domain.com",
"type": "user"
}
}
]
OR 如果您希望以服务主体身份进行身份验证,那么您将使用提供的变量名称导出以下变量:
export ARM_CLIENT_ID="your-service-principal-appid"
export ARM_CLIENT_SECRET="your-service-principal-password"
export ARM_SUBSCRIPTION_ID="your-current-subscription-id"
export ARM_TENANT_ID="your-tenant-id"
现在,您可以 运行 您的 terraform plan
一切都会正常进行。
资源:Configuring the Service Principal in Terraform
就这些了