Azure Bicep - Unable to create a Management Group - azure-bicep

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

Related

How to get RBAC roles assigned to my service principal from PowerShell/CLI/REST API

I have service principal where I assigned multiple roles to it which are required in accessing Azure resources by doing user_impersonation.
Now I want to get these list of roles from Powershell/CLI/REST API.
I'm finding documents for fetching appRoleAssignments of service principal using MS graph :
GET https://graph.microsoft.com/v1.0/servicePrincipals/00063ffc-54e9-405d-b8f3-56124728e051/appRoleAssignedTo
But that is not what I need. Are there any existing commands that helps me to achieve my requirement?
check out this link:
Get-Azroleassignment
Updating my answer with Powershell:
$spn = Get-AzADServicePrincipal -DisplayName "your spn display name"
Get-AzRoleAssignment -ObjectID $spn.id
Also, you must have an atleast active directory reader access to execute this command successfully.

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.

How do I automatically create service principals or MSIs with Terraform for use in Azure Pipelines to manage AKS resources?

I'm following the official docs to create Azure Kubernetes clusters. The docs state that I need to create a service principal first, manually, and provide the client_id and client_secret.
Doing it manually is not an option.
Here is the code for my service principal. It's decorated with links to the most recent Terraform docs for reference.
data "azurerm_subscription" "current" {}
data "azuread_client_config" "current" {}
resource "random_id" "current" {
byte_length = 8
prefix = "ExternalDnsTf"
}
# Create Azure AD App.
# https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/application
resource "azuread_application" "current" {
display_name = random_id.current.hex
owners = [data.azuread_client_config.current.object_id]
}
# Create Service Principal associated with the Azure AD App
# https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/service_principal
resource "azuread_service_principal" "current" {
application_id = azuread_application.current.application_id
app_role_assignment_required = false
owners = [data.azuread_client_config.current.object_id]
}
# Create Service Principal password
# https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/application_password
resource "azuread_application_password" "current" {
application_object_id = azuread_application.current.object_id
}
# Create role assignment for service principal
# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_assignment
resource "azurerm_role_assignment" "current" {
scope = data.azurerm_subscription.current.id
role_definition_name = "Contributor"
# When assigning to a SP, use the object_id, not the appId
# see: https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-cli
principal_id = azuread_service_principal.current.object_id
}
I keep getting the following error in my pipeline: (note, I am the owner of my subscription)
ApplicationsClient.BaseClient.Post(): unexpected status 403 with OData
│ error: Authorization_RequestDenied: Insufficient privileges to complete the
│ operation.
What I'm trying to do is to eliminate the manual steps to setup supporting services. Take ExternalDNS for example. The Azure docs state that I need to use az ad sp create-for-rbac -n ExternalDnsServicePrincipal; az role assignment create --role "Reader" --assignee <appId GUID> --scope <resource group resource id>; az role assignment create --role "Contributor" --assignee <appId GUID> --scope <dns zone resource id>
Ultimately, I'm trying to create the terraform version of the azure cli commands.
Support for create-for-rbac was a feature request on github. That used to work great, but so much has changed, it's not applicable to current API versions. Also, with AAD Graph being deprecated in favor Microsoft Graph API, I wonder if I'm getting snagged on that.
The ExternalDNS docs also suggested Managed Service Identities (MSI). Service principals, MSI, MSGraph API integration, honestly, I don't care which one is used. Whatever is current best-practices is fine so long as I do not have to log into the portal to manually create or give permissions, or manually run az cli commands.
EDIT: Permissions clarification
I'm using Terraform, of course, to provision resources. If I do all of this without terraform (manually or with a bash script), I use azure cli I start setting permissions by doing the following:
az login
az account set -s <my-subscription-id>
I am the owner of my subscription. I can run all commands, create SPs, MSIs, assign roles, etc, with no problem.
In the pipelines, I am using the charleszipp az pipelines terraform plugin. In the logs, I see:
az login --service-principal -t <my-tenant-id> -u *** -p ***
az account set -s <my-subscription-id>
I'm not sure if that makes a difference. I interpret that as ultimately, commands are executed after signing in and setting the account subscription, like I do manually.
Technically, I'm not using a service connection in several of these tasks. However, where one is required, I have created a Service connection and defined its Scope to the subscription level. It's of type Azure Resource Manager.
However, if I click "manage service principal, it takes me to the portal where there are no permissions defined.
While I am the owner of my subscription, I am not the root management group. I'm owned / provisioned by someone else. Ultimately, they have control of Active Directory. I cannot add or edit permissions. If I try to add any under permissions API and select Microsoft Graph, it says that authorization is required. Grant Admin Consent for <parent organization is greyed out.
But why would that be important if I'm the owner of my subscription? If I can do whatever I want via the az cli command line, what's preventing me from doing the same in the pipeline?
I am using user-managed identity for that, it seemed most straightforward and worked fine for me.
resource "azurerm_user_managed_identity", "mi" {
resource_group_name = "rg"
name = "mi"
location = "eastus"
}
resource "azurerm_role_assignment" "ra" {
scope = azurerm_subnet.sn.id // subnet I created earlier
role_definition_name = "Network Contributor" // required with kubenet
principal_id = azurerm_user_managed_identity.mi.principal_id
}
resource "azurerm_kubernetes_cluster" "aks" {
name = "aks"
identity {
type = "UserAssigned"
user_assigned_identity_id = azurerm_user_managed_identity.mi.id
}
<...remaining attributes...>
depends_on = [azurerm_role_assignment.ra] // just to be safe
}

How To Use Service principal To Assign A Role To Another Service Principal

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.

Azure PowerShell or CLI command to Provide a User with Owner access to a specific Web Application

I have around 100 Azure Web Apps and Azure Functions which I created using Azure PowerShell and CLI, now I need to assign Owner Access to these Web Apps to users (Separate users for each Web Apps)
I am unable to find any sample for this, most sample are pointing to Assigning Resource Group Level Access, but not to the Specific Resource.
The task is achievable in the Azure Portal, just need the PowerShell or CLI command to assign users owner or contributor rights to these specific resources.
If possible please provide a sample command
For Power Shell, you could use New-AzureRmRoleAssignment to do this.
For example.
New-AzureRmRoleAssignment -SignInName "test#hotmail.com" -RoleDefinitionName Owner -Scope "/subscriptions/*************/resourceGroups/shuiapp/providers/Microsoft.Web/sites/shuicli"
or
New-AzureRmRoleAssignment -ObjectId "859f0f40-057b-4afc-9d05-fe8b3933ae87" -RoleDefinitionName Owner -Scope "/subscriptions/*****************/resourceGroups/shuiapp/providers/Microsoft.Web/sites/shuicli"
Note: You could get your user object ID with cmdlet get-azureaduser.
Azure CLI
You could use az role assignment create to do this.
For example.
az role assignment create --assignee <user object id> --role Owner --scope "/subscriptions/3b4d41fa-e91d-4bc7-bc11-13d221b3b77d/resourceGroups/shuiapp/providers/Microsoft.Web/sites/shuicli"
Note: If your user is Azure AD user, you could use az ad user list to get user's object id. If your user is a service principal, you could use az ad sp list to get object id.