【Azure Developer - 密钥保管库 】使用 Python Azure SDK 实现从 Azure Key Vault Certificate 中下载证书(PEM文件)

简介: 【Azure Developer - 密钥保管库 】使用 Python Azure SDK 实现从 Azure Key Vault Certificate 中下载证书(PEM文件)

问题描述

Azure Key Vault中,我们可以从Azure门户中下载证书PEM文件到本地。 可以通过OpenSSLPFX文件转换到PEM文件。然后用TXT方式查看内容,操作步骤如下图:

OpenSSL转换命令为:

openssl pkcs12 -in "C:\Users\Downloads\mykeyvault01-cscert01-20220316.pfx" -nokeys -out "C:\tool\xd12.pem"

当然,Azure也提供了通过PowerShell或CLI命令来下载PEM文件,操作为:

az keyvault certificate download --vault-name vault -n cert-name -f cert.pem

(Source : https://docs.microsoft.com/en-us/cli/azure/keyvault/certificate?view=azure-cli-latest#az-keyvault-certificate-download)

那么,如何可以通过Python SDK的代码获取到PEM文件呢?

 

问题解答

查看 Python SDK Certificate中公布出来的接口,并没有 Export, Download 的方法。 Python Azure Key Vault SDK 中并没有可以直接下载PEM文件的方法。

Azure SDK For Python KeyVault -- CertificateClient Class : https://docs.microsoft.com/en-us/python/api/azure-keyvault-certificates/azure.keyvault.certificates.aio.certificateclient?view=azure-python#methods

Methods

backup_certificate

Back up a certificate in a protected form useable only by Azure Key Vault.

Requires certificates/backup permission. This is intended to allow copying a certificate from one vault to another. Both vaults must be owned by the same Azure subscription. Also, backup / restore cannot be performed across geopolitical boundaries. For example, a backup from a vault in a USA region cannot be restored to a vault in an EU region.

cancel_certificate_operation

Cancels an in-progress certificate operation. Requires the certificates/update permission.

create_certificate

Creates a new certificate.

If this is the first version, the certificate resource is created. This operation requires the certificates/create permission. The poller requires the certificates/get permission, otherwise raises an HttpResponseError

create_issuer

Sets the specified certificate issuer. Requires certificates/setissuers permission.

delete_certificate

Delete all versions of a certificate. Requires certificates/delete permission.

If the vault has soft-delete enabled, deletion may take several seconds to complete.

delete_certificate_operation

Deletes and stops the creation operation for a specific certificate.

Requires the certificates/update permission.

delete_contacts

Deletes the certificate contacts for the key vault. Requires the certificates/managecontacts permission.

delete_issuer

Deletes the specified certificate issuer.

Requires certificates/manageissuers/deleteissuers permission.

get_certificate

Gets a certificate with its management policy attached. Requires certificates/get permission.

Does not accept the version of the certificate as a parameter. To get a specific version of the certificate, call get_certificate_version.

get_certificate_operation

Gets the creation operation of a certificate. Requires the certificates/get permission.

get_certificate_policy

Gets the policy for a certificate. Requires certificates/get permission.

Returns the specified certificate policy resources in the key vault.

get_certificate_version

Gets a specific version of a certificate without returning its management policy.

Requires certificates/get permission. To get the latest version of the certificate, or to get the certificate's policy as well, call get_certificate.

get_contacts

Gets the certificate contacts for the key vault. Requires the certificates/managecontacts permission.

get_deleted_certificate

Get a deleted certificate. Possible only in a vault with soft-delete enabled.

Requires certificates/get permission. Retrieves the deleted certificate information plus its attributes, such as retention interval, scheduled permanent deletion, and the current deletion recovery level.

get_issuer

Gets the specified certificate issuer. Requires certificates/manageissuers/getissuers permission.

import_certificate

Import a certificate created externally. Requires certificates/import permission.

Imports an existing valid certificate, containing a private key, into Azure Key Vault. The certificate to be imported can be in either PFX or PEM format. If the certificate is in PEM format the PEM file must contain the key as well as x509 certificates, and you must provide a policy with content_type of pem.

list_deleted_certificates

Lists the currently-recoverable deleted certificates. Possible only if vault is soft-delete enabled.

Requires certificates/get/list permission. Retrieves the certificates in the current vault which are in a deleted state and ready for recovery or purging. This operation includes deletion-specific information.

list_properties_of_certificate_versions

List the identifiers and properties of a certificate's versions.

Requires certificates/list permission.

list_properties_of_certificates

List identifiers and properties of all certificates in the vault.

Requires certificates/list permission.

list_properties_of_issuers

Lists properties of the certificate issuers for the key vault.

Requires the certificates/manageissuers/getissuers permission.

merge_certificate

Merges a certificate or a certificate chain with a key pair existing on the server.

Requires the certificates/create permission. Performs the merging of a certificate or certificate chain with a key pair currently available in the service. Make sure when creating the certificate to merge using create_certificate that you set its issuer to 'Unknown'. This way Key Vault knows that the certificate will not be signed by an issuer known to it.

purge_deleted_certificate

Permanently deletes a deleted certificate. Possible only in vaults with soft-delete enabled.

Requires certificates/purge permission.

Performs an irreversible deletion of the specified certificate, without possibility for recovery. The operation is not available if the recovery_level does not specify 'Purgeable'. This method is only necessary for purging a certificate before its scheduled_purge_date.

recover_deleted_certificate

Recover a deleted certificate to its latest version. Possible only in a vault with soft-delete enabled.

Requires certificates/recover permission. If the vault does not have soft-delete enabled, delete_certificate is permanent, and this method will raise an error. Attempting to recover a non-deleted certificate will also raise an error.

restore_certificate_backup

Restore a certificate backup to the vault. Requires certificates/restore permission.

This restores all versions of the certificate, with its name, attributes, and access control policies. If the certificate's name is already in use, restoring it will fail. Also, the target vault must be owned by the same Microsoft Azure subscription as the source vault.

set_contacts

Sets the certificate contacts for the key vault. Requires certificates/managecontacts permission.

update_certificate_policy

Updates the policy for a certificate. Requires certificiates/update permission.

Set specified members in the certificate policy. Leaves others as null.

update_certificate_properties

Change a certificate's properties. Requires certificates/update permission.

update_issuer

Updates the specified certificate issuer. Requires certificates/setissuers permission.

所以使用原始的SDK Methods方法不可行。

 

寻找解决方案

通过对CLI (az keyvault certificate download)指令的研究,发现CLI使用的是python代码执行的Get Certificates 操作,实质上是调用的Key Vault的REST API:

Get Certificate: https://docs.microsoft.com/en-us/rest/api/keyvault/certificates/get-certificate/get-certificate#getcertificate

DEBUG az 指令:

az keyvault certificate download --vault-name mykeyvault01 -n cscert01 -f cert2.pem  --debug

C:\Users>az keyvault certificate download --vault-name mykeyvault01 -n cscert01 -f cert2.pem  --debug
cli.knack.cli: Command arguments: ['keyvault', 'certificate', 'download', '--vault-name', 'mykeyvault01', '-n', 'cscert01', '-f', 'cert2.pem', '--debug']
cli.knack.cli: __init__ debug log:
Enable color in terminal.
Init colorama.
cli.knack.cli: Event: Cli.PreExecute []
cli.knack.cli: Event: CommandParser.OnGlobalArgumentsCreate [<function CLILogging.on_global_arguments at 0x033452F8>, <function OutputProducer.on_global_arguments at 0x034F0190>, <function CLIQuery.on_global_arguments at 0x03607D60>]
cli.knack.cli: Event: CommandInvoker.OnPreCommandTableCreate []
cli.azure.cli.core: Modules found from index for 'keyvault': ['azure.cli.command_modules.keyvault']
cli.azure.cli.core: Loading command modules:
cli.azure.cli.core: Name                  Load Time    Groups  Commands
cli.azure.cli.core: keyvault                  0.038        19       117
cli.azure.cli.core: Total (1)                 0.038        19       117
cli.azure.cli.core: These extensions are not installed and will be skipped: ['azext_ai_examples', 'azext_next']
cli.azure.cli.core: Loading extensions:
cli.azure.cli.core: Name                  Load Time    Groups  Commands  Directory
cli.azure.cli.core: Total (0)                 0.000         0         0
cli.azure.cli.core: Loaded 19 groups, 117 commands.
cli.azure.cli.core: Found a match in the command table.
cli.azure.cli.core: Raw command  : keyvault certificate download
cli.azure.cli.core: Command table: keyvault certificate download
cli.knack.cli: Event: CommandInvoker.OnPreCommandTableTruncate [<function AzCliLogging.init_command_file_logging at 0x039701D8>]
cli.azure.cli.core.azlogging: metadata file logging enabled - writing logs to 'C:\Users\.azure\commands\2022-03-16.14-46-58.keyvault_certificate_download.21860.log'.
az_command_data_logger: command args: keyvault certificate download --vault-name {} -n {} -f {} --debug
cli.knack.cli: Event: CommandInvoker.OnPreArgumentLoad [<function register_global_subscription_argument.<locals>.add_subscription_parameter at 0x039B6268>, <function register_global_query_examples_argument.<locals>.register_query_examples at 0x039D8928>]
cli.knack.cli: Event: CommandInvoker.OnPostArgumentLoad []
cli.knack.cli: Event: CommandInvoker.OnPostCommandTableCreate [<function register_ids_argument.<locals>.add_ids_arguments at 0x039D8970>, <function register_cache_arguments.<locals>.add_cache_arguments at 0x039D8A00>]
cli.knack.cli: Event: CommandInvoker.OnCommandTableLoaded []
cli.knack.cli: Event: CommandInvoker.OnPreParseArgs []
cli.knack.cli: Event: CommandInvoker.OnPostParseArgs [<function OutputProducer.handle_output_argument at 0x034F01D8>, <function CLIQuery.handle_query_parameter at 0x03607DA8>, <function register_global_query_examples_argument.<locals>.handle_example_parameter at 0x039D88E0>, <function register_ids_argument.<locals>.parse_ids_arguments at 0x039D89B8>]
msrest.universal_http.requests: Configuring retry: max_retries=4, backoff_factor=0.8, max_backoff=90
msrest.service_client: Accept header absent and forced to application/json
msrest.universal_http: Configuring redirects: allow=True, max=30
msrest.universal_http: Configuring request: timeout=100, verify=True, cert=None
msrest.universal_http: Configuring proxies: ''
msrest.universal_http: Evaluate proxies against ENV settings: True
urllib3.connectionpool: Starting new HTTPS connection (1): mykeyvault01.vault.azure.cn:443
urllib3.connectionpool: https://mykeyvault01.vault.azure.cn:443 "GET /certificates/cscert01/?api-version=7.0 HTTP/1.1" 401 97
cli.azure.cli.core._profile: Profile.get_raw_token invoked with resource='https://vault.azure.cn', subscription=None, tenant=None
cli.azure.cli.core.util: attempting to read file C:\Users\.azure\accessTokens.json as utf-8-sig
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - Authority:Performing instance discovery: ...
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - Authority:Performing static instance discovery
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - Authority:Authority validated via static instance discovery
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - TokenRequest:Getting token from cache with refresh if necessary.
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - CacheDriver:finding with query keys: {'_clientId': '...', 'userId': '...'}
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - CacheDriver:Looking for potential cache entries: {'_clientId': '...', 'userId': '...'}
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - CacheDriver:Found 9 potential entries.
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - CacheDriver:Resource specific token found.
adal-python: 3f4f9351-cdc1-4891-b125-1f02ac02741b - CacheDriver:Returning token from cache lookup, AccessTokenId: b'wR5KoJYE=', RefreshTokenId: b'5VNpWgDCg4ydvuf2PeWxGaph/r7KMelGLXVY+jLV89s='
urllib3.connectionpool: https://mykeyvault01.vault.azure.cn:443 "GET /certificates/cscert01/?api-version=7.0 HTTP/1.1" 200 2114
cli.knack.cli: Event: CommandInvoker.OnTransformResult [<function _resource_group_transform at 0x039A5C88>, <function _x509_from_base64_to_hex_transform at 0x039A5CD0>]
cli.knack.cli: Event: CommandInvoker.OnFilterResult []
cli.knack.cli: Event: Cli.SuccessfulExecute []
cli.knack.cli: Event: Cli.PostExecute [<function AzCliLogging.deinit_cmd_metadata_logging at 0x039702F8>]
az_command_data_logger: exit code: 0
cli.__main__: Command ran in 3.206 seconds (init: 0.394, invoke: 2.812)
telemetry.save: Save telemetry record of length 3005 in cache
telemetry.check: Negative: The C:\Users\.azure\telemetry.txt was modified at 2022-03-16 14:43:00.945931, which in less than 600.000000 s

如以上黄色高亮内容, download指令调用了 "GET /certificates/cscert01/?api-version=7.0 HTTP/1.1" 200 2114,且返回的HTTP Code为200 成功。所以当我们单独对get certificates接口请求时,在返回结果中,发现cer属性值就是证书PEM格式内容。通过Postman发送请求并验证结果:

那么,通过Python Azure SDK的 certificate_client.get_certificate方法,获取到certificate对象后,其中包含的cer值,是否也是PEM的内容呢?

我们通过下面的代码来进行验证:

from azure.identity import DefaultAzureCredential
from azure.keyvault.certificates import CertificateClient
import ssl
credential = DefaultAzureCredential()
certificate_client = CertificateClient(vault_url=https://yourkeyvaultname.vault.azure.cn/, credential=credential)
certificate = certificate_client.get_certificate("your certificate name")
print(certificate.name)
print(certificate.properties.version)
print(certificate.policy.issuer_name)
print(str(certificate.cer))
# Convert the certificate to PEM format        
cert_PEM = ssl.DER_cert_to_PEM_cert(certificate.cer);
print("Certificate in PEM format:");
print(cert_PEM);

是的,在certificate对象中,cer就是我们证书的内容,但是由于格式为DER,所以使用了SSL包中的 DER_cert_to_PEM_cert 方法完成转换,最终得到PEM文件内容。

在 python代码中获取到PEM内容后,剩下的部分就是把内容输出到 .pem 文件即可。

##接上一段代码
filename = 'mypem1.pem'
# Open the file in append mode and append the new content in file_object
with open(filename, 'a') as file_object:
    file_object.write(cert_PEM)
print("output the PEM file End!")

注意:在创建 certificate_client对象时,需要使用credential,而以上代码使用的是默认的DefaultAzureCredential(),在执行代码的本机中,已经配置了如下环境变量:

  • AZURE_TENANT_ID
  • AZURE_CLIENT_ID
  • AZURE_CLIENT_SECRET

使用 ClientSecretCredential 认证方式后,代码修改如下:

import os
from azure.keyvault.certificates import CertificateClient
import ssl
from azure.identity import ClientSecretCredential
from msrestazure.azure_cloud import AZURE_CHINA_CLOUD
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"])
credential = ClientSecretCredential (client_id=os.environ["AZURE_CLIENT_ID"],client_secret=os.environ["AZURE_CLIENT_SECRET"],tenant_id=os.environ["AZURE_TENANT_ID"],cloud_environment=AZURE_CHINA_CLOUD,china=True)
certificate_client = CertificateClient(vault_url="https://yourkeyvault.vault.azure.cn/", credential=credential)
certificate = certificate_client.get_certificate("your certificate name")
print(certificate.name)
print(certificate.properties.version)
print(certificate.policy.issuer_name)
print(str(certificate.cer))
# Convert the certificate to PEM format        
cert_PEM = ssl.DER_cert_to_PEM_cert(certificate.cer);
print("Certificate in PEM format:");
print(cert_PEM);
filename = 'mypem2.pem'
# Open the file in append mode and append the new content in file_object
with open(filename, 'a') as file_object:
    file_object.write(cert_PEM)
print("output the PEM file End!")

 

 

参考文档

Retrieve a Certificate:https://docs.microsoft.com/en-us/python/api/overview/azure/keyvault-certificates-readme?view=azure-python#retrieve-a-certificate

Der_cert_to_pem_cert Function Of Ssl Module In Python: https://pythontic.com/ssl/ssl-module/der_cert_to_pem_cert

A certificate bundle consists of a certificate (X509) plus its attributes: https://docs.microsoft.com/en-us/rest/api/keyvault/certificates/get-certificate/get-certificate#certificatebundle

相关文章
|
12天前
|
PyTorch Linux 算法框架/工具
pytorch学习一:Anaconda下载、安装、配置环境变量。anaconda创建多版本python环境。安装 pytorch。
这篇文章是关于如何使用Anaconda进行Python环境管理,包括下载、安装、配置环境变量、创建多版本Python环境、安装PyTorch以及使用Jupyter Notebook的详细指南。
110 1
pytorch学习一:Anaconda下载、安装、配置环境变量。anaconda创建多版本python环境。安装 pytorch。
|
9天前
|
网络协议 数据库连接 Python
python知识点100篇系列(17)-替换requests的python库httpx
【10月更文挑战第4天】Requests 是基于 Python 开发的 HTTP 库,使用简单,功能强大。然而,随着 Python 3.6 的发布,出现了 Requests 的替代品 —— httpx。httpx 继承了 Requests 的所有特性,并增加了对异步请求的支持,支持 HTTP/1.1 和 HTTP/2,能够发送同步和异步请求,适用于 WSGI 和 ASGI 应用。安装使用 httpx 需要 Python 3.6 及以上版本,异步请求则需要 Python 3.8 及以上。httpx 提供了 Client 和 AsyncClient,分别用于优化同步和异步请求的性能。
python知识点100篇系列(17)-替换requests的python库httpx
|
2天前
|
机器人 Shell Linux
【Azure Bot Service】部署Python ChatBot代码到App Service中
本文介绍了使用Python编写的ChatBot在部署到Azure App Service时遇到的问题及解决方案。主要问题是应用启动失败,错误信息为“Failed to find attribute &#39;app&#39; in &#39;app&#39;”。解决步骤包括:1) 修改`app.py`文件,添加`init_func`函数;2) 配置`config.py`,添加与Azure Bot Service认证相关的配置项;3) 设置App Service的启动命令为`python3 -m aiohttp.web -H 0.0.0.0 -P 8000 app:init_func`。
|
4天前
|
数据可视化 数据挖掘 Python
Seaborn 库创建吸引人的统计图表
【10月更文挑战第11天】本文介绍了如何使用 Seaborn 库创建多种统计图表,包括散点图、箱线图、直方图、线性回归图、热力图等。通过具体示例和代码,展示了 Seaborn 在数据可视化中的强大功能和灵活性,帮助读者更好地理解和应用这一工具。
15 3
|
6天前
|
Java Python
> python知识点100篇系列(19)-使用python下载文件的几种方式
【10月更文挑战第7天】本文介绍了使用Python下载文件的五种方法,包括使用requests、wget、线程池、urllib3和asyncio模块。每种方法适用于不同的场景,如单文件下载、多文件并发下载等,提供了丰富的选择。
|
7天前
|
Linux Python
【Azure Function】Python Function部署到Azure后报错No module named '_cffi_backend'
ERROR: Error: No module named '_cffi_backend', Cannot find module. Please check the requirements.txt file for the missing module.
|
7天前
|
数据安全/隐私保护 流计算 开发者
python知识点100篇系列(18)-解析m3u8文件的下载视频
【10月更文挑战第6天】m3u8是苹果公司推出的一种视频播放标准,采用UTF-8编码,主要用于记录视频的网络地址。HLS(Http Live Streaming)是苹果公司提出的一种基于HTTP的流媒体传输协议,通过m3u8索引文件按序访问ts文件,实现音视频播放。本文介绍了如何通过浏览器找到m3u8文件,解析m3u8文件获取ts文件地址,下载ts文件并解密(如有必要),最后使用ffmpeg合并ts文件为mp4文件。
|
8天前
|
JavaScript 前端开发 开发工具
【Azure Developer】使用JavaScript通过SDK进行monitor-query的client认证报错问题
AADSTS90002: Tenant 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud. Check with your subscription administrator, this may happen if there are no active subscriptions for the tenant.
|
10天前
|
Python
Python 三方库下载安装
Python 三方库下载安装
13 1
|
12天前
|
机器学习/深度学习 缓存 PyTorch
pytorch学习一(扩展篇):miniconda下载、安装、配置环境变量。miniconda创建多版本python环境。整理常用命令(亲测ok)
这篇文章是关于如何下载、安装和配置Miniconda,以及如何使用Miniconda创建和管理Python环境的详细指南。
178 0
pytorch学习一(扩展篇):miniconda下载、安装、配置环境变量。miniconda创建多版本python环境。整理常用命令(亲测ok)