What are the EXACT perms needed to use Get-AzureRmRoleAssignment as an app via a ServicePrincipal - azure

I've seen posts like this one where there is confusion on exactly what permission is required to allow a ServicePrincipal to call Get-AzureRmRoleAssignment when logging in using Login-AzureRmAccount.
In my case if I call Get-AzureRmRoleAssignment with the -debug flag I can capture the following error in the body of the HTTP response:
Body:
{
"odata.error": {
"code": "Authorization_RequestDenied",
"message": {
"lang": "en",
"value": "Insufficient privileges to complete the operation."
}
}
}
I have set perms for the application as follows... first the Azure AD access:
And then the Microsoft Graph access:
This still gives the authZ failure error. I have even tried an experiment where I gave the app ALL perms for each API, and that still did not work.
What's missing? What perms EXACTLY are needed to allow read only programmatic access to list the role assignments with this call?

First, as I answered in that case, Get-AzureRmRoleAssignmentdoesn't only needs read access for role assignment with Azure REST API permission but also needs Read directory data permission with Azure AD Graph API. After adding permissions,
Add AAD Graph API Permission:
You also need to click Grant permissions button to do admin consent.
Add Azure REST API Persmssions:
Also, before adding AAD graph API permissions for your sp, ensure your sp has permissions with Azure REST API by assigning a role (E.g. A Contributor Role) to it from Subscriptions RBAC(IAM).
I test this and succeeded.

Related

Unexpected 403 in Sharepoint rest api list items roleassignments call

We created a sharepoint add-in with the follow permissions:
<AppPermissionRequests AllowAppOnlyPolicy="true"><AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="Read"/></AppPermissionRequests>
My understanding is that an app with tenant scope permissions should be able to read all the site contents. In this case the call to
/_api/web/lists('<id>')/items(<id>)/roleassignments
fails with the following error:
Client error 403
{
"odata.error":
{
"code":"-2147024891, System.UnauthorizedAccessException",
"message":
{
"lang":"en-US",
"value":"Access denied. You do not have permission to perform this action or access this resource."
}
}
}
Note that a call to /_api/web/lists('<id>')/items(<id>) for the same item works fine. The roleassignments call with tenant permissions is also working for one of the SPO instances but not for a different one.
We've struggled with this issue on and off, because the solution is not obvious, nor even sensible from a least-privilege perspective. In short:
Your application requires FullControl rights in order to access RoleAssignments.
More details
If using an application created by Azure AD, you can demonstrate this by granting and consenting to SharePoint permissions such as:
AllSites.Read (delegated)
MyFiles.Read (delegated)
Sites.Selected (application)
User.Read.All (delegated)
User.Read.All (application)
If using SharePoint-created application, use appregnew.aspx and appinv.aspx to create the app and grant it Read rights at some reasonable scope; try http://sharepoint/content/tenant.
Then get a bearer token using a client_credentials workflow (use Postman, for example).
Try a query like:
https://your-tenant.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('/Shared Documents')/Files?$select=Length,TimeLastModified,ListItemAllFields,ServerRelativeUrl
Make sure the Authorization header value is Bearer your-access-token
It will work.
Now try the same query, but with getting role assignments:
https://your-tenant.sharepoint.com/_api/web/GetFolderByServerRelativeUrl('/Shared Documents')/Files?$select=Length,TimeLastModified,ListItemAllFields,ServerRelativeUrl&$expand=ListItemAllFields/RoleAssignments/RoleDefinitionBindings/Name
It will fail as you described, with status 403 and System.UnauthorizedAccessException.
Now grant and consent to the SharePoint application permission Sites.FullControl.All, or use appinv.aspx to add FullControl rights. Get a new bearer token. (The old one encodes the old rights granted to the app in the role field of the payload.). You'll need to wait a few minutes until the permissions apparently propagate from AD to SharePoint, if you're using an Azure AD application.
Try the last query again, and it will work.
IMHO, requiring FullControl in order to resolve something like a role assignment, which is needed to capture the permissions required to access content in a SharePoint library, is unjustified. I could understand, sort of, if tenant-scope Read permission were required. However, granting AllSites.Read or tenant-scope (http://sharepoint/content/tenant in appinv.aspx XML permissions) doesn't seem to enable roleassignment lookup.

Create Azure AD group with Group.Create Permission

I am trying to create an Azure AD Group via the Graph API using a service principal. The intent is that the service principal will create the group in a Pipelines run.
The call I am using to attempt to create the group is
az rest --method post \
--uri 'https://graph.microsoft.com/v1.0/groups' \
--body '{"description": "A description", "displayName": "MyAppGroup", "mailEnabled": false, "mailNickname": "test", "securityEnabled": true, "owners#odata.bind": ["https://graph.microsoft.com/v1.0/users/oooooooo-oooo-oooo-oooo-oooooooooooo"]}' \
--headers "Content-Type=application/json"
To graph permissions, I have bound the API permission Group.Create to my service principal. To understand the permissions I am required to grant, I am following this page:
https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=http#permissions
With the Group.Create permissions, when I run the rest call to the Graph API above, I get the following permission error
Forbidden({
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"date": "2020-11-02T13:31:35",
"request-id": "...",
"client-request-id": "..."
}
}
})
I completely understand that if I were to add the Directory.ReadWrite.All, I could make the group and would have all required permissions. However this permission is overscoped and would allow my service principal to disable users in the Active Directory tenant - something my organisation will now allow. Therefore I cannot grant my service principal this permission.
The documentation I have linked above implies to me that Group.Create is a sufficient permission to enable a service principal to create a group.
My question is what I am doing wrong, or what permissions am I missing to be able to create a group? Directory.ReadWrite.All is clearly overscoped to simply create an AD security group and so using it is not an option for me.
Hopefully this helps someone else - I realised the answer immediately after posting this.
I had added the property
"owners#odata.bind": ["https://graph.microsoft.com/v1.0/users/oooooooo-oooo-oooo-oooo-oooooooooooo"]
to the json post data.
Removing this property allowed me to create the group with just the Group.Create permission.
Adding the permission User.Read.All allows the service principal to read the user data for the owner, and so is sufficient to create the group with any necessary owners.
After adding this API permission, my service principal was able to create the group (with owners) as expected.

