【Azure Developer】Python代码通过AAD认证访问微软Azure密钥保管库(Azure Key Vault)中机密信息(Secret)
关键字说明
什么是 Azure Active Directory?Azure Active Directory(Azure AD, AAD) 是 Microsoft 的基于云的标识和访问管理服务,可帮助员工登录和访问 Azure 中的资源:
外部资源,例如 Microsoft 365、Azure 门户(https://portal.azure.cn/)以及成千上万的其他 SaaS 应用程序。
内部资源,例如公司网络和 Intranet 上的应用,以及由自己的组织开发的任何云应用。
什么是Azure Key Vault?Azure Key Vault 是一个用于安全地存储和访问机密的云服务。 机密是你想要严格控制对其的访问的任何内容,例如 API 密钥、密码、证书或加密密钥。 Key Vault 服务支持:保管库。 保管库支持存储软件密钥、机密和证书。
- 机密管理 - Azure Key Vault 可以用来安全地存储令牌、密码、证书、API 密钥和其他机密,并对其访问进行严格控制
- 密钥管理 - Azure Key Vault 也可用作密钥管理解决方案。 可以通过 Azure Key Vault 轻松创建和控制用于加密数据的加密密钥。
- 证书管理 - Azure Key Vault 也是一项服务,可用来轻松预配、管理和部署公用和专用传输层安全性/安全套接字层 (TLS/SSL) 证书,以用于 Azure 以及内部连接资源。
问题描述
在官方的示例文档中,我们可以发现Python 应用程序以使用 Azure 资源(虚拟机 VM)的托管标识(Identity)从 Azure Key Vault 读取信息,那如果同样的Python应用代码,如果想在非Azure托管的客户端运行,如何来实现呢?如何来解决如下的错误呢?
EnvironmentCredential.get_token failed: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
ManagedIdentityCredential.get_token failed: ManagedIdentityCredential authentication unavailable, no managed identity endpoint found.
SharedTokenCacheCredential.get_token failed: Azure Active Directory error '(invalid_resource) AADSTS500011: The resource principal named https://vault.azure.cn was not found in
the tenant named xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Trace ID: 11af8f36-693a-4105-8a6c-9e271a1b9f00
Correlation ID: 43cc4c0d-fd23-4b84-a03b-284ff93484a4
Timestamp: 2021-01-16 07:58:47Z'
DefaultAzureCredential.get_token failed: SharedTokenCacheCredential raised unexpected error "Azure Active Directory error '(invalid_resource) AADSTS500011: The resource principal named https://vault.azure.cn was not found in the tenant named xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Trace ID: 11af8f36-693a-4105-8a6c-9e271a1b9f00
Correlation ID: 43cc4c0d-fd23-4b84-a03b-284ff93484a4
Timestamp: 2021-01-16 07:58:47Z'"
DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
EnvironmentCredential: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
ManagedIdentityCredential: ManagedIdentityCredential authentication unavailable, no managed identity endpoint found.
SharedTokenCacheCredential: Azure Active Directory error '(invalid_resource) AADSTS500011: The resource principal named https://vault.azure.cn was not found in the tenant named xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Trace ID: 11af8f36-693a-4105-8a6c-9e271a1b9f00
Correlation ID: 43cc4c0d-fd23-4b84-a03b-284ff93484a4
Timestamp: 2021-01-16 07:58:47Z'
Traceback (most recent call last):
File "case.py", line 26, in <module>
retrieved_secret = client.get_secret(secretName)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\tracing\decorator.py", line 83, in wrapper_use_tracer
return func(*args, **kwargs)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\keyvault\secrets\_client.py", line 67, in get_secret
bundle = self._client.get_secret(
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\keyvault\secrets\_generated\_operations_mixin.py", line 1475, in get_secret
return mixin_instance.get_secret(vault_base_url, secret_name, secret_version, **kwargs)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\keyvault\secrets\_generated\v7_1\operations\_key_vault_client_operations.py", line 276, in get_secret
pipeline_response = self._client._pipeline.run(request, stream=False, **kwargs)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\_base.py", line 211, in run
return first_node.send(pipeline_request) # type: ignore
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\_base.py", line 71, in send
response = self.next.send(request)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\_base.py", line 71, in send
response = self.next.send(request)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\_base.py", line 71, in send
response = self.next.send(request)
[Previous line repeated 2 more times]
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\policies\_redirect.py", line 157, in send
response = self.next.send(request)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\core\pipeline\policies\_retry.py", line 436, in send
response = self.next.send(request)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\keyvault\secrets\_shared\challenge_auth_policy.py", line 111, in send
self._handle_challenge(request, challenge)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\keyvault\secrets\_shared\challenge_auth_policy.py", line 137, in _handle_challenge
self._token = self._credential.get_token(scope)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\identity\_credentials\default.py", line 144, in get_token
return super(DefaultAzureCredential, self).get_token(*scopes, **kwargs)
File "C:\Users\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\azure\identity\_credentials\chained.py", line 90, in get_token
raise ClientAuthenticationError(message=message)
azure.core.exceptions.ClientAuthenticationError: DefaultAzureCredential failed to retrieve a token from the included credentials.
Attempted credentials:
EnvironmentCredential: EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
ManagedIdentityCredential: ManagedIdentityCredential authentication unavailable, no managed identity endpoint found.
SharedTokenCacheCredential: Azure Active Directory error '(invalid_resource) AADSTS500011: The resource principal named https://vault.azure.cn was not found in the tenant named xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
Trace ID: 11af8f36-693a-4105-8a6c-9e271a1b9f00
Correlation ID: 43cc4c0d-fd23-4b84-a03b-284ff93484a4
Timestamp: 2021-01-16 07:58:47Z'
解决思路
根据错误提示,需要在Azure AD中为Python应用程序注册一个授权应用(AAD Application)。并获取AAD应用中的客户端访问密码(Secret),客户端ID(Client ID),租户ID(Tenant ID),配置Python应用端的环境变量,调用azure.identity库中的DefaultAzureCredential函数,完成访问Key Vault资源的授权。整个方案需要以下3个关键步骤:
- 注册AAD应用并设置客户端密码
- 在Key Vault中对AAD应用完成访问授权(Access Policy)
- 配置Python应用端的环境变量
下文为整个方案的操作步骤
操作步骤
一:注册AAD 应用,复制出应用的关键信息(Client ID, Tenant ID, Object ID)
- 登录Azure 门户,进入AAD页面(https://portal.azure.cn/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview)
- 选择“App registrations”,点击“Add Application”按钮,注册一个新应用,名称唯一即可。如mykeyvaultapp01
- 创建完成后,进入应用Overview页面,复制保存(Client ID, Tenant ID, Object ID)值,以备后续使用。

二:设置AAD 应用客户端密码
- 在AAD应用页面,进入“证书和密码”页面,点击“新客户端密码”按钮,添加新的Secret(因密码值只能在最开始创建时可见,所以必须在离开页面前复制它)

三:在Key Vault中设置访问授权
- 登录Azure门户,进入Key Vault页面(https://portal.azure.cn/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.KeyVault%2Fvaults)
- 选择“Access policies”,点击“Add access policy”,使用第一步中的AAD应用名称或Application ID作为Principal。点击“Add”后“Save”。

四:设置环境变量
使用azure.identity库中的DefaultAzureCredential函数,默认会去检测当前环境中是否包含AZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_CLIENT_SECRET三个变量。
- AZURE_CLIENT_ID:第一步中的Client ID
- AZURE_TENANT_ID:第一步中的Tenant ID
- AZURE_CLIENT_SECRET:第二步中的Secret Value

五:运行Python应用
可以在代码中输出上一步中设定的环境变量,以验证值是否正确。
import os
import cmd
from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential # print('AZURE_TENANT_ID:' +os.environ["AZURE_TENANT_ID"])
# print('AZURE_CLIENT_ID:' +os.environ["AZURE_CLIENT_ID"])
# print('AZURE_CLIENT_SECRET:' +os.environ["AZURE_CLIENT_SECRET"]) keyVaultName = 'mykeyvalue01'
secretName = 'mysecret'
KVUri = f"https://{keyVaultName}.vault.azure.cn" print(KVUri)
credential = DefaultAzureCredential()
token = credential.get_token("https://vault.azure.cn/.default")
print(token)
client = SecretClient(vault_url=KVUri, credential=credential) retrieved_secret = client.get_secret(secretName) print(f"Your secret is '{retrieved_secret.value}'.")
print(f"Your secret properties not_before(nbf) is '{retrieved_secret.properties.not_before}'.")
print(f"Your secret properties expires_on is '{retrieved_secret.properties.expires_on}'.")
六:附加:如何获取代码中的Token值
DefaultAzureCredential方法返回credential对象,如果需要知道请求中使用的token值,调用get_token方法,同时需要指定scope,如这里使用的为"https://vault.azure.cn/.default"
credential = DefaultAzureCredential()
token = credential.get_token("https://vault.azure.cn/.default")
print(token)
测试结果如图:

附录一:如遗忘以上第三步,没有在Key Vault中对AAD应用赋予访问策略(Access Policy),则获取的错误消息为
|
azure.core.exceptions.HttpResponseError: (Forbidden) The user, group or application 'appid=xxxxxxxx-05ad-4999-8679-xxxxxxxxxxxx;oid=xxxxxxxx-e256-4650-8ef8-xxxxxxxxxxxx;iss=https://sts.chinacloudapi.cn/xxxxxxxx-66d7-47a8-8f9f-xxxxxxxxxxxx/' does not have secrets get permission on key vault 'keyvault01;location=chinanorth'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287 |
参考资料
什么是 Azure Active Directory? https://docs.microsoft.com/zh-cn/azure/active-directory/fundamentals/active-directory-whatis
关于 Azure Key Vault: https://docs.azure.cn/zh-cn/key-vault/general/overview
Azure Key Vault 基本概念 : https://docs.azure.cn/zh-cn/key-vault/general/basic-concepts
将 Azure Key Vault 与通过 Python 编写的虚拟机配合使用 :https://docs.azure.cn/zh-cn/key-vault/general/tutorial-python-virtual-machine
DefaultAzureCredential get_token : https://docs.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python#get-token--scopes----kwargs-
使用Postman获取Azure AD中注册应用程序的授权Token,及为Azure REST API设置Authorization : https://www.cnblogs.com/lulight/p/14279338.html
【Azure Developer】Python代码通过AAD认证访问微软Azure密钥保管库(Azure Key Vault)中机密信息(Secret)的更多相关文章
- 【Azure Developer - 密钥保管库 】使用 Python Azure SDK 实现从 Azure Key Vault Certificate 中下载证书(PEM文件)
问题描述 在Azure Key Vault中,我们可以从Azure门户中下载证书PEM文件到本地. 可以通过OpenSSL把PFX文件转换到PEM文件.然后用TXT方式查看内容,操作步骤如下图: Op ...
- Azure Kay Vault(一).NET Core Console App 获取密钥保管库中的机密信息
一,引言 Azure 密钥保管库用于存储敏感信息,例如链接字符串,密码,API 密钥等.我们无法直接从Azure 密钥库中访问机密!那么我们如何才能访问应用程序中的机密信息?比如,在我们的实际项目中, ...
- 在 Azure Resource Manager 中为虚拟机设置密钥保管库
Note Azure 具有两种不同的部署模型,用于创建和处理资源:Resource Manager 模型和经典模型.本文介绍使用 Resource Manager 部署模型.Azure 建议对大多数新 ...
- 【Azure 环境】Azure Key Vault (密钥保管库)中所保管的Keys, Secrets,Certificates是否可以实现数据粒度的权限控制呢?
问题描述 Key Vault (密钥保管库) 能不能针对用户授权实现指定用户只能访问某个或某些特定的key? 如当前有两个用户(User1, User2),在Key Vault中有10个Key,Use ...
- 【Azure Developer】使用 CURL 获取 Key Vault 中 Secrets 中的值
问题描述 在使用CURL通过REST API获取Azure Key Vaualt的Secrets值,提示Missing Token, 问如何来生成正确的Token呢? # curl 命令 curl - ...
- 【Azure Developer】解决Azure Key Vault管理Storage的示例代码在中国区Azure遇见的各种认证/授权问题 - C# Example Code
问题描述 使用Azure密钥保管库(Key Vault)来托管存储账号(Storage Account)密钥的示例中,从Github中下载的示例代码在中国区Azure运行时候会遇见各种认证和授权问题, ...
- 【Azure Developer】【Python 】使用 azure.identity 和 azure.common.credentials 获取Azure AD的Access Token的两种方式
问题描述 使用Python代码,展示如何从Azure AD 中获取目标资源的 Access Token. 如要了解如何从AAD中获取 client id,client secret,tenant id ...
- 梯度下降法的python代码实现(多元线性回归)
梯度下降法的python代码实现(多元线性回归最小化损失函数) 1.梯度下降法主要用来最小化损失函数,是一种比较常用的最优化方法,其具体包含了以下两种不同的方式:批量梯度下降法(沿着梯度变化最快的方向 ...
- Azure Key Vault (1) 入门
<Windows Azure Platform 系列文章目录> 为什么要使用Azure Key Vault? 我们假设在微软云Azure上有1个场景,在Windows VM里面有1个.NE ...
随机推荐
- expdp、impdp状态查看及中断方法
一.expdp状态查看及中断方法 1.查询expdp的job的名字 SQL> select job_name from dba_datapump_jobs; JOB_NAME---------- ...
- windows远程msra windows使用技巧
qq远程太慢,mstsc?又不想把电脑密码告诉好友,怎么办呢?在这里推荐一个方法: 点击开始运行输入msra,确定,邀请信任的人帮助你您,将该邀请另存为文件,然后这个窗口不要关,把密码复制粘贴给好友, ...
- Netty源码解析 -- PoolSubpage实现原理
前面文章说了PoolChunk如何管理Normal内存块,本文分享PoolSubpage如何管理Small内存块. 源码分析基于Netty 4.1.52 内存管理算法 PoolSubpage负责管理S ...
- Web服务器-正则表达式-整理+复习(3.1.1)
@ 目录 1.常用api 2.例子 3.正则表达式模式 关于作者 参考文章 1.常用api re.match(pattern, string, flags=0) pattern 匹配的正则表达式 st ...
- ActiveMq PUT任意文件上传漏洞(CVE-2016-3088)漏洞复现
漏洞原理 该漏洞出现在fileserver应用中,ActiveMQ中的fileserver服务允许用户通过HTTP PUT方法上传文件到指定目录.Fileserver支持写入文件(不解析jsp),但是 ...
- 【进阶之路】线程池拓展与CompletionService操作异步任务
大家好,我是练习java两年半时间的南橘,小伙伴可以一起互相交流经验哦. 一.扩展ThreadPoolExecutor 1.扩展方法介绍 ThreadPoolExecutor是可以扩展的,它内部提供了 ...
- PHP功能代码片段
1.连接MYSQL数据库代码 <?php $connec=mysql_connect("localhost","root","root&qu ...
- 简单谈谈contextlib的使用
简单谈谈contextlib的使用 写在前面 做这件事的原因: 在看书的时候,我发现了有大佬们用contextlib管理上下文,真的很牛皮,但是百度了以下,每个大佬都写了很多很全很深刻,讲道理五花八门 ...
- matplotlib学习日记(二)----图表组成练习
''' 将前面的知识进行练习 plot,scatter,legend等 ''' import matplotlib.pyplot as plt import numpy as np from matp ...
- ConstraintLayout 学习笔记
如何阅读 xml 属性 与 Relativelayout 不同,ConstrainLayout 的属性需要同时说明需要怎么操作自己与目标控件,例如:layout_constraintLeft_toLe ...