在 Terraform 中引导 Azure 服务帐户

Bootstraping an Azure service account in Terraform

我正在尝试编写 Terraform 来创建 Azure“服务帐户”,但我对 Azure AD 所谓的“应用程序”和“服务主体”之间的区别感到非常困惑。实际上,我正在尝试模仿以下 Azure CLI 调用:

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${subscription_id}"

这个想法是让人类管理员 运行 Terraform,设置一次,然后这些凭据可以稍后用于对剩余的 IaC 进行身份验证。 (即,这是一个自举练习。)

我希望在 Terraform 中完成,而不是 Bash 脚本,因为它看起来更明确并且适合我的 IaC 的其余部分。这是我目前所拥有的:

data "azurerm_subscription" "current" {}

data "azuread_client_config" "current" {}

resource "azuread_application" "terraform" {
  display_name = "Terraform"
  owners       = [data.azuread_client_config.current.object_id]
}

resource "azuread_application_password" "terraform" {
  application_object_id = azuread_application.terraform.object_id
}

# resource "azuread_service_principal" "terraform" {
#   application_id = azuread_application.terraform.application_id
#   owners         = [data.azuread_client_config.current.object_id]
# }
# 
# resource "azuread_service_principal_password" "terraform" {
#   service_principal_id = azuread_service_principal.terraform.object_id
# }

resource "local_file" "azurerc" {
  filename        = ".azurerc"
  file_permission = "0600"
  content         = <<EOF
export ARM_ENVIRONMENT="public"
export ARM_SUBSCRIPTION_ID="${data.azurerm_subscription.current.subscription_id}"
export ARM_TENANT_ID="${data.azuread_client_config.current.tenant_id}"
export ARM_CLIENT_ID="${azuread_application.terraform.application_id}"
export ARM_CLIENT_SECRET="${azuread_application_password.terraform.value}"
EOF
}

这 运行s,但稍后使用生成的凭据进行身份验证会出现身份验证错误。具体来说,Terraforms 说:

If you are accessing as application please make sure service principal is properly created in the tenant.

显然我没有这样做——它在上面的代码片段中被注释掉了——但那是因为这是我的理解开始崩溃的地方。为什么我需要两者?为什么应用程序和服务主体都有密码资源?如果我为两者生成密码,哪个是 ARM_CLIENT_SECRET(我 认为 应用程序密码是正确的)?然后是角色分配:我看到有一个 azuread_app_role_assignment 资源,但我无法取消选择它。

I am trying to write the Terraform to create an Azure "service account" and am getting quite confused by the distinction between what Azure AD calls "Applications" and "Service Principals".

可以从 Azure AD 应用程序注册中看到应用程序 blade 其中服务主体也被称为企业应用程序。 Microsoft Documentation.

中详细记录了差异

This runs, but later authenticating with the generated credentials gives an authentication error. Specifically, Terraforms says:

If you are accessing as application please make sure service principal is properly created in the tenant.

这是因为您没有关联服务主体到您从 Terraform 创建的那个 azure 广告应用程序。需要关联才能访问应用程序或使用贡献者角色对 Azure 环境进行身份验证。当从门户创建应用程序注册时,它默认创建 AD 应用程序和服务主体的关联,这默认导致为该应用程序注册创建服务主体。当我们使用 az ad sp create-for-rbac.

时,它也应用相同的概念

Effectively, I'm trying to mimic the following Azure CLI call:

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/${subscription_id}"

您可以使用下面的命令模仿上面的命令:

provider "azurerm" {
    features{}
}
provider "azuread" {}
data "azurerm_subscription" "current" {}

data "azuread_client_config" "current" {}

resource "azuread_application" "terraform" {
  display_name = "Ansumantest"
  owners       = [data.azuread_client_config.current.object_id]
}

resource "azuread_application_password" "terraform" {
  application_object_id = azuread_application.terraform.object_id
}

 resource "azuread_service_principal" "terraform" {
   application_id = azuread_application.terraform.application_id
   owners         = [data.azuread_client_config.current.object_id]
 }

resource "azurerm_role_assignment" "example" {
  scope                = data.azurerm_subscription.current.id
  role_definition_name = "Contributor"
  principal_id         = azuread_service_principal.terraform.object_id
}

resource "local_file" "azurerc" {
  filename        = ".azurerc"
  file_permission = "0600"
  content         = <<EOF
export ARM_ENVIRONMENT="public"
export ARM_SUBSCRIPTION_ID="${data.azurerm_subscription.current.subscription_id}"
export ARM_TENANT_ID="${data.azuread_client_config.current.tenant_id}"
export ARM_CLIENT_ID="${azuread_application.terraform.application_id}"
export ARM_CLIENT_SECRET="${azuread_application_password.terraform.value}"
EOF
}

输出:

使用上述详细信息,我在订阅中创建了一个资源组:

provider "azurerm" {
  features{}
  subscription_id = "88073b30-cadd-459e-b90b-8442c93573ae"
  tenant_id = "ab078f81-xxxx-xxxx-xxxx-620b694ded30"
  client_id = "c022ec46-xxxx-xxxx-xxxx-c72a9b82f429"
  client_secret = "wdV7Q~8Grxxxxxxxxxxxxxx~SCwbRrKIq9"
}
 resource "azurerm_resource_group" "name" {
   name = "testansterraform"
   location = "west us 2"
 }