-
Notifications
You must be signed in to change notification settings - Fork 444
[Modules] Microsoft.Storage/StorageAccounts and Microsoft.KeyVault/vaults policy exemption #2997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
294b011
5ee8a78
dcf3b95
87ab9d3
7291d51
581471d
dae567d
6180988
fe3cddd
7b88fa4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,17 @@ param name string | |
@description('Optional. Location for all resources.') | ||
param location string = resourceGroup().location | ||
|
||
@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 = [] | ||
|
||
|
@@ -338,6 +349,21 @@ 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)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't the storage account deployment be already blocked before we even make it to the excemption? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is not, the storage account is deployed. The common tests for both storage accounts and key vaults deploy a policy assignment that denies the creation of a resource that doesn't meet the policy. I verified that the test is a true test in that the resource doesn't meet the policy, but the exception works and the deployment succeeds. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the policy a deny or an audit policy? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @eriqua, it is a Deny policy (https://portal.azure.com/#blade/Microsoft_Azure_Policy/PolicyDetailBlade/definitionId/%2Fproviders%2FMicrosoft.Authorization%2FpolicyDefinitions%2Fc9d007d0-c057-4772-b18c-01e546713bcd) and in the test deployed with the Deny effect. Same for Key Vault. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting. I'm inclined to see this as an unexpected behaviour of the policy. Probably due to timing? I'm very confused as I'd expect the deny policy to deny the creation of an uncompliant resource, by definition 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is exactly why I needed the PR. We can not create Resource Level exemptions without the resource ID and we can't create the resource with a deny policy in place without the exemption. The only way to do this is through ARM as a single deployment. ARM sorts it out and allows the resource to be created due to the exemption. Without this we would have to temporarily place an exemption at the RG level or disable the policy. |
||
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_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint, index) in privateEndpoints: { | ||
name: '${uniqueString(deployment().name, location)}-StorageAccount-PrivateEndpoint-${index}' | ||
params: { | ||
|
Uh oh!
There was an error while loading. Please reload this page.