Azure Keyvault - "The operation "List" is not enabled in this key vault's access policy." while creating keyvault programmatically - azure

I am creating azure keyvault using .net core 2.1 with OpenIdConnect with following AccessPolicies
AccessPolicies = new List<AccessPolicyEntry>()
{
new AccessPolicyEntry
{
TenantId = Guid.Parse(tenantId),
ObjectId = objectId,
Permissions = new Permissions
{
Secrets = new List<string> { "all" },
Keys = new string[] { "all" },
Certificates = new string[]{"all" }
}
}
}
using that, now, I can create keyvault but while go to newly created keyvault(in Azure portal) settings blade {Key,Secrete,Certificate} it shows warning
"The operation "List" is not enabled in this key vault's access policy."
Note :- As shown in above code "All permission are given".I can see it in azure portal.
What I have tried :-
I have tried to refer following stack-overflow already question-answer
Azure Keyvault - "Operation "list" is not allowed by vault policy" but all permissions are checked
How do I fix an "Operation 'set' not allowed" error when creating an Azure KeyVault secret programmatically?
according to above stackoverflow answer(s) "need to pass the object ID of the service principal of the Azure AD application instead of object ID of your Azure AD application".
I have tried to find out object ID of the service principal of the azure AD application using following powershell script
Get-AzADServicePrincipal -ServicePrincipalName "<app client ID>"
it gives following result
I have tried to use "Id"(in above screenshot) in objectId of AccessPolicyEntry but it not solved problem.
Question :-
Is any other permission need to set in AccessPolicyEntry?
What should be the objectID in AccessPolicyEntry(currently, I am giving obectId of Azure AD application)?
If needed objectId of service princpal. how can get it programmatically?

Well, I can reproduce your issue on my side.
First, the operation pass the object ID of the service principal instead of object ID of your Azure AD application is completely correct. After giving all the permissions to the service principal in the Access policies, the service principal will have the permissions.
But when you check the keyvault in the portal, you are using your user account which login the azure portal instead of the service principal, it caused the warning.
So if you want to fix the warning, just add your user account in the Access policies via + Add Access Policy button in the portal, or you can specify the object id of your user account in your code with the permissions when creating the keyvault.
Then about your questions:
Is any other permission need to set in AccessPolicyEntry?
No, the permissions are enough.
What should be the objectID in AccessPolicyEntry(currently, I am giving obectId of Azure AD application)?
You should not use the object id of the AD App, your option is to use the object id of the service principal/security group/user account, it depends on your requirement, details here.
If needed objectId of service principal. how can get it programmatically?
You can use the powershell command as you used, or the Azure CLI az ad sp show via the service principal name.
Or if you could use Microsoft Graph SDK for C# along with the filter, something like:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var serviceprincipals = await graphClient.Serviceprincipals
.Request().
.Filter("some condition").
.GetAsync();

Related

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.

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.

Azure AD - Add app principal to a Group

