4

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.

Laurent Mazuel
  • 3,422
  • 13
  • 27
90abyss
  • 7,037
  • 19
  • 63
  • 94
  • No idea, the Bearer token may have the wrong audience in or something along those lines - try asking in https://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 Aug 30 '17 at 20:01
  • 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](https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal#assign-application-to-role). – Shui shengbao Aug 31 '17 at 01:15
  • 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 Aug 31 '17 at 01:23
  • What's the specific azure python you're using? I assume you are using the latest one which is 2.0.0rc6 – juvchan Aug 31 '17 at 02:47

5 Answers5

6

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.

Den
  • 16,686
  • 4
  • 47
  • 87
4

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.

juvchan
  • 6,113
  • 2
  • 22
  • 35
2

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

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

Gajen Sunthara
  • 4,470
  • 37
  • 23
1

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)

mccoyp
  • 252
  • 1
  • 7
1

One can use the below class from azure.identity i.e ClientSecretCredential, find the below code ex: snippet

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

TENANT= <TenantId-in-string>
CLIENT_ID = <ClientId-in-string>
CLIENT_SECRET= <ClientSecret-in-string>
credential = ClientSecretCredential(TENANT,CLIENT_ID,CLIENT_SECRET)
VAULT_URL= <AzureVault-url-in-string>
client = SecretClient(vault_url=VAULT_URL, credential=credential)

print(client)
example_secret = client.get_secret(<secret_name_in_string>)
print(example_secret.value)