From 294b011cff369fcbce1db10419e3429d1e91d6c7 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 14:53:03 -0400 Subject: [PATCH 01/10] initial commit for publish --- .../.bicep/nested_policyExemptions.bicep | 63 +++++++++++++++++++ .../.test/common/dependencies.bicep | 17 +++++ .../.test/common/deploy.test.bicep | 10 +++ .../storageAccounts/deploy.bicep | 35 +++++++++++ 4 files changed, 125 insertions(+) create mode 100644 modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep diff --git a/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep b/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep new file mode 100644 index 0000000000..1242ee7707 --- /dev/null +++ b/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep @@ -0,0 +1,63 @@ +@sys.description('Required. The resource ID of the resource to apply the policy exemption to.') +param resourceId string + +@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters.') +@maxLength(64) +param name string + +@sys.description('Optional. The display name of the policy exemption. Maximum length is 128 characters.') +@maxLength(128) +param displayName string = '' + +@sys.description('Optional. The description of the policy exemption.') +param description string = '' + +@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') +param metadata object = {} + +@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated.') +@allowed([ + 'Mitigated' + 'Waiver' +]) +param exemptionCategory string = 'Mitigated' + +@sys.description('Required. The resource ID of the policy assignment that is being exempted.') +param policyAssignmentId string + +@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') +param policyDefinitionReferenceIds array = [] + +@sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z.') +param expiresOn string = '' + +@sys.description('Optional. The option whether validate the exemption is at or under the assignment scope.') +@allowed([ + '' + 'Default' + 'DoNotValidate' +]) +param assignmentScopeValidation string = '' + +@sys.description('Optional. The resource selector list to filter policies by resource properties.') +param resourceSelectors array = [] + +resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' existing = { + name: last(split(resourceId, '/'))! +} + +resource policyExemption 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = { + name: name + properties: { + assignmentScopeValidation: !empty(assignmentScopeValidation) ? assignmentScopeValidation : null + displayName: !empty(displayName) ? displayName : null + description: !empty(description) ? description : null + exemptionCategory: exemptionCategory + expiresOn: !empty(expiresOn) ? expiresOn : null + metadata: !empty(metadata) ? metadata : null + policyAssignmentId: policyAssignmentId + policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : null + resourceSelectors: resourceSelectors + } + scope: storageAccount +} diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index d130bdb97d..c2f08db001 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -7,6 +7,12 @@ param virtualNetworkName string @description('Required. The name of the Managed Identity to create.') param managedIdentityName string +@description('Optional. The name of the policy assignment.') +param policyAssignmentName string = 'Configure your Storage account public access to be disallowed' + +@description('Optional. The policy definition Id to be assigned.') +param policyDefinitionId string = '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' + var addressPrefix = '10.0.0.0/16' resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { @@ -55,6 +61,14 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- location: location } +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = { + name: policyAssignmentName + scope: resourceGroup() + properties: { + policyDefinitionId: policyDefinitionId + } +} + @description('The resource ID of the created Virtual Network Subnet.') output subnetResourceId string = virtualNetwork.properties.subnets[0].id @@ -66,3 +80,6 @@ output managedIdentityResourceId string = managedIdentity.id @description('The resource ID of the created Private DNS Zone.') output privateDNSZoneResourceId string = privateDNSZone.id + +@description('The resource ID of the Policy Assignment.') +output policyAssignmentId string = policyAssignment.id diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/deploy.test.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/deploy.test.bicep index 4fe2601520..152e48e48d 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/deploy.test.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/deploy.test.bicep @@ -69,6 +69,16 @@ module testDeployment '../../deploy.bicep' = { enableHierarchicalNamespace: true enableSftp: true enableNfsV3: true + policyExemptions: [ + { + name: '<>${serviceShort}001-PolicyExemption001' + displayName: '<>${serviceShort}001 Policy Exception' + description: 'Test Policy Exemption 1' + assignmentScopeValidation: 'DoNotValidate' + policyAssignmentId: nestedDependencies.outputs.policyAssignmentId + exemptionCategory: 'Waiver' + } + ] privateEndpoints: [ { service: 'blob' diff --git a/modules/Microsoft.Storage/storageAccounts/deploy.bicep b/modules/Microsoft.Storage/storageAccounts/deploy.bicep index 024bc67e2e..e67a404282 100644 --- a/modules/Microsoft.Storage/storageAccounts/deploy.bicep +++ b/modules/Microsoft.Storage/storageAccounts/deploy.bicep @@ -8,6 +8,9 @@ param location string = resourceGroup().location @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. Array of policy exemption objects that contain the \'name\' and \'policyAssignmentId\' to policy exemptions on this resource.') +param policyExemptions array = [] + @description('Optional. Enables system assigned managed identity on the resource.') param systemAssignedIdentity bool = false @@ -338,6 +341,38 @@ module storageAccount_roleAssignments '.bicep/nested_roleAssignments.bicep' = [f } }] +resource storageAccount_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: storageAccount +}] + +/* +module storageAccount_policyExemptions_Module '.bicep/nested_policyExemptions.bicep' = [for (policyExemption, index) in policyExemptions: { + name: '${uniqueString(deployment().name, location)}-storage-policyException-${index}' + params: { + name: policyExemption.name + assignmentScopeValidation: contains(policyExemption, 'assignmentScopeValidation') ? policyExemption.assignmentScopeValidation : '' + displayName: contains(policyExemption, 'displayName') ? policyExemption.description : '' + description: contains(policyExemption, 'description') ? policyExemption.description : '' + resourceId: storageAccount.id + 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 : '' + } +}] +*/ module storageAccount_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint, index) in privateEndpoints: { name: '${uniqueString(deployment().name, location)}-StorageAccount-PrivateEndpoint-${index}' params: { From 5ee8a7821b2f183831d9cbc3a65c0df535ce62ab Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 15:22:27 -0400 Subject: [PATCH 02/10] updated readme --- .../storageAccounts/readme.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/modules/Microsoft.Storage/storageAccounts/readme.md b/modules/Microsoft.Storage/storageAccounts/readme.md index fefef84885..0142f4b34f 100644 --- a/modules/Microsoft.Storage/storageAccounts/readme.md +++ b/modules/Microsoft.Storage/storageAccounts/readme.md @@ -16,6 +16,7 @@ This module is used to deploy a storage account, with the ability to deploy 1 or | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/policyExemptions` | [2022-07-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-07-01-preview/policyExemptions) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.Network/privateEndpoints` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2022-07-01/privateEndpoints) | @@ -85,6 +86,7 @@ This module is used to deploy a storage account, with the ability to deploy 1 or | `managementPolicyRules` | array | `[]` | | The Storage Account ManagementPolicies Rules. | | `minimumTlsVersion` | string | `'TLS1_2'` | `[TLS1_0, TLS1_1, TLS1_2]` | Set the minimum TLS version on request to storage. | | `networkAcls` | object | `{object}` | | Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny. | +| `policyExemptions` | array | `[]` | | Array of policy exemption objects that contain the 'name' and 'policyAssignmentId' to policy exemptions on this resource. | | `privateEndpoints` | array | `[]` | | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | | `publicNetworkAccess` | string | `''` | `['', Disabled, Enabled]` | 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. | | `queueServices` | _[queueServices](queueServices/readme.md)_ object | `{object}` | | Queue service and queues to create. | @@ -531,6 +533,16 @@ module storageAccounts './Microsoft.Storage/storageAccounts/deploy.bicep' = { } ] } + policyExemptions: [ + { + assignmentScopeValidation: 'DoNotValidate' + description: 'Test Policy Exemption 1' + displayName: '<>ssacom001 Policy Exception' + exemptionCategory: 'Waiver' + name: '<>ssacom001-PolicyExemption001' + policyAssignmentId: '' + } + ] privateEndpoints: [ { privateDnsZoneGroup: { @@ -758,6 +770,18 @@ module storageAccounts './Microsoft.Storage/storageAccounts/deploy.bicep' = { ] } }, + "policyExemptions": { + "value": [ + { + "assignmentScopeValidation": "DoNotValidate", + "description": "Test Policy Exemption 1", + "displayName": "<>ssacom001 Policy Exception", + "exemptionCategory": "Waiver", + "name": "<>ssacom001-PolicyExemption001", + "policyAssignmentId": "" + } + ] + }, "privateEndpoints": { "value": [ { From dcf3b953a4881815e9e66d920fc03c173e54b004 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 15:55:37 -0400 Subject: [PATCH 03/10] updated readme --- .../storageAccounts/.test/common/dependencies.bicep | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index c2f08db001..cb5921a11f 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -8,10 +8,10 @@ param virtualNetworkName string param managedIdentityName string @description('Optional. The name of the policy assignment.') -param policyAssignmentName string = 'Configure your Storage account public access to be disallowed' +param policyAssignmentName string = '${resourceGroup().name}-Configure storage accounts to disable public network access' @description('Optional. The policy definition Id to be assigned.') -param policyDefinitionId string = '/providers/Microsoft.Authorization/roleDefinitions/17d1049b-9a84-46fb-8f53-869881c3d3ab' +param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/a06d0189-92e8-4dba-b0c4-08d7669fce7d' var addressPrefix = '10.0.0.0/16' From 87ab9d3317bab3a716cf5aa2fa3aa3bed108314b Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 16:13:12 -0400 Subject: [PATCH 04/10] updated policyAssignmentName --- .../storageAccounts/.test/common/dependencies.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index cb5921a11f..c93a5a92c6 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -8,7 +8,7 @@ param virtualNetworkName string param managedIdentityName string @description('Optional. The name of the policy assignment.') -param policyAssignmentName string = '${resourceGroup().name}-Configure storage accounts to disable public network access' +param policyAssignmentName string = '${resourceGroup().name}-DisableStoragePublicNetworkAccess' @description('Optional. The policy definition Id to be assigned.') param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/a06d0189-92e8-4dba-b0c4-08d7669fce7d' From 7291d51a71c7b67fc3df1feb1cf54f36bc83e801 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 16:46:16 -0400 Subject: [PATCH 05/10] changed assignment name --- .../storageAccounts/.test/common/dependencies.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index c93a5a92c6..8d0a4475df 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -8,7 +8,7 @@ param virtualNetworkName string param managedIdentityName string @description('Optional. The name of the policy assignment.') -param policyAssignmentName string = '${resourceGroup().name}-DisableStoragePublicNetworkAccess' +param policyAssignmentName string = 'DisableStoragePublicNetworkAccess' @description('Optional. The policy definition Id to be assigned.') param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/a06d0189-92e8-4dba-b0c4-08d7669fce7d' From 581471d6d0572443463945cef1a9e78a38de0c13 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 18:22:52 -0400 Subject: [PATCH 06/10] added userassignedid to test --- .../storageAccounts/.test/common/dependencies.bicep | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index 8d0a4475df..9c2f630883 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -64,8 +64,15 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = { name: policyAssignmentName scope: resourceGroup() + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } properties: { policyDefinitionId: policyDefinitionId + enforcementMode: 'Default' } } From dae567d79488246d0eb18a900eb7bf2a3ec90d11 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 18:34:08 -0400 Subject: [PATCH 07/10] added location to resource --- .../storageAccounts/.test/common/dependencies.bicep | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index 9c2f630883..b3624cfb7e 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -64,6 +64,7 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = { name: policyAssignmentName scope: resourceGroup() + location: location identity: { type: 'UserAssigned' userAssignedIdentities: { From 61809883c89627fe2ba51f6dc8b80ba1757ad8f0 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Tue, 14 Mar 2023 20:19:31 -0400 Subject: [PATCH 08/10] updated false condition on metadata --- modules/Microsoft.Storage/storageAccounts/deploy.bicep | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Microsoft.Storage/storageAccounts/deploy.bicep b/modules/Microsoft.Storage/storageAccounts/deploy.bicep index e67a404282..43731ab9e3 100644 --- a/modules/Microsoft.Storage/storageAccounts/deploy.bicep +++ b/modules/Microsoft.Storage/storageAccounts/deploy.bicep @@ -347,7 +347,7 @@ resource storageAccount_policyExemptions 'Microsoft.Authorization/policyExemptio assignmentScopeValidation: contains(policyExemption, 'assignmentScopeValidation') ? policyExemption.assignmentScopeValidation : '' displayName: contains(policyExemption, 'displayName') ? policyExemption.description : '' description: contains(policyExemption, 'description') ? policyExemption.description : '' - metadata: contains(policyExemption, 'metadata') ? policyExemption.metadata : '' + metadata: contains(policyExemption, 'metadata') ? policyExemption.metadata : {} policyAssignmentId: policyExemption.policyAssignmentId policyDefinitionReferenceIds: contains(policyExemption, 'policyDefinitionReferenceIds') ? policyExemption.policyDefinitionReferenceIds : null exemptionCategory: contains(policyExemption, 'exemptionCategory') ? policyExemption.exemptionCategory : null From fe3cdddb709bd8f0294b89a219315ded14ca66ba Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Thu, 6 Apr 2023 07:55:11 -0400 Subject: [PATCH 09/10] added Keyvault --- .../vaults/.test/common/dependencies.bicep | 25 +++++++++++++++ .../vaults/.test/common/deploy.test.bicep | 10 ++++++ .../Microsoft.KeyVault/vaults/deploy.bicep | 25 +++++++++++++++ modules/Microsoft.KeyVault/vaults/readme.md | 24 ++++++++++++++ .../storageAccounts/deploy.bicep | 31 +++++++------------ .../storageAccounts/readme.md | 2 +- 6 files changed, 96 insertions(+), 21 deletions(-) diff --git a/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep b/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep index 064a1f10d8..ee1f8a147c 100644 --- a/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep +++ b/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep @@ -7,6 +7,12 @@ param virtualNetworkName string @description('Required. The name of the Managed Identity to create.') param managedIdentityName string +@description('Optional. The name of the policy assignment.') +param policyAssignmentName string = 'DisableKeyVaultPublicAccess' + +@description('Optional. The policy definition Id to be assigned.') +param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/405c5871-3e91-4644-8a63-58e19d68ff5b' + var addressPrefix = '10.0.0.0/16' resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { @@ -39,6 +45,22 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- location: location } +resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' = { + name: policyAssignmentName + scope: resourceGroup() + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + policyDefinitionId: policyDefinitionId + enforcementMode: 'Default' + } +} + resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { name: 'privatelink.vaultcore.azure.net' location: 'global' @@ -63,3 +85,6 @@ output managedIdentityPrincipalId string = managedIdentity.properties.principalI @description('The resource ID of the created Private DNS Zone.') output privateDNSResourceId string = privateDNSZone.id + +@description('The resource ID of the Policy Assignment.') +output policyAssignmentId string = policyAssignment.id diff --git a/modules/Microsoft.KeyVault/vaults/.test/common/deploy.test.bicep b/modules/Microsoft.KeyVault/vaults/.test/common/deploy.test.bicep index b01982f72d..72b739a5be 100644 --- a/modules/Microsoft.KeyVault/vaults/.test/common/deploy.test.bicep +++ b/modules/Microsoft.KeyVault/vaults/.test/common/deploy.test.bicep @@ -153,6 +153,16 @@ module testDeployment '../../deploy.bicep' = { } ] } + policyExemptions: [ + { + name: '<>${serviceShort}001-PolicyExemption001' + displayName: '<>${serviceShort}001 Policy Exception' + description: 'Test Policy Exemption 1' + assignmentScopeValidation: 'DoNotValidate' + policyAssignmentId: nestedDependencies.outputs.policyAssignmentId + exemptionCategory: 'Waiver' + } + ] privateEndpoints: [ { privateDnsZoneGroup: { diff --git a/modules/Microsoft.KeyVault/vaults/deploy.bicep b/modules/Microsoft.KeyVault/vaults/deploy.bicep index 7f23143f12..831e405079 100644 --- a/modules/Microsoft.KeyVault/vaults/deploy.bicep +++ b/modules/Microsoft.KeyVault/vaults/deploy.bicep @@ -85,6 +85,17 @@ param diagnosticEventHubName string = '' @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 = [] @@ -295,6 +306,20 @@ module keyVault_privateEndpoints '../../Microsoft.Network/privateEndpoints/deplo } }] +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: { diff --git a/modules/Microsoft.KeyVault/vaults/readme.md b/modules/Microsoft.KeyVault/vaults/readme.md index 37372e309c..3a902695e2 100644 --- a/modules/Microsoft.KeyVault/vaults/readme.md +++ b/modules/Microsoft.KeyVault/vaults/readme.md @@ -15,6 +15,7 @@ This module deploys a key vault and its child resources. | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/policyExemptions` | [2022-07-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-07-01-preview/policyExemptions) | | `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | | `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | | `Microsoft.KeyVault/vaults` | [2022-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2022-07-01/vaults) | @@ -57,6 +58,7 @@ This module deploys a key vault and its child resources. | `location` | string | `[resourceGroup().location]` | | Location for all resources. | | `lock` | string | `''` | `['', CanNotDelete, ReadOnly]` | Specify the type of lock. | | `networkAcls` | object | `{object}` | | Service endpoint object information. For security reasons, it is recommended to set the DefaultAction Deny. | +| `policyExemptions` | array | `[]` | | 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.

| | `privateEndpoints` | array | `[]` | | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | | `publicNetworkAccess` | string | `''` | `['', Disabled, Enabled]` | 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. | | `roleAssignments` | array | `[]` | | 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'. | @@ -506,6 +508,16 @@ module vaults './Microsoft.KeyVault/vaults/deploy.bicep' = { } ] } + policyExemptions: [ + { + assignmentScopeValidation: 'DoNotValidate' + description: 'Test Policy Exemption 1' + displayName: '<>kvvcom001 Policy Exception' + exemptionCategory: 'Waiver' + name: '<>kvvcom001-PolicyExemption001' + policyAssignmentId: '' + } + ] privateEndpoints: [ { privateDnsZoneGroup: { @@ -690,6 +702,18 @@ module vaults './Microsoft.KeyVault/vaults/deploy.bicep' = { ] } }, + "policyExemptions": { + "value": [ + { + "assignmentScopeValidation": "DoNotValidate", + "description": "Test Policy Exemption 1", + "displayName": "<>kvvcom001 Policy Exception", + "exemptionCategory": "Waiver", + "name": "<>kvvcom001-PolicyExemption001", + "policyAssignmentId": "" + } + ] + }, "privateEndpoints": { "value": [ { diff --git a/modules/Microsoft.Storage/storageAccounts/deploy.bicep b/modules/Microsoft.Storage/storageAccounts/deploy.bicep index 43731ab9e3..77cec283f9 100644 --- a/modules/Microsoft.Storage/storageAccounts/deploy.bicep +++ b/modules/Microsoft.Storage/storageAccounts/deploy.bicep @@ -5,12 +5,20 @@ param name string @description('Optional. Location for all resources.') param location string = resourceGroup().location -@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. 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. -@description('Optional. Array of policy exemption objects that contain the \'name\' and \'policyAssignmentId\' to policy exemptions on this resource.') +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. Enables system assigned managed identity on the resource.') param systemAssignedIdentity bool = false @@ -356,23 +364,6 @@ resource storageAccount_policyExemptions 'Microsoft.Authorization/policyExemptio scope: storageAccount }] -/* -module storageAccount_policyExemptions_Module '.bicep/nested_policyExemptions.bicep' = [for (policyExemption, index) in policyExemptions: { - name: '${uniqueString(deployment().name, location)}-storage-policyException-${index}' - params: { - name: policyExemption.name - assignmentScopeValidation: contains(policyExemption, 'assignmentScopeValidation') ? policyExemption.assignmentScopeValidation : '' - displayName: contains(policyExemption, 'displayName') ? policyExemption.description : '' - description: contains(policyExemption, 'description') ? policyExemption.description : '' - resourceId: storageAccount.id - 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 : '' - } -}] -*/ module storageAccount_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint, index) in privateEndpoints: { name: '${uniqueString(deployment().name, location)}-StorageAccount-PrivateEndpoint-${index}' params: { diff --git a/modules/Microsoft.Storage/storageAccounts/readme.md b/modules/Microsoft.Storage/storageAccounts/readme.md index 0142f4b34f..4370216671 100644 --- a/modules/Microsoft.Storage/storageAccounts/readme.md +++ b/modules/Microsoft.Storage/storageAccounts/readme.md @@ -86,7 +86,7 @@ This module is used to deploy a storage account, with the ability to deploy 1 or | `managementPolicyRules` | array | `[]` | | The Storage Account ManagementPolicies Rules. | | `minimumTlsVersion` | string | `'TLS1_2'` | `[TLS1_0, TLS1_1, TLS1_2]` | Set the minimum TLS version on request to storage. | | `networkAcls` | object | `{object}` | | Networks ACLs, this value contains IPs to whitelist and/or Subnet information. For security reasons, it is recommended to set the DefaultAction Deny. | -| `policyExemptions` | array | `[]` | | Array of policy exemption objects that contain the 'name' and 'policyAssignmentId' to policy exemptions on this resource. | +| `policyExemptions` | array | `[]` | | 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.

| | `privateEndpoints` | array | `[]` | | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | | `publicNetworkAccess` | string | `''` | `['', Disabled, Enabled]` | 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. | | `queueServices` | _[queueServices](queueServices/readme.md)_ object | `{object}` | | Queue service and queues to create. | From 7b88fa48e1e1f9b6774038c23cc6d9b279aca916 Mon Sep 17 00:00:00 2001 From: Shawn Meyer Date: Fri, 14 Apr 2023 08:55:09 -0400 Subject: [PATCH 10/10] changed policy assignments to incorporate deny --- .../vaults/.test/common/dependencies.bicep | 9 ++- .../.bicep/nested_policyExemptions.bicep | 63 ------------------- .../.test/common/dependencies.bicep | 9 ++- 3 files changed, 14 insertions(+), 67 deletions(-) delete mode 100644 modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep diff --git a/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep b/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep index ee1f8a147c..10e0010649 100644 --- a/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep +++ b/modules/Microsoft.KeyVault/vaults/.test/common/dependencies.bicep @@ -8,10 +8,10 @@ param virtualNetworkName string param managedIdentityName string @description('Optional. The name of the policy assignment.') -param policyAssignmentName string = 'DisableKeyVaultPublicAccess' +param policyAssignmentName string = 'KeyVaultsShouldBeBackedbyHSM' @description('Optional. The policy definition Id to be assigned.') -param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/405c5871-3e91-4644-8a63-58e19d68ff5b' +param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/587c79fe-dd04-4a5e-9d0b-f89598c7261b' // Key vaults should be backed by a hardware security module (HSM). var addressPrefix = '10.0.0.0/16' @@ -58,6 +58,11 @@ resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' properties: { policyDefinitionId: policyDefinitionId enforcementMode: 'Default' + parameters: { + effect: { + value: 'Deny' + } + } } } diff --git a/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep b/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep deleted file mode 100644 index 1242ee7707..0000000000 --- a/modules/Microsoft.Storage/storageAccounts/.bicep/nested_policyExemptions.bicep +++ /dev/null @@ -1,63 +0,0 @@ -@sys.description('Required. The resource ID of the resource to apply the policy exemption to.') -param resourceId string - -@sys.description('Required. Specifies the name of the policy exemption. Maximum length is 64 characters.') -@maxLength(64) -param name string - -@sys.description('Optional. The display name of the policy exemption. Maximum length is 128 characters.') -@maxLength(128) -param displayName string = '' - -@sys.description('Optional. The description of the policy exemption.') -param description string = '' - -@sys.description('Optional. The policy exemption metadata. Metadata is an open ended object and is typically a collection of key-value pairs.') -param metadata object = {} - -@sys.description('Optional. The policy exemption category. Possible values are Waiver and Mitigated. Default is Mitigated.') -@allowed([ - 'Mitigated' - 'Waiver' -]) -param exemptionCategory string = 'Mitigated' - -@sys.description('Required. The resource ID of the policy assignment that is being exempted.') -param policyAssignmentId string - -@sys.description('Optional. The policy definition reference ID list when the associated policy assignment is an assignment of a policy set definition.') -param policyDefinitionReferenceIds array = [] - -@sys.description('Optional. The expiration date and time (in UTC ISO 8601 format yyyy-MM-ddTHH:mm:ssZ) of the policy exemption. e.g. 2021-10-02T03:57:00.000Z.') -param expiresOn string = '' - -@sys.description('Optional. The option whether validate the exemption is at or under the assignment scope.') -@allowed([ - '' - 'Default' - 'DoNotValidate' -]) -param assignmentScopeValidation string = '' - -@sys.description('Optional. The resource selector list to filter policies by resource properties.') -param resourceSelectors array = [] - -resource storageAccount 'Microsoft.Storage/storageAccounts@2022-05-01' existing = { - name: last(split(resourceId, '/'))! -} - -resource policyExemption 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = { - name: name - properties: { - assignmentScopeValidation: !empty(assignmentScopeValidation) ? assignmentScopeValidation : null - displayName: !empty(displayName) ? displayName : null - description: !empty(description) ? description : null - exemptionCategory: exemptionCategory - expiresOn: !empty(expiresOn) ? expiresOn : null - metadata: !empty(metadata) ? metadata : null - policyAssignmentId: policyAssignmentId - policyDefinitionReferenceIds: !empty(policyDefinitionReferenceIds) ? policyDefinitionReferenceIds : null - resourceSelectors: resourceSelectors - } - scope: storageAccount -} diff --git a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep index b3624cfb7e..ea17fb196b 100644 --- a/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep +++ b/modules/Microsoft.Storage/storageAccounts/.test/common/dependencies.bicep @@ -8,10 +8,10 @@ param virtualNetworkName string param managedIdentityName string @description('Optional. The name of the policy assignment.') -param policyAssignmentName string = 'DisableStoragePublicNetworkAccess' +param policyAssignmentName string = 'StorAcctsAccessfromMSServices' @description('Optional. The policy definition Id to be assigned.') -param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/a06d0189-92e8-4dba-b0c4-08d7669fce7d' +param policyDefinitionId string = '/providers/Microsoft.Authorization/policyDefinitions/c9d007d0-c057-4772-b18c-01e546713bcd' //Storage accounts should allow access from trusted Microsoft services var addressPrefix = '10.0.0.0/16' @@ -74,6 +74,11 @@ resource policyAssignment 'Microsoft.Authorization/policyAssignments@2022-06-01' properties: { policyDefinitionId: policyDefinitionId enforcementMode: 'Default' + parameters: { + effect: { + value: 'Deny' + } + } } }