Onboarding
Below is necessary information that is needed for application setup. Activities, scripts below will help you in obtaining them.
Subscription Id: "xxxxx"
Management Group Id: "xxxxx"
Management Group Name: "xxxxx"
Application Client Id: "xxxxx"
Application Client Secret: "xxxxx"
Secret Expires On: "xxxxx"
TenantId: "xxxxx"
Manually
1 - Creating Service Principal
Go to Microsoft Entra ID and choose App registrations then click New registration.
Use name according to you naming conventions for example sp-bkb-cloud
.
For other settings keep defaults as is in screenshot and click Register.
Note down following details:
- Application (client) ID
- Directory (tenant) ID
Go to Certificates & secrets
and generate new secret, set validity one year or higher.
Note down the generated secret and expiry date.
2 - Granting Permissions
Scope of permissions can be either Subscription
or Management Group
.
Process is additive, meaning that if you start with Subscription, you can later go for Management Group.
If you want to use multiple subscriptions, just repeat same process for those.
For scanning whole tenant, we need permissions on the top Management Group, if you are using custom Management Group that has all desired subscriptions, it is fine to grant permissions only for that Management Group, in other cases target Management group is Tenant Root Group
.
Creating custom role
Open the container resource resource e.g. Management Group.
Open Access control (IAM)
and choose Add
followed by Add custom role
, to trigger wizard for creating new role.
Specify name of custom role such as BKB Cloud
and optionally description.
Without changing anything else, go to JSON
tab.
Copy below JSON and paste it into working text area.
Change assignableScopes
to array of resource identifiers, based on your scope.
Example has resource identifier for both Subscriptions and Management Groups.
If you only intend to grant permissions only on one Subscription, delete the other line from Management Group and vice versa.
Finish the wizard for creating custom role.
{
"properties": {
"roleName": "BKB Cloud",
"description": "View all resources, modify tags and does not allow to make any other changes.",
"assignableScopes": [
"/providers/Microsoft.Management/managementGroups/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
],
"permissions": [
{
"actions": [
"*/read",
"Microsoft.Resources/tags/*"
],
"notActions": [],
"dataActions": [],
"notDataActions": []
}
]
}
}
Assigning custom role to service principal
To assign created custom role to Service Principal, on the same resource as you wish to grant access, navigate to Access control (IAM)
blade and choose Add
followed by Add role assignment
Search for custom role, select it and choose next.
Choose User, group, or service principal
option and Select members
, in the Select members
window search for service principal by name.
Finish the assignment.
If you followed this guide sequentially, at this point you have:
- Service Principal with its Application ID, Client Secret and its expiration time.
- Tenant Id, also called Directory ID
- Scope such as Subscription ID or Management Group Name
- Permissions to the Service Principal are granted on the desired scope
Via PowerShell Script
Authenticate to Azure before running the scripts by executing Connect-AzAccount
in your terminal.
Before you execute any of the PowerShell scripts, please make sure following preconditions are met:
- Script requires PowerShell 7.4.0+, Azure PowerShell module
- User executing script needs to have permissions to:
- Create App Registrations (Application Administrator)
- Create custom roles at desired level e.g. Subscription, Management Group (Owner level permissions)
- Assign permissions at desired level e.g. Owner of Subscription
1 - Creating Service Principal
Script will perform manual steps above and write info to console.
Copy the script into text editor, change the initial values if needed and run the edited script in authenticated PowerShell terminal.
#region Initial Values
[string] $ServicePrincipalName = 'sp-bkb-cloud'; # change according to your naming conventions
[int] $SecretValidityInYears = 2;
#endregion
$ErrorActionPreference = 'Stop';
$servicePrincipal = Get-AzADServicePrincipal -DisplayName $ServicePrincipalName;
if ($ServicePrincipal -eq $null) {
Write-Host "Creating Service Principal $ServicePrincipalName" -ForegroundColor Yellow;
$servicePrincipal = New-AzADServicePrincipal -DisplayName $ServicePrincipalName;
Start-Sleep -Seconds 10;
}
$appObj = Get-AzADApplication -ApplicationId $servicePrincipal.AppId;
$currentDateTime = Get-Date;
$endDate = $currentDateTime.AddYears($SecretValidityInYears);
Write-Host "Creating Service Principal Secret";
$newCredential = New-AzADAppCredential -ObjectId $appObj.Id -StartDate $currentDateTime -EndDate $endDate;
$result = [PSCustomObject]@{
TenantId = (Get-AzContext).Tenant.Id;
ClientId = $servicePrincipal.AppId;
ClientSecret = $newCredential.SecretText;
SecretExpiresOn = $endDate.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss");
}
Write-Host "";
Write-Host "";
Write-Host "Please share below JSON:";
Write-Host ($result | ConvertTo-Json) -ForegroundColor Green;
2 - Granting Subscription Level Permissions
Use below script to grant subscription level permissions including creation of custom role.
Script will perform manual steps above and write info to console.
Copy the script into text editor, change the initial values if needed and run the edited script in authenticated PowerShell terminal.
#region Initial Values
[string] $CustomRoleName = 'BKB Cloud';
[string] $ClientId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; # Service Principal (app registration) Application ID
[string] $SubscriptionId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
#endregion
$ErrorActionPreference = 'Stop';
[string[]] $CustomRolePermissions = @(
"*/read",
"Microsoft.Resources/tags/*"
);
$customRole = [Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition]::new();
$customRole.Name = $CustomRoleName;
$customRole.Description = 'View all resources, modify tags and does not allow to make any other changes.';
$customRole.Actions = $CustomRolePermissions;
$customRole.IsCustom = $true;
$scope = '/subscriptions/' + $SubscriptionId;
$existingRole = Get-AzRoleDefinition -Name $CustomRoleName -WarningAction SilentlyContinue;
if ($existingRole -eq $null) {
$customRole.AssignableScopes = @($scope);
Write-Host "Creating Custom Role `"$CustomRoleName`"" -ForegroundColor Yellow;
[Void](New-AzRoleDefinition -Role $customRole);
Write-Host "Waiting for Role to be available via API, this might take a while..." -ForegroundColor Yellow;
do{
Start-Sleep -Seconds 10;
}until(Get-AzRoleDefinition -Name $CustomRoleName -WarningAction SilentlyContinue);
$customRole.Id = (Get-AzRoleDefinition -Name $CustomRoleName).Id;
}else {
$customRole.Id = $existingRole.Id;
$customRole.AssignableScopes = (@($scope) + $existingRole.AssignableScopes) | Select-Object -Unique;
Write-Host "Updating Custom Role `"$CustomRoleName`"" -ForegroundColor Yellow;
[Void](Set-AzRoleDefinition -Role $customRole);
}
$servicePrincipal = Get-AzADServicePrincipal -ApplicationId $ClientId;
$assignment = Get-AzRoleAssignment -Scope $scope -RoleDefinitionId $customRole.Id -ObjectId $servicePrincipal.Id;
if ($assignment -eq $null) {
Write-Host "Assigning Custom Role to Service Principal" -ForegroundColor Yellow;
[Void](New-AzRoleAssignment -ObjectId $servicePrincipal.Id -RoleDefinitionId $customRole.Id -Scope $scope);
}
$result = [PSCustomObject]@{
SubscriptionId = $SubscriptionId;
}
Write-Host "";
Write-Host "Please share below JSON:";
Write-Host ($result | ConvertTo-Json) -ForegroundColor Green;
2 - Granting Management Group Level Permissions
Use below script to grant management group level permissions including creation of custom role.
Script will perform manual steps above and write info to console.
Copy the script into text editor, change the initial values if needed and run the edited script in authenticated PowerShell terminal.
#region Initial Values
[string] $CustomRoleName = 'BKB Cloud';
[string] $ClientId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'; # Service Principal (app registration) Application ID
[string] $ManagementGroupDisplayName = 'xxxxx';
#endregion
$ErrorActionPreference = 'Stop';
[string[]] $CustomRolePermissions = @(
"*/read",
"Microsoft.Resources/tags/*"
);
$customRole = [Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition]::new();
$customRole.Name = $CustomRoleName;
$customRole.Description = 'View all resources, modify tags and does not allow to make any other changes.';
$customRole.Actions = $CustomRolePermissions;
$customRole.IsCustom = $true;
$mgmtGroup = Get-AzManagementGroup | Where-Object {$_.DisplayName -eq $ManagementGroupDisplayName -or $_.Name -eq $ManagementGroupDisplayName};
$scope = $mgmtGroup.Id;
$existingRole = Get-AzRoleDefinition -Name $CustomRoleName -WarningAction SilentlyContinue;
if ($existingRole -eq $null) {
$customRole.AssignableScopes = @($scope);
Write-Host "Creating Custom Role `"$CustomRoleName`"" -ForegroundColor Yellow;
[Void](New-AzRoleDefinition -Role $customRole);
Write-Host "Waiting for Role to be available via API, this might take a while..." -ForegroundColor Yellow;
do{
Start-Sleep -Seconds 10;
}until(Get-AzRoleDefinition -Name $CustomRoleName -WarningAction SilentlyContinue);
$customRole.Id = (Get-AzRoleDefinition -Name $CustomRoleName).Id;
}else {
$customRole.Id = $existingRole.Id;
$customRole.AssignableScopes = (@($scope) + $existingRole.AssignableScopes) | Select-Object -Unique;
Write-Host "Updating Custom Role `"$CustomRoleName`"" -ForegroundColor Yellow;
[Void](Set-AzRoleDefinition -Role $customRole);
}
$servicePrincipal = Get-AzADServicePrincipal -ApplicationId $ClientId;
$assignment = Get-AzRoleAssignment -Scope $scope -RoleDefinitionId $customRole.Id -ObjectId $servicePrincipal.Id;
if ($assignment -eq $null) {
Write-Host "Assigning Custom Role to Service Principal" -ForegroundColor Yellow;
[Void](New-AzRoleAssignment -ObjectId $servicePrincipal.Id -RoleDefinitionId $customRole.Id -Scope $scope);
}
$result = [PSCustomObject]@{
ManagementGroupDisplayName = $mgmtGroup.DisplayName;
ManagementGroupName = $mgmtGroup.Name;
}
Write-Host "";
Write-Host "Please share below JSON:";
Write-Host ($result | ConvertTo-Json) -ForegroundColor Green;