Creating a Resource Group with a Service Principal for Deployments

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.

  1. param (
  2.     [Parameter(Mandatory)]
  3.     [string]$RegionCode,
  4.  
  5.     [Parameter(Mandatory)]
  6.     [string]$ApplicationCode,
  7.  
  8.     [Parameter(Mandatory)]
  9.     [string]$EnvironmentCode,
  10.  
  11.     [Parameter()]
  12.     [Hashtable]$Tags,
  13.  
  14.     [Parameter()]
  15.     [string[]]$AllowedRegions
  16. )
  17.  
  18. # Authenticate to the Subscription
  19. $ARM_Password = ConvertTo-SecureString -String $env:ARM_SubscriptionServicePrincipalSecret -AsPlainText -Force
  20. $Credentials = New-Object -TypeName System.Management.Automation.PSCredential($env:ARM_SubscriptionServicePrincipalId, $ARM_Password)
  21.  
  22. Connect-AzAccount -ServicePrincipal -Credential $Credentials -Subscription $env:ARM_Subscription -Tenant $env:ARM_TenantId
  23.  
  24. # Create a Resource Group
  25. if ($Tags.Count = = 0) {
  26.     $Tags = @{Environment = $EnvironmentCode; Application = $Application; Owner = $Owner }
  27. }
  28.  
  29. if (!$Tags.ContainsKey("Application") -and $Tags.ContainsKey("ApplicationCode")) {
  30.     $Tags.Add("Application", $Tags.Keys["ApplicationCode"])
  31. }
  32.  
  33. $NextId = (Get-AzResourceGroup -Tag @{Application = $Application } -Location $RegionCode | Measure-Object).Count
  34.  
  35. $ResoureGroupName = "rg-$($ApplicationCode)-$($EnvironmentCode)-$($RegionCode)-$(([string]($NextId + 1)).PadLeft(3, "0"))"
  36.  
  37. $ResourceGroup = New-AzResourceGroup `
  38.     -Name $ResoureGroupName `
  39.     -Location $RegionCode `
  40.     -Tags $Tags
  41.  
  42. # Set Resource Group Permissions
  43. if (! [String]::IsNullOrWhiteSpace($AllowedRegions)) {
  44.     $Policy = Get-AzPolicyDefinition -BuiltIn | Where-Object { $_.Properties.DisplayName -eq 'Allowed locations' }
  45.  
  46.     $AllowedRegionsJson = @{ listOfAllowedLocations = $AllowedRegions }
  47.  
  48.     New-AzPolicyAssignment -Name 'RegionAllowedLocations' -PolicyDefinition $Policy -Scope $ResourceGroup.ResourceId -PolicyParameterObject $AllowedRegionsJson
  49. }
  50.  
  51. # Create a Service Principal for the Resource Group
  52. $ServicePrincipal = New-AzADServicePrincipal -Scope $ResourceGroup.ResourceId -Role Contributor -DisplayName "sp-$($ResoureGroupName)"
  53.  
  54. $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($ServicePrincipal.Secret)
  55. $UnsecureSecret = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
  56.  
  57. # Return Important Information
  58. Write-Host ""
  59. Write-Host -ForegroundColor Green "-------------------------------------------------------------------------------------"
  60. Write-Host ""
  61. Write-Host -ForegroundColor Green "Resource Group:    $($ResourceGroup.ResourceGroupName)"
  62. Write-Host -ForegroundColor Green "Service Principal: $($ServicePrincipal.ApplicationId) / $($UnsecureSecret)"
  63. Write-Host ""
  64. Write-Host -ForegroundColor Green "-------------------------------------------------------------------------------------"
  65. 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.