【发布时间】:2021-11-04 04:59:27
【问题描述】:
短版:
我正在创建一个 Azure Active Directory 组、该组有权访问的 Azure KeyVault、该保管库中的一个密钥、一个其主体是该组成员的 PostgresServer。服务器被包装在一个 ComponentResource 中。
服务器应该使用密钥进行加密,但一开始没有访问权限 - 只有在尝试使用密钥之前存在时间延迟时才能访问密钥。
问题:在尝试使用密钥进行加密之前,如何确保权限已传播?
加长版
基础设施与我上面描述的相同。它是这样创建的:
group = azuread.Group(
"security_group",
display_name=display_name,
description=description,
owners=None,
opts=ResourceOptions(),
security_enabled=True,
)
policy = azure.keyvault.AccessPolicyEntryArgs(
object_id=group.object_id,
tenant_id=tenant_id,
permissions=azure.keyvault.PermissionsArgs(
keys=['get', 'list', 'unwrapKey', 'wrapKey']
)
)
vault = azure.keyvault.Vault(
"key_vault",
resource_group_name=resource_group_name,
location=location,
properties=azure.keyvault.VaultPropertiesArgs(
access_policies=[policy],
# other properties
),
opts=opts
)
class Postgres(ComponentResource)
def __init__(self, group, vault):
server = azure.dbforpostgresql.Server(
"postgres_server",
identity=azure.dbforpostgresql.ResourceIdentityArgs(type="SystemAssigned"),
# other properties
)
postgres_principal_group_membership = azure_ad.GroupMember(
"postgres-group-member",
group_object_id=group.object_id,
member_object_id=server.identity.principal_id,
)
key = azure.keyvault.Key(
"encryption-key",
key_name=f"encryption-key",
# other properties
)
def make_key_uri_with_version(args):
vault_name, key_name, key_uri_with_version = args
key_version = key_uri_with_version.rsplit('/', 1)[-1]
return f"{vault_name}_{key_name}_{key_version}"
postgres_key_name = Output.all(
encryption_key_vault.name,
key.name,
key.key_uri_with_version
).apply(make_key_name)
### Everything before here is created without issues
### This resource cannot be created during the first attempt to run this - but is sucessfull during the second run
### We can also make it succeed during the first try if we do:
# import time
# time.sleep(120)
### This sleep does not need to be placed right here or inside the constructor at all.
### It will help as long as it happens after creating the vault, but before completing the constructor
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,
# other properties
)
Postgres(group, vault)
第一次执行时,出现如下错误:
Error: resource partially created but read failed autorest/azure: Service returned an error.
Status=404
Code="ResourceNotFound"
Message="The requested resource of type 'Microsoft.DBforPostgreSQL/servers/keys' with name '<name of the key>' was not found.":
Code="AzureKeyVaultMissingPermissions"
Message="The server '<name of the postgres server>' requires following Azure Key Vault permissions: 'Get, WrapKey, UnwrapKey'. Please grant any missing permissions to the service principal with ID '<postgres server principal ID>'."
我已经通过在尝试连接加密密钥之前直言不讳地使用time.sleep(120) 验证了问题是时间问题之一,这使得该过程正常工作。为了使代码更稳定/更快(而不是等待固定时间并希望它足够长),我认为检查实际权限是要走的路。
目前,我没有看到任何方法可以使用 Pulumi 的 azure-native 提供程序来做到这一点。
因此,我正在考虑直接使用 azure API - 这意味着一个新的依赖项,这本身并不理想。
问题:有没有更好的方法来达到预期的结果?我在设置加密密钥时尝试了各种显式的dependsOn 值,但均未成功。
谢谢!
【问题讨论】:
-
您知道具体需要检查什么吗?该问题似乎是由于从 Azure AD 传播到 KeyVault/ARM 的延迟引起的 - 你知道如何验证它是否已完成?
-
我们需要验证的是postgres服务器访问key vault的AD权限是否到位。 ARM似乎在未经许可生效的情况下将“创建”返回给Pulumi。这就是为什么 Pulumi 代码在 postgres 服务器尝试访问 keyvault 中的客户管理密钥时崩溃的原因。我们必须确保“权限 postgres -> keyvault”有效。
-
您知道允许这样做的 API 端点吗?
-
实际上,给我们保管库权限的端点似乎马上就有了AD组和权限。因此,我想到的唯一检查是尝试与预期用户一起从保险库中读取秘密 - 但由于在我们的例子中这是一个托管身份,我不知道有什么方法可以实现这一点。换句话说:权限似乎以正确的方式到位,但在未知的时间内无效。我还必须补充一点,我们正在组件资源中尝试所有这些,所有事情都发生在构造函数中。
-
如果您能找到允许您检查的 API 调用,您可以使用类似于此处描述的方法 github.com/pulumi/pulumi-aws/issues/673#issuecomment-569944177,更新您的
make_key_uri_with_version函数以查询密钥准备情况。
标签: python azure azure-active-directory pulumi