How To Use Service principal To Assign A Role To Another Service Principal - azure-devops

How can I give a service principal access to assign a role to a resource it created?
Here's the scenario.
I...
Created an Azure DevOps pipeline
Created a Service Connection (which creates a service principal and grants it Contributor access to the entire subscription).
Created a pipeline task AzureCLI#1 using the service connection
Executed az group create … - SUCCESS - made a resource group!
Executed az group deployment create … - SUCCESS - deployed some stuff!
^-- (Unless I do any role assignments as part of my ARM template)
Executed az role assignment create … - FAILURE
ERROR: Insufficient privileges to complete the operation.
I tried making the service principal Owner instead of Contributor. No difference.
This made me understand (kinda) why: Azure Service principal insufficient permissions to manage other service principals
Which lead me here: https://learn.microsoft.com/en-ca/azure/devops/pipelines/release/azure-rm-endpoint?view=azure-devops#failed-to-assign-contributor-role
But I'm a little stuck. I think I'm supposed to grant my service principal some sort of role within active directory so that it's allowed to manage role assignments.
I found this: https://learn.microsoft.com/en-us/azure/active-directory/users-groups-roles/roles-delegate-by-task#roles-and-administrators
Based on that, it seems I should give my service principal Privileged role administrator access. scary.
Then I found this: https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles
Because I wanted to limit this service principal to only be able to flex the active directory powers within a single subscription, which seems to be possible in the AssignableScopes property.
But two things are giving me pause, which brings me here.
1) I'm relatively unfamiliar with what I'm doing, and I'm tossing around big scary terms like Administrator shudder. Time to consult some experts!
2) This seems complex. The task I'm performing seems like it should not be complex. I'm just trying to deploy AKS and a Container Registry in an Azure Pipeline and give AKS access to the registry. Which is what all the docs say to do (albeit at the commandline, not in a pipeline).
So, should I really be creating a custom role just for the subscription which gives Privileged role administrator type privileges assignable only to the subscription, then granting my service principal that role?
Or... How do I do this?
EDIT:
I did try creating a custom role with action Microsoft.Authorization/write. It failed with this error: 'Microsoft.Authorization/write' does not match any of the actions supported by the providers.
But I succeeded in creating one with action Microsoft.Authorization/*/write as well as Microsoft.Authorization/*
My .json definition looks like:
{
"Name": "...", "Description": "...", "IsCustom": true,
"Actions": [ "Microsoft.Authorization/*" ],
"AssignableScopes": [
"/subscriptions/[subscriptionid]"
]
}
After assigning the role to the service principal, it still failed with insufficient access. I logged in locally via az login --service-principal, tried to use my new powers, and got this message:
The client '...' with object id '...' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourceGroups/.../Microsoft.Authorization/read' over scope '/subscriptions/.../resourceGroups/.../.../providers/Microsoft.Authorization/roleDefinitions' or the scope is invalid. If access was recently granted, please refresh your credentials.
EDIT: SOLUTION
{
"Name": "...", "Description": "...", "IsCustom": true,
"Actions": [
"Microsoft.Authorization/roleAssignments/read",
"Microsoft.Authorization/roleAssignments/write"
],
"AssignableScopes": [
"/subscriptions/[subscriptionid]"
]
}
This works with az role definition create.
The service principal also needs to be a Directory Reader, unless you specify the role assignment by object-id. Azure Active Directory: Add Service Principal to Directory Readers Role with PowerShell
It can be assigned to the service principal, and when executing az commands as that service principal, it succeeds in creating role assignments.

you need to grant it Microsoft.Authorization/roleAssignments/write custom permission or the built-in role of owner. scope would be subscription if you want to be able to do that for every resource group\resource in the subscription or you can be more granular (say specific resource groups or even resources).
your custom role link is the right way to create custom roles.
edit: OP needed to add Microsoft.Authorization/roleAssignments/read as well, for me it works without it.

Related

Azure Release Pipeline does not have enough permissions to deploy Bicep/ARM template

When I try to deploy my Bicep template through a DevOps release pipeline I get the following error:
Deployment failed with multiple errors: 'Authorization failed for
template resource '1525ed81-ad25-486e-99a3-124abd455499' of type
'Microsoft.Authorization/roleDefinitions'. The client
'378da07a-d663-4d11-93d0-9c383eadcf45' with object id
'378da07a-d663-4d11-93d0-9c383eadcf45' does not have permission to
perform action 'Microsoft.Authorization/roleDefinitions/write' at
scope
'/subscriptions/8449f684-37c6-482b-8b1a-576b999c77ef/resourceGroups/rgabpddt/providers/Microsoft.Authorization/roleDefinitions/1525ed81-ad25-486e-99a3-124abd455499'.:Authorization
failed for template resource '31c1daec-7d4a-4255-8528-169fc45fc14d' of
type 'Microsoft.Authorization/roleAssignments'.
I understand through this post that I have to grant "something" the Owner or User Access Administrator role.
But I don't understand what user has the ObjectId 378da07a-d663-4d11-93d0-9c383eadcf45.
I tried to look it up with the following az CLI command, but it says that it cannot find a resource with that Id:
az ad user show --id 378da07a-d663-4d11-93d0-9c383eadcf45
The response it returns:
Resource '378da07a-d663-4d11-93d0-9c383eadcf45' does not exist or one of its queried reference-property objects are not present.
I'm a but clueless here. What do I exactly have to grant permission?
When you use service connection in DevOps pipeline, for example Azure Resource Manager service connection, it will create a service principal(app registry) on Azure portal-> Active Directory. You can find the service principal by clicking the link on service connection:
When you deploy with service connection, please make sure you have give correct permission for this service principal on target resource, like mentioned Microsoft.Authorization/roleDefinitions/write. Suggest to give contributor role on the resource. Otherwise it will reports the error in your pipeline log.
When you add the role, you will find the object id, it's different with service principal application ID or object id.
It's azure role not Azure AD role. You can find the difference in the doc.

Azure Bicep - Unable to create a Management Group

I am in the process of trying to learn Bicep, as a part of that self-instruction I have been trying unsuccessfully to create a management group hierarchy. I am attempting to create a single management group using the following but am getting an error message when I deploy the bicep file.
targetScope = 'tenant'
param mgName string = 'test-displayname'
resource mgmtGroup 'Microsoft.Management/managementGroups#2021-04-01' = {
name: mgName
}
When I attempt to deploy I get the following error message:
"Deployment failed for c:\bicep\Management Groups\azuredeploy.bicep. Tenant scope deployment is not currently supported."
I have tried changing API versions, deploying to the management group scope, etc. all with no success.
Any ideas are greatly appreciated!
Thanks
By default, the SPN does not have permission to deploy tenant resources. You need to grant it at the root scope "/" to make it work.
First, you need to elevate your permissions as user Global Administrator into Azure AD:
https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin
Connect-AzAccount
$user = Get-AzADUser -SignedIn
New-AzRoleAssignment -Scope '/' -RoleDefinitionName 'Owner' -ObjectId $user.Id
Now you are able to set your SPN with the correct permissions:
https://github.com/Azure/Enterprise-Scale/blob/main/docs/EnterpriseScale-Setup-azure.md
$spndisplayname = "<SPN Display Name>"
$spn = (Get-AzADServicePrincipal -DisplayName $spndisplayname).id
New-AzRoleAssignment -Scope '/' -RoleDefinitionName 'Owner' -ObjectId $spn
I think you may be running into a few different issues.
How are you deploying the template? The error you posted doesn't sound like it's coming from the service but the client...
Your bicep file is targeting the tenant scope, for that you need permission to create template deployments at tenant scope (even if you create no resources). The principal deploying the template will need permission (contributor at least, owner is not required) at the tenant scope as Wesley mentioned. The thing to be aware of here is that this gives that principal contributor access to everything in the tenant - all MGs, All subs, All RGs. It's very permissive and needs to be used carefully/sparingly. Also, note that you do not need to target the tenant scope to create the MG in a template. You can set the targetScope in bicep to a RG, Sub or MG. But the principal deploying the template must have permission at whatever scope you target the bicep file to.
A principal need not be given any special permission to simply create a MG - all users have this permission. You can test this by creating an MG on the cmd line. When that user creates the MG, the user is made the "owner" of that MG.
Point being, be very careful about granting perms at the tenant level and use only when necessary.
All that said, if your goal is to create MGs and deploy resources to those MGs in the same bicep deployment, the best path is to give the principal permissions (contributor is best) at the tenant level. Otherwise you will run into replication delays with permissions on the newly created MGs.
HTH

With MS Graph API, how do I force my programmatically created Service Principals, MSIs, and IaC code to be scoped to my subscription only?

Active Directory Graph API is now fully deprecated, in favor of MS Graph API.
My company has given me my own Visual Studio Professional subscription. I also have a DevOps organization. I am the Owner role in both.
with AADG API, I could use Terraform, for example, to create Service Principals and manage roles. Service Connections in DevOps were scoped to my subscription.
Example:
## These are in my resource group
...
resource "azuread_service_principal" "example" {
application_id = azuread_application.example.application_id
app_role_assignment_required = false
owners = [data.azuread_client_config.current.object_id]
}
...
resource "azurerm_role_assignment" "kubweb_to_acr" {
scope = azurerm_container_registry.acr.id
role_definition_name = "AcrPull"
principal_id = azurerm_kubernetes_cluster.kubweb.kubelet_identity[0].object_id
}
This used to work great. Now it does not. Now I get errors like:
Error: authorization.RoleAssignmentsClient#Create: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="AuthorizationFailed" Message="The client '3520c717-e1cc-4d0b-b021-2f93a1b05d80' with object id '3520c717-e1cc-4d0b-b021-2f93a1b05d80' does not have authorization to perform action 'Microsoft.Authorization/roleAssignments/write
and
ApplicationsClient.BaseClient.Post(): unexpected status 403 with OData
│ error: Authorization_RequestDenied: Insufficient privileges to complete the
│ operation.
Even though I own my subscription, there is a parent organization above me. My SPs get scoped to their AD where I can't manage them. I can't use "Grant Admin Consent" through MS Graph API. Also, in DevOps, when I create an ARM Service Connection, for example, I scope it to my Subscription. It never scopes to my subscription, but the parent's, and I can't change its permissions.
How do I alter my development or scope my resources so that I don't have to defer to parent organization?
What role do they need to give me so I don't have to involve them?
I'm already the owner of my subscription. How do I create these types of resources in a way that I have full control over managing them again?
Side-note, it's interesting. I can use Azure CLI and run the same commands via terminal, and I have no problems creating or altering resources. The same commands az ad sp create-for-rbac don't throw any errors at all, and it's using the same permissions and scope defined in the pipelines.
Both errors you show are due to the service principal that Terraform is running as has not been authorized to perform the action in question. (From the Azure role assignment error, we can know this is the service principal with object ID "3520c717-e1cc-4d0b-b021-2f93a1b05d80".)
To assign an Azure role to a user, group, or service principal (your first error), the service principal used by Terraform needs to be have been granted a role that includes the "Microsoft.Authorization/roleAssignments/write" operation, scoped to (at least) scope you're trying to grant the role at (e.g. the specific Azure resource, the resource group it's in, or the subscription it's in). Typically, if you need to create Azure role assignments, this is the "Owner" role. More details from Terraform in Allowing the Service Principal to manage the Subscription. If you're "Owner" of the Azure subscription, then you will be able to do this yourself.
To create Azure AD application and service principals (your second error): The service principal used by Terraform needs to be granted permission to do this in the Azure AD tenant in question. For example, the app roles (application permissions) Application.Read.All and Application.ReadWrite.OwnedBy would suffice in many cases. These are actions that take place in the Azure AD tenant, so an Azure AD administrator will need to grant this access—you cannot do this on your own if you're not an admin of the Azure AD tenant. More details from Terraform in Configuring a User or Service Principal for managing Azure Active Directory.
How do I alter my development or scope my resources so that I don't have to defer to parent organization?
You could have an entirely separate Azure AD tenant (where you'd be administrator), and point the Azure subscription to trust that tenant. This may or may not be compatible with your organization's policies and practices.
I'm already the owner of my subscription. How do I create these types of resources in a way that I have full control over managing them again?
Azure AD applications and service principals are not a part of your Azure subscription, they're in the "parent" Azure AD tenant. You (the user) probably do have permission over these objects (e.g. you're owner of them in Azure AD), but Terraform isn't running as you—it's running as a separate service principal.
Side-note, it's interesting. I can use Azure CLI and run the same commands via terminal, and I have no problems creating or altering resources. The same commands az ad sp create-for-rbac don't throw any errors at all, and it's using the same permissions and scope defined in the pipelines.
You're probably connecting to Azure CLI as yourself (i.e. your user account), instead of the service principal Terraform is using. If you connect to Azure CLI using the same service principal (e.g. az login --service-principal ...), you'd likely experience the same errors, because that service principal hasn't been granted privileges over the Azure AD tenant and the Azure subscription yet.

Creating Service Principle for a specific Azure user

In the quickstart it talks about creating a service principle for the current user. I want to have more of a hierarchical security structure. I would be the current user and I want to have "super-user" or admin rights to this key vault. However I have created another user that would have lower access rights. For both of these scenarios I gather I need to generate a unique service principle name. How do I generate a service principle name for an arbitrary Azure User?
You can just create another service principal name under your current account for this created user. And you just need to assign the lower access rights to the key vault for this service principal. Then the user can access to the key vault with this service principal which has lower access permission.
An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. You can create as many as service principals as you want for different access permissions. If you want to generate a service principal under the created user account, you might have to login as this created user. Otherwise, i am afraid it cannot be done.
You can also set the access permission for this user to this key vault directory without using service principal. See here
az keyvault set-policy --name keyVaultName --object-id userObjectId --secret-permissions permissions --key-permissions permissions
You can get the user's Object id with below command: See here
az ad user show --id <email-address-of-user>

How to create Azure DevOps Service Connection scoped to multiple Resource Groups

I have a project whose resources spanned across 3 resource groups. I want to create a Service connection scoped to all those resource groups so that i can manage access at one place through that service connection. Currently i created 3 service connections scoped to each resource group. I don't want to scope it to subscription since there are other teams handling projects in that subscription. It will give me maintenance and audit issues in the future.
If i create a service principal and assign it to 3 resource groups and then attach this service principal to service connection then would it be good design?
Is there any better way to achieve this ?
When you create a new Service Connection in the Azure DevOps, it will create an Azure AD app registration, and a new service principal will be created for the Resource Group you choose.
So you can just go to any resource group and then add a principal using the Access control (IAM). Select the Add role assignment option and then select the role as a contributor in the role grid, press next. From the next screen, select user, group, or service principal as the option for Assign access to. Click on the + Select members, search for our AD Registered app name, the display name and then select the same from the result, click on the select button. Finally, click the Review + assign button.
I have written a detailed article to explain the steps, you can read that here.
You don't have to create the service principal manually. You can use the interface to create the service principal, grant permissions on the first resource group and configure the connection automatically for you.
Then once it's done, look at the service connection to identify the service principal in use, and give it permissions on the other resource groups.
And yes it is a good design, the only drawback compared to 3 service principals is that you have less granularity over who in Azure DevOps has access to each of these 3 resource groups via permissions on the service service connection(s) (as you only have one and not 3)