如何等待Azure AD组权限生效后再配置PostgreSQL的KeyVault加密密钥?
解决方案
问题本质
你遇到的是Azure Active Directory身份与权限的异步传播问题:当组成员关系、KeyVault访问策略创建接口返回成功时,Azure后台的权限同步还未完成,所以即使加了dependsOn依赖也无法解决,必须等待权限实际生效后再创建ServerKey资源。
最优方案:自定义权限校验等待(无需硬编码固定时长)
推荐使用Pulumi的重试机制搭配权限校验逻辑,只有实际验证通过后才继续执行后续资源创建,比固定sleep更高效稳定,可选两种实现方式:
方式1:使用pulumi_command本地执行az CLI校验(无需额外代码依赖)
只要执行Pulumi部署的环境已登录Azure CLI,就可以直接用本地命令校验权限,配合内置重试参数实现等待:
from pulumi_command import local from pulumi import ResourceOptions # 新增权限校验步骤 permission_check = local.Command( "check-postgres-keyvault-permission", # 尝试获取加密密钥,有权限则命令执行成功 create=Output.all(vault.name, key.name).apply( lambda args: f"az keyvault key show --vault-name {args[0]} --name {args[1]}" ), opts=ResourceOptions( # 依赖组成员关系创建完成后再开始校验 depends_on=[postgres_principal_group_membership], # 开启重试,最多重试24次,每次间隔5秒,总最长等待2分钟 retry_on_failure=True, retries=24, retry_interval=5 ) ) # 创建ServerKey时显式依赖校验步骤 azure.dbforpostgresql.ServerKey( f"server-use-encryption-key", key_name=postgres_key_name, server_key_type="AzureKeyVault", server_name=server.name, uri=key.key_uri_with_version, opts=ResourceOptions( depends_on=[permission_check] ) )
方式2:在Output.apply中嵌入重试逻辑
如果不想引入pulumi_command依赖,可以直接在Output的回调函数中实现重试逻辑:
import time from azure.identity import DefaultAzureCredential from azure.keyvault.keys import KeyClient from pulumi import Output def wait_for_permission(args): vault_uri, key_name = args max_retries = 24 retry_interval = 5 credential = DefaultAzureCredential() key_client = KeyClient(vault_url=vault_uri, credential=credential) for _ in range(max_retries): try: # 尝试获取密钥,验证权限是否生效 key_client.get_key(key_name) return True except Exception as e: if "Forbidden" in str(e) or "permission" in str(e).lower(): time.sleep(retry_interval) continue raise raise TimeoutError("KeyVault权限传播超时,超过2分钟未生效") # 构造等待权限生效的Output permission_ready = Output.all(vault.properties.vault_uri, key.name).apply(wait_for_permission) # 创建ServerKey时添加依赖 azure.dbforpostgresql.ServerKey( f"server-use-encryption-key", key_name=postgres_key_name, server_key_type="AzureKeyVault", server_name=server.name, uri=key.key_uri_with_version, opts=ResourceOptions( depends_on=[postgres_principal_group_membership, permission_ready] ) )
内容的提问来源于stack exchange,提问作者Kjeld Schmidt
相关产品推荐
相关产品推荐

