You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需全局管理员角色部署azuread_claims_mapping_policy?

问题:Terraform部署azuread_claims_mapping_policy权限不足,寻求无需全局管理员角色的解决方案

我尝试通过Terraform部署azuread_claims_mapping_policy,但因权限不足失败,错误信息如下:

│ Error: retrieving Claims Mapping Policy with object ID: "<GUID HERE>"
│ 
│   with azuread_claims_mapping_policy.integration_claims_mapping[0],
│   on active_directory.tf line 54, in resource "azuread_claims_mapping_policy" "integration_claims_mapping":
│   54: resource "azuread_claims_mapping_policy" "integration_claims_mapping" {
│ 
│ ClaimsMappingPolicyClient.BaseClient.Get(): unexpected status 403 with
│ OData error: Authorization_RequestDenied: Insufficient privileges to
│ complete the operation.

代码通过托管标识执行。根据Terraform AzureAD提供商文档:

使用服务主体认证时,该资源需要以下应用角色:Policy.ReadWrite.ApplicationConfiguration和Policy.Read.All
使用用户主体认证时,该资源需要以下目录角色之一:应用管理员或全局管理员

我已为该托管标识添加Application Administrator目录角色,但仍出现上述错误;使用Global Administrator角色可成功执行,但希望避免使用该高权限角色。请问是否存在无需全局管理员角色即可部署azuread_claims_mapping_policy的方法?

以下是我使用的代码:

locals {
  entity_ids = {
    "dev" : ["entity-id"],
  }

  redirect_uris = {
    "dev" : ["redirect-uri"],
  }
}

data "azuread_client_config" "current" {}

resource "azuread_application" "saml_integration" {
  count           = var.env == "prod" ? 0 : 1
  display_name    = "SAML integration - ${upper(var.env)}"
  owners          = [data.azuread_client_config.current.object_id]
  identifier_uris = local.entity_ids[var.env]

  web {
    redirect_uris = local.redirect_uris[var.env]
  }

  feature_tags {
    enterprise            = true
    gallery               = false
    custom_single_sign_on = true
  }

  app_role {
    allowed_member_types = ["Application", "User"]
    description          = "Default role for standard users used for SAML integration"
    display_name         = "IntegrationUser"
    enabled              = true
    id                   = "GUID HERE"
    value                = "IntegrationUser"
  }
}

resource "azuread_service_principal" "saml_integration_service_principal" {
  count                        = var.env == "prod" ? 0 : 1
  application_id               = azuread_application.saml_integration[0].application_id
  app_role_assignment_required = false
  owners                       = [data.azuread_client_config.current.object_id]

  use_existing                  = true
  preferred_single_sign_on_mode = "saml"

  feature_tags {
    enterprise            = true
    gallery               = false
    custom_single_sign_on = true
  }
}

resource "azuread_service_principal_token_signing_certificate" "signing_certificate" {
  service_principal_id = azuread_service_principal.saml_integration_service_principal[0].id
}

resource "azuread_service_principal_claims_mapping_policy_assignment" "app" {
  count                    = var.env == "prod" ? 0 : 1
  claims_mapping_policy_id = azuread_claims_mapping_policy.integration_claims_mapping[0].id
  service_principal_id     = azuread_service_principal.saml_integration_service_principal[0].id
}

resource "azuread_claims_mapping_policy" "integration_claims_mapping" {
  count        = var.env == "prod" ? 0 : 1
  display_name = "Claims Mapping for ${azuread_application.saml_integration[0].display_name}"
  definition = [
    jsonencode(
      {
        ... hidden
    )
  ]
}

resource "azuread_user" "test_user" {
  count               = var.env == "prod" ? 0 : 1
  user_principal_name = "test-saml-user-${var.env}@contoso.com"
  mail                = "test-saml-user-${var.env}@contoso.com"
  display_name        = "Test Contoso SSO User ${var.env}"
  given_name = "Test"
  surname = "User ${upper(var.env)}"
  password            = "SUBERPASSWORD"
}

resource "azuread_group" "test_app_users_group" {
  count            = var.env == "prod" ? 0 : 1
  display_name     = "Test SAML integration - ${upper(var.env)}"
  owners           = [data.azuread_client_config.current.object_id]
  security_enabled = true
  members = [
    azuread_user.test_user[0].object_id
  ]
}

resource "azuread_app_role_assignment" "test_user_group_assignment" {
  app_role_id         = azuread_service_principal.saml_integration_service_principal[0].app_role_ids["IntegrationUser"]
  principal_object_id = azuread_group.test_app_users_group[0].object_id
  resource_object_id  = azuread_service_principal.saml_integration_service_principal[0].object_id
}

注:部分敏感值已隐藏。


解决方案

可以通过以下方式实现无需全局管理员角色部署azuread_claims_mapping_policy:

1. 为托管标识分配正确的应用角色而非目录角色

你之前添加的Application Administrator是目录角色,但根据文档,服务主体(托管标识属于服务主体)认证时需要的是Microsoft Graph应用角色。需要给托管标识分配以下两个应用权限:

  • Policy.ReadWrite.ApplicationConfiguration
  • Policy.Read.All

操作步骤:

  1. 进入Azure AD门户,找到目标托管标识(企业应用程序 -> 所有应用程序 -> 搜索托管标识名称)
  2. 切换到「权限」选项卡,点击「添加权限」
  3. 选择「Microsoft Graph」->「应用权限」
  4. 搜索并勾选上述两个权限,点击「添加权限」
  5. 点击「授予管理员同意」完成权限配置

2. 确认托管标识的应用所有者身份生效

你的Terraform代码中已将托管标识设置为应用的所有者(owners = [data.azuread_client_config.current.object_id]),需确认该配置已正确生效。应用所有者身份结合上述应用角色权限,即可满足部署需求。

额外排查点

  • 权限授予后需等待数分钟让配置生效,避免立即执行Terraform
  • 确认Terraform使用的托管标识与配置权限的标识一致,避免混淆不同环境的资源
  • 检查azuread_claims_mapping_policy的definition格式是否正确,排除语法错误导致的间接权限问题

内容的提问来源于stack exchange,提问作者Krzysztof Madej

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:17:19