1
votes

This Python script is deployed to run from Azure Function App on Linux Consumption plan, This script is expected to read secrets from Azure Key Vault.

Apart from code deployment, following configurations are made

  1. System Assigned Managed Access Enabled for Azure Function App
  2. Azure Key Vault's Role Assignments Reference this Function App with Reader role.

Here is the script from __init.py__

import azure.functions as func
import os
from azure.identity import ManagedIdentityCredential
from azure.keyvault.secrets import SecretClient

def main(mytimer: func.TimerRequest) -> None:
    identity = ManagedIdentityCredential()
    secretClient = SecretClient(vault_url="https://vault-name.vault.azure.net/", credential=identity)
    secret = secretClient.get_secret('secret-name').
    print (secret.value)

This function app requires following libraries and defined in requirements.txt file

azure-functions
azure-keyvault-secrets
azure-identity

This function runs and ends up following exception.

Result: Failure Exception: HttpResponseError: (Forbidden) The user, group or application 'appid=6fb8XXXX-bba6-4fa7-8a76-a193XXXXd8d7;oid=e4c1XXXX-602d-44b7-a2e6-f646XXXXe360;iss=https://sts.windows.net/320bXXXX-7580-46ef-a61a-7f3fXXXXbe8f/' does not have secrets get permission on key vault 'vault-name;location=northcentralus'. 
For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287 Stack: 

File "/azure-functions-host/workers/python/3.7/LINUX/X64/azure_functions_worker/dispatcher.py", 
line 315, in _handle__invocation_request self.__run_sync_func, invocation_id, fi.func, args) File "/usr/local/lib/python3.7/concurrent/futures/thread.py", 
line 57, in run result = self.fn(*self.args, **self.kwargs) File "/azure-functions-host/workers/python/3.7/LINUX/X64/azure_functions_worker/dispatcher.py", 
line 434, in __run_sync_func return func(**params) File "/home/site/wwwroot/FunctionAppName/__init__.py", 
line 14, in main secret = secretClient.get_secret('secret-name') File "/home/site/wwwroot/.python_packages/lib/site-packages/azure/core/tracing/decorator.py", 
line 83, in wrapper_use_tracer return func(*args, **kwargs) File "/home/site/wwwroot/.python_packages/lib/site-packages/azure/keyvault/secrets/_client.py", 
line 71, in get_secret **kwargs File "/home/site/wwwroot/.python_packages/lib/site-packages/azure/keyvault/secrets/_shared/_generated/v7_0/operations/_key_vault_client_operations.py", 
line 1625, in get_secret map_error(status_code=response.status_code, response=response, error_map=error_map) File "/home/site/wwwroot/.python_packages/lib/site-packages/azure/core/exceptions.py", 
line 102, in map_error raise error

This error describes that the Application does not have Secrets get permission on Key Vault, But as mentioned above Role assignments are made to Function App with Reader role on Key Vault.

What will be the possible issue with configuration and how to mitigate?

2

2 Answers

3
votes

In order to read secrets you actually need to create an access policy and add the managed identity related to your Azure Function:

enter image description here

1
votes

You can also update Key Vault access policies through the Azure SDK, using the azure-mgmt-keyvault library. Here's an example of how you could give your app permission to get secrets, which would resolve your issue:

from azure.identity import ManagedIdentityCredential
from azure.mgmt.keyvault import KeyVaultManagementClient
from azure.mgmt.keyvault.v2019_09_01.models import AccessPolicyEntry, AccessPolicyUpdateKind, SecretPermissions, Permissions, VaultAccessPolicyParameters, VaultAccessPolicyProperties

subscription_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
tenant_id = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
object_id = "object ID of your app"
client_id = "client ID of your app"

credential = ManagedIdentityCredential()
client = KeyVaultManagementClient(credential, subscription_id)

permissions = Permissions(secrets=[SecretPermissions.get])
access_policy = AccessPolicyEntry(
    tenant_id=tenant_id,
    object_id=object_id,
    application_id=client_id,
    permissions=permissions
)
access_policy_property = VaultAccessPolicyProperties(access_policies=[access_policy])
access_policy_params = VaultAccessPolicyParameters(properties=access_policy_property)

client.vaults.update_access_policy(
    resource_group_name="resource-group",
    vault_name="vault-name",
    operation_kind=AccessPolicyUpdateKind.add,
    parameters=access_policy_params
)

(I work on the Azure SDK in Python)