- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
- OverflowAI GenAI features for Teams
- OverflowAPI Train & fine-tune LLMs
- Labs The future of collective knowledge sharing
- About the company Visit the blog
Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Get early access and see previews of new features.
Staging Ground badges
Earn badges by improving or asking questions in Staging Ground.
Assign an app-role to a managed-identity service principal
Like demonstrated here , I want to secure an Azure Function app with AzureAD and only be able to call/invoke it from an Azure API Management instance (with system-assigned managed identity enabled). This works fine. However I really want to isolate access to the API (Functions app). As it stands now, ANY app in my tenant would be able to successfully authenticate and invoke the API. Therefore, I chose to enable user-assignment for that app registration.
So basically, there is 1 API (Azure Functions) that is AzureAD protected. Then there is 1 service calling the API (Azure API Management). Without a role-assignment there is the following error message I can understand.
So I created an app role in the API's app registration. The normal guidance on how to assign such a role to an application can be found here (EDIT: WRONG LINK SEE ANSWER) . However this does only apply to the service principal manually created (read: not a MSI) because this requires the service principal can be found in the portal UI. This is not the case with anything related to a mangaged-identity.
Since the above link also states that assignment can also be done using the Graph API I tried this as a workaround.
This does not work yielding the following error response (I have tried appId and objectId for id/principalId/resourceId):
Do you have any suggestions on what could be done? Any help is greatly appreciated.
- azure-active-directory
- azure-functions
- microsoft-graph-api
- azure-api-management
- Reading this answer, the correct way to dit is to use objectIds (which I also tried). The guy answering also blogged about this, which is exactly what I want to do.... so the approach appears to be valid, still it's not working in my specific case. – baouss Commented Mar 16, 2021 at 22:06
The MS-Graph link in the doc was false. It referred to the assignment of a role to a user, though an application in the linking text body was implied. This is the correct reference.
POST / servicePrincipals /{objectId}/appRoleAssignments
Also make sure, that in case you have created the Azure subscription with a personal account (eg. outlook.com, hotmail.com) to not use the bearer token of that user in the graph call. Instead create a user in AzureAD, assign proper permissions, and use that account's token.
Your Answer
Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more
Sign up or log in
Post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .
Not the answer you're looking for? Browse other questions tagged azure-active-directory azure-functions microsoft-graph-api azure-api-management or ask your own question .
- The Overflow Blog
- Brain Drain: David vs Goliath
- How API security is evolving for the GenAI era
- Featured on Meta
- Preventing unauthorized automated access to the network
- Upcoming initiatives on Stack Overflow and across the Stack Exchange network...
- Proposed designs to update the homepage for logged-in users
Hot Network Questions
- How does speed telemetry displayed in SpaceX live videos work?
- Convert french spelled out numbers to integer
- Pickles with protons
- Can you make all the squares the same color?
- Why do some of the Galilean moons receive so much less radiation than others?
- Is it possible to transfer files and copy text from VirtualBox with QNX to Windows 10 without Guest Addition?
- Why does a Fenestron tail rotor require so much speed compared to an open rotor?
- Is Ukraine considering restoring nuclear weapons?
- Is it ever reasonable to infer impossibility from high improbability?
- Fraction with a numerator having a long exponent
- How might a creature be so adapted to the temperature of its home planet that it can't survive on any other without protection?
- Why does Alien B, who can't see Alien A (and vice versa), crash their ship specifically into Alien A?
- What's the Name of this Debating/Rhetorical Strategy?
- 50s B&W sci-fi movie about an alien(s) that was eventually killed by cars' headlights
- Why is my voltage divider circuit not accurate?
- What would happen if a natural disaster occurred on election Day?
- Horror film from the 60's that ends with the protagonist kissing a woman, who becomes a rotten corpse
- How to translate interjections/sounds like "whoa" and "gulp" into German?
- How did the money go from buyers to the firm's account?
- What is the significance of the bizarre lizard-like charm Ralph Bohner uses in "Agatha All Along"?
- Could there be a legitimate reason for a SSH server to allow null authentication, to anyone?
- Learning music theory on guitar and piano at the same time
- What was "the amnesty" that Voices from Chernobyl refers to?
- What is the significance of Paramus as the location of Ralph Bohner's one-man show in "Agatha All Along"?
Add-PnPAzureADServicePrincipalAppRole
Required Permissions
- Microsoft Graph API: AppRoleAssignment.ReadWrite.All and Application.Read.All or AppRoleAssignment.ReadWrite.All and Directory.Read.All
Adds an app role to a service principal/application registration in Azure Active Directory.
By built in type
By resource, description.
Allows adding of an app role such as Sites.FullControl.All to a service principal/application registration in Azure Active Directory. This can be used to grant permissions to a service principal/application registration, such as a Managed Identity.
Adds the permission Directory.Read.All for Microsoft Graph to the service principal with the object id 62614f96-cb78-4534-bf12-1f6693e8237c
Adds the permission Site.FullControl.All for SharePoint Online to the service principal with the object id 62614f96-cb78-4534-bf12-1f6693e8237c
Adds the permission Group.ReadWrite.All for Microsoft Graph to the service principal with the name mymanagedidentity.
Adds the permission MyApplication.Read for the application registration with object id b8c2a8aa-33a0-43f4-a9d3-fe2851c5293e to the service principal with the object id 62614f96-cb78-4534-bf12-1f6693e8237c
The object id, name or instance of the service principal/application registration to add the app role to.
The object id, name or instance of the application role to add to the service principal/application registration.
-BuiltInType
The built in application type to use for the app role. This can be MicrosoftGraph or SharePointOnline.
The object id, name or instance of the application to which the role belongs you wish to add to the service principal/application registration. If omitted, it will try to define the owning service principal from the passed in AppRole.
-Connection
Optional connection to be used by the cmdlet. Retrieve the value for this parameter by either specifying -ReturnConnection on Connect-PnPOnline or by executing Get-PnPConnection.
RELATED LINKS
Microsoft 365 Patterns and Practices Microsoft Graph documentation
Microsoft 365 Security
Everything about microsoft security, everything about service principals, applications, and api permissions.
Service Principals are identities used by created applications, services, and automation tools to access specific resources. It only needs to do specific things, which can be controlled by assigning the required API permissions. The majority of organizations that work a lot with Azure AD, have service principals as well. Every time when an application has been registered. It will automatically create an application object, and a service principal in a tenant.
An service principal can authenticate via two different options. The first one is via password-based authentication, whereby an client secret has been created for an application.
The second option is to use certificate-based authentication. This form of authentication is done via an certificate, which can be self-signed for instance.
API Permissions
As discussed previously, we know that applications have certain API permissions assigned to it. This allows an application being able to access the specific resources that it needs.
We can see for example that this application has ‘Directory.ReadWrite.All’ permission assigned to it, which is considered an sensitive permission. This allows a Service Principal to grant admin consent through automation for example. Having this permission assigned to an application is not immediately the end of the world, because there are legit use-cases that require it. One of the use-case to grant an application ‘Directory.ReadWrite.All’ is, to allow an application to make backups of Azure AD.
SolarWinds Campaign
During the SolarWinds campaign, we have seen adversaries targeting Service Principals, in order to access Microsoft 365 mailboxes of users.
Let’s now take a step back. At the beginning of the blog post, we discussed that once an application has been registered. It will automatically create an application object and a service principal.
Once the application has been registered. We are able to assign API permissions to the application to allow it perform specific operations. This could include the following ‘Mail.Read’ permissions, which allows a Service Principal to read all the mailboxes of users.
Organizations have tons of different applications, but how often are these permissions reviewed? – I can tell from experience it rarely happens. An other important thing to highlight is, that organizations don’t monitor Service Principals in the first place nor understand what applications are considered ”critical”.
What applications are considered critical?
As we (may) know, organizations have tons of different applications. Every application contains certain permissions, but not every application is immediately critical. I believe there should be some form of ‘baseline’ in terms of what API permissions are considered ”critical”.
Great thing is that Microsoft has shared this with us, and they have marked the following API permissions as sensitive:
- Mail.* (including Mail.Send*, but not Mail.ReadBasic*)
- Contacts. *
- MailboxSettings.*
- Directory.AccessAsUser.All
- User_Impersonation
Delegated and AppOnly versions of the following permissions:
- Application.ReadWrite.All
- Directory.ReadWrite.All
- Domain.ReadWrite.All*
- EduRoster.ReadWrite.All*
- Group.ReadWrite.All
- Member.Read.Hidden*
- RoleManagement.ReadWrite.Directory
- User.ReadWrite.All*
- User.ManageCreds.All
- All other AppOnly permissions that allow write access
We can use the AzureADIR PowerShell module of Microsoft to make an export of all the permissions that have been assigned to applications.
In order to install this module, we have to run the following command:
Once the PowerShell module has been installed, we have to run the following command:
Now we have to connect to our Azure AD tenant.
We are now connected with our tenant. The final step is to run the following command, which will export all the application permissions in a CSV file.
Application Permissions Types
There are two types of permissions, which are known as ‘ Application ‘ and ‘ Delegated ‘ permission types. Besides that, there is a term known as effective permissions , which are the permissions that your application has, when it makes a request to the target resource.
Application permissions are used by apps that run without a signed-in user present, for example, apps that run as background services.
For application permissions, the effective permissions of your app are the full level of privileges . For example, an app that has the Mail.Read permission can read the mailboxes of every user in the organization.
Delegated permissions are used by apps that have a signed-in user present. For these apps, either the user or an administrator consents to the permissions that the app requests. The app is delegated with the permission to act as a signed-in user when it makes calls to the target resource.
For delegated permissions , the effective permissions of your app are the least-privileged intersection of the delegated permissions the app has been granted (by consent) and the privileges of the currently signed-in user. Your app can never have more privileges than the signed-in user.
Let’s assume your app has been granted the User.ReadWrite.All delegated permission . This permission nominally grants your app permission to read and update the profile of every user in an organization. If the signed-in user is a global administrator or equivalent, your app can update the profile of every user in the organization. However, if the signed-in user doesn’t have an administrator role, your app can update only the profile of the signed-in user. It can NOT update the profiles of other users in the organization, because the user that it has permission to act on behalf of, doesn’t have the rights.
Analyzing Permissions
We have made an export of all the permissions that are associated with the applications. The second step is now to analyze the permissions. As discussed previously, Microsoft has some kind of baseline when it comes down to permissions, that are classified as ‘sensitive’. This means that not every application is considered critical if it doesn’t have a sensitive permission.
During this example, we will be using Azure Data Explorer. This allows us to ingest the CSV files and query it with Kusto. However, it does not mean that ADX is required. Feel free to use something else that can help in analyzing datasets.
Application Permission
- Here we are running a simple query to display the permissions of each application.
At the sample result, we can see all the applications with the associated permission(s). I have left the display name of the application out of the results due to privacy reasons.
2. The second step is to look for applications with sensitive permissions. Microsoft has shared an list of API permissions to look at, which we will be using in our query.
At the sample result, we can see all the application with the specified permissions.
3. Last part will now only look at the applications that are considered ”critical”, because they may have one of the sensitive permissions.
At the sample result, we can see 3 applications. These are the applications that have sensitive permissions and need to be monitored properly.
Delegated Permission
An reminder, but delegated permissions are used by apps that have a signed-in user present. For these apps, either the user or an administrator consents to the permissions that the app requests. The app is delegated with the permission to act as a signed-in user when it makes calls to the target resource.
This section is basically the exact same thing as the previous one, but with the focus on the ‘Delegated’ permission types.
- We are now looking at the delegated permission type. This will be a simple query to display all the delegated permission types that are associated with each application.
At the sample result, we can see a couple of applications.
At the sample result, we can see different application that have at least one of the specified permission(s).
3. Last part will now look at the applications that are considered ”critical”, because they may have one of the sensitive permissions.
At the sample result, we can see a couple of application that have one of the specified permission(s).
How to get visibility in Service Principals and Applications?
We can use Log Analytics to configure these data sources. It is very important to do this, because Service Principal Sign-Ins logs, as well as Non-Interactive User sign-in logs, are NOT stored in Unified Audit Logs. This means that, when we are looking at it from a forensics perspective. We won’t be able to determine where a SP has logged in or what kind of Non-Interactive logins were happening, and so on.
There are some interesting use-cases that we will cover later in this blog post, which will include detection as well.
In order to create a Log Analytics workspace:
- Go to the Azure Portal
- Search for “Log Analytics workspace” in the search bar and press enter
- Click on “Create”
- Fill the rest of information in and finish
Once we have finished that:
- Go to the Azure Portal
- Click on “Azure Active Directory”
- Click on “Diagnostic settings”
- Click on “Add diagnostic setting”
Select the following data sources:
- NonInteractiveUserSignInLogs
- ServicePrincipalSignInLogs
Service Principal Sign-Ins from untrusted location
This section will cover an interesting use-case with Log Analytics. The plan is to create an detection rule once a Service Principal has signed-in from a untrusted location.
Once we have Service Principal Sign-In logs enabled. We can start querying the logs by calling the ‘AADServicePrincipalSignInLogs’ table.
Before we are doing that, we will first look at the ‘ Application ‘ permission type, and list all the Applications that we considered critical. There were 3 results in this example.
The second step is to understand from which IP range(s) or addresses the Service Principal usually sign-ins from. If you already collecting ‘AADServicePrincipalSignInLogs’ in Log Analytics, you can run the following query as an example.
At the sample result, we can see that the Service Principal has signed-in from 7 different IP addresses. The important thing now is to verify if it’s legitimate or not.
Let’s say that we could verify all of them and the IP addresses are legit. We can start writing a KQL query, whereby we will exclude a list of IP addresses or ranges. In order to do this, we can use the ipv4_is_match( ) function in KQL.
At the sample result, we can now see there are 0 results. This means that once a Service Principal would sign-in from an IP address that was not listed in our query. We can alert on it!
We still have two applications left that have sensitive permissions, so we have to do it for those applications as well. Once everything is finished. We can start finalizing our KQL query, which may look like the following:
There are no results now. However, when one of the specified Service Principals sign-ins from a different IP address, that is not listed in the query. We can start alerting on it.
Here is an example of creating an alert based of a KQL query.
Non-Interactive User Sign-In Logs
Non-interactive user sign-ins are sign-ins that were performed by a client app or an OS component on behalf of a user. Like interactive user sign-ins, these sign-ins are done on behalf of a user. The device or client app uses a token or code to authenticate or access a resource on behalf of a user.
Read this one more time:
Ok, we are now going to explain this in steps. We can see an application with ‘User.ReadWrite.All’ and the permission type is set as ‘Delegated’
If we now run the following query:
We can see which identities have signed-in to the application. The App has ‘User.ReadWrite.All’ permission as we discussed before. However, it is important to look at which identities have signed-in to the application that are an Global Admin or equivalent.
As we discussed previously, delegated permissions are used by apps that have a signed-in user present. In order for an application to update the profile of every user in the organization. The signed-in user needs to be a Global Admin or equivalent in the tenant. When this is not the case, the application can update only the profile of the signed-in user.
Last thing, which is important to highlight. There is a huge blind spot for investigators, because API calls that have been made via MS Graph are not logged.
We started with explaining what Service Principals are and followed-up with a use-case on how they have been abused in real cases. Once we have done that, we started explaining what API permissions are considered ‘sensitive’ by Microsoft, and how we can audit those permissions with the AzureADIR PowerShell module.
After we made an export of all the application permissions. We have learned the difference between ‘Application’ and ‘Delegated’ permission types. It can be confusing sometimes, so it’s good to understand the difference.
After that, we covered some use-cases with Log Analytics. This helps us to get visibility in our Service Principals and Applications.
- Microsoft Graph permissions reference: https://github.com/microsoftgraph/microsoft-graph-docs/blob/main/concepts/permissions-reference.md
- AzureADIncidentResponse PowerShell Module: https://www.powershellgallery.com/packages/AzureADIncidentResponse/4.0
- Non-interactive logins: minimizing the blind spot: https://techcommunity.microsoft.com/t5/azure-sentinel/non-interactive-logins-minimizing-the-blind-spot/ba-p/2287932
- Log Analytics tutorial: https://docs.microsoft.com/en-us/azure/azure-monitor/logs/log-analytics-tutorial
- App consent grant investigation: https://docs.microsoft.com/en-us/security/compass/incident-response-playbook-app-consent
Share this:
- Click to share on Twitter (Opens in new window)
- Click to share on Facebook (Opens in new window)
- Click to share on LinkedIn (Opens in new window)
- Azure Active Directory
Leave a comment Cancel reply
- Already have a WordPress.com account? Log in now.
- Subscribe Subscribed
- Copy shortlink
- Report this content
- View post in Reader
- Manage subscriptions
- Collapse this bar
GoToGuy Blog
A blog about enterprise mobility + security, azure ad, datacenter management, service delivery, automation, monitoring, cloud os, azure and anything worthwhile sharing with the cloud and datacenter community., add graph application permissions to managed identity using graph explorer.
I use Managed Identites in Azure for a lot of different automation scenarios, for example if I want run a Logic App or an Azure Function that should securely call an API like Microsoft Graph..
In such a scenario, the Managed Identity, represented by its Service Principal, needs to be granted application permissions to the API. Let’s say for example that you want to list Intune Managed Devices in your Organization using the Microsoft Graph API, using a Function App or Logic App for example and connect to the Graph API using a Managed Identity.
Then you would need to give that Managed Identity an App Role assignment for the application permission in Graph that is called DeviceManagementManagedDevices.Read.All. If you use that Managed Identity for example in a Function App or Logic App, they could then call the Microsoft Graph API as illustrated below:
Currently there are no way to manage these application role assignments in the Azure Portal GUI. You can verify the permissions, but not add or remove them.
For reference, usually you would do this using cmdlets in Azure AD PowerShell:
See Gist from my GitHub on how to create App Role Assignment for Managed Identity using PowerShell
Today I would like to show how you can do this with a “GUI” after all, by using the Microsoft Graph Explorer!
Prerequisite – Sign in and Connect to Graph Explorer
Many of you might be familiar with Graph Explorer, but if you aren’t you can find it at the Microsoft Graph documentation site, or just use this short url: https://aka.ms/ge .
In Graph Explorer you need to sign in (and consent to permissions) so that you can access your organizations’ data via Graph API. Note that your organisation might have restrictions in place for users consenting to permissions for API’s, and in any case if you want to use my example here for adding Microsoft Graph API application permissions, you will need to be a Global Administrator anyway.
Part 1 – Find the Service Principal of the Managed Identity
The first thing we need to do is to find the Service Principal that represents your Managed Identity. I will assume that you already have a Managed Identity created and are familiar with the concept, if not you can read more about it and how to create on this link: https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview .
I will now search for the Service Principal in Graph Explorer. You can do this by running something similar to this query:
PS! You must add ConsistencyLevel = eventual i Request Header to be able to run the search and count parameter.
In my example I’m searching for a User Assigned Managed Identity that I know I have prefixed with the name “msi”, but you can also search for System Assigned Managed Identities, these will have the name of the resource you have assigned it to (name of the Function App, Logic App, etc).
When I run this example query currently in my tenant, I get a count of 5 service principals, one of which is the Managed Identity I’m looking for. The thing of interest for me here is the Id of the Service Principal, in the green box below. I have also a yellow box around the name of the Managed Identity, which you can see is a User Assigned Identity created in a Resource Group where I connect it to Logic Apps.
Take a note of that Id, you will need it later. You can now also get the Service Principal directly by Id:
Part 2 – Find the Service Principal of the Microsoft Graph (or other) API
Next, we also need to find the service principal in your organisation that represent your instance of the multi tenant App that is “Microsoft Graph”.
Microsoft Graph API always has the appId that is: 00000003-0000-0000-c000-000000000000
In every Azure AD organisation the Microsoft Graph API application is represented by a Service Principal, you can find this with the following query:
You will now need to note the “id” of that Service Principal, that will be the “resourceId” to be used later, and this resource “id” is different for every Azure AD organization/tenant:
Part 3 – Find the Application Role that will be the Permission you want to assign
Now that we have the Service Principal Id of the Managed Identity, and the Service Principal Id of the Microsoft Graph Resource in your Azure AD Organization, we need to find the Id of the actual application role permission you want to assign.
You can now use the Service Principal Id you retreived in part 2, to list all available app roles by appending /appRoles to the query:
Now, there are a lot of application role permissions for Microsoft Graph, so we need to do a search. Unfortunately, not all Graph resources support all OData filter queries, and not everything is documented, but as far I can see I cannot use $search or $filter inside a specific service principal resource. For example I would want to do something similar to this query:
But this will return an error like this:
This might be fixed at a later time, but for now we can just use the browser’s search function (CTRL+F), so when I query for all /appRoles, I will get them all listed, and then just search for the application permission I want:
Not so elegant, I know, but at least I will get that specific application role id I need for the next step.
(PS! Graph API will usually return max 100 values and in this case the Graph API has less than that. If there were to be more than 100 results, then the request will be paged and with a odata.nextlink for the next page of results).
Anyway, I now have the 3 parts I need to create the application role assigment for the Managed Identity.
Part 4 – Assign Application Role to Managed Identity
We can now assign the application role to the service principal, and as documented here , we will need the following 3 id’s:
- principalId: The id of the user, group or client servicePrincipal to which you are assigning the app role. This will be the id of the Managed Identity service principal we found in part 1 .
- resourceId: The id of the resource servicePrincipal which has defined the app role. This will be the id of the Microsoft Graph service principal we found in part 2 .
- appRoleId: The id of the appRole (defined on the resource service principal) to assign to a user, group, or service principal. This the app role id we found by searching the appRoles for the resource id in part 3 .
To create this assignement we need to do a POST query in Graph Explorer, with Content-Type application/json in the Header, and the following request body:
After you run this query, you should get a status of 201 Created and a response like the following:
You can now also verify this assignment in the Azure AD Portal. If you go to Enterprise Applications, and search for {your-managed-identity-service-principal-id}, you should find your Managed Identity. From there you can click on Permissions under Security, and you will see the application permissions that you have granted. PS! I had already added another for writes as well:
Part 5 – Managing Application Role Assignments
After adding application permissions for the Managed Identity, you can also use Graph Explorer for viewing current application role assignments, as well as remove existing role assignments.
To get App Role Assignments for the Service Principal that is your Managed Identity, use the following query:
This will return all the application permissions assigned to this Managed Identity Service Principal:
And then if you want to delete an application role assignment, you need to run a DELETE query as following:
The {appRoleAssignment-id} would be the “id” from the GET /appRoleAssignments shown above. When run successfully you should you should receive as status of 204 – No Content:
In this blog post I have show how you can use Graph Explorer to add Graph API application role permissions to your Managed Identity. Similar steps can be used against any Azure AD protected API other than Graph you would want your Managed Identity to access.
Thanks for reading!
Share this:
8 thoughts on “ add graph application permissions to managed identity using graph explorer ”.
Can we do this for already existing app on Azure AD ? Can managed identity work with Azure Ad app and Graph API ? instead of finding the appID of the permission?
Managed Identities can be given permissions for any API’s protected by Azure AD, so if you have an App exposed as an API, use that resource instead of the Graph API.
Pingback: Mailbox usage reports, Graph API, and Logic Apps. What's not to like? - JanBakker.tech
Pingback: Automated Intune Devices Report via Azure Automation with Managed Identity - Rui Qiu's Blog
This was super helpful. The only way I could figure out how to give a USER MANAGED identity Graph API permissions.
I found while doing some unrelated work a much easier way, there is a very handy cmdlet in the Sharepoint PNP module for this.
https://pnp.github.io/powershell/cmdlets/Add-PnPAzureADServicePrincipalAppRole.html
You only need the object ID you for the managed identity which you can view in the automation account. After that just add the appropriate permission.
Pingback: Build your own Security Copilot using Azure Open AI and your data! | GoToGuy Blog
Pingback: Add Graph Application Permissions to Managed Identity using Bicep Graph Extension | GoToGuy Blog
Leave a comment Cancel reply
- Already have a WordPress.com account? Log in now.
- Subscribe Subscribed
- Copy shortlink
- Report this content
- View post in Reader
- Manage subscriptions
- Collapse this bar
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Steps to assign an Azure role
- 4 contributors
Azure role-based access control (Azure RBAC) is the authorization system you use to manage access to Azure resources. To grant access, you assign roles to users, groups, service principals, or managed identities at a particular scope. This article describes the high-level steps to assign Azure roles using the Azure portal , Azure PowerShell , Azure CLI , or the REST API .
Step 1: Determine who needs access
You first need to determine who needs access. You can assign a role to a user, group, service principal, or managed identity. This is also called a security principal .
- User - An individual who has a profile in Microsoft Entra ID. You can also assign roles to users in other tenants. For information about users in other organizations, see Microsoft Entra B2B .
- Group - A set of users created in Microsoft Entra ID. When you assign a role to a group, all users within that group have that role.
- Service principal - A security identity used by applications or services to access specific Azure resources. You can think of it as a user identity (username and password or certificate) for an application.
- Managed identity - An identity in Microsoft Entra ID that is automatically managed by Azure. You typically use managed identities when developing cloud applications to manage the credentials for authenticating to Azure services.
Step 2: Select the appropriate role
Permissions are grouped together into a role definition . It's typically just called a role . You can select from a list of several built-in roles. If the built-in roles don't meet the specific needs of your organization, you can create your own custom roles.
Roles are organized into job function roles and privileged administrator roles.
Job function roles
Job function roles allow management of specific Azure resources. For example, the Virtual Machine Contributor role allows a user to create and manage virtual machines. To select the appropriate job function role, use these steps:
Begin with the comprehensive article, Azure built-in roles . The table at the top of the article is an index into the details later in the article.
In that article, navigate to the service category (such as compute, storage, and databases) for the resource to which you want to grant permissions. The easiest way to find what your looking for is typically to search the page for a relevant keyword, like "blob", "virtual machine", and so on.
Review the roles listed for the service category and identify the specific actions you need. Again, always start with the most restrictive role.
For example, if a security principal needs to read blobs in an Azure storage account, but doesn't need write access, then choose Storage Blob Data Reader rather than Storage Blob Data Contributor (and definitely not the administrator-level Storage Blob Data Owner role). You can always update the role assignments later as needed.
If you don't find a suitable role, you can create a custom role .
Privileged administrator roles
Privileged administrator roles are roles that grant privileged administrator access, such as the ability to manage Azure resources or assign roles to other users. The following roles are considered privileged and apply to all resource types.
Azure role | Permissions |
---|---|
For best practices when using privileged administrator role assignments, see Best practices for Azure RBAC . For more information, see Privileged administrator role definition .
Step 3: Identify the needed scope
Scope is the set of resources that the access applies to. In Azure, you can specify a scope at four levels: management group , subscription, resource group , and resource. Scopes are structured in a parent-child relationship. Each level of hierarchy makes the scope more specific. You can assign roles at any of these levels of scope. The level you select determines how widely the role is applied. Lower levels inherit role permissions from higher levels.
When you assign a role at a parent scope, those permissions are inherited to the child scopes. For example:
- If you assign the Reader role to a user at the management group scope, that user can read everything in all subscriptions in the management group.
- If you assign the Billing Reader role to a group at the subscription scope, the members of that group can read billing data for every resource group and resource in the subscription.
- If you assign the Contributor role to an application at the resource group scope, it can manage resources of all types in that resource group, but not other resource groups in the subscription.
It's a best practice to grant security principals the least privilege they need to perform their job. Avoid assigning broader roles at broader scopes even if it initially seems more convenient. By limiting roles and scopes, you limit what resources are at risk if the security principal is ever compromised. For more information, see Understand scope .
Step 4: Check your prerequisites
To assign roles, you must be signed in with a user that is assigned a role that has role assignments write permission, such as Role Based Access Control Administrator at the scope you are trying to assign the role. Similarly, to remove a role assignment, you must have the role assignments delete permission.
- Microsoft.Authorization/roleAssignments/write
- Microsoft.Authorization/roleAssignments/delete
If your user account doesn't have permission to assign a role within your subscription, you see an error message that your account "does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/write'." In this case, contact the administrators of your subscription as they can assign the permissions on your behalf.
If you are using a service principal to assign roles, you might get the error "Insufficient privileges to complete the operation." This error is likely because Azure is attempting to look up the assignee identity in Microsoft Entra ID and the service principal cannot read Microsoft Entra ID by default. In this case, you need to grant the service principal permissions to read data in the directory. Alternatively, if you are using Azure CLI, you can create the role assignment by using the assignee object ID to skip the Microsoft Entra lookup. For more information, see Troubleshoot Azure RBAC .
Step 5: Assign role
Once you know the security principal, role, and scope, you can assign the role. You can assign roles using the Azure portal, Azure PowerShell, Azure CLI, Azure SDKs, or REST APIs.
You can have up to 4000 role assignments in each subscription. This limit includes role assignments at the subscription, resource group, and resource scopes. Eligible role assignments and role assignments scheduled in the future do not count towards this limit. You can have up to 500 role assignments in each management group. For more information, see Troubleshoot Azure RBAC limits .
Check out the following articles for detailed steps for how to assign roles.
- Assign Azure roles using the Azure portal
- Assign Azure roles using Azure PowerShell
- Assign Azure roles using Azure CLI
- Assign Azure roles using the REST API
- Tutorial: Grant a user access to Azure resources using the Azure portal
Was this page helpful?
Additional resources
Create and manage a Service Principal using the Azure CLI
This post explains how to create and how to manage a Service Principal using the Azure CLI
1. Introduction
A few weeks ago I started to learn about Github Actions , and my first goal was to create a simple workflow, that provisions a resource group on Azure using Terraform . I created a blank .yml file, and added the necessary steps until I needed to sign in to my Azure subscription. I was used to work with Azure DevOps for establishing CI/CD pipelines, and expected something similar to a Service connection of ADO to get access from the pipeline to the Azure subscription by using this very comfortable managed approach (see also one of my previous posts Build an Azure DevOps Pipeline using YAML for provisioning a Microservice in Azure with Terraform ). Now it was necessary to create a Service Principal for establishing the connection from the pipeline to my Azure subscription. I already created several Service Principals - but without taking a closer look at that concept. As I again had to deal with it, I’ve made my mind to get a better idea of it. Therefore, I also decided to write a blog post about it.
So, this blog post is intended to all who would like to start with creating, and managing a Service Principal on Azure using the Azure CLI
2. Prerequisites
- Azure subscription
3. What is a Service Prinicial?
Before you can add, change, or delete resources on Azure , you have to sign in to your Azure subscription - for sure. So it’s clear that this is also mandatory, if you would like to achieve that in automated way - in my case by using pipelines. Without a successful login to an Azure subscription, specific e.g.: Terraform commands included in a GitHub Action would not work. You would never come to the idea of using the credentials of your fully privileged user in the pipeline code. So, if you would like to achieve the login to an Azure subscription in an automated way, by using e.g. pipelines, then you should use a Service Principal . It allows automated tools, applications or hosted services to conduct the Azure authentication, but the permissions are restricted in contrast to a user identity (e.g.: your fully privileged user). Providing the Service Principal only as much as necessary permissions is recommended. Consider therefore carefully which role and which scope you set.
learn.microsoft.com - create Azure Service Principal
4. Create and manage a Service Principal
4.1 login to your azure subscription.
The authentication to Azure has to done before a Service Principal can be created: in VS Code that’s conducted by opening a new Terminal and entering the following command:
A browser session will be opened, and an account has to be chosen, which will be used for the login. After confirming the credentials, the logs should be similar to those in the picture below:
In addition, ensure that the right subscription is used. The subscription can be changed by using the following command:
learn.microsoft.com - manage Azure scubscriptions with Azure CLI
4.2 Create a Service Principal
As a next step, the Service Principal has to be created. Following command is used to create a Service Principal named “AZ_SP_AZUREWORKSHOP_PATRICKS_DEMO”:
The subscription id can be retrieved using:
Let’s take a closer look at the parameters:
- name : the desired name of the Service Principal
- role : the role, which will be assigned. There are different already existing so-called “built-in roles” on Azure . Ensure that a proper role is chosen regarding the purpose of the Service Principal - see List of built-in roles
- scope : in my example, the Service Principal gets the role “Contributor”, which will be set to the whole subscription. The scope can also be restricted to e.g. a single resource group. Set also the scope carefully - see examples regarding to the value of the scope at learn.microsoft.com - azure-cli-sp-tutorial-1
The Service Principal will be created after executing the command below. The logs will reveal several credentials, save them afterward.
learn.microsoft.com - azure-cli-sp-tutorial
learn.microsoft.com - az-sp-create-for-rbac
4.3 Get details of the created Service Principal
Specific details of the Service Principal can be listed by using the following command:
Executing that command, lists the DisplayName , the id , the AppId , and the *CreatedDateTime" of all Service Principals , which DisplayName starts with ‘AZ_SP’:
This reveals among others the id , which can be used for an additional command (see below) to retrieve more details.
The green rectangle marks the id of the Service Principal :
The access details can also be verified in the Azure Portal , by clicking on the “Check access” button and on the specific Service Principal in the IAM section of the subscription:
4.4 Remove permissions from a Service Principal
No worries if you have to reconsider the permissions that you set - they can be updated. Using the following command removes the “Contributor” role for the scope of the whole subscription from the Service Principal named “AZ_SP_AZUREWORKSHOP_PATRICKS_DEMO”:
Checking again the access should prove that there a no current role assignments any more:
learn.microsoft.com - azure-cli-sp-tutorial-5
learn.microsoft.com - azure-cli-sp-tutorial-1
4.5 Add permissions to a Service Principal
The “Contributor” role was removed, but some proper role assignments would be useful - otherwise, it is not meaningful. Those can be added using the command seen below: in that case, again a “Contributor” role will be assigned, but it is not applied for the whole subscription: the scope is now set to a specific resource group named “githubactions-demonstration” instead:
This restricts the permission of the Service Principal to this resource group:
Again the access can be verified in the Azure Portal - be aware to prove that at the level of the specific resource group and not at the level for the whole subscription:
Add repository secrets in GitHub
As already mentioned, after creating the Service Principal , the following credentials will appear:
These credentials can be added as repository secrets in GitHub . Three different variables are created:
- CLIENT_ID - which gets the value of the “appId”
- CLIENT_SECRET - which gets the value of the “password”
- TENANT_ID - which gets the value of the “tenant”
Those variables can be used e.g.: in GitHub Actions to establish the connection to the Azure subscription. I’m using that approach now to automate my Azure resources with Terraform and GitHub Actions.
azure.microsoft - Azure subscription
learn.microsoft.com - Azure CLI
learn.microsoft.com - list of built-in roles
learn.microsoft.com - az-ad-sp-list
cloud.hacktricks - az-azuread
stackoverflow.com - how-to-use-filter-with-az-ad-app-to-do-a-bulk-delete
{ | |
"description": "Grant service principal X reader access on application Z.", | |
"client_type" : "application", | |
"client_principal_name": "service-principal-x-prod", | |
"server_app_registration_name": "app-registration-z-prod", | |
"role_name": "reader" | |
}, |
You can use the script like this:
- Download the script and the config file.
- Update the config files to your needs
- Trigger the script via PowerShell
If you are interested, this is how the script looks like:
param ( | |
[string] $TenantId, | |
[string] $ConfigFilePath | |
) | |
$ErrorActionPreference = "Stop" | |
Write-Host Start Azure AD role assignment script | |
Write-Host "-Tenant Id:" $TenantId -ForegroundColor Gray | |
Write-Host "-Config File Path:" $ConfigFilePath -ForegroundColor Gray | |
Write-Host Installing and importing AzureAD Module | |
if (Get-Module -ListAvailable -Name AzureAD) { | |
Import-Module -Name "AzureAD" | |
} | |
else { | |
Install-Module -Name "AzureAD" -Force | |
} | |
Write-Host Connecting to Azure AD Tenant within current security context | |
$azure_context = Get-AzContext | |
$account_id = $azure_context.Account.Id | |
Write-Host "-Account Id:" $azure_context.Account.Id -ForegroundColor Gray | |
Connect-AzureAD -TenantId $TenantId -AccountId $account_id | |
Write-Host Loading role assignments from config file | |
$role_assignments = (Get-Content $ConfigFilePath -Raw) | ConvertFrom-Json | |
Write-Host Looping each configured role assignment | |
foreach($role_assignment in $role_assignments) | |
{ | |
Write-Host Applying role assigment... started -ForegroundColor Green | |
Write-Host "-Description:" $role_assignment.description -ForegroundColor Gray | |
Write-Host "-Client principal Name:" $role_assignment.client_principal_name -ForegroundColor Gray | |
Write-Host "-Server App Registration Name:" $role_assignment.server_app_registration_name -ForegroundColor Gray | |
Write-Host "-Role Name:" $role_assignment.role_name -ForegroundColor Gray | |
Write-Host Getting the server application registration | |
$aad_filter = "DisplayName eq '" + $role_assignment.server_app_registration_name + "'" | |
$server_application_registration = Get-AzureADApplication -Filter $aad_filter | |
if (!$server_application_registration) { throw "Cannot find configured server application registration with name '" + $role_assignment.server_app_registration_name + "'" } | |
Write-Host Getting the server service principal id | |
$aad_filter = "AppId eq '" + $server_application_registration.AppId + "'" | |
$server_service_principal = Get-AzureADServicePrincipal -Filter $aad_filter | |
$server_service_principal_id = $server_service_principal.ObjectId | |
Write-Host "-Server service principal Id: " $server_service_principal_id -ForegroundColor Gray | |
Write-Host Getting the Id for the configured application role | |
$role_id = ($server_application_registration.AppRoles | Where-Object DisplayName -eq $role_assignment.role_name).Id | |
if (!$role_id) { throw "Cannot find configured application role with name '" + $role_assignment.role_name + "'" } | |
Write-Host "-Role Id: " $role_id -ForegroundColor Gray | |
if(($role_assignment.client_type -ne "application") -and ($role_assignment.client_type -ne "user")) { throw "Incorrect client_type '" + $role_assignment.client_type + "' provided." } | |
switch ($role_assignment.client_type) | |
{ | |
"application" | |
{ | |
Write-Host Getting the configured client service principal | |
$aad_filter = "DisplayName eq '" + $role_assignment.client_principal_name + "'" | |
$client_service_principal = (Get-AzureADServicePrincipal -Filter $aad_filter) | |
if (!$client_service_principal) { throw "Cannot find configured client service principal with name '" + $role_assignment.client_principal_name + "'" } | |
$client_service_principal_id = $client_service_principal.ObjectId | |
$client_service_principal_name = $client_service_principal.DisplayName | |
Write-Host "-Client service principal Id:" $client_service_principal_id -ForegroundColor Gray | |
Write-Host Assigning the Azure Ad role to the configured service principal | |
try | |
{ | |
New-AzureADServiceAppRoleAssignment -Id $role_id -ResourceId $server_service_principal_id -ObjectId $client_service_principal_id -PrincipalId $client_service_principal_id | |
} | |
catch | |
{ | |
if( $_.Exception.Message -like '*Permission being assigned already exists on the object*') | |
{ | |
Write-Host Permission already exists | |
} | |
else | |
{ | |
Write-Error $_.Exception.Message | |
} | |
} | |
} | |
"user" | |
{ | |
Write-Host Getting the configured client user | |
$user = Get-AzureADUser -searchstring $role_assignment.client_principal_name | |
if (!$user) { throw "Cannot find configured client users with name '" + $role_assignment.client_principal_name + "'" } | |
$user_id = $user.ObjectId | |
Write-Host "-User Id:" $user_id -ForegroundColor Gray | |
Write-Host Assigning the Azure Ad role to the configured user | |
try | |
{ | |
New-AzureADUserAppRoleAssignment -Id $role_id -ResourceId $server_service_principal_id -ObjectId $user_id -PrincipalId $user_id | |
} | |
catch | |
{ | |
if( $_.Exception.Message -like '*Permission being assigned already exists on the object*') | |
{ | |
Write-Host Permission already exists | |
} | |
else | |
{ | |
Write-Error $_.Exception.Message | |
} | |
} | |
} | |
} | |
Write-Host Applying role assigment... done -ForegroundColor Green | |
} |
I hope that this script helps you to accelerate your security automation.
Cheers Toon
UPCOMING TRAININGS
CHECK OUT OUR TRAININGS
Azure Integration Services
Azure migration.
- Azure Governance
Azure Security
Azure foundations, recent posts.
- Looking back at INTEGRATE 2024
- Azure Service Bus vs Event Grid Pull Delivery
- Trying the new Microsoft Applied Skills
- Finally a correct way to configure RBAC for DevOps agents!
- What do the new API Management v2 tiers mean for you?
- Announcement
- API Management
- Architecture
- Azure App Service
- Azure Data Factory
- Azure DevOps
- Azure Event Grid
- Azure Functions
- Azure Kubernetes Service
- Azure Policy
- Azure Resource Graph
- Azure Resource Manager
- Azure Service Bus
- Azure Stream Analytics
- BizTalk Server
- Container Apps
- Geen categorie
- Home Automation
- Microsoft Learn
- Service Bus
MEET THE YOUR AZURE COACH TEAM
Your Azure Coach is specialized in organizing Azure trainings that are infused with real-life experience. All our coaches are active consultants, who are very passionate and who love to share their Azure expertise with you.
Toon Vanhoutte
Azure integration services & serverless.
Wim Matthyssen
Azure infra, security & governance, azure development and ai/ml, azure identity and security, stéphane eyskens, cloud-native azure architecture, geert baeke, azure kubernetes service & containerization, maik van der gaag, azure infrastructure as code & devops, bart verboven, sammy deprez, azure ai, ml & cognitive services, sander van de velde.
COMMENTS
Assign an app role for a resource service principal, to a user, group, or client service principal. App roles that are assigned to service principals are also known as application permissions. Application permissions can be granted directly with app role assignments, or through a consent experience.
Application permissions can be granted directly with app role assignments, or through a consent experience. To grant an app role assignment to a client service principal, you need three identifiers: principalId: The id of the client service principal to which you are assigning the app role.
App roles can also be assigned to the service principal for another application, or to the service principal for a managed identity. Currently, if you add a service principal to a group, and then assign an app role to that group, Microsoft Entra ID doesn't add the roles claim to tokens it issues.
The normal guidance on how to assign such a role to an application can be found here (EDIT: WRONG LINK SEE ANSWER). However this does only apply to the service principal manually created (read: not a MSI) because this requires the service principal can be found in the portal UI.
Allows adding of an app role such as Sites.FullControl.All to a service principal/application registration in Azure Active Directory. This can be used to grant permissions to a service principal/application registration, such as a Managed Identity.
Service Principals are identities used by created applications, services, and automation tools to access specific resources. It only needs to do specific things, which can be controlled by assigning the required API permissions.
Part 4 – Assign Application Role to Managed Identity. We can now assign the application role to the service principal, and as documented here, we will need the following 3 id’s: principalId: The id of the user, group or client servicePrincipal to which you are assigning the app role.
To grant access, you assign roles to users, groups, service principals, or managed identities at a particular scope. This article describes the high-level steps to assign Azure roles using the Azure portal, Azure PowerShell, Azure CLI, or the REST API.
4.5 Add permissions to a Service Principal. The “Contributor” role was removed, but some proper role assignments would be useful - otherwise, it is not meaningful.
When using Azure Active Directory for adding role-based access control to your web applications and APIs, it is highly recommended to use application roles. This allows you to define custom application roles and these can be assigned to users and applications.