From 48ec9e9c49ab65c5af57f7a8d8bd85692a5d15ff Mon Sep 17 00:00:00 2001 From: judyer28 <60985418+judyer28@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:49:28 -0400 Subject: [PATCH] feat: avm/res/alerts management/action rule (#2184) ## Description This is a new Bicep module for creating an alert processing rule (action rule) based on the following proposal: https://github.com/Azure/Azure-Verified-Modules/issues/883 ## Pipeline Reference [![avm.res.alerts-management.action-rule](https://github.com/judyer28/bicep-registry-modules/actions/workflows/avm.res.alerts-management.action-rule.yml/badge.svg?branch=avm%2Fres%2Falerts-management%2Faction-rule)](https://github.com/judyer28/bicep-registry-modules/actions/workflows/avm.res.alerts-management.action-rule.yml) ## Type of Change - [ ] Update to CI Environment or utlities (Non-module effecting changes) - [ ] Azure Verified Module updates: - [ ] Bugfix containing backwards compatible bug fixes, and I have NOT bumped the MAJOR or MINOR version in `version.json`: - [ ] Someone has opened a bug report issue, and I have included "Closes #{bug_report_issue_number}" in the PR description. - [ ] The bug was found by the module author, and no one has opened an issue to report it yet. - [ ] Feature update backwards compatible feature updates, and I have bumped the MINOR version in `version.json`. - [ ] Breaking changes and I have bumped the MAJOR version in `version.json`. - [ ] Update to documentation ## Checklist - [x] I'm sure there are no other open Pull Requests for the same update/change - [x] I have run `Set-AVMModule` locally to generate the supporting module files. - [x] My corresponding pipelines / checks run clean and green without any errors or warnings --- .github/CODEOWNERS | 1 + .github/ISSUE_TEMPLATE/avm_module_issue.yml | 1 + .../avm.res.alerts-management.action-rule.yml | 90 +++ .../alerts-management/action-rule/README.md | 730 ++++++++++++++++++ .../alerts-management/action-rule/main.bicep | 165 ++++ .../alerts-management/action-rule/main.json | 309 ++++++++ .../tests/e2e/defaults/main.test.bicep | 47 ++ .../tests/e2e/max/dependencies.bicep | 66 ++ .../action-rule/tests/e2e/max/main.test.bicep | 191 +++++ .../tests/e2e/waf-aligned/dependencies.bicep | 14 + .../tests/e2e/waf-aligned/main.test.bicep | 71 ++ .../action-rule/version.json | 7 + 12 files changed, 1692 insertions(+) create mode 100644 .github/workflows/avm.res.alerts-management.action-rule.yml create mode 100644 avm/res/alerts-management/action-rule/README.md create mode 100644 avm/res/alerts-management/action-rule/main.bicep create mode 100644 avm/res/alerts-management/action-rule/main.json create mode 100644 avm/res/alerts-management/action-rule/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/alerts-management/action-rule/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/alerts-management/action-rule/tests/e2e/max/main.test.bicep create mode 100644 avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/alerts-management/action-rule/version.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 64ec6b5fac..e8a73484b0 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -14,6 +14,7 @@ /avm/ptn/policy-insights/remediation/ @Azure/avm-ptn-policyinsights-remediation-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/ptn/security/security-center/ @Azure/avm-ptn-security-securitycenter-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/aad/domain-service/ @Azure/avm-res-aad-domainservice-module-owners-bicep @Azure/avm-core-team-technical-bicep +/avm/res/alerts-management/action-rule/ @Azure/avm-res-alertsmanagement-actionrule-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/analysis-services/server/ @Azure/avm-res-analysisservices-server-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/api-management/service/ @Azure/avm-res-apimanagement-service-module-owners-bicep @Azure/avm-core-team-technical-bicep /avm/res/app/container-app/ @Azure/avm-res-app-containerapp-module-owners-bicep @Azure/avm-core-team-technical-bicep diff --git a/.github/ISSUE_TEMPLATE/avm_module_issue.yml b/.github/ISSUE_TEMPLATE/avm_module_issue.yml index 44bf6cf839..877f371d25 100644 --- a/.github/ISSUE_TEMPLATE/avm_module_issue.yml +++ b/.github/ISSUE_TEMPLATE/avm_module_issue.yml @@ -49,6 +49,7 @@ body: - "avm/ptn/policy-insights/remediation" - "avm/ptn/security/security-center" - "avm/res/aad/domain-service" + - "avm/res/alerts-management/action-rule" - "avm/res/analysis-services/server" - "avm/res/api-management/service" - "avm/res/app-configuration/configuration-store" diff --git a/.github/workflows/avm.res.alerts-management.action-rule.yml b/.github/workflows/avm.res.alerts-management.action-rule.yml new file mode 100644 index 0000000000..748f484b76 --- /dev/null +++ b/.github/workflows/avm.res.alerts-management.action-rule.yml @@ -0,0 +1,90 @@ +name: "avm.res.alerts-management.action-rule" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + customLocation: + type: string + description: "Default location overwrite (e.g., eastus)" + required: false + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.alerts-management.action-rule.yml" + - "avm/res/alerts-management/action-rule/**" + - "avm/utilities/pipelines/**" + - "!avm/utilities/pipelines/platform/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/alerts-management/action-rule" + workflowPath: ".github/workflows/avm.res.alerts-management.action-rule.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-latest + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + permissions: + id-token: write # For OIDC + contents: write # For release tags + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/alerts-management/action-rule/README.md b/avm/res/alerts-management/action-rule/README.md new file mode 100644 index 0000000000..f952455200 --- /dev/null +++ b/avm/res/alerts-management/action-rule/README.md @@ -0,0 +1,730 @@ +# Action Rules `[Microsoft.AlertsManagement/actionRules]` + +This module deploys an Alert Processing Rule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) +- [Data Collection](#Data-Collection) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AlertsManagement/actionRules` | [2021-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AlertsManagement/2021-08-08/actionRules) | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/alerts-management/action-rule:`. + +- [Using small parameter set](#example-1-using-small-parameter-set) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using small parameter set_ + +This instance deploys the module with min features enabled. + + +
+ +via Bicep module + +```bicep +module actionRule 'br/public:avm/res/alerts-management/action-rule:' = { + name: 'actionRuleDeployment' + params: { + // Required parameters + name: 'aprmin001' + // Non-required parameters + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "aprmin001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module actionRule 'br/public:avm/res/alerts-management/action-rule:' = { + name: 'actionRuleDeployment' + params: { + // Required parameters + name: 'aprmax001' + // Non-required parameters + actions: [ + { + actionGroupIds: [ + '' + ] + actionType: 'AddActionGroups' + } + ] + aprDescription: 'Test deployment of the module with the max set of parameters.' + conditions: [ + { + field: 'AlertContext' + operator: 'NotEquals' + values: [ + 'myAlertContext' + ] + } + { + field: 'AlertRuleId' + operator: 'Equals' + values: [ + '' + ] + } + { + field: 'AlertRuleName' + operator: 'Equals' + values: [ + '' + ] + } + { + field: 'Description' + operator: 'Contains' + values: [ + 'myAlertRuleDescription' + ] + } + { + field: 'MonitorService' + operator: 'Equals' + values: [ + 'ActivityLog Administrative' + ] + } + { + field: 'MonitorCondition' + operator: 'Equals' + values: [ + 'Fired' + ] + } + { + field: 'TargetResourceType' + operator: 'DoesNotContain' + values: [ + 'myAlertResourceType' + ] + } + { + field: 'TargetResource' + operator: 'Equals' + values: [ + 'myAlertResource1' + 'myAlertResource2' + ] + } + { + field: 'TargetResourceGroup' + operator: 'Equals' + values: [ + '' + ] + } + { + field: 'Severity' + operator: 'Equals' + values: [ + 'Sev0' + 'Sev1' + 'Sev2' + 'Sev3' + 'Sev4' + ] + } + { + field: 'SignalType' + operator: 'Equals' + values: [ + 'Health' + 'Log' + 'Metric' + 'Unknown' + ] + } + ] + enabled: true + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + scopes: [ + '' + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "aprmax001" + }, + // Non-required parameters + "actions": { + "value": [ + { + "actionGroupIds": [ + "" + ], + "actionType": "AddActionGroups" + } + ] + }, + "aprDescription": { + "value": "Test deployment of the module with the max set of parameters." + }, + "conditions": { + "value": [ + { + "field": "AlertContext", + "operator": "NotEquals", + "values": [ + "myAlertContext" + ] + }, + { + "field": "AlertRuleId", + "operator": "Equals", + "values": [ + "" + ] + }, + { + "field": "AlertRuleName", + "operator": "Equals", + "values": [ + "" + ] + }, + { + "field": "Description", + "operator": "Contains", + "values": [ + "myAlertRuleDescription" + ] + }, + { + "field": "MonitorService", + "operator": "Equals", + "values": [ + "ActivityLog Administrative" + ] + }, + { + "field": "MonitorCondition", + "operator": "Equals", + "values": [ + "Fired" + ] + }, + { + "field": "TargetResourceType", + "operator": "DoesNotContain", + "values": [ + "myAlertResourceType" + ] + }, + { + "field": "TargetResource", + "operator": "Equals", + "values": [ + "myAlertResource1", + "myAlertResource2" + ] + }, + { + "field": "TargetResourceGroup", + "operator": "Equals", + "values": [ + "" + ] + }, + { + "field": "Severity", + "operator": "Equals", + "values": [ + "Sev0", + "Sev1", + "Sev2", + "Sev3", + "Sev4" + ] + }, + { + "field": "SignalType", + "operator": "Equals", + "values": [ + "Health", + "Log", + "Metric", + "Unknown" + ] + } + ] + }, + "enabled": { + "value": true + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "scopes": { + "value": [ + "" + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 3: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module actionRule 'br/public:avm/res/alerts-management/action-rule:' = { + name: 'actionRuleDeployment' + params: { + // Required parameters + name: 'aprwaf001' + // Non-required parameters + actions: [ + { + actionGroupIds: [ + '' + ] + actionType: 'AddActionGroups' + } + ] + aprDescription: 'Test deployment of the module with the waf aligned set of parameters.' + location: '' + scopes: [ + '' + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "aprwaf001" + }, + // Non-required parameters + "actions": { + "value": [ + { + "actionGroupIds": [ + "" + ], + "actionType": "AddActionGroups" + } + ] + }, + "aprDescription": { + "value": "Test deployment of the module with the waf aligned set of parameters." + }, + "location": { + "value": "" + }, + "scopes": { + "value": [ + "" + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the alert processing rule. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`actions`](#parameter-actions) | array | Actions to be applied. | +| [`aprDescription`](#parameter-aprdescription) | string | Description of the alert processing rule. | +| [`conditions`](#parameter-conditions) | array | Conditions on which alerts will be filtered. | +| [`enabled`](#parameter-enabled) | bool | Indicates if the given alert processing rule is enabled or disabled. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`schedule`](#parameter-schedule) | object | Scheduling for alert processing rule. | +| [`scopes`](#parameter-scopes) | array | Scopes on which alert processing rule will apply. | +| [`tags`](#parameter-tags) | object | Resource tags. | + +### Parameter: `name` + +Name of the alert processing rule. + +- Required: Yes +- Type: string + +### Parameter: `actions` + + Actions to be applied. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + { + actionType: 'RemoveAllActionGroups' + } + ] + ``` + +### Parameter: `aprDescription` + +Description of the alert processing rule. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `conditions` + + Conditions on which alerts will be filtered. + +- Required: No +- Type: array + +### Parameter: `enabled` + +Indicates if the given alert processing rule is enabled or disabled. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `'global'` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container". + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `schedule` + +Scheduling for alert processing rule. + +- Required: No +- Type: object + +### Parameter: `scopes` + +Scopes on which alert processing rule will apply. + +- Required: No +- Type: array +- Default: + ```Bicep + [ + '[subscription().id]' + ] + ``` + +### Parameter: `tags` + +Resource tags. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the Alert Processing Rule. | +| `resourceGroupName` | string | The resource group the action group was deployed into. | +| `resourceId` | string | The resource ID of the Alert Processing Rule. | + +## Cross-referenced modules + +_None_ + +## Data Collection + +The software may collect information about you and your use of the software and send it to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may turn off the telemetry as described in the [repository](https://aka.ms/avm/telemetry). There are also some features in the software that may enable you and Microsoft to collect data from users of your applications. If you use these features, you must comply with applicable law, including providing appropriate notices to users of your applications together with a copy of Microsoft’s privacy statement. Our privacy statement is located at . You can learn more about data collection and use in the help documentation and our privacy statement. Your use of the software operates as your consent to these practices. diff --git a/avm/res/alerts-management/action-rule/main.bicep b/avm/res/alerts-management/action-rule/main.bicep new file mode 100644 index 0000000000..a5b3808c0d --- /dev/null +++ b/avm/res/alerts-management/action-rule/main.bicep @@ -0,0 +1,165 @@ +metadata name = 'Action Rules' +metadata description = 'This module deploys an Alert Processing Rule.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the alert processing rule.') +param name string + +@description('Optional. Description of the alert processing rule.') +param aprDescription string = '' + +@description('Optional. Location for all resources.') +param location string = 'global' + +@description('Optional. Indicates if the given alert processing rule is enabled or disabled.') +param enabled bool = true + +@description('Optional. Scopes on which alert processing rule will apply.') +param scopes array = [ + subscription().id +] + +@description('Optional. Actions to be applied.') +param actions array = [ + { + actionType: 'RemoveAllActionGroups' + } +] + +@description('Optional. Conditions on which alerts will be filtered.') +param conditions array? + +@description('Optional. Scheduling for alert processing rule.') +param schedule object? + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Resource tags.') +param tags object? + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'f58310d9-a9f6-439a-9e8d-f62e7b41a168' + ) + 'User Access Administrator': subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' + ) +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.alertsmanagement-actionrule.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +resource actionRule 'Microsoft.AlertsManagement/actionRules@2021-08-08' = { + name: name + location: location + tags: tags + properties: { + description: aprDescription + enabled: enabled + scopes: scopes + actions: actions + conditions: conditions + schedule: schedule + } +} + +resource actionRule_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' + ? 'Cannot delete resource or child resources.' + : 'Cannot delete or modify the resource or child resources.' + } + scope: actionRule +} + +resource actionRule_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [ + for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(actionRule.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) + ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] + : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') + ? roleAssignment.roleDefinitionIdOrName + : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: actionRule + } +] + +@description('The resource ID of the Alert Processing Rule.') +output resourceId string = actionRule.id + +@description('The name of the Alert Processing Rule.') +output name string = actionRule.name + +@description('The location the resource was deployed into.') +output location string = actionRule.location + +@description('The resource group the action group was deployed into.') +output resourceGroupName string = resourceGroup().name + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/alerts-management/action-rule/main.json b/avm/res/alerts-management/action-rule/main.json new file mode 100644 index 0000000000..4a62d4ab7f --- /dev/null +++ b/avm/res/alerts-management/action-rule/main.json @@ -0,0 +1,309 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.27.1.19265", + "templateHash": "9711931770347899266" + }, + "name": "Action Rules", + "description": "This module deploys an Alert Processing Rule.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the alert processing rule." + } + }, + "aprDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Description of the alert processing rule." + } + }, + "location": { + "type": "string", + "defaultValue": "global", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates if the given alert processing rule is enabled or disabled." + } + }, + "scopes": { + "type": "array", + "defaultValue": [ + "[subscription().id]" + ], + "metadata": { + "description": "Optional. Scopes on which alert processing rule will apply." + } + }, + "actions": { + "type": "array", + "defaultValue": [ + { + "actionType": "RemoveAllActionGroups" + } + ], + "metadata": { + "description": "Optional. Actions to be applied." + } + }, + "conditions": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Conditions on which alerts will be filtered." + } + }, + "schedule": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Scheduling for alert processing rule." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.alertsmanagement-actionrule.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "actionRule": { + "type": "Microsoft.AlertsManagement/actionRules", + "apiVersion": "2021-08-08", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "description": "[parameters('aprDescription')]", + "enabled": "[parameters('enabled')]", + "scopes": "[parameters('scopes')]", + "actions": "[parameters('actions')]", + "conditions": "[parameters('conditions')]", + "schedule": "[parameters('schedule')]" + } + }, + "actionRule_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.AlertsManagement/actionRules/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "actionRule" + ] + }, + "actionRule_roleAssignments": { + "copy": { + "name": "actionRule_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.AlertsManagement/actionRules/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.AlertsManagement/actionRules', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "actionRule" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the Alert Processing Rule." + }, + "value": "[resourceId('Microsoft.AlertsManagement/actionRules', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the Alert Processing Rule." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('actionRule', '2021-08-08', 'full').location]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the action group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/alerts-management/action-rule/tests/e2e/defaults/main.test.bicep b/avm/res/alerts-management/action-rule/tests/e2e/defaults/main.test.bicep new file mode 100644 index 0000000000..29e2f2eac2 --- /dev/null +++ b/avm/res/alerts-management/action-rule/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,47 @@ +targetScope = 'subscription' + +metadata name = 'Using small parameter set' +metadata description = 'This instance deploys the module with min features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-alertsmanagement.actionrule-${serviceShort}-rg' + +@description('Optional. The location to deploy resource group to.') +param resourceLocation string = deployment().location + +@description('Optional. Location to deploy alert processing rule to.') +param location string = 'global' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'aprmin' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + location: location + } + } +] diff --git a/avm/res/alerts-management/action-rule/tests/e2e/max/dependencies.bicep b/avm/res/alerts-management/action-rule/tests/e2e/max/dependencies.bicep new file mode 100644 index 0000000000..0cefd83bf6 --- /dev/null +++ b/avm/res/alerts-management/action-rule/tests/e2e/max/dependencies.bicep @@ -0,0 +1,66 @@ +@description('Required. The name of the Action Group to create.') +param actionGroupName string + +@description('Required. The name of the Actvity Log Alert to create.') +param actvityLogAlertName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +resource actionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = { + name: actionGroupName + location: 'global' + properties: { + groupShortName: substring(replace(actionGroupName, '-', ''), 0, 11) + enabled: true + } +} + +resource activityLogAlert 'Microsoft.Insights/activityLogAlerts@2020-10-01' = { + name: actvityLogAlertName + location: 'global' + properties: { + scopes: [ + subscription().id + ] + condition: { + allOf: [ + { + field: 'category' + equals: 'Administrative' + } + { + field: 'operationName' + equals: 'Microsoft.Logic/integrationAccounts/listKeyVaultKeys/action' + } + ] + } + actions: { + actionGroups: [ + { + actionGroupId: actionGroup.id + } + ] + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Action Group.') +output actionGroupResourceId string = actionGroup.id + +@description('The resource name of the created actvityLogAlert.') +output activityLogAlertResourceName string = activityLogAlert.name + +@description('The resource name of the created actvityLogAlert.') +output activityLogAlertResourceId string = activityLogAlert.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/alerts-management/action-rule/tests/e2e/max/main.test.bicep b/avm/res/alerts-management/action-rule/tests/e2e/max/main.test.bicep new file mode 100644 index 0000000000..cc7789d93f --- /dev/null +++ b/avm/res/alerts-management/action-rule/tests/e2e/max/main.test.bicep @@ -0,0 +1,191 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-alertsmanagement.actionrule-${serviceShort}-rg' + +@description('Optional. The location to deploy resource group to.') +param resourceLocation string = deployment().location + +@description('Optional. Location to deploy alert processing rule to.') +param location string = 'global' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'aprmax' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + actionGroupName: 'dep-${namePrefix}-ag-${serviceShort}' + actvityLogAlertName: 'dep-${namePrefix}-ala-${serviceShort}' + location: resourceLocation + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + aprDescription: 'Test deployment of the module with the max set of parameters.' + location: location + enabled: true + scopes: [ + resourceGroup.id + ] + conditions: [ + { + field: 'AlertContext' + operator: 'NotEquals' + values: [ + 'myAlertContext' + ] + } + { + field: 'AlertRuleId' + operator: 'Equals' + values: [ + nestedDependencies.outputs.activityLogAlertResourceId + ] + } + { + field: 'AlertRuleName' + operator: 'Equals' + values: [ + nestedDependencies.outputs.activityLogAlertResourceName + ] + } + { + field: 'Description' + operator: 'Contains' + values: [ + 'myAlertRuleDescription' + ] + } + { + field: 'MonitorService' + operator: 'Equals' + values: [ + 'ActivityLog Administrative' + ] + } + { + field: 'MonitorCondition' + operator: 'Equals' + values: [ + 'Fired' + ] + } + { + field: 'TargetResourceType' + operator: 'DoesNotContain' + values: [ + 'myAlertResourceType' + ] + } + { + field: 'TargetResource' + operator: 'Equals' + values: [ + 'myAlertResource1' + 'myAlertResource2' + ] + } + { + field: 'TargetResourceGroup' + operator: 'Equals' + values: [ + resourceGroup.id + ] + } + { + field: 'Severity' + operator: 'Equals' + values: [ + 'Sev0' + 'Sev1' + 'Sev2' + 'Sev3' + 'Sev4' + ] + } + { + field: 'SignalType' + operator: 'Equals' + values: [ + 'Metric' + 'Log' + 'Unknown' + 'Health' + ] + } + ] + actions: [ + { + actionGroupIds: [ + nestedDependencies.outputs.actionGroupResourceId + ] + actionType: 'AddActionGroups' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId( + 'Microsoft.Authorization/roleDefinitions', + 'acdd72a7-3385-48ef-bd42-f606fba81ae7' + ) + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + } +] diff --git a/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..962eaba676 --- /dev/null +++ b/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,14 @@ +@description('Required. The name of the Action Group to create.') +param actionGroupName string + +resource actionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = { + name: actionGroupName + location: 'global' + properties: { + groupShortName: substring(replace(actionGroupName, '-', ''), 0, 11) + enabled: false + } +} + +@description('The resource ID of the created Action Group.') +output actionGroupResourceId string = actionGroup.id diff --git a/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/main.test.bicep b/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..574776bf31 --- /dev/null +++ b/avm/res/alerts-management/action-rule/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,71 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-alertsmanagement.actionrule-${serviceShort}-rg' + +@description('Optional. The location to deploy resource group to.') +param resourceLocation string = deployment().location + +@description('Optional. Location to deploy alert processing rule to.') +param location string = 'global' + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'aprwaf' + +@description('Optional. A token to inject into the name of each resource. This value can be automatically injected by the CI.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: resourceLocation +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, resourceLocation)}-nestedDependencies' + params: { + actionGroupName: 'dep-${namePrefix}-ag-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [ + for iteration in ['init', 'idem']: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + name: '${namePrefix}${serviceShort}001' + aprDescription: 'Test deployment of the module with the waf aligned set of parameters.' + location: location + scopes: [ + resourceGroup.id + ] + actions: [ + { + actionGroupIds: [ + nestedDependencies.outputs.actionGroupResourceId + ] + actionType: 'AddActionGroups' + } + ] + } + } +] diff --git a/avm/res/alerts-management/action-rule/version.json b/avm/res/alerts-management/action-rule/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/alerts-management/action-rule/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +}