When managing an environment with multiple teams accessing and managing different services in the same subscription it is sometimes ideal to segregate the services by a resource group dedicated for each team. Segragation on top of subscription can be achieved by Resource Groups.
When multiple teams and resource groups exists, it is important to apply some security. For example that each team has access only to its own resources and not the others. That deployments can be managed through some automation or other type of restrictions.
The PowerShell script in this article provide a base solution for creating a resource group restricted to specific list of regions, or left open, with a dedicated service principal for deployments. The service principal is given the role ‘Contributor’ on the resource group.
param (
[Parameter(Mandatory)]
[string]$RegionCode,
[Parameter(Mandatory)]
[string]$ApplicationCode,
[Parameter(Mandatory)]
[string]$EnvironmentCode,
[Parameter()]
[Hashtable]$Tags,
[Parameter()]
[string[]]$AllowedRegions
)
# Authenticate to the Subscription
$ARM_Password = ConvertTo-SecureString -String $env:ARM_SubscriptionServicePrincipalSecret -AsPlainText -Force
$Credentials = New-Object -TypeName System.Management.Automation.PSCredential($env:ARM_SubscriptionServicePrincipalId, $ARM_Password)
Connect-AzAccount -ServicePrincipal -Credential $Credentials -Subscription $env:ARM_Subscription -Tenant $env:ARM_TenantId
# Create a Resource Group
if ($Tags.Count = = 0) {
$Tags = @{Environment = $EnvironmentCode; Application = $Application; Owner = $Owner }
}
if (!$Tags.ContainsKey("Application") -and $Tags.ContainsKey("ApplicationCode")) {
$Tags.Add("Application", $Tags.Keys["ApplicationCode"])
}
$NextId = (Get-AzResourceGroup -Tag @{Application = $Application } -Location $RegionCode | Measure-Object).Count
$ResoureGroupName = "rg-$($ApplicationCode)-$($EnvironmentCode)-$($RegionCode)-$(([string]($NextId + 1)).PadLeft(3, "0"))"
$ResourceGroup = New-AzResourceGroup `
-Name $ResoureGroupName `
-Location $RegionCode `
-Tags $Tags
# Set Resource Group Permissions
if (! [String]::IsNullOrWhiteSpace($AllowedRegions)) {
$Policy = Get-AzPolicyDefinition -BuiltIn | Where-Object { $_.Properties.DisplayName -eq 'Allowed locations' }
$AllowedRegionsJson = @{ listOfAllowedLocations = $AllowedRegions }
New-AzPolicyAssignment -Name 'RegionAllowedLocations' -PolicyDefinition $Policy -Scope $ResourceGroup.ResourceId -PolicyParameterObject $AllowedRegionsJson
}
# Create a Service Principal for the Resource Group
$ServicePrincipal = New-AzADServicePrincipal -Scope $ResourceGroup.ResourceId -Role Contributor -DisplayName "sp-$($ResoureGroupName)"
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ServicePrincipal.Secret)
$UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
# Return Important Information
Write-Host ""
Write-Host -ForegroundColor Green "-------------------------------------------------------------------------------------"
Write-Host ""
Write-Host -ForegroundColor Green "Resource Group: $($ResourceGroup.ResourceGroupName)"
Write-Host -ForegroundColor Green "Service Principal: $($ServicePrincipal.ApplicationId) / $($UnsecureSecret)"
Write-Host ""
Write-Host -ForegroundColor Green "-------------------------------------------------------------------------------------"
Write-Host ""
To execute the above script from the command line:
PowerShell -ExecutionPolicy Bypass .\Create_Resource_Group_With_SP.ps1 -ApplicationCode <application_code> -EnvironmentCode <env_code> -RegionCode <region_code_for_rg> -Tags @{ tagname = 'tagvalue'; [tagname2 = 'tagvalue'; ...] } -AllowedRegions <region_code_1>,{<region_code_2, ...>}
The output of the script will consist in the Resource Group Name and the Service Principal ID and Secret. The Service Principal details are in the format Client ID / Client Secret
It is important to store the Service Principal details before closing of the command line.