0
votes

I'm trying to acquire the secret (dbUser password) from an Azure key vault that I created. When I run the below code it throws exception where no valid token could be acquired.

        public static string GetDBConnectString(ILogger logger)
        {
            try
            {
                string dbUserName = Environment.GetEnvironmentVariable("SqlDBUsername"); // [dbUserName]
                logger.LogInformation($"Info: Creating DB Connection string as user {dbUserName}.");
                AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
                KeyVaultClient keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                string vaultConnect = Environment.GetEnvironmentVariable("SqlDBKeyvault"); // ["https://keyvault.vault.azure.net/secrets/dbUserName/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
                // The below line fails
                SecretBundle secret = keyVaultClient.GetSecretAsync(vaultConnect).GetAwaiter().GetResult();
                string sqlConnection = string.Format(Environment.GetEnvironmentVariable("SqlDBConnectionString"), dbUserName, secret.Value);
                return sqlConnection;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message, ex);
                return string.Empty;
            }
        }

Exception.Message = "Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried the following 3 methods to get an access token, but none of them worked. Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Managed Service Identity. Unable to connect to the Managed Service Identity (MSI) endpoint. Please check that you are running on an Azure resource that has MSI setup. Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Exception for Visual Studio token provider Microsoft.Asal.TokenService.exe : TS003: Error, TS002: The account '[email protected]' was not found in the tenant 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'. "

I've seen the various solutions here where a ClientId authorization is created but all those require a username/password to create which defeats the purpose of the vault?

Has anyone a solution that does not require user's credentials to open the vault?

2

2 Answers

2
votes

There are two types of identities: system-assigned identity and user-assigned identity. The one you need is system-assigned identity, where your Azure function will be used to retrieve the secrets from key vault.

Rather than reading the secret value inside your function, you should add a setting which will retrieve it from key vault.

Example:

Key           Value
MySecret      @Microsoft.KeyVault(SecretUri=secret_uri_with_version)

enter image description here

then in your code, you'll use:

 Environment.GetVariable("MySecret);

More info:

https://azure.microsoft.com/en-us/blog/simplifying-security-for-serverless-and-web-apps-with-azure-functions-and-app-service/

https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity?tabs=dotnet

0
votes

The below change to the code worked for local development. Still have to identify a method that works universally when it deploys. Tried using "RunAs=App;AppId={valid app id}" but it failed to connect.

Making sure the tools > options > AzureServiceAuthentication account is chosen and VS is connected to the Azure cloud.

This works.

AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider("RunAs=Developer; DeveloperTool=VisualStudio");