Public/Set-CallerRBACAssignment.ps1
|
function Set-CallerRBACAssignment { <# .SYNOPSIS Determines, evaluates, and (optionally) applies the least-privilege RBAC a caller needs to run a command. .DESCRIPTION End-to-end PSAutoRBAC entry point. For a given platform command it: 1. Resolves the minimum required role(s) from the knowledge base. 2. Resolves the target Azure scope. 3. Tests whether the caller already holds each required role. 4. Generates idempotent grant / revoke snippets for any missing role. 5. With -WhatIf it only reports; otherwise it grants missing roles (honouring -Confirm via ShouldProcess). Designed for Zero Trust / least-privilege provisioning: the framework runs as an identity holding only roleAssignments/write, and uses that to grant the caller exactly the roles needed for the operation -- and no more. .PARAMETER Tenant The Entra tenant id (recorded on output; not required for offline use). .PARAMETER SubscriptionId The Azure subscription id. Used to build the scope when -Scope is absent. .PARAMETER ResourceGroupName Optional resource group, used to build a resource-group scope. .PARAMETER CallerId The caller identity (UPN / sign-in name) the roles are evaluated for. .PARAMETER Scope Explicit Azure scope. Overrides scope built from subscription / group. .PARAMETER Platform The execution platform, e.g. 'Azure PowerShell'. .PARAMETER Command The command whose RBAC requirement is being evaluated. .PARAMETER ArgumentList Optional command arguments (recorded on output for traceability). .PARAMETER MapPath Optional alternate knowledge-base path (chiefly for testing). .PARAMETER RoleAssignment Optional pre-fetched role assignments for offline evaluation. .EXAMPLE Set-CallerRBACAssignment -Tenant $tid -SubscriptionId $sid ` -CallerId 'patrick.gallucci@microsoft.com' -Platform 'Azure PowerShell' ` -Command 'Connect-AzAccount' -WhatIf Reports the Reader requirement and whether the caller holds it, without making any change. .OUTPUTS PSCustomObject per required role with UPN, Role, State, scope, the command context, and AddScript / RemoveScript snippets. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [OutputType([pscustomobject])] param( [Parameter()] [string]$Tenant, [Parameter()] [string]$SubscriptionId, [Parameter()] [string]$ResourceGroupName, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$CallerId, [Parameter()] [string]$Scope, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Platform, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Command, [Parameter()] [Alias('Args')] [object[]]$ArgumentList, [Parameter()] [string]$MapPath, [Parameter()] [object[]]$RoleAssignment ) # 1. Minimum requirement. $reqParams = @{ Platform = $Platform; Command = $Command } if ($MapPath) { $reqParams['MapPath'] = $MapPath } $requirement = Get-CommandRBACRequirement @reqParams # 2. Scope. $resolvedScope = Resolve-RBACScope -Scope $Scope -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName # 3. Current state. $testParams = @{ CallerId = $CallerId RequiredRole = $requirement.Roles Scope = $resolvedScope } if ($PSBoundParameters.ContainsKey('RoleAssignment')) { $testParams['RoleAssignment'] = $RoleAssignment } $states = Test-CallerRBACAssignment @testParams foreach ($state in $states) { $scripts = New-RBACAssignmentScript -CallerId $CallerId -Role $state.Role -Scope $resolvedScope # 4/5. Apply when missing and not in WhatIf mode. $applied = $false if (-not $state.State) { if ($PSCmdlet.ShouldProcess("$CallerId at $resolvedScope", "Grant role '$($state.Role)'")) { if (Get-Command -Name 'New-AzRoleAssignment' -ErrorAction SilentlyContinue) { New-AzRoleAssignment -SignInName $CallerId -RoleDefinitionName $state.Role -Scope $resolvedScope -ErrorAction Stop | Out-Null $applied = $true } else { Write-Warning "New-AzRoleAssignment unavailable; emitting AddScript only. Run it from an identity with roleAssignments/write." } } } [pscustomobject]@{ PSTypeName = 'PSAutoRBAC.CallerAssignment' Tenant = $Tenant UPN = $CallerId Platform = $requirement.Platform Command = $Command ArgumentList = $ArgumentList Scope = $resolvedScope Role = $state.Role State = $state.State IsKnown = $requirement.IsKnown Applied = $applied Notes = $requirement.Notes AddScript = $scripts.AddScript RemoveScript = $scripts.RemoveScript } } } |