Azure / ALZ-Bicep

This repository contains the Azure Landing Zones (ALZ) Bicep modules that help deliver and deploy the Azure Landing Zone conceptual architecture in a modular approach. https://aka.ms/alz/docs
MIT License
748 stars 499 forks source link

Add resource locks to templates #608

Closed amp-pds closed 7 months ago

amp-pds commented 1 year ago

Contact Details

alan.phillips@pds.police.uk

Describe the feature end to end, including deployment scenario details under which the feature would occur.

Add Microsoft.Authorization locks to all bicep templates adding ability to ensure all key resources can have the CanNotDelete enabled at the resource scope.

Maybe set CanNotDelete as default in parameter file.

For example, for Azure VWan.

resource resVwanlock 'Microsoft.Authorization/locks@2020-05-01' = { name: donotdeletelock scope: resVwan properties: { level: 'CanNotDelete' } }

Why is this feature important. Describe why this would be important for your organization and others. Would this impact similar orgs in the same way?

MS best practice to enable resource locks to protect key resources.

Can you describe any alternatives that you have taken since this feature does not exist?

If not provided in repo we would have to create custom copies of all templates, then unable to use future pulled versions.

Version

v0.16.1

Feature Implementation

No response

check previous github issues

Code of Conduct

jtracey93 commented 1 year ago

Thanks @amp-pds for the feature request.

Would you like to see this on a per resource level or at a resource group level?

Let us know

amp-pds commented 1 year ago

Hi Jack,

Per resource please.

Thanks Alan.

jtracey93 commented 1 year ago

I will discuss this with the team to review and see how we want to implement this

thatbluesky commented 8 months ago

Could I make a suggestion to this one? Would it be useful to put this as a policy, for something like adding a lock based on a tag? Such as the custom one below? I know this is targetting resource groups, but could be amended for resources

targetScope = 'managementGroup'

param policyCategory string = 'Custom' param policySource string = 'Guardrails' param miroledefinition string = '/providers/microsoft.authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' // contributor role for deployIfNotExists/modify effects NOTE: this may be different depending on the policy param parLocation string = ''

resource bicepDeployResourceLock 'Microsoft.Authorization/policyDefinitions@2021-06-01' = { name: 'Deploy Do Not Delete resource locks based on tags' properties: { displayName: 'Deploy Do Not Delete resource lock on resource groups based on tag' description: 'Deploy Do Not Delete resource lock on resource groups based on tag' policyType: 'Custom' mode: 'All' metadata: { category: policyCategory source: policySource version: '0.1.0' securityCenter: { RemediationDescription: 'The resource group should have a Do Not Delete resource locks assigned. Go to the resource group and assign a resource lock or adjust the tag value' Severity: 'High' } } parameters: { tagName: { type: 'String' metadata: { displayName: 'Tag Name' description: 'The Tag name to audit against (i.e. Environment CostCenter etc.)' } } tagValue: { type: 'String' metadata: { displayName: 'Tag Value' description: 'Value of the tag to audit against (i.e. Prod/UAT/TEST 12345 etc.)' } } } policyRule: { if: { allOf: [ { field: 'type' equals: 'Microsoft.Resources/subscriptions/resourceGroups' } { field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]' equals: '[parameters(\'tagValue\')]' } ] } then: { effect: 'deployIfNotExists' details: { type: 'Microsoft.Authorization/locks' roleDefinitionIds: [ '/providers/microsoft.authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635' ] existenceCondition: { field: 'Microsoft.Authorization/locks/level' equals: 'CanNotDelete' } deployment: { properties: { mode: 'incremental' template: { '$schema': 'http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#' contentVersion: '1.0.0.0' parameters: {} variables: {} resources: [ { name: 'DoNotDelete' type: 'Microsoft.Authorization/locks' apiVersion: '2020-05-01' properties: { level: 'CanNotDelete' notes: 'Prevent deletion of the resource group or its resources' } } ] outputs: { policy: { type: 'string' value: '[concat(\'Added resource lock\')]' } } } } } } } } } }

resource resPolicyAssignment 'Microsoft.Authorization/policyAssignments@2021-06-01' = { name: 'Deploy-DNDResourceLocks' identity: { type: 'SystemAssigned' } location: parLocation properties: { displayName: 'Deploy Do Not Delete resource locks based on tags' description: 'Deploy Do Not Delete resource locks based on tags' policyDefinitionId: bicepDeployResourceLock.id parameters: { tagName: { value: 'DoNotDelete' } tagValue: { value: 'True' } } } }

resource resRoleassignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { name: guid(resPolicyAssignment.name, resPolicyAssignment.type) properties: { principalId: resPolicyAssignment.identity.principalId principalType: 'ServicePrincipal' roleDefinitionId: miroledefinition // contributor role for deployIfNotExists/modify effects NOTE: this may be different depending on the policy } }

output policyDefId string = bicepDeployResourceLock.id

jtracey93 commented 7 months ago

Hey @awood86,

Thanks for the suggestions here 👍

Theres actually a better way, in my opinion, if you want to achieve this via policy thanks to the new DenyAction effect. (think resource locks assigned via policy at scale).

And we actually already have some definitions and an initiative included with the ALZ custom policies that use this today for protecting diagnostic settings and activity logs exports on subscriptions that can be seen here: https://www.azadvertizer.net/azpolicyinitiativesadvertizer/DenyAction-DeleteProtection.html

So you can take inspiration for this and adapt for the resources and scopes that you'd want to do this at 👍

For this feature ask, which is now in PR #712, we want to add native support for locking at the resources rather than relying on policy in anyway to be fully declarative 👍