-
Notifications
You must be signed in to change notification settings - Fork 436
Expand file tree
/
Copy pathdeploy.bicep
More file actions
352 lines (300 loc) · 16.2 KB
/
deploy.bicep
File metadata and controls
352 lines (300 loc) · 16.2 KB
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
// ================ //
// Parameters //
// ================ //
@description('Required. Name of the Key Vault. Must be globally unique.')
@maxLength(24)
param name string
@description('Optional. Location for all resources.')
param location string = resourceGroup().location
@description('Optional. Array of access policies object.')
param accessPolicies array = []
@description('Optional. All secrets to create.')
@secure()
param secrets object = {}
@description('Optional. All keys to create.')
param keys array = []
@description('Optional. Specifies if the vault is enabled for deployment by script or compute.')
param enableVaultForDeployment bool = true
@description('Optional. Specifies if the vault is enabled for a template deployment.')
param enableVaultForTemplateDeployment bool = true
@description('Optional. Specifies if the azure platform has access to the vault for enabling disk encryption scenarios.')
param enableVaultForDiskEncryption bool = true
@description('Optional. Switch to enable/disable Key Vault\'s soft delete feature.')
param enableSoftDelete bool = true
@description('Optional. softDelete data retention days. It accepts >=7 and <=90.')
param softDeleteRetentionInDays int = 90
@description('Optional. Property that controls how data actions are authorized. When true, the key vault will use Role Based Access Control (RBAC) for authorization of data actions, and the access policies specified in vault properties will be ignored (warning: this is a preview feature). When false, the key vault will use the access policies specified in vault properties, and any policy stored on Azure Resource Manager will be ignored. If null or not specified, the vault is created with the default value of false. Note that management actions are always authorized with RBAC.')
param enableRbacAuthorization bool = false
@description('Optional. The vault\'s create mode to indicate whether the vault need to be recovered or not. - recover or default.')
param createMode string = 'default'
@description('Optional. Provide \'true\' to enable Key Vault\'s purge protection feature.')
param enablePurgeProtection bool = true
@description('Optional. Specifies the SKU for the vault.')
@allowed([
'premium'
'standard'
])
param vaultSku string = 'premium'
@description('Optional. Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny.')
param networkAcls object = {}
@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set and networkAcls are not set.')
@allowed([
''
'Enabled'
'Disabled'
])
param publicNetworkAccess string = ''
@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.')
@minValue(0)
@maxValue(365)
param diagnosticLogsRetentionInDays int = 365
@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
param diagnosticStorageAccountId string = ''
@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
param diagnosticWorkspaceId string = ''
@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.')
param diagnosticEventHubAuthorizationRuleId string = ''
@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.')
param diagnosticEventHubName string = ''
@allowed([
''
'CanNotDelete'
'ReadOnly'
])
@description('Optional. Specify the type of lock.')
param lock string = ''
@description('''Optional. Array of policy exemption objects that contain the \'name\' and \'policyAssignmentId\' to policy exemptions on this resource.
Exemptions have extra security measures because of the impact of granting an exemption.
Beyond requiring the Microsoft.Authorization/policyExemptions/write operation on the resource hierarchy or individual resource,
the creator of an exemption must have the exempt/Action verb on the target assignment which could be at the Management Group, Subscription, or Resource Group levels.
The built-in roles Resource Policy Contributor and Security Admin both have the read and write permissions.
''')
param policyExemptions array = []
@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.')
param roleAssignments array = []
@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.')
param privateEndpoints array = []
@description('Optional. Resource tags.')
param tags object = {}
@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).')
param enableDefaultTelemetry bool = true
@description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource.')
@allowed([
'allLogs'
'AuditEvent'
'AzurePolicyEvaluationDetails'
])
param diagnosticLogCategoriesToEnable array = [
'allLogs'
]
@description('Optional. The name of metrics that will be streamed.')
@allowed([
'AllMetrics'
])
param diagnosticMetricsToEnable array = [
'AllMetrics'
]
@description('Optional. The name of the diagnostic setting, if deployed.')
param diagnosticSettingsName string = '${name}-diagnosticSettings'
// =========== //
// Variables //
// =========== //
var diagnosticsLogsSpecified = [for category in filter(diagnosticLogCategoriesToEnable, item => item != 'allLogs'): {
category: category
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}]
var diagnosticsLogs = contains(diagnosticLogCategoriesToEnable, 'allLogs') ? [
{
categoryGroup: 'allLogs'
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}
] : diagnosticsLogsSpecified
var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: {
category: metric
timeGrain: null
enabled: true
retentionPolicy: {
enabled: true
days: diagnosticLogsRetentionInDays
}
}]
var formattedAccessPolicies = [for accessPolicy in accessPolicies: {
applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : ''
objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : ''
permissions: accessPolicy.permissions
tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId
}]
var secretList = !empty(secrets) ? secrets.secureList : []
var enableReferencedModulesTelemetry = false
// ============ //
// Dependencies //
// ============ //
resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) {
name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}'
properties: {
mode: 'Incremental'
template: {
'$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#'
contentVersion: '1.0.0.0'
resources: []
}
}
}
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = {
name: name
location: location
tags: tags
properties: {
enabledForDeployment: enableVaultForDeployment
enabledForTemplateDeployment: enableVaultForTemplateDeployment
enabledForDiskEncryption: enableVaultForDiskEncryption
enableSoftDelete: enableSoftDelete
softDeleteRetentionInDays: softDeleteRetentionInDays
enableRbacAuthorization: enableRbacAuthorization
createMode: createMode
enablePurgeProtection: enablePurgeProtection ? enablePurgeProtection : null
tenantId: subscription().tenantId
accessPolicies: formattedAccessPolicies
sku: {
name: vaultSku
family: 'A'
}
networkAcls: !empty(networkAcls) ? {
bypass: contains(networkAcls, 'bypass') ? networkAcls.bypass : null
defaultAction: contains(networkAcls, 'defaultAction') ? networkAcls.defaultAction : null
virtualNetworkRules: contains(networkAcls, 'virtualNetworkRules') ? networkAcls.virtualNetworkRules : []
ipRules: contains(networkAcls, 'ipRules') ? networkAcls.ipRules : []
} : null
publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) && empty(networkAcls) ? 'Disabled' : null)
}
}
resource keyVault_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock)) {
name: '${keyVault.name}-${lock}-lock'
properties: {
level: any(lock)
notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.'
}
scope: keyVault
}
resource keyVault_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) {
name: diagnosticSettingsName
properties: {
storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null
workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null
eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null
eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null
metrics: diagnosticsMetrics
logs: diagnosticsLogs
}
scope: keyVault
}
module keyVault_accessPolicies 'accessPolicies/deploy.bicep' = if (!empty(accessPolicies)) {
name: '${uniqueString(deployment().name, location)}-KeyVault-AccessPolicies'
params: {
keyVaultName: keyVault.name
accessPolicies: formattedAccessPolicies
enableDefaultTelemetry: enableReferencedModulesTelemetry
}
}
module keyVault_secrets 'secrets/deploy.bicep' = [for (secret, index) in secretList: {
name: '${uniqueString(deployment().name, location)}-KeyVault-Secret-${index}'
params: {
name: secret.name
value: secret.value
keyVaultName: keyVault.name
attributesEnabled: contains(secret, 'attributesEnabled') ? secret.attributesEnabled : true
attributesExp: contains(secret, 'attributesExp') ? secret.attributesExp : -1
attributesNbf: contains(secret, 'attributesNbf') ? secret.attributesNbf : -1
contentType: contains(secret, 'contentType') ? secret.contentType : ''
tags: contains(secret, 'tags') ? secret.tags : {}
roleAssignments: contains(secret, 'roleAssignments') ? secret.roleAssignments : []
enableDefaultTelemetry: enableReferencedModulesTelemetry
}
}]
module keyVault_keys 'keys/deploy.bicep' = [for (key, index) in keys: {
name: '${uniqueString(deployment().name, location)}-KeyVault-Key-${index}'
params: {
name: key.name
keyVaultName: keyVault.name
attributesEnabled: contains(key, 'attributesEnabled') ? key.attributesEnabled : true
attributesExp: contains(key, 'attributesExp') ? key.attributesExp : -1
attributesNbf: contains(key, 'attributesNbf') ? key.attributesNbf : -1
curveName: contains(key, 'curveName') ? key.curveName : 'P-256'
keyOps: contains(key, 'keyOps') ? key.keyOps : []
keySize: contains(key, 'keySize') ? key.keySize : -1
kty: contains(key, 'kty') ? key.kty : 'EC'
tags: contains(key, 'tags') ? key.tags : {}
roleAssignments: contains(key, 'roleAssignments') ? key.roleAssignments : []
enableDefaultTelemetry: enableReferencedModulesTelemetry
rotationPolicy: contains(key, 'rotationPolicy') ? key.rotationPolicy : {}
}
}]
module keyVault_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint, index) in privateEndpoints: {
name: '${uniqueString(deployment().name, location)}-KeyVault-PrivateEndpoint-${index}'
params: {
groupIds: [
privateEndpoint.service
]
name: contains(privateEndpoint, 'name') ? privateEndpoint.name : 'pe-${last(split(keyVault.id, '/'))}-${privateEndpoint.service}-${index}'
serviceResourceId: keyVault.id
subnetResourceId: privateEndpoint.subnetResourceId
enableDefaultTelemetry: enableReferencedModulesTelemetry
location: reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location
lock: contains(privateEndpoint, 'lock') ? privateEndpoint.lock : lock
privateDnsZoneGroup: contains(privateEndpoint, 'privateDnsZoneGroup') ? privateEndpoint.privateDnsZoneGroup : {}
roleAssignments: contains(privateEndpoint, 'roleAssignments') ? privateEndpoint.roleAssignments : []
tags: contains(privateEndpoint, 'tags') ? privateEndpoint.tags : {}
manualPrivateLinkServiceConnections: contains(privateEndpoint, 'manualPrivateLinkServiceConnections') ? privateEndpoint.manualPrivateLinkServiceConnections : []
customDnsConfigs: contains(privateEndpoint, 'customDnsConfigs') ? privateEndpoint.customDnsConfigs : []
ipConfigurations: contains(privateEndpoint, 'ipConfigurations') ? privateEndpoint.ipConfigurations : []
applicationSecurityGroups: contains(privateEndpoint, 'applicationSecurityGroups') ? privateEndpoint.applicationSecurityGroups : []
customNetworkInterfaceName: contains(privateEndpoint, 'customNetworkInterfaceName') ? privateEndpoint.customNetworkInterfaceName : ''
}
}]
resource keyVault_policyExemptions 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = [for policyExemption in policyExemptions: if (!empty(policyExemptions)) {
name: policyExemption.name
properties: {
assignmentScopeValidation: contains(policyExemption, 'assignmentScopeValidation') ? policyExemption.assignmentScopeValidation : ''
displayName: contains(policyExemption, 'displayName') ? policyExemption.description : ''
description: contains(policyExemption, 'description') ? policyExemption.description : ''
metadata: contains(policyExemption, 'metadata') ? policyExemption.metadata : {}
policyAssignmentId: policyExemption.policyAssignmentId
policyDefinitionReferenceIds: contains(policyExemption, 'policyDefinitionReferenceIds') ? policyExemption.policyDefinitionReferenceIds : null
exemptionCategory: contains(policyExemption, 'exemptionCategory') ? policyExemption.exemptionCategory : null
expiresOn: contains(policyExemption, 'expiresOn') ? policyExemption.expiresOn : ''
}
scope: keyVault
}]
module keyVault_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment, index) in roleAssignments: {
name: '${uniqueString(deployment().name, location)}-KeyVault-Rbac-${index}'
params: {
description: contains(roleAssignment, 'description') ? roleAssignment.description : ''
principalIds: roleAssignment.principalIds
principalType: contains(roleAssignment, 'principalType') ? roleAssignment.principalType : ''
roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName
condition: contains(roleAssignment, 'condition') ? roleAssignment.condition : ''
delegatedManagedIdentityResourceId: contains(roleAssignment, 'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : ''
resourceId: keyVault.id
}
}]
// =========== //
// Outputs //
// =========== //
@description('The resource ID of the key vault.')
output resourceId string = keyVault.id
@description('The name of the resource group the key vault was created in.')
output resourceGroupName string = resourceGroup().name
@description('The name of the key vault.')
output name string = keyVault.name
@description('The URI of the key vault.')
output uri string = keyVault.properties.vaultUri
@description('The location the resource was deployed into.')
output location string = keyVault.location