As I understand, so long as I setup grants to KeyVault, my function should be able to read from it by using
#Microsoft.KeyVault(SecretUri=MYSECRETFULLURL), and I assume this would be transformed at run-time?
Any idea how I would debug this?
Currently, as thats getting to my function, is the above, with nothing transformed.
Running as system-managed.
If I debug, this is all I get:
However I can see my audit on azure key vault its being hit.
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
ILogger log)
{
var accountToMoveFrom = System.Environment.GetEnvironmentVariable("accountToMonitor");
log.LogCritical(accountToMoveFrom);
var accessToken = System.Environment.GetEnvironmentVariable("accessToken");
}
Adding the final resolution:
Make sure you do not have the "authorized application" or applicationId settings configured.
From the documentation
Create an access policy in Key Vault for the application identity you created earlier. Enable the "Get" secret permission on this policy. Do not configure the "authorized application" or applicationId settings, as this is not compatible with a managed identity.
Note: Does your code actually work? Logging the value of a key is intercepted and is displayed as
#Microsoft.KeyVault(SecretUri=MYSECRETFULLURL)
in logs to avoid sensitive configuration from KeyVault ending up in
log files that may reach a wider audience.
It works fine as per the docs (extract below), also double check you have:
Managed Service Identity (MSI) configured on the function app
Restarted your function app after adding the function's app setting
The function's MSI is given access to to the relevant KeyVault, not to the Management Plane but on the Access Policies.
If you are running/debugging locally in Visual Studio, you need to give the account signed in to Visual Studio rights on the Key Vault since because it is the identity presented.
Sourcing Application Settings from Key Vault The Key Vault references feature makes it so that your app can work as if it were
using App Settings as they have been, meaning no code changes are
required. You can get all of the details from our Key Vault reference
documentation, but I’ll outline the basics here.
This feature requires a system-assigned managed identity for your app.
Later in this post I’ll be talking about user-assigned identities, but
we’re keeping these previews separate for now.
You’ll then need to configure an access policy on your Key Vault which
gives your application the GET permission for secrets. Learn how to
configure an access policy.
Lastly, set the value of any application setting to a reference of the
following format:
#Microsoft.KeyVault(SecretUri=secret_uri_with_version)
Where secret_uri_with_version is the full URI for a secret in Key
Vault. For example, this would be something like:
https://myvault.vault.azure.net/secrets/mysecret/ec96f02080254f109c51a1f14cdb1931
Related
I am creating a script using Azure CLI that will automatically generate an App Registration (service principal), and then use that App Registration to create a secret that will be stored in Azure Key Vault.
However, I am getting the following error:
The user, group or application 'appid=04b07795-8ddb-461a-bbee-02f9e1bf7b46;oid=0ec2b0e8-daeb-46a8-b627-0d4f61f87157;numgroups=134;iss=https://sts.windows.net/72f988bf-86f1-41af-91ab-2d7cd011db47/' does not have secrets set permission on key vault 'asakeyabcfelaqpgsfnxcy;location=eastus'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287
Can anyone provide guidance on what this ID is and how to resolve this error? This is not my App Registration Object ID or App ID.
I think there're 2 points you're now concerning, one is you failed to add secret, another is the app id in the error message is not the one you registered.
I think you've followed the document to execute the cli command, so I just want to explain the second point. Pls allow me show you a code sample for a better explanation.
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
public async Task<IActionResult> PrivacyAsync()
{
var kvUri = "https://your_vault_name.vault.azure.net/";
var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
_ = await client.SetSecretAsync("test0311", "hello");
return View();
}
When we want to add key vault secret to azure, we need to provide a credential so that our operations are authenticated. This is the DefaultAzureCredential() here, and it has several sources to get the authentication like screenshot below.
That means if someone sets the environment variables for authentication, then it will cover the information you entered when executing cli command, this may usually cause the issue that the app is different from what you set. I think you may follow this document to check all your configurations and try again, or you can directly add environment variables with the app you registered on your computer.
By the way, pls don't forget to add access policy in azure portal for the azure ad app you registered.
I have a secret personal access token (only for building purposes) in my .npmrc file. As this secret is exposed, I thought of replacing this using Azure Key Vault. I haven't found any documentation around it. When I created the personal token before, I had given it only packaging/building access. How can I achieve this, please help me with this? Or is there any better way to include the personal access token in the .npmrc file?
Since you confirmed you are using Azure DevOps for your build, you don't need to maintain PAT in the .npmrc file. Just keep your npm registry URL there (I assume the private npm registry is also in the Azure DevOps) like below:
registry={your npm registry URL}
always-auth=false
Now, in the build pipeline, add npm Authenticate task before npm install.
- task: npmAuthenticate#0
inputs:
workingFile: <relative path to your .npmrc file>
Providing secrets to your resource can be done in many ways.
Some resources in Azure allow you to specify environment variables through the Azure CLI. Here's an example with the Azure container instances: link.
On Azure, once you have a Key Vault instance, you can use your Key Vault to provide secrets to your App Service and Azure Function instances. This is documented here: link, with a focus for Azure Resource Manager templates, which is specially useful for automated deployments.
Although the following is explained in the documentation link above, the general picture on how to use Key Vault secrets from other Azure resources requires the following:
Make a user assigned identity or Azure Active Directory application.
Grant access to this identity (or AAD app) by going to the Access Policies of your Key Vault (this can be done through the portal, of course), and giving your identity at least read access to your Key Vault.
After that, create a secret on your Key Vault, go to the secret details and copy the "Secret Identifier". This will be a URI similar to: https://myvault.vault.azure.net/secrets/mysecret/.
That's the URI you can use to bring Key Vault secrets to other resources.
You'll be able to access this secret from other resources by ensuring the resource has access to the same identity, and by providing the URI through a syntax similar to: #Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/).
For example, if you link an Azure Function to the same identity you granted read access to your Key Vault, you can provide a secret through environment variables by setting configuration properties in your resource. By going to the Azure Portal, locating your resource, then going to Configuration, then to Application settings, if you proceed to add the name of your environment variable, and as the value something similar to: #Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/mysecret/), you'll be providing the expected environment variable with the expected secret value to your resource.
The final approach I can think of is by using the #azure/keyvault-secrets client. If using an NPM library to retrieve Key Vault secrets sounds interesting, this is the dependency for you. All the information needed to work with this library should be available on NPM: same link. But in any case, a sample using this client would look as follows:
const { DefaultAzureCredential } = require("#azure/identity");
const { SecretClient } = require("#azure/keyvault-secrets");
const credential = new DefaultAzureCredential();
const client = new SecretClient(`https://my-key-vault.vault.azure.net`, credential);
async function main() {
const secretName = "MySecretName";
const latestSecret = await client.getSecret(secretName);
console.log(`Latest version of the secret ${secretName}: `, latestSecret);
}
main();
You could use this library to load your secrets at any point while your service or program is running.
Please let me know if this information is useful for you. I'm here to help!
In my Startup.cs I add key vault clients as such:
services.AddAzureClients(s =>
{
var keyVaultUri = new Uri(Configuration["KeyVault:Uri"]);
s.AddCertificateClient(keyVaultUri);
s.AddSecretClient(keyVaultUri);
s.UseCredential(new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
VisualStudioTenantId = Configuration["AzureAd:TenantId"]
}));
});
Locally, I can authenticatie with the VisualStudioCredential. All works fine. When deployed I run into the following error:
The key vault returns a 401 even though I successfully got a token. I am using Access Control on the key vault and it my Managed Identity is a Key Vault Administrator.
What could be going on here and how can I debug this further? I have been stuck on this for a while now.
EDIT:
Title is misleading and what I thought was happening was not happening. There was no authentication issue but it looked as such in the logs due to another exception I was getting. This was occurring due to the fact my App Service Plan didn't have SSL/TLS functionality required to work with certificates, I needed a more expensive App Service Plan.
Please see this GitHub issue: https://github.com/dotnet/runtime/issues/30658#issuecomment-523987878
You need to give your Managed Identity an access policy on the Key Vault, not an RBAC access.
RBAC in this case is for management plane operation. Access policies are for data plane operations - which is what you want.
https://learn.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault
I am pretty new to Azure and I am trying to simulate a real production environment.
So, I've deployed a .netcore 3.1 app to an AppService resource. This web app is able to get the configuration from two other services - KeyVault and App Configuration. I already have configuraed the AppService identity.
I can get the keys from KeyVault using the following code:
var settings = config.Build();
var web = settings["KeyVault:Name"];
var clientId = settings["KeyVault:ClientId"];
var clientSecret = settings["KeyVault:ClientSecret"];
config.AddAzureKeyVault($"https://{web}.vault.azure.net/",
clientId,
clientSecret);
As I can get the keys from the App Configuration:
var settings = config.Build();
config.AddAzureAppConfiguration(settings["AppSettings:Endpoint"]);
And I am able to use them both at the same time through identities and AppConfiguration's key reference
var settings = config.Build();
config.AddAzureAppConfiguration(options =>
{
options
.Connect(settings["AppSettings:Endpoint"])
.ConfigureKeyVault(kv =>
{
kv.SetCredential(new DefaultAzureCredential());
});
});
So, my question is about the code snippet #3: is it safe to store the AppSettings:Endpoint value the appconfig.json in a production environment? To be clear, I am referring to this value:
Moreover, I found here and explanation on how to use the two services together. But first of all, that solution doesn't work for me - I get an Azure.Identity.CredentialUnavailableException: 'ManagedIdentityCredential authentication unavailable, no managed identity endpoint found.'.
On the second hand, he's not clear on where to store the AppSettings:AppConfiguration:Endpoint and AppSettings:Identity:ClientId values, it doesn't answer to my first question then.
Thanks in advance
Short answer - the endpoint https://[your_app_name].azconfig.io is safe to leave anywhere. It does nothing without the other parts that make up the connection string.
Long answer - you can and probably should store the parts that are sensitive, connection strings and their parts, in Key Vault as secrets. If your code needs those values you have options on how to get the values to it. Consider using the web config (it's equivalent as a place that would ordinarily have the secret values but put Key Vault references there instead. Your way works also. Keep in mind that your way may require a code change if your config shifts away from what you've coded.
Be sure that your access policy on KV is using the service principal of your app. I repeat, be sure that your access policy on KV is using the service principal of your app. It will likely only need permissions "list" and "get" for secrets and NOTHING ELSE.
Do not store secrets in your web config or its equivalent. Key Vault is almost free, it's so cheap. I don't deploy apps without them getting their own vault as part of the solution.
Leave comments if this is unclear or needs web references.
You should be able to use Azure Marange Identity to connect to APP Configuration. Use Azure.Identity preview version.
c# Example
https://github.com/nishanperera/Azure-App-Configuration-With-Key-Vault
When I try to link a variable group to key vault in VSTS, every time I select my endpoint, it tells me:
"Specified Azure endpoint needs to have "Get, List" secret management permissions on the selected key vault. Click "Authorize" to enable VSTS to set these permissions or manage secret permissions in Azure portal."
It makes no sense. That specific endpoint has Get and List for secrets, keys, certificates. The endpoint is using the correct Service Principal Client ID- I know because I pulled its corresponding app registration up in Azure by searching with that ID. And the app registration is specifically listed in the key vault's Access policies, with the correct permissions.
Trying to click "Authorize" in VSTS just give me
"Resource not found for the segment 'DirectoryDataService.getServicePrincipalsByAppIds'. For troubleshooting refer to https://go.microsoft.com/fwlink/?linkid=835898"
and the endpoint is broken until I re-verify it.
I'm kind of at my wit's end here- everything is set exactly as https://learn.microsoft.com/en-us/vsts/build-release/concepts/library/variable-groups?view=vsts says it should be.
Edit: Turns out the Azure tried to add the app reg as a person instead of an app when I listed it in the ARM template by object ID (app ID most definitely does not work there). So now I just need to figure out how to add it as an application in the ARM template...
Edit Edit: Soooo... the Object ID the Azure Portal shows for an App Registration? That's not the Object ID the ARM template wants. It wants the... I'm not sure what you'd call it. In Powershell, you use it with -Object ID, but when you list the properties, it's under "Id". Whatever. To get it, you run
Get-AzureRmADServicePrincipal -SearchString "[your-app-reg-name]"
And it shows up under Id. That's what you want to use as an object ID in your ARM template.
According to the error Resource not found for the segment 'DirectoryDataService.getServicePrincipalsByAppIds, the issue seems more related to Azure side.
To access azure-keyvault you need four things :
- clientId = "<client id of your application registed on Azure AD>";
- domain = "<your talnet id>";
- secret = "<client key of your application registed on Azure AD>";
- subscription = "<your subscription id>";
Then these will combine ApplicationTokenCredentials, finally Authorize to KeyVaultClient . Suggest you take a look at this question: Azure keyvault client 1.0.0 initiate client
Besides also double check/confirm the specific endpoint has Get and List for secrets, keys, certificates.