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

能否通过Azure DevOps管道服务连接实现Azure AD服务主体客户端令牌自动轮换?

自动轮换Azure DevOps服务连接的Azure AD服务主体令牌方案

主流实践:Azure Key Vault + Azure Functions 自动化方案

这是社区广泛采用的可靠方案,通过云服务组合实现全流程自动轮换,无需手动干预。

前置准备

  • 创建并配置Azure Key Vault:启用软删除与 purge 保护,创建两个机密项,分别存储服务主体的客户端ID和初始的客户端密钥。
  • 配置权限:
    • 给Azure Functions分配Key Vault的Secret User权限,用于读取和更新机密。
    • 给Functions或运行身份分配Azure DevOps的Project Administrator(或集合级管理员)权限,用于更新服务连接。
    • 确保运行身份拥有Azure AD的Application Administrator权限,用于为服务主体生成新密钥。

核心实现步骤

  1. 编写Azure Functions逻辑
    采用定时器触发器(可根据令牌过期周期设置触发时间,比如过期前7天执行),核心逻辑分为三步:

    • 调用Microsoft Graph API为服务主体生成新的客户端密钥,设置合理的过期时间。
    • 将新密钥更新到Azure Key Vault的对应机密项中(支持版本化存储,便于回溯)。
    • 调用Azure DevOps REST API,定位目标服务连接,更新其授权参数中的客户端密钥。

    示例Python代码片段:

    import os
    import msal
    import requests
    from azure.keyvault.secrets import SecretClient
    from azure.identity import DefaultAzureCredential
    
    # 初始化客户端
    kv_vault_url = os.environ["KEY_VAULT_URL"]
    kv_client = SecretClient(vault_url=kv_vault_url, credential=DefaultAzureCredential())
    devops_pat = os.environ["DEVOPS_PAT"]
    tenant_id = os.environ["TENANT_ID"]
    sp_client_id = kv_client.get_secret("sp-client-id").value
    old_secret = kv_client.get_secret("sp-client-secret").value
    
    # 1. 生成新的服务主体密钥
    graph_app = msal.ConfidentialClientApplication(
        sp_client_id,
        client_credential=old_secret,
        authority=f"https://login.microsoftonline.com/{tenant_id}"
    )
    graph_token = graph_app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
    new_secret_req = requests.post(
        f"https://graph.microsoft.com/v1.0/applications/{sp_client_id}/addPassword",
        headers={"Authorization": f"Bearer {graph_token['access_token']}"},
        json={"passwordCredential": {"displayName": "Auto-Rotated-Secret", "endDateTime": "2025-12-31T23:59:59Z"}}
    )
    new_secret = new_secret_req.json()["secretText"]
    
    # 2. 更新Key Vault中的机密
    kv_client.set_secret("sp-client-secret", new_secret)
    
    # 3. 更新Azure DevOps服务连接
    devops_headers = {"Authorization": f"Basic {devops_pat}", "Content-Type": "application/json"}
    service_conn_id = os.environ["SERVICE_CONNECTION_ID"]
    devops_org = os.environ["DEVOPS_ORG"]
    devops_project = os.environ["DEVOPS_PROJECT"]
    requests.patch(
        f"https://dev.azure.com/{devops_org}/{devops_project}/_apis/serviceendpoint/endpoints/{service_conn_id}?api-version=7.1-preview.4",
        headers=devops_headers,
        json={
            "authorization": {
                "parameters": {"serviceprincipalkey": new_secret},
                "scheme": "ServicePrincipal"
            }
        }
    )
    
  2. 配置触发与监控

    • 设置定时器表达式(例如0 0 12 * * 1,每周一中午执行,根据密钥有效期调整)。
    • 启用Azure Application Insights监控Functions运行状态,配置失败警报,确保轮换异常时能及时告警。

其他可选方案

  • 直接引用Key Vault机密的服务连接:若你的服务连接类型支持,可在Azure DevOps服务连接配置中选择"使用Azure Key Vault",直接引用存储在Key Vault的服务主体密钥。后续仅需轮换Key Vault中的机密,无需更新服务连接(部分服务类型支持此方式,需提前验证兼容性)。
  • Azure Automation Runbook:逻辑与Functions类似,使用PowerShell或Python编写Runbook,通过定时器触发完成密钥轮换与服务连接更新,适合已使用Automation账户的场景。

关键注意事项

  • 保留旧密钥24小时以上,避免因系统缓存导致服务连接短暂中断。
  • 先在非生产环境测试轮换流程,验证无误后再推广到生产环境。
  • 确保服务主体和运行身份的权限最小化,遵循权限原则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:52:38