Azure Key Vault: The user, group, or app does not have secrets set permission on key vault - azure

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.

Related

BotBuilder Authentication Multitenant

I want to create Microsoft BotBuilder following this tutorial. But it seems SO complicated compared to v3.(BTW: starting a tutorial with 3 authentications that cover 75% of the article is not a good sign)
So I follow the EchoBot sample (I chose MultiTenant because my server is outside AND it seems the most covered):
const credentialsFactory = new BotBuilder.ConfigurationServiceClientCredentialFactory({
MicrosoftAppId: '***',
MicrosoftAppPassword: '***',
MicrosoftAppType: 'MultiTenant',
});
const botFrameworkAuthentication = BotBuilder.createBotFrameworkAuthenticationFromConfiguration(null, credentialsFactory);
const onTurnErrorHandler = async (context, error) => { /* for errors */ }
const adapter = new BotBuilder.CloudAdapter(botFrameworkAuthentication);
adapter.onTurnError = onTurnErrorHandler;
Questions:
How do I test everything is working ? isValidAppId() and isAuthenticationDisabled() are the only available method and seems OK.
How do I get MicrosoftAppPassword ? According to the documentation I have to click manage, then create a value/secret pair. Should I use value ? or secret ? Why none is named password ? Anyway none works ...
To test if it works, I follow the sample:
setup an HTTP POST Endpoint (with Node-RED)
declare the endpoint in Azure Portal Bot Configuration
go to webchat to test
I correctly receive the Messages then try to do some authentication/parisng (I assume) :
await adapter.process(msg.req, msg.res, (context) => {
/* do some stuff */
});
But it fails with a very explicit error :
Error: 1 validation issue(s)
Issue #0: custom_error at [[root]]
Response
I think, the errors is related to an authentication issue, since I don't understand what/how to set the password. I guess I have to go through this CloudAdapter in order to get a parsed context and be able to send messages.
EDIT 07/05/2022:
I use the AppId from here :
I click "Manage" but where is the AppPassword ?
EDIT 12/05/2022:
Using cURL I manage to validate the appID and appPassword (the value (hidden by stars) of the secret).
BotBuilder is mixing the Communication Stack (HTTP / WebSocket) and the Logic stack (Turn Conversation). I think it's a bad habbit but I manage a workaround:
I use a BotFrameworkAdapter instead of CloudAdpater
I call adapter.processActivity() instead of adapter.process()
The adapter still want to end() the request and set deprecated values but it works in Node-RED. The context handle all the requirement to call sendActivity() anywhere multiple times.
To answer second question in your case, kindly go through the link :https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration?view=azure-bot-service-4.0&tabs=multitenant
To answer the first question in your case, kindly check disabling and enabling the authentication to test the app: https://learn.microsoft.com/en-us/azure/bot-service/bot-service-troubleshoot-authentication-problems?view=azure-bot-service-4.0&tabs=csharp
As far as getting the password goes, when you create a new Multi Tenant Azure Bot resource, the app password goes into the Azure Key Vault created alongside it. The AppId and AppPassword are randomly generated by Azure. You can get them from the key vault in the Azure portal in the correct resource group.
If you want to create a resource manually using the CLI and define your own password, you can use this docs page for deploying a bot. Make sure you select the correct tabs. I have pre-selected C# and Multi Tenant in a new resource group for the above link.
Single Tenant is for limiting your bot's connections to Azure resources within the same tenant, and a User Assigned Managed Identity is if you want to make use of an Azure Managed Identity across the bot's resources instead of having a password for each resource.
You should be able to simply add the AppId and AppPassword to the echo bot sample and deploy it.

Unable to get access token. 'AADSTS500011: The resource principal named 'xxx' was not found in the tenant -tenantid

I am trying to get the access token for the Azure function app. I have enabled managed identity for the function app(system assigned). but while fetching the token using the nuget Azure.Identity.
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { "https://xxx.azure-api.net/" + "/.default" }) { }
);
I am getting the error.
The resource principal named 'xxx.azure-api.net' was not found in
the tenant 123
but when run az cli to check the subscription details, the subscription indeed part of the tenant 123 only.
Here is what I have finally done.
I have registered an App in AD. and Exposed the API of that App.
I have assigned System Assigned Managed Identity to the Function.
In the local I am not able to request token because Azure CLI is not given consent.
After deploying the application in Function my Function app can request a token using its identity.
You need to register the application in azure ad and enable the access token. Once that is done the you need to provide RBAC access to your xxx.azurewebsites.net
Follow this article for the step by step documentation Microsoft Document Reference
Unfortunately, the error message is not really helpful. But adding a scope to the app registration solved the problem for me:
In Azure Portal navigate to App Registrations
Find your app, in the left side menu select Manage => Expose an API
Add a scope. I named mine api_access as this was where this error occurred.
In my case I then got an API URI (like api://client-id/scope_name) which I used in my Angular app. Error message was gone.
Also, make sure that in the Enterprise Application you have created, under Manage => Properties, "Assignment required" and "Visible to users" is turned on.

How to use Azure Key Vault in npmrc file?

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!

Access denied linking variable group to key vault in VSTS

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.

How to give MSI enabled Function App access to Key Vault?

I have a Function App with Managed service identity (MSI) enabled.
I'm trying to use this Function App to access a secret from my Key Vault.
I have added the code into my Function App to retrieve the secret.
AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
var secret = await keyVaultClient.GetSecretAsync("https://test-prototype-vault.vault.azure.net/secrets/batman/guidhere").ConfigureAwait(false);
I receive the following error:
Microsoft.Azure.WebJobs.Script: One or more errors occurred. Microsoft.Azure.KeyVault: Access denied.
I think this is because I need to (as described in the link above).
You may need to configure the target resource to allow access from
your application. For example, if you request a token to Key Vault,
you need to make sure you have added an access policy that includes
your application's identity.
I don't know how to do that. I have gone to my Key Vault and tried to add an Access Policy - I can't find the application to Select Principle option.
Setup of Azure Function.
What happens when I try to add the principal.
This blog has details but you need to go into key vault and give the function app access to secrets in a new access policy
https://medium.com/#jeffhollan/getting-key-vault-secrets-in-azure-functions-37620fd20a0b
The name of your function app should show in list of users

Resources