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

如何在Terraform中动态获取Azure DevOps默认SPN用于Key Vault变量组扩展

解决Terraform创建Azure DevOps项目时Key Vault权限问题

核心问题解答

1. 是否必须使用默认SPN?

是。Azure DevOps变量组与Key Vault的集成扩展仅支持项目自动创建的默认SPN,自定义SPN无法实现变量组自动拉取Key Vault机密的功能,这是官方设计的限制。

2. 能否通过模糊匹配获取默认SPN?

可以。利用Terraform的AzureAD数据源,通过项目名称前缀模糊匹配,再过滤出带随机UID后缀的SPN(项目会生成两个SPN,其中用于Key Vault的那个名称格式为<项目名>-<随机UID>)。

3. 处理这类默认应用注册的经验

  • 必须确保Azure DevOps项目创建完成后再查询SPN,避免因SPN未同步到AzureAD导致查询失败;
  • 必要时添加延迟等待,应对AzureAD与Azure DevOps之间的同步延迟;
  • 变量组资源需依赖Key Vault访问策略,确保权限配置完成后再创建变量组。

具体Terraform实现步骤

1. 创建Azure DevOps项目

resource "azuredevops_project" "my_project" {
  name               = "my-devops-project"
  description        = "项目描述"
  visibility         = "private"
  version_control    = "Git"
  work_item_template = "Agile"
}

2. 等待SPN同步并查询OID

由于Azure DevOps创建SPN后同步到AzureAD存在延迟,添加30秒等待:

resource "time_sleep" "wait_for_spn_sync" {
  create_duration = "30s"
  depends_on      = [azuredevops_project.my_project]
}

data "azuread_service_principals" "ado_project_spns" {
  display_name_contains = azuredevops_project.my_project.name
  depends_on            = [time_sleep.wait_for_spn_sync]
}

# 过滤出用于Key Vault的SPN(名称带随机后缀)
locals {
  keyvault_spn = [
    for spn in data.azuread_service_principals.ado_project_spns.service_principals : spn
    if length(regexall("${azuredevops_project.my_project.name}-[a-f0-9]{8,}", spn.display_name)) > 0
  ][0]
}

3. 配置Key Vault访问策略

resource "azurerm_key_vault_access_policy" "ado_spn_access" {
  key_vault_id = azurerm_key_vault.my_kv.id
  tenant_id    = data.azuread_client_config.current.tenant_id

  object_id = local.keyvault_spn.object_id

  # 变量组需要的机密权限
  secret_permissions = [
    "Get",
    "List",
  ]
}

4. 创建关联Key Vault的变量组

resource "azuredevops_variable_group" "kv_secrets" {
  name          = "KeyVaultSecrets"
  project_id    = azuredevops_project.my_project.id
  description   = "从Key Vault拉取的机密变量"
  allow_access  = true

  variable {
    name         = "DB_PASSWORD"
    is_secret    = true
    key_vault_id = azurerm_key_vault.my_kv.id
    secret_name  = "db-password"
  }

  depends_on = [azurerm_key_vault_access_policy.ado_spn_access]
}

错误原因回顾

│ Error: Expanding variable group resource data: Failed to get the Azure Key valut. Erroe: ( code: forbidden, messge: Failed to query service connection API: 'https://mykv.vault.azure.net/secrets?api-version=2016-10-01'. Status Code: 'Forbidden', Response from server: '{"error":{"code":"Forbidden","message":"The user, group or application 'appid=xxxxxxxx;oid=xxxxxxxx;iss=https://sts.windows.net//' does not have secrets list permission on key vault 'mykv;location=uksouth'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287","innererror":{"code":"AccessDenied"}}}' )

该错误是因为Azure DevOps项目创建的默认SPN未被添加到Key Vault访问策略中,导致变量组无法拉取机密。通过上述动态获取SPN OID并配置权限的方式,可避免手动提取OID重复执行apply的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:52:47