3
votes

I need to retrieve secrets from keyvault. This is my code so far:

from azure.mgmt.keyvault import KeyVaultManagementClient
from azure.common.credentials import ServicePrincipalCredentials


subscription_id = 'x'
# See above for details on creating different types of AAD credentials
credentials = ServicePrincipalCredentials(
    client_id = 'x',
    secret = 'x',
    tenant = 'x'
)

kv_client = KeyVaultManagementClient(credentials, subscription_id)

for vault in kv_client.vaults.list():
    print(vault)

But I am getting this error:

msrestazure.azure_exceptions.CloudError: Azure Error: AuthorizationFailed Message: The client 'x' with object id 'x' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resources/read' over scope '/subscriptions/x'.

Now I am able to access the same keyvault with same credentials using C# code/ POwershell so there is definitely nothing wrong with authorization. Not sure why it isnt working using SDK. Please help.

4
No idea, the Bearer token may have the wrong audience in or something along those lines - try asking in github.com/Azure/azure-sdk-for-python/issues if you're sure the SPN is good for that resource. Try to find a way to turn on tracing, maybe it hints you about what's in the token.evilSnobu
Your code works for me, I could list secrets in the key vault. If possible, could you give your service principal Owner pernission and try again. Assign application to role.Shui shengbao
Also, you could give Contributer permission, it also works for me. It is very strange, I am not sure why the service principal works on C# and PowerShell. But, I suggest you could check and try give permission.Shui shengbao
What's the specific azure python you're using? I assume you are using the latest one which is 2.0.0rc6juvchan

4 Answers

4
votes

If you are looking to access via a ServicePrincipalCredentials instance, you can just use:

from azure.keyvault import KeyVaultClient, KeyVaultAuthentication
from azure.common.credentials import ServicePrincipalCredentials

credentials = None

def auth_callback(server, resource, scope):
    credentials = ServicePrincipalCredentials(
        client_id = '',
        secret = '',
        tenant = '',
        resource = "https://vault.azure.net"
    )
    token = credentials.token
    return token['token_type'], token['access_token']

client = KeyVaultClient(KeyVaultAuthentication(auth_callback))

secret_bundle = client.get_secret("https://vault_url", "secret_id", "")

print(secret_bundle.value)

This assumes that you don't want to pass a version. If you do, you can substitute the last parameter for it.

3
votes

I run your code sample above and it is able to list the key vaults without any issue, hence it is not a code issue.

I have assigned the Contributor role to my AD application on the subscription where the key vault is provisioned and set the Access Policies to allow GET & LIST permissions for Key and Secret to the AD application.

The versions of my Azure Python packages used running under Python 3.6.2 runtime environment:

  • azure.common (1.1.8)
  • azure.mgmt.keyvault (0.40.0)
  • msrestazure(0.4.13)

I'll recommend you to try on the Python runtime version and Azure Python packages versions which is verified working.

Addendum:

If the above Python runtime environment version as well as Azure Python packages also does not work for you, you should probably consider creating a new issue in the Azure SDK for Python GitHub as it is working with the same credential with Azure .NET SDK as well as PowerShell.

1
votes

You can also get secret by the name of the secret instead of ID:

secret_bundle = client.get_secret(<VAULT URL>, "<NAME>", "")

0
votes

There are some good answers already, but the Azure SDK has since released new packages for working with Key Vault in Python that replace azure-keyvault:

azure-identity is also the package that should be used with these for authentication.

Documentation for working with the secrets library can be found on the azure-sdk-for-python GitHub repository, and here's a sample for retrieving secrets as you were doing:

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

credential = DefaultAzureCredential()

secret_client = SecretClient(
    vault_url="https://my-key-vault.vault.azure.net/",
    credential=credential
)
secret = secret_client.get_secret("secret-name")

You can provide the same credentials that you used for ServicePrincipalCredentials by setting environment variables corresponding to the client_id, secret, and tenant:

export AZURE_CLIENT_ID="client_id"
export AZURE_CLIENT_SECRET="secret"
export AZURE_TENANT_ID="tenant"

(I work on the Azure SDK in Python)