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

时间:2015-03-19 16:17:41

标签: python azure oauth-2.0 identity app-secret

我对使用Azure最近发布的用于秘密管理的新服务非常感兴趣。我已经找到了一些示例指南,介绍了如何通过powershell cmdlet和c#与密钥保管库进行交互,但是在开始使用其余API方面却没有找到太多帮助。

我特别困惑的是处理oauth2 w / active目录。我编写了一个oauth2应用程序监听器,用AD实例构建了一个Web应用程序,现在可以生成一个“access_token”。我不清楚如何继续这样做,因为我似乎在尝试使用我的access_token执行密钥库API调用时始终收到401 HTTP resp代码。

任何有关使用蔚蓝密钥保险库和python的指南/提示都将非常感谢!

5 个答案:

答案 0 :(得分:5)

以下代码在以下代码运行之前需要执行以下步骤...希望我能记住一切!

  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 secret show [vault] [secret]

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

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

  4. 然后,以下代码将允许您使用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 :(得分:2)

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

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

答案 2 :(得分:1)

对于使用 Key Vault 的 REST API,reference documentationservice documentation 应该会有所帮助。

现在通过 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)

答案 3 :(得分:0)

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

您可以提前了解权限和资源,但通常会更准备好让您的代码始终处理401,特别是如果您使用多个保险库。

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

答案 4 :(得分:0)

我为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")