I have an Azure AD app (AAD App1) which has user assignment enabled. So only, users from a particular group let's say "Group A" can access any resource (let's say an Azure Function API) protected by that Azure AD app.
Now I have another daemon Azure function job, which needs to make an authenticated call to the above mentioned Azure function API. Since this is a daemon job, I have generated another Azure AD app (AAD App2) for this.
Below is my code to get access tokens:
string resourceId = "id of app used to authenticate azure function"; // AAD app ID used by the Azure function for authentication
string clientId = "id of app registered for the daemon job";// AAD app ID of your console app
string clientSecret = "secret of app registered for the daemon job"; // Client secret of the AAD app registered for console app
string resourceUrl = "https://blahblah.azurewebsites.net/api/events";
string domain = "<mytenant>.onmicrosoft.com"; //Tenant domain
var accessToken = await TokenHelper.GetAppOnlyAccessToken(domain, resourceId, clientId, clientSecret);
Now when I try to generate access token to access the Azure function API, I get an invalid grant error as below:
AdalException:
{"error":"invalid_grant","error_description":"AADSTS50105: Application
'' is not assigned to a role for the application
''.\r\nTrace ID:
6df90cf440-c16d-480e-8daf-2349ddef3800\r\nCorrelation ID:
4c4bf7bf-2140-4e01-93e3-b85d1ddfc09d4d\r\nTimestamp: 2018-05-09
17:28:11Z","error_codes":[50105],"timestamp":"2018-05-09
17:28:11Z","trace_id":"690cf440-c16d-480e-8daf-2349ddef3800","correlation_id":"4c4bf7bf-2140-4e01-93ef3-b85d1dc09d4d"}:
Unknown error
I am able to properly generate AAD access tokens if I disable the user assignment.
I am trying to avoid creating a service account here. Is there anyway I can add an app principal to an Azure AD group or add it as a member of another Azure AD app?
Unfortunately, you cannot add an AAD application/service principal as a member of Azure AD group.
I have confirmed this issue in My Answer for another similar question [EDIT - now seems to be possible, see said answer]
You can also upvote this idea in our Feedback Forum. Azure AD Team will review it.
Hope this helps!

Add AAD application as a member of a security group

I'm trying to enable service to service auth using AAD tokens. My plan is to validate "groups" claim in the token to make sure the caller is a member of a security group that we created.
For example, we will create group1 for readers and group2 for writers. Then based on "groups" claim, I will figure out the right access level.
I use AAD app to issue the tokens (not a user), so I need that app to be a member of the security group. Azure AD powershell doesn't seem to accept application ids as group members. How to solve this? are there any other recommended patterns when the caller is another AAD app?
Command used:
https://learn.microsoft.com/en-us/powershell/module/azuread/Add-AzureADGroupMember?view=azureadps-2.0
Error:
Add-AzureADGroupMember : Error occurred while executing AddGroupMember
Code: Request_BadRequest
Message: An invalid operation was included in the following modified references: 'members'.
RequestId: 0441a156-3a34-484b-83d7-a7863d14654e
DateTimeStamp: Mon, 11 Dec 2017 21:50:41 GMT
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
At line:1 char:1
+ Add-AzureADGroupMember -ObjectId "9c2cdf89-b8d6-4fb9-9116-7749adec85c ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-AzureADGroupMember], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.AddGroupMember
Unfortunately, you cannot add an application as a member of Azure AD group.
Though the official document for the Powershell cmdlet Add-AzureADGroupMember doesn't make clear you cannot use Application's ObjectId as the RefObjectId, absolutely you cannot use it.
You cannot add an application as a member of Azure AD group neither.
For example, we will create group1 for readers and group2 for writers.
Then based on "groups" claim, I will figure out the right access
level.
For your scenario, I'm afraid that you couldn't achieve this for now. I understand why you need this. According to your request, my thought is assigning your application from Enterprise Application to Groups or users and manger users with different access rights. However, you cannot choose more roles for the selected group. The only one role is default access If want to define more roles for the app, you can refer to this documentation.
I also tried to use Azure AD RBAC and create new conditional access for my test app,but all don't have read only this choice.
You can also put your idea in Azure Feedback Forum, azure team will see it. Also, I will upvote your idea.
Update:
Currently, you can add a service principal to an AAD Group:
Example:
$spn = Get-AzureADServicePrincipal -SearchString "yourSpName"
$group = Get-AzureADGroup -SearchString "yourGroupName"
Add-AzureADGroupMember -ObjectId $($group.ObjectId) -RefObjectId $($spn.ObjectId)
Updated 2:
Recently, I also see lots of users want to assign roles to a service principal to let the service principal have some permissions to access to the app with a role.
I want to make clear here. Role-based authorized should be used for users, NOT applications. And it's not designed for applications. If you want to give some different permissions you may consider to assign application permissions to your service principal instead.
You can expose your Web App/API with application permissions by editing the Manifest in app registrations.
You can go to Azure portal > Azure Active Directory > App registrations > Select your App > Manifest.
In appRoles, you can insert content like this:
{
"allowedMemberTypes": [
"Application"
],
"displayName": "Access to the settings data",
"id": "c20e145e-5459-4a6c-a074-b942bbd4cfe1",
"isEnabled": true,
"description": "Administrators can access to the settings data in their tenant",
"value": "Settingsdata.ReadWrite.All"
},
Then, you can go another app registration you want to give permission > Settings > require permissions > Add > Search the application name you want to access > Choose the application permission you created before.
Therefore, your sp can obtain a token with that application permissions in token claims.
Also, for authorization from the resource, you need to add code logic to give control policy for that token with Settingsdata.ReadWrite.All claim.
Update 3
Currently, you can add the service principal to one AAD Group directly in Azure portal:
Following Update 3 in the answer of #Wayne Yang, I've successfully implemented this using C# and the MS Graph SDK.
But I think the same should be possible using Powershell and simple REST API calls.
// create new application registration
var app = new Application
{
DisplayName = principal.DisplayName,
Description = principal.Description,
};
app = await _graphClient.Applications.Request().AddAsync(app);
// create new service Principal based on newly created application
var servicePrincipal = new ServicePrincipal
{
AppId = app.AppId
};
// add service principal
servicePrincipal = await _graphClient.ServicePrincipals.Request().AddAsync(servicePrincipal);
// add service principal to existing security group
await _graphClient.Groups[groupId].Members.References.Request().AddAsync(servicePrincipal);

New-AzureRmRoleAssignment programmatically in a .NET Core console application

It seems I'm on a journey to first programmatically create an Azure application and then use Azure Management APIs to do create some resource. There's a new snag I'd like to ask from the community, how to do basically the PowerShell command New-AzureRmRoleAssignment -RoleDefinitionName Owner -ServicePrincipalName $adApp.ApplicationId.Guid using HttpClient (or some smarter method with the exact needed permissions using Microsoft Graph API libraries).
Trying to be a better person this time (being more around, providing code), I prepared a repo in GH, but the issue basically boils down to what kind of a URI should be used (here). The code is
var roleAssignment = $"{{something here}}";
var roleAssignementContent = new StringContent(roleAssignment, Encoding.UTF8, "application/json");
var roleAssignmentResponse = await client.PostAsync($"https://graph.windows.net/{tenants.value[0].tenantId}/applications/{createdApplication.appId}?api-version=1.6", roleAssignementContent).ConfigureAwait(false);
var roleAssignement = await roleAssignmentResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
I fiddled with Graph API Explorer too if things were easier using it (or the libraries) but with less luck. Indeed, the ultimate goal is to create application programmatically so that it becomes possible to use Azure Management Libraries to make a deployment. That is, all in code from the beginning to an end.
(Also, the code is of throwaway quality, to provide a more functioning example only.)
New-AzureRmRoleAssignment is used to assign the specified RBAC role to the specified service principal , you could achieve that by using the Resource Manager create role assignment API:
Get ObjectId of application service principal.
if you have got the objectId of application service principal before , you could skip this step .If not , you could use Azure ad graph api to request an application's service principal by application id :
GET https://graph.windows.net/<TenantID>/servicePrincipals?$filter=servicePrincipalNames/any(c:%20c%20eq%20'applicationID')&api-version=1.6
Authorization: Bearer eyJ0eXAiOiJK*****-kKorR-pg
Get Azure RBAC role identifier
To assign the appropriate RBAC role to your service principal, you must know the identifier of the Azure RBAC role(Owner in your scenario), you could call the Resource Manager role definition API to list all Azure RBAC roles and search then iterate over the result to find the desired role definition by name.:
GET https://management.azure.com/subscriptions/ed0caab7-c6d4-45e9-9289-c7e5997c9241/providers/Microsoft.Authorization/roleDefinitions?$filter=roleName%20eq%20'Owner'&api-version=2015-07-01
Authorization: Bearer
Assign the appropriate RBAC role to service principal:
PUT https://management.azure.com/subscriptions/ed0caab7-c6d4-45e9-9289-c7e5997c9241/providers/Microsoft.Authorization/roleAssignments/16fca587-013e-45f2-a03c-cfc9899a6ced?api-version=2015-07-01
Authorization: Bearer eyJ0eXAiOiJKV1QiL*****FlwO1mM7Cw6JWtfY2lGc5
Content-Type: application/json
{
"properties": {
"roleDefinitionId": "/subscriptions/XXXXXXXXXXXXXXX/providers/Microsoft.Authorization/roleDefinitions/XXXXXXXXXXXXXXXXX",
"principalId": "XXXXXXXXXXXXXXXXXXXXX"
}
}
roleDefinitionId is the id you get in step 2 ,principalId is the objectId you get in step 1 . ed0caab7-c6d4-45e9-9289-c7e5997c9241 is the subscription id ,16fca587-013e-45f2-a03c-cfc9899a6ced is a new guid created for the new role assignment .
Please refer to below document for more details :
Use Resource Manager authentication API to access subscriptions

Resources