From 5003d32cad211078187d46015f8ee97531f837f4 Mon Sep 17 00:00:00 2001 From: Jurjen Ladenius Date: Thu, 18 Apr 2024 09:00:04 +0200 Subject: [PATCH] PIM settings script #99024 Script for management group overview #97859 --- Custom roles/Storage Data Contributor.json | 4 +- Custom roles/Storage Data Reader.json | 3 +- .../key vault should be in rbac mode.json | 65 ++++++++++ Powershell/Lists/Azure/ManagementGroups.ps1 | 113 ++++++++++++++++++ Powershell/Tools/AzurePIM - role settings.ps1 | 95 +++++++++++++++ Powershell/Tools/AzurePIMpatch.json | 96 +++++++++++++++ ...zure Custom Roles.ps1 => Custom Roles.ps1} | 2 - Powershell/Tools/SQLAudit.ps1 | 4 + 8 files changed, 378 insertions(+), 4 deletions(-) create mode 100644 Policies/key vault should be in rbac mode.json create mode 100644 Powershell/Lists/Azure/ManagementGroups.ps1 create mode 100644 Powershell/Tools/AzurePIM - role settings.ps1 create mode 100644 Powershell/Tools/AzurePIMpatch.json rename Powershell/Tools/{Azure Custom Roles.ps1 => Custom Roles.ps1} (93%) create mode 100644 Powershell/Tools/SQLAudit.ps1 diff --git a/Custom roles/Storage Data Contributor.json b/Custom roles/Storage Data Contributor.json index b227a28..aca74b2 100644 --- a/Custom roles/Storage Data Contributor.json +++ b/Custom roles/Storage Data Contributor.json @@ -74,6 +74,8 @@ "/subscriptions/c4b0c496-dbc1-483b-890b-fc46012125d8", "/subscriptions/cea89b67-6bfd-47c6-b7fa-9b8006b664ea", "/subscriptions/2161debe-6042-4633-b10e-de77c06cabc6", - "/subscriptions/e33c30f7-06c7-4765-86a9-7a8979b6d1cc" + "/subscriptions/e33c30f7-06c7-4765-86a9-7a8979b6d1cc", + "/subscriptions/2021c41e-3582-40a1-85e5-59588741e6d3", + "/subscriptions/17a9bacf-5a67-44bf-a532-950a4b3bf25d" ] } \ No newline at end of file diff --git a/Custom roles/Storage Data Reader.json b/Custom roles/Storage Data Reader.json index 058d4db..7276174 100644 --- a/Custom roles/Storage Data Reader.json +++ b/Custom roles/Storage Data Reader.json @@ -57,6 +57,7 @@ "/subscriptions/c4b0c496-dbc1-483b-890b-fc46012125d8", "/subscriptions/cea89b67-6bfd-47c6-b7fa-9b8006b664ea", "/subscriptions/2161debe-6042-4633-b10e-de77c06cabc6", - "/subscriptions/e33c30f7-06c7-4765-86a9-7a8979b6d1cc" + "/subscriptions/2021c41e-3582-40a1-85e5-59588741e6d3", + "/subscriptions/17a9bacf-5a67-44bf-a532-950a4b3bf25d" ] } diff --git a/Policies/key vault should be in rbac mode.json b/Policies/key vault should be in rbac mode.json new file mode 100644 index 0000000..77d7e14 --- /dev/null +++ b/Policies/key vault should be in rbac mode.json @@ -0,0 +1,65 @@ +{ + "properties": { + "displayName": "Key Vault should be in RBAC authentication mode.", + "policyType": "Custom", + "mode": "All", + "description": "This policy allows enforcing RBAC authentication for Key Vault.", + "metadata": { + "category": "Key Vault", + "createdBy": "c6025a2e-416c-42da-96ef-dd507382793a", + "createdOn": "2024-04-12T14:36:53.5411731Z", + "updatedBy": null, + "updatedOn": null + }, + "version": "1.0.0", + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "Enable or disable the execution of the policy" + }, + "allowedValues": [ + "audit", + "deny", + "disabled" + ], + "defaultValue": "audit" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.KeyVault/vaults" + }, + { + "not": + { + "field": "Microsoft.KeyVault/vaults/enableRbacAuthorization", + "equals": "true" + } + } + ] + }, + "then": { + "effect": "[parameters('effect')]" + } + }, + "versions": [ + "1.0.0" + ] + }, + "id": "/providers/Microsoft.Management/managementGroups/ManagementGroup_SurveySoftware/providers/Microsoft.Authorization/policyDefinitions/e889bb98-9f0c-4bec-8c72-6019781549e5", + "type": "Microsoft.Authorization/policyDefinitions", + "name": "e889bb98-9f0c-4bec-8c72-6019781549e5", + "systemData": { + "createdBy": "jurjen.ladenius@effectory.com", + "createdByType": "User", + "createdAt": "2024-04-12T14:36:53.5414063Z", + "lastModifiedBy": "jurjen.ladenius@effectory.com", + "lastModifiedByType": "User", + "lastModifiedAt": "2024-04-12T14:36:53.5414063Z" + } +} \ No newline at end of file diff --git a/Powershell/Lists/Azure/ManagementGroups.ps1 b/Powershell/Lists/Azure/ManagementGroups.ps1 new file mode 100644 index 0000000..b72c025 --- /dev/null +++ b/Powershell/Lists/Azure/ManagementGroups.ps1 @@ -0,0 +1,113 @@ +#Connect-AzAccount + +class ResourceCheck { + [string] $SubscriptionId = "" + [string] $SubscriptionName = "" + [string] $SubscriptionState = "" + [string] $Level0_ManagementGroupId = "" + [string] $Level1_ManagementGroupId = "" + [string] $Level2_ManagementGroupId = "" + [string] $Level0_ManagementGroupName = "" + [string] $Level1_ManagementGroupName = "" + [string] $Level2_ManagementGroupName = "" +} + +Write-Host "======================================================================================================================" +Write-Host "Creating list of Effectory Management Groups and subscriptions." +Write-Host "- Note: not very dynamic; Starts at hard coded root group and works up max 2 levels." +Write-Host "======================================================================================================================" + +[string] $date = Get-Date -Format "yyyy-MM-dd HHmm" +$fileName = ".\$date azure_managementgroups.csv" +[ResourceCheck[]]$Result = @() + +$rootManagementGroup = (Get-AzManagementGroup -GroupId 'e9792fd7-4044-47e7-a40d-3fba46f1cd09' -Expand)[0] + +#level 0 +Write-Host "---------------------------------------------------------------------------------------------" +Write-Host "Level 0 Management group [$($rootManagementGroup.Name)]" +Write-Host "---------------------------------------------------------------------------------------------" + +$subscriptions = $rootManagementGroup.Children | Where-Object Type -EQ '/subscriptions' + +foreach ($subscription in $subscriptions) +{ + $scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length) + $subscriptionId = $scope.Replace("/subscriptions/", "") + Write-Host "Subscription [$($subscription.DisplayName) - $subscriptionId]" + + [ResourceCheck] $resourceCheck = [ResourceCheck]::new() + $resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id + $resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName + $resourceCheck.SubscriptionId = $subscriptionId + $resourceCheck.SubscriptionName = $subscription.DisplayName + $resourceCheck.SubscriptionState = $subscription.State + $Result += $resourceCheck +} + +#level 1 +foreach ($level1ManagementGroupLister in ($rootManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups')) +{ + $level1ManagementGroup = (Get-AzManagementGroup -Group $level1ManagementGroupLister.Name -Expand)[0] + + Write-Host " ---------------------------------------------------------------------------------------------" + Write-Host " Level 1 Management group [$($level1ManagementGroup.Name)]" + Write-Host " ---------------------------------------------------------------------------------------------" + + $subscriptions = $level1ManagementGroup.Children | Where-Object Type -EQ '/subscriptions' + + foreach ($subscription in $subscriptions) + { + $scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length) + $subscriptionId = $scope.Replace("/subscriptions/", "") + Write-Host " Subscription [$($subscription.DisplayName) - $subscriptionId]" + + [ResourceCheck] $resourceCheck = [ResourceCheck]::new() + $resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id + $resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName + $resourceCheck.Level1_ManagementGroupId = $level1ManagementGroup.Id + $resourceCheck.Level1_ManagementGroupName = $level1ManagementGroup.DisplayName + $resourceCheck.SubscriptionId = $subscriptionId + $resourceCheck.SubscriptionName = $subscription.DisplayName + $resourceCheck.SubscriptionState = $subscription.State + $Result += $resourceCheck + } + + #level 2 + foreach ($level2ManagementGroupLister in ($level1ManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups')) + { + $level2ManagementGroup = (Get-AzManagementGroup -Group $level2ManagementGroupLister.Name -Expand)[0] + + Write-Host " ---------------------------------------------------------------------------------------------" + Write-Host " Level 2 Management group [$($level2ManagementGroup.Name)]" + Write-Host " ---------------------------------------------------------------------------------------------" + + $subscriptions = $level2ManagementGroup.Children | Where-Object Type -EQ '/subscriptions' + + foreach ($subscription in $subscriptions) + { + $scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length) + $subscriptionId = $scope.Replace("/subscriptions/", "") + Write-Host " Subscription [$($subscription.DisplayName) - $subscriptionId]" + + [ResourceCheck] $resourceCheck = [ResourceCheck]::new() + $resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id + $resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName + $resourceCheck.Level1_ManagementGroupId = $level1ManagementGroup.Id + $resourceCheck.Level1_ManagementGroupName = $level1ManagementGroup.DisplayName + $resourceCheck.Level2_ManagementGroupId = $level2ManagementGroup.Id + $resourceCheck.Level2_ManagementGroupName = $level2ManagementGroup.DisplayName + $resourceCheck.SubscriptionId = $subscriptionId + $resourceCheck.SubscriptionName = $subscription.DisplayName + $resourceCheck.SubscriptionState = $subscription.State + $Result += $resourceCheck + } + } +} + +$Result | Export-Csv -Path $fileName -NoTypeInformation + + +Write-Host "=============================================================================================" +Write-Host "Done." + diff --git a/Powershell/Tools/AzurePIM - role settings.ps1 b/Powershell/Tools/AzurePIM - role settings.ps1 new file mode 100644 index 0000000..13d9d81 --- /dev/null +++ b/Powershell/Tools/AzurePIM - role settings.ps1 @@ -0,0 +1,95 @@ + +function GetAllPolicies { + + param ( + [string] $scope + ) + + #https://learn.microsoft.com/en-us/rest/api/authorization/role-management-policies/list-for-scope?view=rest-authorization-2020-10-01&tabs=HTTP + + $access_token = (Get-AzAccessToken -TenantId "e9792fd7-4044-47e7-a40d-3fba46f1cd09").Token + + $url = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleManagementPolicies?api-version=2020-10-01" + + $head = @{ Authorization =" Bearer $access_token" } + $response = Invoke-RestMethod -Uri $url -Method GET -Headers $head + + $response | ForEach-Object { + $responseValue = $_.value + if ($responseValue.Length -gt 0) { + return $responseValue + } + else { + return "" + } + } +} + +function UpdatePolicy { + param ( + [string] $scope, + [string] $roleManagementPolicyName, + [string] $patchValue + ) + #https://learn.microsoft.com/en-us/rest/api/authorization/role-management-policies/update?view=rest-authorization-2020-10-01&tabs=HTTP + + $access_token = (Get-AzAccessToken -TenantId "e9792fd7-4044-47e7-a40d-3fba46f1cd09").Token + $url = "https://management.azure.com/$scope/providers/Microsoft.Authorization/roleManagementPolicies/$($roleManagementPolicyName)?api-version=2020-10-01" + $head = @{ Authorization =" Bearer $access_token" } + Invoke-RestMethod -Uri $url -Method Patch -Headers $head -Body $patchValue -ContentType "application/json" | Out-Null +} + +Write-Host "==========================================================================================" +Write-Host "Setting standard PIM role settings on modified roles." +Write-Host "==========================================================================================" + +[string] $patchValue = Get-Content .\AzurePIMpatch.json -Raw + +$managementGroups = Get-AzManagementGroup + +foreach ($managementGroup in $managementGroups) +{ + Write-Host "--------------------------------------------------------------------" + Write-Host "Management group [$($managementGroup.Name)]" + + + $scope = "providers/Microsoft.Management/managementGroups/$($managementGroup.Name)" + $assignments = GetAllPolicies -scope $scope | Where-Object { + $prop = $_.properties + if ($prop.LastModifiedDateTime) { return $_ } + } + + foreach ($assignment in $assignments) + { + $assignmentName = $assignment.name + Write-Host "Updating assignment [$($assignment.id)]" + UpdatePolicy -scope $scope -roleManagementPolicyName $assignmentName -patchValue $patchValue + } + + # $subscriptions = Get-AzManagementGroupSubscription -Group $managementGroup.Name | Where-Object State -eq "Active" + + # foreach ($subscription in $subscriptions) + # { + # Write-Host " --------------------------------------------------------------------" + + # $scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length) + # $subscriptionId = $scope.Replace("/subscriptions/", "") + # Write-Host " Subscription [$($subscription.DisplayName) - $subscriptionId]" + # Write-Host " --------------------------------------------------------------------" + + # $assignments = GetAllPolicies -scope $scope | Where-Object { + # $prop = $_.properties + # if ($prop.LastModifiedDateTime) { return $_ } + # } + + # foreach ($assignment in $assignments) + # { + # $assignmentName = $assignment.name + # Write-Host " Updating assignment [$($assignment.id)]" + # UpdatePolicy -scope $scope -roleManagementPolicyName $assignmentName -patchValue $patchValue + # } + # } +} + Write-Host "==========================================================================================" + Write-Host "Done." + diff --git a/Powershell/Tools/AzurePIMpatch.json b/Powershell/Tools/AzurePIMpatch.json new file mode 100644 index 0000000..207ddc9 --- /dev/null +++ b/Powershell/Tools/AzurePIMpatch.json @@ -0,0 +1,96 @@ +{ + "properties": { + "rules": [ + { + "isExpirationRequired": false, + "maximumDuration": "PT10H", + "id": "Expiration_EndUser_Assignment", + "ruleType": "RoleManagementPolicyExpirationRule", + "target": { + "caller": "EndUser", + "operations": [ + "All" + ], + "level": "Assignment", + "targetObjects": [], + "inheritableSettings": [], + "enforcedSettings": [] + } + }, + { + "enabledRules": [ + "MultiFactorAuthentication" + ], + "id": "Enablement_EndUser_Assignment", + "ruleType": "RoleManagementPolicyEnablementRule", + "target": { + "caller": "EndUser", + "operations": [ + "All" + ], + "level": "Assignment", + "targetObjects": [], + "inheritableSettings": [], + "enforcedSettings": [] + } + }, + { + "notificationType": "Email", + "recipientType": "Admin", + "isDefaultRecipientsEnabled": false, + "notificationLevel": "All", + "notificationRecipients": [], + "id": "Notification_Admin_EndUser_Assignment", + "ruleType": "RoleManagementPolicyNotificationRule", + "target": { + "caller": "EndUser", + "operations": [ + "All" + ], + "level": "Assignment", + "targetObjects": [], + "inheritableSettings": [], + "enforcedSettings": [] + } + }, + { + "notificationType": "Email", + "recipientType": "Requestor", + "isDefaultRecipientsEnabled": false, + "notificationLevel": "All", + "notificationRecipients": [], + "id": "Notification_Requestor_EndUser_Assignment", + "ruleType": "RoleManagementPolicyNotificationRule", + "target": { + "caller": "EndUser", + "operations": [ + "All" + ], + "level": "Assignment", + "targetObjects": [], + "inheritableSettings": [], + "enforcedSettings": [] + } + }, + { + "notificationType": "Email", + "recipientType": "Approver", + "isDefaultRecipientsEnabled": false, + "notificationLevel": "All", + "notificationRecipients": [], + "id": "Notification_Approver_EndUser_Assignment", + "ruleType": "RoleManagementPolicyNotificationRule", + "target": { + "caller": "EndUser", + "operations": [ + "All" + ], + "level": "Assignment", + "targetObjects": [], + "inheritableSettings": [], + "enforcedSettings": [] + } + } + ] + } +} diff --git a/Powershell/Tools/Azure Custom Roles.ps1 b/Powershell/Tools/Custom Roles.ps1 similarity index 93% rename from Powershell/Tools/Azure Custom Roles.ps1 rename to Powershell/Tools/Custom Roles.ps1 index 810e13a..6b8e610 100644 --- a/Powershell/Tools/Azure Custom Roles.ps1 +++ b/Powershell/Tools/Custom Roles.ps1 @@ -22,8 +22,6 @@ $subscriptionId = "3190b0fd-4a66-4636-a204-5b9f18be78a6" ; $resourceGroupName = $subscriptionId = "86945e42-fa5a-4bbc-948f-3f5407f15d3e" ; $resourceGroupName = "hierarchy"; $accountName = "hierarchyeff"; $principalIdReader = "dd576450-b564-4659-ac00-163036bf1dff"; $principalIdWriter = "591b32ff-33b8-4839-bf35-58ec262b014f" -$subscriptionId = "70cae949-5013-4c40-b718-911dbf9b9a80" ; $resourceGroupName = "participantcore"; $accountName = "participantcore"; $principalIdReader = "a7f7f051-90ad-4419-b040-2868c0e6bbff"; $principalIdWriter = "0bbbf6d4-bdf4-450a-bcc7-4024451558e5" - $subscriptionId = "f9ab522b-4895-492d-b8a8-ca6e1f60c2a8" ; $resourceGroupName = "participant-exchange"; $accountName = "participantexchange"; $principalIdReader = "3b3ebcdf-04b6-4cf8-a237-425cc3952770"; $principalIdWriter = "6c38e6fb-4190-45bc-a347-b132afb47cba" $subscriptionId = "7feeb150-9ee0-4aea-992a-5f3a89d933e6" ; $resourceGroupName = "results-calculation"; $accountName = "results-calculation"; $principalIdReader = "645b069a-c367-4e0e-9dac-38595663acab"; $principalIdWriter = "fa86c1a4-570c-4f00-8960-1a17eb23d613" diff --git a/Powershell/Tools/SQLAudit.ps1 b/Powershell/Tools/SQLAudit.ps1 new file mode 100644 index 0000000..29fcd15 --- /dev/null +++ b/Powershell/Tools/SQLAudit.ps1 @@ -0,0 +1,4 @@ +az login +az account set --subscription 'a134faf1-7a89-4f2c-8389-06d00bd5e2a7' +az sql server audit-policy show -g 'Default-SQL-WestEurope' -n 'c0m7f8nybr' +az sql server audit-policy update -g 'Default-SQL-WestEurope' -n 'c0m7f8nybr' --state Disabled \ No newline at end of file