Get-AzureAssessPrivilegedRoleAssignments.ps1
<#
.SYNOPSIS Get Privilege role assignement for specific Id (resource or container) .EXAMPLE PS C:\Get-AzureAssessPrivilegedRoleAssginments -Id /subscriptions/151f94b9-9d98-45cd-bc0b-d3bdee8d2969 #> $privilgedRoles = @{} $managementGroupNames = @{} $subscriptionNames = @{} function Get-AzureAssessPrivilegedRoleAssignments { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 1)] [string]$SubscriptionId, [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 2)] [string]$ResourceGroupName ) # get context $context = get-azcontext # Get assignement for privileged roles: Owner, Contributor, User Access Administrator, Role Bases Access Control Administrator if ($script:privilgedRoles.Count -eq 0) { $res = invoke-azrestmethod -method "GET" -path "/providers/Microsoft.Authorization/roleDefinitions?api-version=2022-04-01" if ($res.StatusCode -eq 200) { $res.Content ` | ConvertFrom-Json | Select-Object -ExpandProperty value ` | Where-Object { $_.properties.roleName -in ("Owner","Contributor","User Access Administrator","Role Based Access Control Administrator")} | foreach-Object { $script:privilgedRoles[$_.name] = $_.properties.roleName } } } # get the role assignements for the resource group $res = invoke-azrestmethod -method "GET" -path "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01" if ($res.StatusCode -ne 200) { return } # returned columns # roleId,role,principalId,principalType,scope,source,resourceType,resourceName $assignments = @(,$res.Content | ConvertFrom-Json | Select-Object -ExpandProperty value | Select-Object -ExpandProperty properties ` | Where-Object { ($_.roleDefinitionId -split "/")[-1] -in $privilgedRoles.Keys } ` | Select-Object ` @{N="roleId";E={($_.roleDefinitionId -split "/")[-1]}}, ` @{N="role";E={""}}, ` principalId, ` principalType, ` scope, ` @{N="source";E={"RBAC"}}, ` @{N="resourceType";E={""}}, ` @{N="resourceName";E={($_.scope -split "/")[-1]}}, ` @{N="link";E={"https://portal.azure.com/#@$($context.Tenant.Id)/resource$($_.scope)/users"}}) # expand columns foreach($assignment in $assignments) { $assignment.role = $script:privilgedRoles[$assignment.roleId] if ($assignment.scope -eq "/") { $assignment.resourceType = "managementGroups" $assignment.resourceName = "root" if ($assignment.resourceName -notin $script:managementGroupNames.Keys) { $res = Invoke-AzRestMethod -Method GET -Path "/providers/Microsoft.Management/managementGroups/$($context.Tenant.Id)?api-version=2020-05-01" if ($res.StatusCode -eq 200) { $script:managementGroupNames[$assignment.resourceName] = ($res.Content | ConvertFrom-Json).properties.displayName } } if ($assignment.resourceName -in $script:managementGroupNames.Keys) { $assignment.scope = $assignment.scope -replace $assignment.resourceName,$script:managementGroupNames[$assignment.resourceName] $assignment.link = "https://portal.azure.com/#@$($context.Tenant.Id)/resource/providers/Microsoft.Management/managementGroups/$($context.Tenant.Id)/users" $assignment.resourceName = $script:managementGroupNames[$assignment.resourceName] } } elseif ($assignment.scope -imatch "/providers/Microsoft.Management/managementGroups/[^/]+") { $assignment.resourceType = "managementGroups" if ($assignment.resourceName -notin $script:managementGroupNames.Keys) { $res = Invoke-AzRestMethod -Method GET -Path "/providers/Microsoft.Management/managementGroups/$($assignment.resourceName)?api-version=2020-05-01" if ($res.StatusCode -eq 200) { $script:managementGroupNames[$assignment.resourceName] = ($res.Content | ConvertFrom-Json).properties.displayName } } if ($assignment.resourceName -in $script:managementGroupNames.Keys) { $assignment.scope = $assignment.scope -replace $assignment.resourceName,$script:managementGroupNames[$assignment.resourceName] $assignment.link = $assignment.link -replace $assignment.resourceName,$script:managementGroupNames[$assignment.resourceName] $assignment.resourceName = $script:managementGroupNames[$assignment.resourceName] } } elseif ($assignment.scope -imatch "/subscriptions/[^/]+/resourceGroups/[^/]+/providers/.+") { $assignment.resourceType = ($assignment.scope -split "/")[6..7] -join "/" } elseif ($assignment.scope -imatch "/subscriptions/[^/]+/resourceGroups/[^/]+") { $assignment.resourceType = "resourceGroups" } elseif ($assignment.scope -imatch "/subscriptions/[^/]+") { $assignment.resourceType = "subscriptions" if ($assignment.resourceName -notin $script:subscriptionNames.Keys) { $res = Invoke-AzRestMethod -Method GET -Path "/subscriptions/$($assignment.resourceName)?api-version=2016-06-01" if ($res.StatusCode -eq 200) { $script:subscriptionNames[$assignment.resourceName] = ($res.Content | ConvertFrom-Json).displayName } } if ($assignment.resourceName -in $script:subscriptionNames.Keys) { $assignment.resourceName = $script:subscriptionNames[$assignment.resourceName] } } } # add inherited roles at resourceGroup level $inherits = $assignments | Where-Object { $_.resourceType -iin ("subscriptions","managementGroups")} foreach($inherit in $inherits) { $copy = $inherit.PsObject.Copy() $copy.scope = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName" $copy.resourceType = "resourceGroups" $copy.resourceName = $ResourceGroupName $copy.source = "Inherit" $copy.link = "https://portal.azure.com/#@$($context.Tenant.Id)/resource$($copy.scope)/users" $assignments += $copy } # add passing down roles to resources # get all resources of resourcegroup $res = invoke-azrestmethod -method GET -path "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/resources?api-version=2021-04-11" if ($res.StatusCode -ne 200) { return $assignments } $resources = $res.Content | ConvertFrom-Json | Select-Object -ExpandProperty value | Select-Object id,name,type $childassignments = $assignments | Where-Object { $_.resourceType -iin ("subscriptions","managementGroups","resourceGroups") -and $_.source -eq "RBAC"} foreach($childassignement in $childassignments) { foreach($resource in $resources) { $copy = $childassignement.PsObject.Copy() $copy.scope = $resource.id $copy.resourceType = $resource.type $copy.resourceName = $resource.name $copy.source = "Inherit" $copy.link = "https://portal.azure.com/#@$($context.Tenant.Id)/resource$($copy.scope)/users" $assignments += $copy } } $assignments } # SIG # Begin signature block # MIIRWAYJKoZIhvcNAQcCoIIRSTCCEUUCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDsmQl6OT4cAx3u # wt2QEhXGY3IRQABXNb4lKvkACmaczaCCDZIwgga5MIIEoaADAgECAhEAmaOACiZV # O2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNV # BAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBD # ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQg # TmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIxOFowVjEL # MAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjEk # MCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5cTbq96y34 # vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7VS5+djSo # McbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1PH9ud0IF+ # njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOouu9Tj1yHI # ohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv8aGUsRda # CtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtMLK+Wo837 # Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9lDV2nT8m # FSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/JHuurfTI # 5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkKbWpQ5bou # fUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADaCi2JSplK # ShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAWd18Jx5n8 # 58JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFN10 # XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8+tT4HKbR # Og79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAwBgNVHR8E # KTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3JsMGwGCCsG # AQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVt # LmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0 # bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEWGGh0dHA6 # Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhYD+WPUCia # U58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUStJl490L9 # 4C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChDUyuQy6rG # DxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiRsWrhWM2f # 8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7bWRLDm0Cd # Y9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mATwZWwSD+B # 7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3/bFAEloM # U+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESYkOh1/w1t # VxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR+x+zPF/2 # DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C+xN4YaNj # t2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qwt4HOUBCr # W602NCmvO1nm+/80nLy5r0AZvCQxaQ4wggbRMIIEuaADAgECAhBNn7NsFkgeJAAl # SKxTsSjWMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhB # c3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNp # Z25pbmcgMjAyMSBDQTAeFw0yNDAxMTYxMjAwMzRaFw0yNTAxMTUxMjAwMzNaMHcx # CzAJBgNVBAYTAkJFMRgwFgYDVQQIDA9XYWxsb29uIEJyYWJhbnQxHjAcBgNVBAoM # FU9wZW4gU291cmNlIERldmVsb3BlcjEuMCwGA1UEAwwlT3BlbiBTb3VyY2UgRGV2 # ZWxvcGVyLCBDZWRyaWMgQmxvbWFydDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBALp1WzPLBGmSjvJ2se9K+HWIzxlPIh9vmddaj0Sc6Yz3jJizVN7WphR7 # 1kR4KFEfCFL6eleZlIkqDMkNfwBTpfVCx7MYR85YSceHo8ieEIV5MmWSZ1CR36/A # wXrUvXzlX85Rf/RuotfluSmdhTRoBbCN9aIsSm50pEZixvUOcipTNZbuY29NvjXP # JAH1RX0od6QYCGt/v+5C+hBippk+QohxmKQYLilh4+58fdZvnXaKPvEuEpbhXCeh # /HbASrvTbZXXbh8fMbHOq+xnCemK/6aqjfqgRzkXn9unjl6wj6KT7MoEp1tCn+9z # cmi/zW3KeI3Alld5B6IEvVfZVmaCrvSsRBNFnVpVg5eGQNRyan0xfblEwKLrsoNk # WhUtJY3SD53kvz8OHBKRY1quaq70UefcIDuPq4+76CVovjbpT/wnmP6PFnHtNrDj # KzMAnUWOeseIcDhp7ETzVyoh2rWofTpXUr5aEau5mkXs0MclqjimMeWf0r3NyBa5 # E3k0rG/xtpmTFB9e4w7b0VQUxNUcVdmocGL7Rj4ouWLjUDUkiE2DctxMTaPmqKJE # nx8cFsBCrDmgNYxGOZ03ykPmPbwc3SooZeS5rRmR4v2GTVrbsmbiiggtYDjhJddo # sC/TtJ+65JL48oTHDK1KVMtSjUBr/Q16Nzg0JaXfiZ4JS+MX45ylAgMBAAGjggF4 # MIIBdDAMBgNVHRMBAf8EAjAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jY3Nj # YTIwMjEuY3JsLmNlcnR1bS5wbC9jY3NjYTIwMjEuY3JsMHMGCCsGAQUFBwEBBGcw # ZTAsBggrBgEFBQcwAYYgaHR0cDovL2Njc2NhMjAyMS5vY3NwLWNlcnR1bS5jb20w # NQYIKwYBBQUHMAKGKWh0dHA6Ly9yZXBvc2l0b3J5LmNlcnR1bS5wbC9jY3NjYTIw # MjEuY2VyMB8GA1UdIwQYMBaAFN10XUwA23ufoHTKsW73PMAywHDNMB0GA1UdDgQW # BBQ2dBi+EnTsl++Xmrax5h7dyzC12TBLBgNVHSAERDBCMAgGBmeBDAEEATA2Bgsq # hGgBhvZ3AgUBBDAnMCUGCCsGAQUFBwIBFhlodHRwczovL3d3dy5jZXJ0dW0ucGwv # Q1BTMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG # 9w0BAQsFAAOCAgEAZm3wL05QNFh25ll601jtST553L2VVS4ugvlHmX90PSOkjmX3 # jQ2ERwdz9MHWhoOvW1EdOrBlm31YRt2GmCz4/82vq9fTTNwLSzk3csHEIgHuAbN1 # INCVgz0l7Ya7mkxFLHoZ4BJ9LluS4p2NjvU9r7OGnBCgfFaLriC+qRY8QxCeMQOl # l1BTTaUBMp0pgxh3XOOxOQfNeFCkXg0q4QULkaRuApJFZi/pY+PMA6p8bjOTP4YI # 9VNsoc7ReBYMDL588oupc1CTiDaf0e6YaN80z6WoIGuNja3VPDEG4VmWZG+Of9gO # XUNllvR8n1IXXsvWEuHRTCV9jjK89NHGaNroeXHr1C6eERnoNUPbEuIb/parUnGB # n5MKWL+2TlL9Z34lSFz6e1Efi4oJeDznUojNZKJzOMvBS+JJyr0aVuW4lDoqbqkl # 9vFLjHi1oGM7mBrlL8AHEC3iUNEOwgPcbsIYAqV85RyXYNQqLu1ik1MmmpKy/Tma # Mmi/AiXxtjC6RrnrkN6tIHR7Nky9b5jWfMxCCG2b119gr7SkJ8qVOH8I9oBxMDPR # IjBi5rEjSbDOCpRhZiqmx7K7gW2Gyp1OCIffVyiqmeZh+YLxpdP0tymxtqg/HVqV # If3xn0Sgl7HcUpcRkY3EgTPUqNaVzOSO5h8KyzA9nVtUX2XwSx9C4vb6uqcxggMc # MIIDGAIBATBqMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBT # eXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBD # QQIQTZ+zbBZIHiQAJUisU7Eo1jANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3 # AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG # AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCAeSVpEt1Xi # 1nJamorDGe33dZkEDVAZmBNfyZboykFOUDANBgkqhkiG9w0BAQEFAASCAgA4jhO4 # 9X/1Z1acYDFmeUBCc0XhEgLlo5mNs82YhHXV07NRHO9IcL5kK6ISgxqe6tQNH8sD # xwhcMw1Y3wMnYJV35um4Qt2qFaKQRUsE2oWhsYtK54Cx+Px/YxNt9118/Y+ujdEu # ia1j6ZAYDsEowNg2VuP17s2TFWzTaM7e+fNf9buOibN4sM7w85v/1jfTGalNW8eu # JcA0WWnDugbFpQhkIpCRrhAVtiYLPCB2YMKkGGj1wxfbWcfDJMLlXZi59jQMkp3J # OuPshFTEoA1SrLELGFC0l01MBp5GmFFST9zswA0UBlfuV6Nn5KJ60faz8m9F99wm # 16exCs+mYxKm+jHrKo9+pD+guk/BuQEaIHuBOryVmNNFkVLDV0euFhIzHYkousR0 # IYV8R9Vo2Ts2aw4frXOhfSIou4s0QdP1b4lBOOuWhHbI+JGt2t43y0bjQeIWt0Xc # mv2q3mzuZFZqh92LJIxhl0vy/k7FbHjvZAq4JFF0VsAYkAZmZkzAOHCcp54lOg5y # J2Q98d5uxm2BCwWnnT9SSUlmdLg6qxhy6DjG2AYIv2zeLc2GCdFUekbOL3MII+Ul # ByznDH9jj0ct7TWqHtUkDqCdG8DhDc6rhC2LgcfETT1xEkV+freAj03w52ecIQo8 # IgSQNYJ9GEAhjL7jgyQHvlS1koFjr0vhglY91g== # SIG # End signature block |