Interacting with Azure Key Vault using python w/ rest api

别说谁变了你拦得住时间么 提交于 2020-01-15 06:58:10

问题


I am very interested in using the new service recently released for secret management within Azure. I have found a few example guides walking through how to interact with key vault via powershell cmdlets and c#, however haven't found much at all in regards to getting started with using the rest API.

The thing I am particularly confused with is the handling of oauth2 w/ active directory. I have written a oauth2 application listener, built a web application with an AD instance and can now generate a "access_token". It is very unclear to me how to proceed beyond this though, as I seem to consistently receive a 401 HTTP resp code whenever attempting to use my access_token to perform a key vault API call.

Any guides / tips on using azure key vault with python would be greatly appreciated!


回答1:


Here are some steps you'll need to do before the following code will work... Hopefully I remembered everything!

  1. You'll need to have an application in AD with at least get access

    note: you need this to get the CLIENT_ID and CLIENT_SECRET anyway then run:

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

  2. You'll also need the id's for your secrets, which you can get with the Azure CLI using:

    azure keyvault secret show [vault] [secret]

    or

    azure keyvault secret show -h # if this is unclear

  3. Copy the key (last argument in the URL)

Then the following code will allow you to query the key vault using 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('')



回答2:


Here are a couple of things that you can check:

  1. When you make the request for the Bearer token, make sure that you include the "resource" header, and that it is set to "https://vault.azure.net". If you don't, you'll get a token, but you won't be able to access any vault data with it.
  2. When you make a call to the vault.azure.net URL, make sure you include the correct "api-version" It can be found in the API documentation. The current value is "2015-02-01-preview".
  3. Of course, check that the Key Vault Access Policy is set correctly for the vault you are trying to access.



回答3:


When Key Vault returns a 401 response, it includes a www-authenticate header containing authority and resource. You must use both to get a valid bearer token. Then you can redo your request with that token, and if you use the same token on subsequent requests against the same vault, it shouldn't return a 401 until the token expires.

You can know the authority and resource in advance, but it's generally more robust to prepare your code to always handle the 401, specially if you use multiple vaults.

Be sure to only trust on a www-authenticate header of a valid SSL connection, otherwise you might be a victim of spoofing!




回答4:


I have written a simple python wrapper for the REST APIs for Azure Key Vault. You can check out out here AzureKeyVaultPythonSDK

Crust of the logic is here

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


来源:https://stackoverflow.com/questions/29149806/interacting-with-azure-key-vault-using-python-w-rest-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!