繁体   English   中英

使用 python w/rest api 与 Azure Key Vault 交互

[英]Interacting with Azure Key Vault using python w/ rest api

我对使用最近发布的用于 Azure 中的机密管理的新服务非常感兴趣。 我找到了一些示例指南,介绍了如何通过 powershell cmdlet 和 c# 与 Key Vault 交互,但是在开始使用 rest API 方面还没有找到太多内容。

我特别困惑的是对 oauth2 和活动目录的处理。 我编写了一个 oauth2 应用程序侦听器,使用 AD 实例构建了一个 Web 应用程序,现在可以生成“access_token”。 但是,我不清楚如何进行此操作,因为每当尝试使用我的 access_token 执行密钥库 API 调用时,我似乎始终收到 401 HTTP 响应代码。

任何有关在 python 中使用 Azure Key Vault 的指南/提示将不胜感激!

以下是在以下代码生效之前您需要执行的一些步骤...希望我记住了一切!

  1. 您需要在 AD 中有一个应用程序,至少可以访问

    注意:无论如何,您都需要它来获取 CLIENT_ID 和 CLIENT_SECRET 然后运行:

    azure keyvault set-policy --vault-name 'VAULTNAME' --spn CLIENT_ID --perms-to-secrets '["get"]'

  2. 您还需要用于您的机密的 ID,您可以使用 Azure CLI 使用:

    azure keyvault 秘密显示 [保险库] [秘密]

    或者

    azure keyvault secret show -h # 如果不清楚

  3. 复制密钥(URL 中的最后一个参数)

然后以下代码将允许您使用 oauth2 查询密钥保管库:

import json
import requests

AUTHORITY_HOST = "login.windows.net"
TENANT_ID      = < your tenant id >
CLIENT_ID      = < your client id >
CLIENT_SECRET  = < your client secret >
VAULT          = 'MyVault'

data = { "grant_type" : "client_credentials", 
        "client_id" : CLIENT_ID, 
        "client_secret" : CLIENT_SECRET, 
        "resource" : "https://vault.azure.net"
    }

secrets = [( "i_like_pie", "8a7680a2cf5e4d539494aa0ce265297" )]

headers = { "Content-Type" : "application/x-www-form-urlencoded" }

r = requests.post("https://login.windows.net/{}/oauth2/token".format(TENANT_ID), data=data, headers=headers)
access_token = r.json()['access_token']

for secret, secret_id in secrets.iteritems():

    headers = {"Authorization":"Bearer {}".format(access_token) }
    r = requests.get('https://{}.vault.azure.net/secrets/{}/{}?api-version=2015-06-01'.format(VAULT, secret, secret_id), headers=headers)

    print('##### {} #####'.format(secret))
    print(r.json())
    print('')

您可以检查以下几项内容:

  1. 请求 Bearer 令牌时,请确保包含“资源”标头,并将其设置为“ https://vault.azure.net ”。 如果不这样做,您将获得一个令牌,但您将无法使用它访问任何保险库数据。
  2. 调用 vault.azure.net URL 时,请确保包含正确的“api-version”。它可以在API 文档中找到。 当前值为“2015-02-01-preview”。
  3. 当然,请检查是否为您尝试访问的保管库正确设置了 Key Vault 访问策略。

对于使用 Key Vault 的 REST API,参考文档服务文档应该会有所帮助。

现在通过 Azure SDK 可以更轻松地将 Key Vault 与 Python 结合使用。 有三个 Python 包用于处理现有的保管库数据,一个用于创建/管理保管库:

azure-identity也是应该与这些一起用于身份验证的包。

借助 SDK,使用访问令牌处理来自授权应用程序的现有保管库就像创建凭据和客户端一样简单:

from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient

credential = DefaultAzureCredential()
client = SecretClient("https://{vault-name}.vault.azure.net", credential)
secret = client.get_secret("secret-name")

(我使用 Python 开发 Azure SDK)

当 Key Vault 返回 401 响应时,它包含一个包含权限和资源的www-authenticate标头。 您必须同时使用两者才能获得有效的不记名令牌。 然后您可以使用该令牌重做您的请求,并且如果您在针对同一保管库的后续请求中使用相同的令牌,则在令牌到期之前它不应返回 401。

您可以提前知道权限和资源,但准备您的代码以始终处理 401 通常会更健壮,特别是在您使用多个保管库时。

确保只信任有效 SSL 连接的www-authenticate标头,否则您可能成为欺骗的受害者!

我为 Azure Key Vault 的 REST API 编写了一个简单的 Python 包装器。 您可以在此处查看AzureKeyVaultPythonSDK

逻辑的外壳在这里

class AzureKeyVaultManager(object):

section_name="KeyVaultSection"

# Constructor
def __init__(self, fileName="private.properties"):
    prop_file=os.path.dirname(os.path.realpath(sys.argv[0])) + "/" + fileName
    config = ConfigParser.RawConfigParser()
    config.read(prop_file)
    self.client_id=config.get(self.section_name,'client.id')
    self.client_secret=config.get(self.section_name,'client.secret')
    self.tenant_id=config.get(self.section_name,'tenant.id')
    self.resource=config.get(self.section_name,'resource')
    self.key_vault=config.get(self.section_name,'key.vault')

# Authenticate
def initialize(self):
    if self.client_id and self.client_secret and self.tenant_id and self.resource and self.key_vault:
        print "Got all the properties from file "
        token_url="https://login.windows.net/{0}/oauth2/token".format(self.tenant_id)
        payload = {'client_id':self.client_id, 'client_secret':self.client_secret, 'resource':self.resource, 'grant_type':'client_credentials'}
        response=requests.post(token_url, data=payload).json()
        self.access_token=response['access_token']
    else:
        raise ValueError("Couldn't get the key vault properties from properties file")

# Get secret from a specific keyvault
def getSecretFromKeyVault(self, secretName, keyVault=None):
    if keyVault is None:
        keyVault=self.key_vault

    endpoint = 'https://{0}.vault.azure.net/secrets/{1}?api-version=2015-06-01'.format(keyVault, secretName)
    headers = {"Authorization": 'Bearer ' + self.access_token}
    response = requests.get(endpoint,headers=headers).json()

    if 'value' in response:
        return response['value']
    else:
        raise ValueError("Value not found in response")

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM