Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/arsenvlad/azure-ad-permission-create-service-principal-from-another-tenant
In this sample, we look at what is the least-privilege permission or Azure AD role that an app identity needs to be able to create a Service Principal from a multi-tenant application registration in another Azure AD tenant.
https://github.com/arsenvlad/azure-ad-permission-create-service-principal-from-another-tenant
Last synced: 3 days ago
JSON representation
In this sample, we look at what is the least-privilege permission or Azure AD role that an app identity needs to be able to create a Service Principal from a multi-tenant application registration in another Azure AD tenant.
- Host: GitHub
- URL: https://github.com/arsenvlad/azure-ad-permission-create-service-principal-from-another-tenant
- Owner: arsenvlad
- License: mit
- Created: 2022-07-15T21:49:36.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2022-07-17T18:02:09.000Z (over 2 years ago)
- Last Synced: 2023-03-02T17:11:25.510Z (over 1 year ago)
- Size: 170 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Azure AD least-privilege permission for creating service principal from a multi-tenant application registration in another Azure AD tenant
In this sample, we look at what is the least-privilege permission or Azure AD role that an app identity needs to be able to create a Service Principal from a multi-tenant application registration in another Azure AD tenant. See related video at [Azure AD least-privilege permission for creating Service Principal from a multi-tenant application registration in another tenant](https://arsenvlad.medium.com/azure-ad-least-privilege-permission-for-creating-service-principal-from-a-multi-tenant-application-1a6f338dac67).
By least-privilege we mean that we don't want our app identity to have the `Application Administrator` or `Cloud Application Administrator` roles at the scope of the full directory and don't want it to be able to delete or update service principals.
An example scenario for this requirement is a Continuous Integration (CI) testing automation workload that needs to create Service Principals from another Azure AD tenant programmatically - but we don't want this CI app identity to have full application admin access.
Currently in July 2022, Microsoft Graph REST API document [Create servicePrincipals](https://docs.microsoft.com/graph/api/serviceprincipal-post-serviceprincipals?view=graph-rest-1.0&tabs=http) says that in order to create cross-tenant service principals the app identity must be assigned `Cloud Application Administrator` or `Application Administrator` role. However, there is an open [GitHub issue](https://github.com/microsoftgraph/microsoft-graph-docs/issues/16138#issuecomment-1158861560) that provides more details about corrections that need to be made to that document:
![Table listing permissions required to create service principals](./images/permissions-table.png)
As we can see from the table above, the only least-privilege option we have is to give our app identity a [custom Azure Active Directory role](https://docs.microsoft.com/azure/active-directory/roles/custom-create) that includes the `microsoft.directory/servicePrincipals/create` permission ([full list of app permissions](https://docs.microsoft.com/azure/active-directory/roles/custom-enterprise-app-permissions#full-list-of-permissions)). Note that to be able to create custom roles in Azure AD, we need to have **Azure AD Premium P1 or P2** licenses.
We cannot use the `Application.ReadWrite.OwnedBy` app permission because it is **not** sufficient to be able to create service principals from app registrations in **another** Azure AD tenant.
## Experiment
Below are steps for a quick experiment to validate that app identity with Azure AD custom role that includes only the `microsoft.directory/servicePrincipals/create` can successfully create cross-tenant service principals, but cannot read or delete the created principal.
Create our app identity that we will experiment with (https://docs.microsoft.com/azure/active-directory/develop/howto-create-service-principal-portal)
Create the custom role in Azure AD (https://docs.microsoft.com/en-us/azure/active-directory/roles/custom-create)
```bash
az rest --method POST --url https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions --body '@aad-custom-role-sp-creator.json' -o json
```Assign the custom role to our app identity (https://docs.microsoft.com/en-us/azure/active-directory/roles/custom-create#assign-a-custom-role-scoped-to-a-resource)
```bash
az rest --method POST --url https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignments --body "{\"principalId\": \"OUR_SERVICE_PRINCIPAL_OBJECT_ID\",\"roleDefinitionId\": \"ID_OF_THE_ROLE_CREATED_ABOVE\", \"directoryScopeId\": \"/\"}"
```Login using our app identity
```bash
az login --service-principal -u OUR_APPLICATION_ID --password '' --tenant dd74924a-88ce-421a-ac87-00fc9dbe4baf --allow-no-subscriptions
```Create service principal from a multi-tenant application registration (e.g., 9938aa28-a37e-4ba3-8eb5-43228ce62080) in another tenant
```bash
az rest --method POST --url https://graph.microsoft.com/v1.0/servicePrincipals --headers Content-type=application/json --body "{\"appId\": \"MULTITENANT_APP_ID\"}" -o json
```Try reading the service principal information, which should fail since our app identity doesn't have read permissions
```bash
az rest --method GET --url https://graph.microsoft.com/v1.0/servicePrincipals/SERVICE_PRINCIPAL_ID -o json
```To be able to read the cross-tenant service principals that our workload creates, we would also need to give it the `Application.Read.All` app permission or additional custom role permission like `microsoft.directory/servicePrincipals/allProperties/read`. This would enable our workload identity to read properties of **all** service principals.
![Application registration API permissions - Application.Read.All](./images/application-read-all.png)
> Note that when making changes to permissions of an already existing app identity you would need to re-login and wait some time for the cache to refresh and new permissions to apply. I saw it take up to 1 hour. Therefore, while experimenting, instead of making a change and waiting, it could be faster to create a new app identity and to use it instead.
After we are done with the experiments, **delete** the objects created above: our test service principal, custom role, and the multi-tenant service principal.
## User consent in the browser
The experiment above describes how an **application** can **programmatically** create a service principal after an implicit consent. If it is a **user** (i.e., not application), that needs to create the service principal, the user can use can grant the required permissions via **Azure AD consent page** by visiting:
![User consent in the browser](./images/user-consent.png)