Azure : Permission for Service Principal to get list of Service Principals

I am using the Fluent Azure SDK for .NET to try fetching the list of all service principals in the tenant.
var authenticatedContext = Azure.Authenticate(
await SdkContext.AzureCredentialsFactory.FromServicePrincipal(aadClientId, aadClientSecret, tenantId, "AzureGlobalCloud")
);
var sps = authenticatedContext.ServicePrincipals.ListAsync().GetAwaiter().GetResults();
The service principal with the AAD Client Id has Directory.Read.All API permission.
(Just to be sure I'm not missing anything : I see this permission in ServicePrincipal -> Permissions section in the Azure Portal)
But still, the following error is thrown :
Microsoft.Azure.Management.Graph.RBAC.Fluent.Models.GraphErrorException: Operation return an invalid status code 'Forbidden'
However, the callouts to get ADGroup and list of subscriptions work
var subs = authenticatedContext.Subscriptions.ListAsync().GetAwaiter().GetResults();
var sgs = authenticatedContext.Subscriptions.ActiveDirectoryGroups().GetByIdAsync(someId).GetAwaiter().GetResults();
I don't know what permissions are missing.
I test the code in my side, and use fiddler to catch the request. It seems the sdk request Azure AD graph api but not Microsoft graph api to list the service principals. So you need to add permission Directory.Read.All of AAD graph but not Microsoft graph. Please refer to the steps below:
After adding the permission, do not forget grant admin consent for it. Then you can run your code success to get the service principal.
By the way, there is a bug with AAD permission Directory.Read.All. If we add AAD permission Directory.Read.All into the registered app, then the permission can not be removed even if we remove it from the page. So you still can run the code success even if you remove the Directory.Read.All from "API permissions" tab on the page.

Azure Function Authentication: Azure Active Directory: Use Security Group to include identities (users and service principals) to access Function

I have an Azure Function with Azure Active Directory authentication enabled (including "Action to take when request is not authenticated" = "Log in with Azure Active Directory"). Additionally the option "User assignment required?" of the Azure Function related service principal (sp_func) is set to "Yes" to avoid everybody in the tenant being able to in the end run the function.
The goal is to have a single security group (that can include users as well as service principals) that is added to "Users and groups" of sp_func so that the assignment to the group decides if the function can be accessed or not. With users this works fine but not with service principals (sp_nonfunc). For them (sp_nonfunc) to work I have to set the permissions for them (sp_nonfunc) what in the end allows them to interact with the Azure Function no matter if they (sp_nonfunc) are assigned to the group or not.
Is it possible that I can just add a service principal (sp_nonfunc) to a group with the group being added to sp_func and then be able to execute the Function by using sp_nonfunc (without giving explicit permissions to sp_nonfunc)?
EDIT: it also does not seem to be possible to add sp_nonfunc to sp_func directly even if I defined an own appRole in the Manifest. The only way currently seems to be to add permissions on sp_nonfunc for sp_func - but that is what I want to avoid.
EDIT2: here how I have defined the role in the sp_func manifest
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"displayName": "AzureFunctionAccess",
"id": "xxx-xxx-xxx-xxx-xxx",
"isEnabled": true,
"description": "Access Azure Function.",
"value": "AzureFunctionAccess"
}
]
EDIT3: when I don't assign a role directly to sp_nonfunc but just add sp_nonfunc to the security group I get, when making a request to https://login.microsoftonline.com/<tenant id>/oauth2/token with resource = Application ID URI of the registered app of sp_func:
{
"error": "invalid_grant",
"error_description": "AADSTS501051: Application 'xxx-xxx-xx-xx-xx'(xxx) is not assigned to a role for the application 'https://xxx'(xxx).\r\nTrace ID: xxx-xxx-xx-xx-xx\r\nCorrelation ID: xxx-xxx-xx-xx-xx\r\nTimestamp: xx-xx-xx xx:xx:xxZ",
"error_codes": [
501051
],
"timestamp": "xx-xx-xx xx:xx:xxZ",
"trace_id": "5xxx-xxx-xx-xx-xx",
"correlation_id": "xxx-xxx-xx-xx-xx",
"error_uri": "https://login.microsoftonline.com/error?code=501051"
}
This way will not work, to use a service principal(in your case, the sp_nonfunc) get the token for the function app(sp_func), you need to give the API permission for the sp_nonfunc.
Navigate to the App Registration related to the sp_nonfunc in the portal -> API permissions -> add the AzureFunctionAccess you defined, at last click the Grant admin consent for xxx button.
Then get the token with the client credential flow, it will work fine. (I use the v2.0 endpoint, if you use the v1.0, it will also work.)
For more details about the steps, I wrote in this post before, you could refer to it.

Microsoft Azure AD Graph API to add member to a group

Trying to add members to a group using Microsoft graph API, was able to add member to the group to which Application owner is the owner of but not to the group that was created by other member.
When I try to add member to the group and Application owner is not the owner of the group, I am receiving the following error
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "2c5a99ff-70XXXXXXXXXXXXXXXXX",
"date": "2X-XX-XXXX 23:42:54"
}
}
}
These are the permissions given to the App API
Can someone help me understand how the add member to group works with Azure? only group owner will be able to add member to the group? Is there any configuration that needs to be enabled for Application to let Application owner add member to any group?
If you are using Delegated permissions, the effective permissions of a token will be the combined permissions of the app and user.
If the user does not have the necessary role/ownership, then your app can't do it either.
If your app needs to act with more permissions than the user has, you'll need to use application permissions instead of delegated permissions.
To use app permissions, your app back-end must acquire tokens using the client credentials flow, which does not involve a user.
In this case only the application's app permissions matter, delegated permissions will have no effect.

Resources