Public/Add-FinOpsServicePrincipal.ps1
<#
.SYNOPSIS Grants the specified service principal or managed identity access to an Enterprise Agreement billing account or department. .PARAMETER ObjectId The object ID of the service principal or managed identity. .PARAMETER TenantId The Azure Active Directory tenant which contains the identity. .PARAMETER BillingAccountId The billing account ID (enrollment number) to grant permissions against. .PARAMETER DepartmentId The department ID to grant permissions against. .EXAMPLE Add-FinOpsServicePrincipal -ObjectId 00000000-0000-0000-0000-000000000000 -TenantId 00000000-0000-0000-0000-000000000000 -BillingAccountId 12345 Grants Enterprise Administrator (read only) permissions to the specified service principal or managed identity .EXAMPLE Add-FinOpsServicePrincipal -ObjectId 00000000-0000-0000-0000-000000000000 -TenantId 00000000-0000-0000-0000-000000000000 -BillingAccountId 12345 -DepartmentId 67890 Grants Department Administrator (read only) permissions to the specified service principal or managed identity #> function Add-FinOpsServicePrincipal { param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ObjectId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TenantId, [Parameter(Mandatory = $true)] [string]$BillingAccountId, [Parameter(Mandatory = $false)] [string]$DepartmentId ) $apiVersion = "2019-10-01-preview" # TODO: Update to latest version $azContext = Get-AzContext if (![string]::IsNullOrEmpty($DepartmentId) -and ![string]::IsNullOrEmpty($BillingAccountId)) { $BillingScope = 'Department' } elseif ([string]::IsNullOrEmpty($DepartmentId) -and ![string]::IsNullOrEmpty($BillingAccountId)) { $BillingScope = 'Enrollment' } else { throw ($LocalizedData.ServicePrincipal_BillingAccountNotSpecified) } switch ($BillingScope) { 'Enrollment' { if ([string]::IsNullOrEmpty($BillingAccountId)) { Write-Output $LocalizedData.ServicePrincipal_BillingAccountNotSpecifiedForDept Write-Output '' exit 1 } $roleDefinitionId = "/providers/Microsoft.Billing/billingAccounts/{0}/billingRoleDefinitions/24f8edb6-1668-4659-b5e2-40bb5f3a7d7e" -f $BillingAccountId $restUri = "{0}providers/Microsoft.Billing/billingAccounts/{1}/billingRoleAssignments/{2}?api-version={3}" -f $azContext.Environment.ResourceManagerUrl, $BillingAccountId, (New-Guid).Guid, $apiVersion $body = '{"properties": { "PrincipalId": "{0}", "PrincipalTenantId": "{1}", "roleDefinitionId": "{2}" } }' $body = $body.Replace("{0}", $ObjectId) $body = $body.Replace("{1}", $TenantId) $body = $body.Replace("{2}", $roleDefinitionId) } 'Department' { if ([string]::IsNullOrEmpty($BillingAccountId)) { Write-Output $LocalizedData.ServicePrincipal_BillingAccountNotSpecifiedForDept Write-Output '' exit 1 } if ([string]::IsNullOrEmpty($DepartmentId)) { Write-Output $LocalizedData.ServicePrincipal_DeptIdNotSpecified Write-Output '' exit 1 } $roleDefinitionId = "/providers/Microsoft.Billing/billingAccounts/{0}/departments/{1}/billingRoleDefinitions/db609904-a47f-4794-9be8-9bd86fbffd8a" -f $BillingAccountId, $DepartmentId $restUri = "{0}providers/Microsoft.Billing/billingAccounts/{1}/departments/{2}/billingRoleAssignments/{3}?api-version={4}" -f $azContext.Environment.ResourceManagerUrl, $BillingAccountId, $DepartmentId, (New-Guid).Guid, $apiVersion $body = '{"properties": { "PrincipalId": "{0}", "PrincipalTenantId": "{1}", "roleDefinitionId": "{2}" } }' $body = $body.Replace("{0}", $ObjectId) $body = $body.Replace("{1}", $TenantId) $body = $body.Replace("{2}", $roleDefinitionId) } default { throw ($LocalizedData.ServicePrincipal_InvalidBillingScope -f $BillingScope) } } $azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile $profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile) $token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId) $authHeader = @{ 'Content-Type' = 'application/json' 'Authorization' = 'Bearer ' + $token.AccessToken } try { # TODO: Switch to Invoke-Rest Invoke-RestMethod -Uri $restUri -Method Put -Headers $authHeader -Body $body Write-Output ($LocalizedData.ServicePrincipal_SuccessMessage -f $BillingScope) } catch { if ($_.Exception.Response.StatusCode -eq 409) { Write-Output ($LocalizedData.ServicePrincipal_AlreadyGrantedMessage -f $BillingScope) } else { $body throw $_.Exception } } } |