-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathlaunch.ps1
205 lines (178 loc) · 9.22 KB
/
launch.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
<#
.SYNOPSIS
Deploy Azure Policies.
.DESCRIPTION
REQUIRED : Internet access & Already connected to an Azure tenant
REQUIRED : PowerShell modules, see variables
.PARAMETER env
Mandatory
Environment where to deploy Azure Policies
.NOTES
AUTHOR: James Dumont le Douarec
.LINK
https://medium.com/microsoftazure/an-azure-policy-journey-7bb53b41c43d
https://github.com/JamesDLD/azure-policies
.EXAMPLE
./launch.ps1
#>
################################################################################
# Variable
################################################################################
Set-StrictMode -Version 2
$ErrorActionPreference = "Stop"
$complianceJobs = @()
$AzRoleDefinitions = @()
$Scopes = @()
$PowerShellModules = @(
@{
Name = "Az.ManagedServiceIdentity"
MinimumVersion = "0.7.3"
},
@{
Name = "Az.Accounts"
MinimumVersion = "2.7.0"
},
@{
Name = "Az.Resources"
MinimumVersion = "5.1.0"
}
@{
Name = "Az.PolicyInsights"
MinimumVersion = "1.4.1"
}
)
################################################################################
# Pre-requisite
################################################################################
ForEach ($PowerShellModule in $PowerShellModules) {
Write-host "Importing Module $($PowerShellModule.Name) with MinimumVersion $($PowerShellModule.MinimumVersion)"
Import-Module -Name $($PowerShellModule.Name) -MinimumVersion $($PowerShellModule.MinimumVersion) -ErrorAction Stop
}
################################################################################
# Connectivity
################################################################################
# Login first with Connect-AzAccount if not using Cloud Shell
################################################################################
# Action
################################################################################
# $SubscriptionId = "<Your Subscription Id>"
# Select-AzSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop
## Create or ensure that the needed custom roles exist
foreach ($item in Get-Item .\roles\*.json) {
$roles = (Get-Content -Path $item.FullName) | ConvertFrom-Json
foreach ($role in $roles) {
$AzRoleDefinition = Get-AzRoleDefinition -Name $role.Name
if (!$AzRoleDefinition ) {
Write-Output "Creating the custom role $($role.Name)"
$AzRoleDefinitions += New-AzRoleDefinition -InputFile $item.FullName
}
else { $AzRoleDefinitions += $AzRoleDefinition }
}
}
$deploymentScriptMinimumPrivilege = $AzRoleDefinitions | Where-Object { $_.Name -like "Deployment script minimum privilege for deployment principal" }
## Create or Update Azure Policies Definition and Azure Policies Initiative Definition
foreach ($item in Get-Item .\policies\*\policy.parameters.json) {
$policy = (Get-Content -Path $($item.FullName -replace "policy.parameters.json", "policy.json")) | ConvertFrom-Json
$parameters = (Get-Content -Path $item.FullName) | ConvertFrom-Json
if ($policy.properties.policyType -ne "BuiltIn") {
Write-Output "Deploying the Azure Policy : $($policy.properties.displayName)"
New-AzPolicyDefinition -Name $policy.name `
-DisplayName $policy.properties.displayName `
-Policy ($policy.properties | ConvertTo-Json -Depth 20) `
-Parameter ($parameters | ConvertTo-Json -Depth 20) `
-Metadata ($policy.properties.metadata | ConvertTo-Json) `
-ManagementGroupName $policy.id.Split("/")[4] `
-Mode $policy.properties.mode
}
}
foreach ($item in Get-Item .\initiatives\*\policy.parameters.json) {
$policy = (Get-Content -Path $($item.FullName -replace "policy.parameters.json", "policyset.json")) | ConvertFrom-Json
$parameters = (Get-Content -Path $item.FullName) | ConvertFrom-Json
Write-Output "Deploying the Azure Policy Initiative : $($policy.properties.displayName)"
$initiativePolicy = New-AzPolicySetDefinition -Name $policy.name `
-DisplayName $policy.properties.displayName `
-PolicyDefinition ($policy.properties.policyDefinitions | ConvertTo-Json -Depth 5) `
-Parameter ($parameters | ConvertTo-Json) `
-ManagementGroupName $policy.id.Split("/")[4] `
-Metadata ($policy.properties.metadata | ConvertTo-Json)
foreach ($item_assign in Get-Item "$($item.Directory.FullName)\assign.*.json") {
$assign = (Get-Content -Path $item_assign.FullName) | ConvertFrom-Json
## Assign the Initiative Policy
if ($assign.properties.notScopes) {
$PolicyAssignment = New-AzPolicyAssignment -Name $assign.name `
-DisplayName $assign.properties.displayName `
-PolicySetDefinition $initiativePolicy `
-Scope $assign.properties.scope `
-NotScope $assign.properties.notScopes `
-AssignIdentity `
-Location $assign.location `
-PolicyParameter ($assign.properties.parameters | ConvertTo-Json)
}
else {
$PolicyAssignment = New-AzPolicyAssignment -Name $assign.name `
-DisplayName $assign.properties.displayName `
-PolicySetDefinition $initiativePolicy `
-Scope $assign.properties.scope `
-AssignIdentity `
-Location $assign.location `
-PolicyParameter ($assign.properties.parameters | ConvertTo-Json)
}
## Extract the ObjectID of the Policy Assignment Managed Identity
$objectID = [GUID]($PolicyAssignment.Identity.principalId) #[GUID]($assign.identity.principalId) #
## Create a role assignment from the role definition ids available in each policies initiatives
# Role assignment is done on the Policy assignment Identity and on the User Managed Identity used for the deployment script on ARM Template (used for remediation)
$roleDefinitionIds = @()
$initiativePolicy.Properties.PolicyDefinitions.policyDefinitionId | ForEach-Object {
$AzPolicyDefinition = Get-AzPolicyDefinition -Id $_
$then = $AzPolicyDefinition.Properties.PolicyRule.then
if ($then | Get-Member | Where-Object { $_.Name -like "details" }) {
if ($then.details | Get-Member | Where-Object { $_.Name -like "roleDefinitionIds" } ) {
$roleDefinitionIds += $then.details.roleDefinitionIds
}
}
}
$roleDefinitionIds = $roleDefinitionIds | Select-Object -Unique
$AzRoleAssignment = Get-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $objectID -RoleDefinitionId $deploymentScriptMinimumPrivilege.Id -ErrorAction SilentlyContinue
if (!$AzRoleAssignment) {
New-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $objectID.Guid -RoleDefinitionId $deploymentScriptMinimumPrivilege.Id
}
foreach ($roleDefinitionId in $roleDefinitionIds) {
$AzRoleAssignment = Get-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $objectID -RoleDefinitionId "$($roleDefinitionId.Split("/")[-1])" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if (!$AzRoleAssignment) {
New-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $objectID.Guid -RoleDefinitionId "$($roleDefinitionId.Split("/")[-1])"
}
}
## User Managed Identity used for the deployment script on ARM Template (used for remediation)
if ($assign.properties.parameters | Get-Member | Where-Object { $_.Name -like "identityId" } ) {
$AzureRmContext = Get-AzSubscription -SubscriptionId $assign.properties.parameters.identityId.value.split("/")[2] | Set-AzContext -ErrorAction Stop
Select-AzSubscription -Name $AzureRmContext.Subscription.Name -Context $AzureRmContext -Force -ErrorAction Stop | Out-Null
$AzUserAssignedIdentity = Get-AzUserAssignedIdentity -ResourceGroupName $assign.properties.parameters.identityId.value.split("/")[-5] -Name $assign.properties.parameters.identityId.value.split("/")[-1]
$AzRoleAssignment = Get-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $AzUserAssignedIdentity.PrincipalId -RoleDefinitionId $deploymentScriptMinimumPrivilege.Id -ErrorAction SilentlyContinue
if (!$AzRoleAssignment) {
New-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $AzUserAssignedIdentity.PrincipalId -RoleDefinitionId $deploymentScriptMinimumPrivilege.Id
}
foreach ($roleDefinitionId in $roleDefinitionIds) {
$AzRoleAssignment = Get-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $AzUserAssignedIdentity.PrincipalId -RoleDefinitionId "$($roleDefinitionId.Split("/")[-1])" -ErrorVariable notPresent -ErrorAction SilentlyContinue
if (!$AzRoleAssignment) {
New-AzRoleAssignment -Scope "$($assign.properties.scope)" -ObjectId $AzUserAssignedIdentity.PrincipalId -RoleDefinitionId "$($roleDefinitionId.Split("/")[-1])"
}
}
}
## Prepare the compliance scan
$Scopes += $assign.properties.scope
}
}
# Start a compliance scan
$Scopes = $Scopes | Select-Object -Unique
foreach ($Scope in $Scopes) {
if ($Scope -like "*resourceGroups*") {
$complianceJobs += Start-AzPolicyComplianceScan -ResourceGroupName $Scope.Split("/")[-1] -AsJob
}
else {
$complianceJobs += Start-AzPolicyComplianceScan -AsJob
}
}
<#
Memo to get the job info -->
$complianceJobs | Select-Object Id, State, PSBeginTime
#>