From 4ada4c3343eb231611fc803bbcf654002b210540 Mon Sep 17 00:00:00 2001 From: elisa anzelmo Date: Sat, 21 Oct 2023 14:02:06 +0200 Subject: [PATCH 01/14] Create avm.res.authorization.policyassignment.yml --- ...avm.res.authorization.policyassignment.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/avm.res.authorization.policyassignment.yml diff --git a/.github/workflows/avm.res.authorization.policyassignment.yml b/.github/workflows/avm.res.authorization.policyassignment.yml new file mode 100644 index 00000000000..3a4b2329abf --- /dev/null +++ b/.github/workflows/avm.res.authorization.policyassignment.yml @@ -0,0 +1,81 @@ +name: "avmres.authorization.policyassignment" + +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 + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avmres.authorization.policyassignment" + - "avm/res/authorization/policyassignment/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/authorization/policyassignment" + workflowPath: ".github/workflows/avm.res.authorization.policyassignment" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From a85f7315c3084cd1a50256f0d9a862532a0750c5 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 19:39:36 +0100 Subject: [PATCH 02/14] draft avm useridentity --- .../user-assigned-identity/README.md | 431 ++++++++++++++++++ .../federated-identity-credential/README.md | 76 +++ .../federated-identity-credential/main.bicep | 44 ++ .../federated-identity-credential/main.json | 81 ++++ .../user-assigned-identity/main.bicep | 156 +++++++ .../user-assigned-identity/main.json | 393 ++++++++++++++++ .../tests/e2e/defaults/main.test.bicep | 44 ++ .../tests/e2e/max/dependencies.bicep | 13 + .../tests/e2e/max/main.test.bicep | 80 ++++ .../tests/e2e/waf-aligned/dependencies.bicep | 13 + .../tests/e2e/waf-aligned/main.test.bicep | 79 ++++ .../user-assigned-identity/version.json | 7 + 12 files changed, 1417 insertions(+) create mode 100644 avm/res/managed-identity/user-assigned-identity/README.md create mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md create mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json create mode 100644 avm/res/managed-identity/user-assigned-identity/main.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/main.json create mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/managed-identity/user-assigned-identity/version.json diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md new file mode 100644 index 00000000000..fab918d8af1 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/README.md @@ -0,0 +1,431 @@ +# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` + +This module deploys a User Assigned Identity. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| 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/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.ManagedIdentity/userAssignedIdentities` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities) | +| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | + +## 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:bicep/modules/managed-identity.user-assigned-identity:1.0.0`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: {} +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +name: '${uniqueString(deployment().name, location)}-test-miauimax' + params: { + name: 'miuaimax001' + enableTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-miuaimax-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: '' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: '' + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + 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": { + "enableTelemetry": { + "value": "" + }, + "federatedIdentityCredentials": { + "value": [ + { + "audiences": [ + "api://AzureADTokenExchange" + ], + "issuer": "", + "name": "test-fed-cred-miuaimax-001", + "subject": "system:serviceaccount:default:workload-identity-sa" + } + ] + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "name": { + "value": "miuaimax001" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "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-pratices of the Well-Architectured-Framework. + + +

+ +via Bicep module + +```bicep +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +name: '${uniqueString(deployment().name, location)}-test-miauiwaf' + params: { + name: 'miuaiwaf001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-miuaiwaf-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: '' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: '' + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + 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": { + "federatedIdentityCredentials": { + "value": [ + { + "audiences": [ + "api://AzureADTokenExchange" + ], + "issuer": "", + "name": "test-fed-cred-miuaiwaf-001", + "subject": "system:serviceaccount:default:workload-identity-sa" + } + ] + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "name": { + "value": "miuaiwaf001" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ + +## Parameters + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`federatedIdentityCredentials`](#parameter-federatedidentitycredentials) | array | The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`name`](#parameter-name) | string | Name of the User Assigned Identity. | +| [`roleAssignments`](#parameter-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'. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `federatedIdentityCredentials` + +The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `location` + +Location for all resources. +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. +- Required: No +- Type: object + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`kind`](#parameter-lockkind) | No | string | Optional. Specify the type of lock. | +| [`name`](#parameter-lockname) | No | string | Optional. Specify the name of lock. | + +### Parameter: `lock.kind` + +Optional. Specify the type of lock. + +- Required: No +- Type: string +- Allowed: `[CanNotDelete, None, ReadOnly]` + +### Parameter: `lock.name` + +Optional. Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `name` + +Name of the User Assigned Identity. +- Required: No +- Type: string +- Default: `[guid(resourceGroup().id)]` + +### Parameter: `roleAssignments` + +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'. +- Required: No +- Type: array + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`condition`](#parameter-roleassignmentscondition) | No | string | 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`](#parameter-roleassignmentsconditionversion) | No | string | Optional. Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | No | string | Optional. The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | No | string | Optional. The description of the role assignment. | +| [`principalId`](#parameter-roleassignmentsprincipalid) | Yes | string | Required. The principal ID of the principal (user/group/identity) to assign the role to. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | No | string | Optional. The principal type of the assigned principal ID. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | Yes | string | Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | + +### Parameter: `roleAssignments.condition` + +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" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Optional. Version of the condition. + +- Required: No +- Type: string +- Allowed: `[2.0]` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +Optional. The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +Optional. The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalId` + +Required. The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.principalType` + +Optional. The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: `[Device, ForeignGroup, Group, ServicePrincipal, User]` + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. + +- Required: Yes +- Type: string + +### Parameter: `tags` + +Tags of the resource. +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `clientId` | string | The client ID (application ID) of the user assigned identity. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the user assigned identity. | +| `principalId` | string | The principal ID (object ID) of the user assigned identity. | +| `resourceGroupName` | string | The resource group the user assigned identity was deployed into. | +| `resourceId` | string | The resource ID of the user assigned identity. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md new file mode 100644 index 00000000000..c391846523b --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md @@ -0,0 +1,76 @@ +# User Assigned Identity Federated Identity Credential `[Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials]` + +This module deploys a User Assigned Identity Federated Identity Credential. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | +| [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | +| [`name`](#parameter-name) | string | The name of the secret. | +| [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedIdentityName`](#parameter-userassignedidentityname) | string | The name of the parent user assigned identity. Required if the template is used in a standalone deployment. | + +### Parameter: `audiences` + +The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. +- Required: Yes +- Type: array + +### Parameter: `issuer` + +The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. +- Required: Yes +- Type: string + +### Parameter: `name` + +The name of the secret. +- Required: Yes +- Type: string + +### Parameter: `subject` + +The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. +- Required: Yes +- Type: string + +### Parameter: `userAssignedIdentityName` + +The name of the parent user assigned identity. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the federated identity credential. | +| `resourceGroupName` | string | The name of the resource group the federated identity credential was created in. | +| `resourceId` | string | The resource ID of the federated identity credential. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep new file mode 100644 index 00000000000..3c3979fd720 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep @@ -0,0 +1,44 @@ +metadata name = 'User Assigned Identity Federated Identity Credential' +metadata description = 'This module deploys a User Assigned Identity Federated Identity Credential.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment.') +param userAssignedIdentityName string + +@description('Required. The name of the secret.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token.') +param audiences array + +@description('Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged.') +param issuer string + +@description('Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD.') +param subject string + +resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { + name: userAssignedIdentityName +} + +resource federatedIdentityCredential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = { + name: name + parent: userAssignedIdentity + properties: { + audiences: audiences + issuer: issuer + subject: subject + } +} + +@description('The name of the federated identity credential.') +output name string = federatedIdentityCredential.name + +@description('The resource ID of the federated identity credential.') +output resourceId string = federatedIdentityCredential.id + +@description('The name of the resource group the federated identity credential was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json new file mode 100644 index 00000000000..daba95ce533 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json @@ -0,0 +1,81 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "4906524580099045986" + }, + "name": "User Assigned Identity Federated Identity Credential", + "description": "This module deploys a User Assigned Identity Federated Identity Credential.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "userAssignedIdentityName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "audiences": { + "type": "array", + "metadata": { + "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." + } + }, + "issuer": { + "type": "string", + "metadata": { + "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." + } + }, + "subject": { + "type": "string", + "metadata": { + "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", + "properties": { + "audiences": "[parameters('audiences')]", + "issuer": "[parameters('issuer')]", + "subject": "[parameters('subject')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the federated identity credential." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the federated identity credential." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the federated identity credential was created in." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/managed-identity/user-assigned-identity/main.bicep b/avm/res/managed-identity/user-assigned-identity/main.bicep new file mode 100644 index 00000000000..07ea640d3ac --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/main.bicep @@ -0,0 +1,156 @@ +metadata name = 'User Assigned Identities' +metadata description = 'This module deploys a User Assigned Identity.' +metadata owner = 'Azure/module-maintainers' + +// ================ // +// Parameters // +// ================ // +@description('Optional. Name of the User Assigned Identity.') +param name string = guid(resourceGroup().id) + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object.') +param federatedIdentityCredentials array = [] + +@description('Optional. The lock settings of the service.') +param lock lockType + +@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 roleAssignmentType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +// =========== // +// Variables // +// =========== // + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') + 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') + 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +// ============ // +// Dependencies // +// ============ // + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.managedidentity-userassignedidentity.${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 userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { + name: name + location: location + tags: tags +} + +resource userMsi_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: userAssignedIdentity +} + +module userMsi_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [for (federatedIdentityCredential, index) in federatedIdentityCredentials: { + name: '${uniqueString(deployment().name, location)}-UserMSI-FederatedIdentityCredential-${index}' + params: { + name: federatedIdentityCredential.name + userAssignedIdentityName: userAssignedIdentity.name + audiences: federatedIdentityCredential.audiences + issuer: federatedIdentityCredential.issuer + subject: federatedIdentityCredential.subject + } +}] + +resource userMsi_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(userAssignedIdentity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : 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: userAssignedIdentity +}] + +@description('The name of the user assigned identity.') +output name string = userAssignedIdentity.name + +@description('The resource ID of the user assigned identity.') +output resourceId string = userAssignedIdentity.id + +@description('The principal ID (object ID) of the user assigned identity.') +output principalId string = userAssignedIdentity.properties.principalId + +@description('The client ID (application ID) of the user assigned identity.') +output clientId string = userAssignedIdentity.properties.clientId + +@description('The resource group the user assigned identity was deployed into.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = userAssignedIdentity.location + +// =============== // +// Definitions // +// =============== // + +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 name of the role to assign. If it cannot be found you can specify the role definition ID instead.') + 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' | null)? + + @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/managed-identity/user-assigned-identity/main.json b/avm/res/managed-identity/user-assigned-identity/main.json new file mode 100644 index 00000000000..b1fbbaec327 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/main.json @@ -0,0 +1,393 @@ +{ + "$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.23.1.45101", + "templateHash": "17564684040391369711" + }, + "name": "User Assigned Identities", + "description": "This module deploys a User Assigned Identity.", + "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 name of the role to assign. If it cannot be found you can specify the role definition ID instead." + } + }, + "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", + "defaultValue": "[guid(resourceGroup().id)]", + "metadata": { + "description": "Optional. Name of the User Assigned Identity." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "federatedIdentityCredentials": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "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'." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "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')]", + "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", + "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", + "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 (Preview)": "[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.managedidentity-userassignedidentity.{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" + } + } + } + } + }, + "userAssignedIdentity": { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]" + }, + "userMsi_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.ManagedIdentity/userAssignedIdentities/{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": [ + "userAssignedIdentity" + ] + }, + "userMsi_roleAssignments": { + "copy": { + "name": "userMsi_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 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], 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": [ + "userAssignedIdentity" + ] + }, + "userMsi_federatedIdentityCredentials": { + "copy": { + "name": "userMsi_federatedIdentityCredentials", + "count": "[length(parameters('federatedIdentityCredentials'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-UserMSI-FederatedIdentityCredential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].name]" + }, + "userAssignedIdentityName": { + "value": "[parameters('name')]" + }, + "audiences": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].audiences]" + }, + "issuer": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].issuer]" + }, + "subject": { + "value": "[parameters('federatedIdentityCredentials')[copyIndex()].subject]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "4906524580099045986" + }, + "name": "User Assigned Identity Federated Identity Credential", + "description": "This module deploys a User Assigned Identity Federated Identity Credential.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "userAssignedIdentityName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "audiences": { + "type": "array", + "metadata": { + "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." + } + }, + "issuer": { + "type": "string", + "metadata": { + "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." + } + }, + "subject": { + "type": "string", + "metadata": { + "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", + "properties": { + "audiences": "[parameters('audiences')]", + "issuer": "[parameters('issuer')]", + "subject": "[parameters('subject')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the federated identity credential." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the federated identity credential." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the federated identity credential was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "userAssignedIdentity" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the user assigned identity." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the user assigned identity." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" + }, + "principalId": { + "type": "string", + "metadata": { + "description": "The principal ID (object ID) of the user assigned identity." + }, + "value": "[reference('userAssignedIdentity').principalId]" + }, + "clientId": { + "type": "string", + "metadata": { + "description": "The client ID (application ID) of the user assigned identity." + }, + "value": "[reference('userAssignedIdentity').clientId]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the user assigned identity was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('userAssignedIdentity', '2023-01-31', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep new file mode 100644 index 00000000000..48084597af7 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,44 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-managedidentity.userassignedidentities-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: {} +} +] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep new file mode 100644 index 00000000000..a7f42aee7bd --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep new file mode 100644 index 00000000000..01870333cb0 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep @@ -0,0 +1,80 @@ +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}-managedidentity.userassignedidentities-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${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' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-${serviceShort}-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +} +] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 00000000000..a7f42aee7bd --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,13 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 00000000000..77c431083fc --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-managedidentity.userassignedidentities-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaiwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + managedIdentityName: 'dep-${namePrefix}-msi-${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' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-${serviceShort}-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +} +] diff --git a/avm/res/managed-identity/user-assigned-identity/version.json b/avm/res/managed-identity/user-assigned-identity/version.json new file mode 100644 index 00000000000..7fa401bdf78 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 690cfe359ea7fb0678092f22a514027c0cc2d3b1 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 20:06:05 +0100 Subject: [PATCH 03/14] workflow --- ...anaged-identity.user-assigned-identity.yml | 81 ++++ .../user-assigned-identity/README.md | 251 +++++------- .../user-assigned-identity/_README.md | 384 ++++++++++++++++++ .../federated-identity-credential/_README.md | 76 ++++ .../federated-identity-credential/main.bicep | 3 - .../tests/e2e/defaults/main.test.bicep | 4 +- .../tests/e2e/max/main.test.bicep | 2 + .../tests/e2e/waf-aligned/main.test.bicep | 2 + 8 files changed, 650 insertions(+), 153 deletions(-) create mode 100644 .github/workflows/avm.res.managed-identity.user-assigned-identity.yml create mode 100644 avm/res/managed-identity/user-assigned-identity/_README.md create mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md diff --git a/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml b/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml new file mode 100644 index 00000000000..ff0026488cc --- /dev/null +++ b/.github/workflows/avm.res.managed-identity.user-assigned-identity.yml @@ -0,0 +1,81 @@ +name: "avm.res.managed-identity.user-assigned-identity" + +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 + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.managed-identity.user-assigned-identity.yml" + - "avm/res/managed-identity/user-assigned-identity/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/managed-identity/user-assigned-identity" + workflowPath: ".github/workflows/avm.res.managed-identity.user-assigned-identity.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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 parameter 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 }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Module" + 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 }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md index fab918d8af1..a440aff8673 100644 --- a/avm/res/managed-identity/user-assigned-identity/README.md +++ b/avm/res/managed-identity/user-assigned-identity/README.md @@ -25,7 +25,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/managed-identity.user-assigned-identity:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm-res-managedidentity-userassignedidentity:1.0.0`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -41,10 +41,39 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: {} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaimin-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' } ``` @@ -76,38 +105,39 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { -name: '${uniqueString(deployment().name, location)}-test-miauimax' - params: { - name: 'miuaimax001' - enableTelemetry: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-miuaimax-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: '' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: '' - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +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-managedidentity.userassignedidentities-miuaimax-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' } ``` @@ -122,48 +152,7 @@ name: '${uniqueString(deployment().name, location)}-test-miauimax' { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", - "parameters": { - "enableTelemetry": { - "value": "" - }, - "federatedIdentityCredentials": { - "value": [ - { - "audiences": [ - "api://AzureADTokenExchange" - ], - "issuer": "", - "name": "test-fed-cred-miuaimax-001", - "subject": "system:serviceaccount:default:workload-identity-sa" - } - ] - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "name": { - "value": "miuaimax001" - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } + "parameters": {} } ``` @@ -180,37 +169,39 @@ This instance deploys the module in alignment with the best-pratices of the Well via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { -name: '${uniqueString(deployment().name, location)}-test-miauiwaf' - params: { - name: 'miuaiwaf001' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-miuaiwaf-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: '' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: '' - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaiwaf-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaiwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' } ``` @@ -225,45 +216,7 @@ name: '${uniqueString(deployment().name, location)}-test-miauiwaf' { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", - "parameters": { - "federatedIdentityCredentials": { - "value": [ - { - "audiences": [ - "api://AzureADTokenExchange" - ], - "issuer": "", - "name": "test-fed-cred-miuaiwaf-001", - "subject": "system:serviceaccount:default:workload-identity-sa" - } - ] - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "name": { - "value": "miuaiwaf001" - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } + "parameters": {} } ``` diff --git a/avm/res/managed-identity/user-assigned-identity/_README.md b/avm/res/managed-identity/user-assigned-identity/_README.md new file mode 100644 index 00000000000..a440aff8673 --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/_README.md @@ -0,0 +1,384 @@ +# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` + +This module deploys a User Assigned Identity. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| 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/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.ManagedIdentity/userAssignedIdentities` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities) | +| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | + +## 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-managedidentity-userassignedidentity:1.0.0`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using large parameter set](#example-2-using-large-parameter-set) +- [WAF-aligned](#example-3-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +
+ +via Bicep module + +```bicep +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaimin-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +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-managedidentity.userassignedidentities-miuaimax-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaimax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' +} +``` + +
+

+ +

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

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

+ +via Bicep module + +```bicep +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { +} +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaiwaf-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'miuaiwaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: '' +} +``` + +
+

+ +

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

+ + +## Parameters + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`federatedIdentityCredentials`](#parameter-federatedidentitycredentials) | array | The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`name`](#parameter-name) | string | Name of the User Assigned Identity. | +| [`roleAssignments`](#parameter-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'. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `federatedIdentityCredentials` + +The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `location` + +Location for all resources. +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. +- Required: No +- Type: object + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`kind`](#parameter-lockkind) | No | string | Optional. Specify the type of lock. | +| [`name`](#parameter-lockname) | No | string | Optional. Specify the name of lock. | + +### Parameter: `lock.kind` + +Optional. Specify the type of lock. + +- Required: No +- Type: string +- Allowed: `[CanNotDelete, None, ReadOnly]` + +### Parameter: `lock.name` + +Optional. Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `name` + +Name of the User Assigned Identity. +- Required: No +- Type: string +- Default: `[guid(resourceGroup().id)]` + +### Parameter: `roleAssignments` + +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'. +- Required: No +- Type: array + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`condition`](#parameter-roleassignmentscondition) | No | string | 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`](#parameter-roleassignmentsconditionversion) | No | string | Optional. Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | No | string | Optional. The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | No | string | Optional. The description of the role assignment. | +| [`principalId`](#parameter-roleassignmentsprincipalid) | Yes | string | Required. The principal ID of the principal (user/group/identity) to assign the role to. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | No | string | Optional. The principal type of the assigned principal ID. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | Yes | string | Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | + +### Parameter: `roleAssignments.condition` + +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" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Optional. Version of the condition. + +- Required: No +- Type: string +- Allowed: `[2.0]` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +Optional. The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +Optional. The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalId` + +Required. The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.principalType` + +Optional. The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: `[Device, ForeignGroup, Group, ServicePrincipal, User]` + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. + +- Required: Yes +- Type: string + +### Parameter: `tags` + +Tags of the resource. +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `clientId` | string | The client ID (application ID) of the user assigned identity. | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the user assigned identity. | +| `principalId` | string | The principal ID (object ID) of the user assigned identity. | +| `resourceGroupName` | string | The resource group the user assigned identity was deployed into. | +| `resourceId` | string | The resource ID of the user assigned identity. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md new file mode 100644 index 00000000000..c391846523b --- /dev/null +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md @@ -0,0 +1,76 @@ +# User Assigned Identity Federated Identity Credential `[Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials]` + +This module deploys a User Assigned Identity Federated Identity Credential. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | +| [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | +| [`name`](#parameter-name) | string | The name of the secret. | +| [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`userAssignedIdentityName`](#parameter-userassignedidentityname) | string | The name of the parent user assigned identity. Required if the template is used in a standalone deployment. | + +### Parameter: `audiences` + +The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. +- Required: Yes +- Type: array + +### Parameter: `issuer` + +The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. +- Required: Yes +- Type: string + +### Parameter: `name` + +The name of the secret. +- Required: Yes +- Type: string + +### Parameter: `subject` + +The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. +- Required: Yes +- Type: string + +### Parameter: `userAssignedIdentityName` + +The name of the parent user assigned identity. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the federated identity credential. | +| `resourceGroupName` | string | The name of the resource group the federated identity credential was created in. | +| `resourceId` | string | The resource ID of the federated identity credential. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep index 3c3979fd720..c229e10643b 100644 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep @@ -8,9 +8,6 @@ param userAssignedIdentityName string @description('Required. The name of the secret.') param name string -@description('Optional. Location for all resources.') -param location string = resourceGroup().location - @description('Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token.') param audiences array diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep index 48084597af7..2fc6811ef3f 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep @@ -39,6 +39,8 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' ]: { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: {} + params: { + location: location + } } ] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep index 01870333cb0..e3c9580dd5a 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep @@ -35,6 +35,7 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { + location: location managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' } } @@ -49,6 +50,7 @@ module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep index 77c431083fc..8ff89ce27b9 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep @@ -35,6 +35,7 @@ module nestedDependencies 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-nestedDependencies' params: { + location: location managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' } } @@ -48,6 +49,7 @@ module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { name: '${namePrefix}${serviceShort}001' + location: location lock: { kind: 'CanNotDelete' name: 'myCustomLockName' From f253c0a59823065aa3ca44437d120a057b243008 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 20:27:08 +0100 Subject: [PATCH 04/14] readme --- .../user-assigned-identity/README.md | 251 +++++++----- .../user-assigned-identity/_README.md | 384 ------------------ .../federated-identity-credential/README.md | 8 + .../federated-identity-credential/_README.md | 76 ---- 4 files changed, 157 insertions(+), 562 deletions(-) delete mode 100644 avm/res/managed-identity/user-assigned-identity/_README.md delete mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md index a440aff8673..fab918d8af1 100644 --- a/avm/res/managed-identity/user-assigned-identity/README.md +++ b/avm/res/managed-identity/user-assigned-identity/README.md @@ -25,7 +25,7 @@ The following section provides usage examples for the module, which were used to >**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-managedidentity-userassignedidentity:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br:bicep/modules/managed-identity.user-assigned-identity:1.0.0`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -41,39 +41,10 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -metadata name = 'Using only defaults' -metadata description = 'This instance deploys the module with the minimum set of required parameters.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaimin-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimin' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: {} } ``` @@ -105,39 +76,38 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -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-managedidentity.userassignedidentities-miuaimax-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimax' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +name: '${uniqueString(deployment().name, location)}-test-miauimax' + params: { + name: 'miuaimax001' + enableTelemetry: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-miuaimax-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: '' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: '' + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } } ``` @@ -152,7 +122,48 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", - "parameters": {} + "parameters": { + "enableTelemetry": { + "value": "" + }, + "federatedIdentityCredentials": { + "value": [ + { + "audiences": [ + "api://AzureADTokenExchange" + ], + "issuer": "", + "name": "test-fed-cred-miuaimax-001", + "subject": "system:serviceaccount:default:workload-identity-sa" + } + ] + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "name": { + "value": "miuaimax001" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } } ``` @@ -169,39 +180,37 @@ This instance deploys the module in alignment with the best-pratices of the Well via Bicep module ```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -metadata name = 'WAF-aligned' -metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaiwaf-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaiwaf' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' +module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +name: '${uniqueString(deployment().name, location)}-test-miauiwaf' + params: { + name: 'miuaiwaf001' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + federatedIdentityCredentials: [ + { + name: 'test-fed-cred-miuaiwaf-001' + audiences: [ + 'api://AzureADTokenExchange' + ] + issuer: '' + subject: 'system:serviceaccount:default:workload-identity-sa' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: '' + principalType: 'ServicePrincipal' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } } ``` @@ -216,7 +225,45 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", - "parameters": {} + "parameters": { + "federatedIdentityCredentials": { + "value": [ + { + "audiences": [ + "api://AzureADTokenExchange" + ], + "issuer": "", + "name": "test-fed-cred-miuaiwaf-001", + "subject": "system:serviceaccount:default:workload-identity-sa" + } + ] + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "name": { + "value": "miuaiwaf001" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } } ``` diff --git a/avm/res/managed-identity/user-assigned-identity/_README.md b/avm/res/managed-identity/user-assigned-identity/_README.md deleted file mode 100644 index a440aff8673..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/_README.md +++ /dev/null @@ -1,384 +0,0 @@ -# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` - -This module deploys a User Assigned Identity. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Usage examples](#Usage-examples) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| 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/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.ManagedIdentity/userAssignedIdentities` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities) | -| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | - -## 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-managedidentity-userassignedidentity:1.0.0`. - -- [Using only defaults](#example-1-using-only-defaults) -- [Using large parameter set](#example-2-using-large-parameter-set) -- [WAF-aligned](#example-3-waf-aligned) - -### Example 1: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. - - -
- -via Bicep module - -```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -metadata name = 'Using only defaults' -metadata description = 'This instance deploys the module with the minimum set of required parameters.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaimin-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimin' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": {} -} -``` - -
-

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

- -via Bicep module - -```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -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-managedidentity.userassignedidentities-miuaimax-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimax' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": {} -} -``` - -
-

- -### Example 3: _WAF-aligned_ - -This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework. - - -

- -via Bicep module - -```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -} -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - -metadata name = 'WAF-aligned' -metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-managedidentity.userassignedidentities-miuaiwaf-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaiwaf' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: '' -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": {} -} -``` - -
-

- - -## Parameters - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`federatedIdentityCredentials`](#parameter-federatedidentitycredentials) | array | The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. | -| [`location`](#parameter-location) | string | Location for all resources. | -| [`lock`](#parameter-lock) | object | The lock settings of the service. | -| [`name`](#parameter-name) | string | Name of the User Assigned Identity. | -| [`roleAssignments`](#parameter-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'. | -| [`tags`](#parameter-tags) | object | Tags of the resource. | - -### Parameter: `enableTelemetry` - -Enable/Disable usage telemetry for module. -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `federatedIdentityCredentials` - -The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `location` - -Location for all resources. -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - -### Parameter: `lock` - -The lock settings of the service. -- Required: No -- Type: object - - -| Name | Required | Type | Description | -| :-- | :-- | :--| :-- | -| [`kind`](#parameter-lockkind) | No | string | Optional. Specify the type of lock. | -| [`name`](#parameter-lockname) | No | string | Optional. Specify the name of lock. | - -### Parameter: `lock.kind` - -Optional. Specify the type of lock. - -- Required: No -- Type: string -- Allowed: `[CanNotDelete, None, ReadOnly]` - -### Parameter: `lock.name` - -Optional. Specify the name of lock. - -- Required: No -- Type: string - -### Parameter: `name` - -Name of the User Assigned Identity. -- Required: No -- Type: string -- Default: `[guid(resourceGroup().id)]` - -### Parameter: `roleAssignments` - -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'. -- Required: No -- Type: array - - -| Name | Required | Type | Description | -| :-- | :-- | :--| :-- | -| [`condition`](#parameter-roleassignmentscondition) | No | string | 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`](#parameter-roleassignmentsconditionversion) | No | string | Optional. Version of the condition. | -| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | No | string | Optional. The Resource Id of the delegated managed identity resource. | -| [`description`](#parameter-roleassignmentsdescription) | No | string | Optional. The description of the role assignment. | -| [`principalId`](#parameter-roleassignmentsprincipalid) | Yes | string | Required. The principal ID of the principal (user/group/identity) to assign the role to. | -| [`principalType`](#parameter-roleassignmentsprincipaltype) | No | string | Optional. The principal type of the assigned principal ID. | -| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | Yes | string | Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | - -### Parameter: `roleAssignments.condition` - -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" - -- Required: No -- Type: string - -### Parameter: `roleAssignments.conditionVersion` - -Optional. Version of the condition. - -- Required: No -- Type: string -- Allowed: `[2.0]` - -### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` - -Optional. The Resource Id of the delegated managed identity resource. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.description` - -Optional. The description of the role assignment. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.principalId` - -Required. The principal ID of the principal (user/group/identity) to assign the role to. - -- Required: Yes -- Type: string - -### Parameter: `roleAssignments.principalType` - -Optional. The principal type of the assigned principal ID. - -- Required: No -- Type: string -- Allowed: `[Device, ForeignGroup, Group, ServicePrincipal, User]` - -### Parameter: `roleAssignments.roleDefinitionIdOrName` - -Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. - -- Required: Yes -- Type: string - -### Parameter: `tags` - -Tags of the resource. -- Required: No -- Type: object - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `clientId` | string | The client ID (application ID) of the user assigned identity. | -| `location` | string | The location the resource was deployed into. | -| `name` | string | The name of the user assigned identity. | -| `principalId` | string | The principal ID (object ID) of the user assigned identity. | -| `resourceGroupName` | string | The resource group the user assigned identity was deployed into. | -| `resourceId` | string | The resource ID of the user assigned identity. | - -## Cross-referenced modules - -_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md index c391846523b..fee9a25b03f 100644 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md @@ -22,6 +22,7 @@ This module deploys a User Assigned Identity Federated Identity Credential. | Parameter | Type | Description | | :-- | :-- | :-- | | [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | | [`name`](#parameter-name) | string | The name of the secret. | | [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | @@ -38,6 +39,13 @@ The list of audiences that can appear in the issued token. Should be set to api: - Required: Yes - Type: array +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. +- Required: No +- Type: bool +- Default: `True` + ### Parameter: `issuer` The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md deleted file mode 100644 index c391846523b..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/_README.md +++ /dev/null @@ -1,76 +0,0 @@ -# User Assigned Identity Federated Identity Credential `[Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials]` - -This module deploys a User Assigned Identity Federated Identity Credential. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | - -## Parameters - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | -| [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | -| [`name`](#parameter-name) | string | The name of the secret. | -| [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | - -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`userAssignedIdentityName`](#parameter-userassignedidentityname) | string | The name of the parent user assigned identity. Required if the template is used in a standalone deployment. | - -### Parameter: `audiences` - -The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. -- Required: Yes -- Type: array - -### Parameter: `issuer` - -The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. -- Required: Yes -- Type: string - -### Parameter: `name` - -The name of the secret. -- Required: Yes -- Type: string - -### Parameter: `subject` - -The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. -- Required: Yes -- Type: string - -### Parameter: `userAssignedIdentityName` - -The name of the parent user assigned identity. Required if the template is used in a standalone deployment. -- Required: Yes -- Type: string - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the federated identity credential. | -| `resourceGroupName` | string | The name of the resource group the federated identity credential was created in. | -| `resourceId` | string | The resource ID of the federated identity credential. | - -## Cross-referenced modules - -_None_ From e2bbb12caca469b70e969d2a55d3d4130f282623 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 20:38:24 +0100 Subject: [PATCH 05/14] telemtry removed --- .../federated-identity-credential/README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md index fee9a25b03f..c391846523b 100644 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md +++ b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md @@ -22,7 +22,6 @@ This module deploys a User Assigned Identity Federated Identity Credential. | Parameter | Type | Description | | :-- | :-- | :-- | | [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | | [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | | [`name`](#parameter-name) | string | The name of the secret. | | [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | @@ -39,13 +38,6 @@ The list of audiences that can appear in the issued token. Should be set to api: - Required: Yes - Type: array -### Parameter: `enableTelemetry` - -Enable/Disable usage telemetry for module. -- Required: No -- Type: bool -- Default: `True` - ### Parameter: `issuer` The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. From fd17c75d1446f2986489b06c97535435ec85d1b9 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 20:52:30 +0100 Subject: [PATCH 06/14] added space --- .../user-assigned-identity/tests/e2e/defaults/main.test.bicep | 2 +- .../user-assigned-identity/tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep index 2fc6811ef3f..6e27ba06080 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep @@ -36,7 +36,7 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' ]: { +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep index e3c9580dd5a..a7062031241 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep @@ -45,7 +45,7 @@ module nestedDependencies 'dependencies.bicep' = { // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' ]: { +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep index 8ff89ce27b9..060548c4e74 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep @@ -44,7 +44,7 @@ module nestedDependencies 'dependencies.bicep' = { // Test Execution // // ============== // @batchSize(1) -module testDeployment '../../../main.bicep' =[for iteration in [ 'init', 'idem' ]: { +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' params: { From abb396414ee5f300f4e20be4a8263f8330b8ad1a Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Mon, 6 Nov 2023 21:05:20 +0100 Subject: [PATCH 07/14] location --- .../user-assigned-identity/README.md | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md index fab918d8af1..5a1ddf0d848 100644 --- a/avm/res/managed-identity/user-assigned-identity/README.md +++ b/avm/res/managed-identity/user-assigned-identity/README.md @@ -25,7 +25,7 @@ The following section provides usage examples for the module, which were used to >**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:bicep/modules/managed-identity.user-assigned-identity:1.0.0`. +>**Note**: To reference the module, please use the following syntax `br/public:avm-res-managedidentity-userassignedidentity:1.0.0`. - [Using only defaults](#example-1-using-only-defaults) - [Using large parameter set](#example-2-using-large-parameter-set) @@ -41,10 +41,12 @@ This instance deploys the module with the minimum set of required parameters.

via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: {} + params: { + location: '' + } } ``` @@ -59,7 +61,11 @@ module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-ide { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", - "parameters": {} + "parameters": { + "location": { + "value": "" + }, + } } ``` @@ -76,11 +82,12 @@ This instance deploys the module with most of its features enabled. via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { name: '${uniqueString(deployment().name, location)}-test-miauimax' params: { name: 'miuaimax001' enableTelemetry: '' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -138,6 +145,9 @@ name: '${uniqueString(deployment().name, location)}-test-miauimax' } ] }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", @@ -180,10 +190,11 @@ This instance deploys the module in alignment with the best-pratices of the Well via Bicep module ```bicep -module userAssignedIdentity 'br:bicep/modules/managed-identity.user-assigned-identity:1.0.0' = { +module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { name: '${uniqueString(deployment().name, location)}-test-miauiwaf' params: { name: 'miuaiwaf001' + location: '' lock: { kind: 'CanNotDelete' name: 'myCustomLockName' @@ -238,6 +249,9 @@ name: '${uniqueString(deployment().name, location)}-test-miauiwaf' } ] }, + "location": { + "value": "" + }, "lock": { "value": { "kind": "CanNotDelete", From f69d9232bd6009f3e22496199e12eeb36d5bca04 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Tue, 7 Nov 2023 10:09:44 +0100 Subject: [PATCH 08/14] #_namePrefix_# --- .../user-assigned-identity/tests/e2e/defaults/main.test.bicep | 2 +- .../user-assigned-identity/tests/e2e/max/main.test.bicep | 2 +- .../tests/e2e/waf-aligned/main.test.bicep | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep index 6e27ba06080..12e87cf4167 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep @@ -18,7 +18,7 @@ param location string = deployment().location param serviceShort string = 'miuaimin' @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep index a7062031241..c4edfe9f3d8 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep @@ -18,7 +18,7 @@ param location string = deployment().location param serviceShort string = 'miuaimax' @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep index 060548c4e74..980f1590d66 100644 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep @@ -18,7 +18,7 @@ param location string = deployment().location param serviceShort string = 'miuaiwaf' @description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '[[namePrefix]]' +param namePrefix string = '#_namePrefix_#' // ============ // // Dependencies // From 0adb3e31fb985f3c4fba86002d3de4a44664bab1 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Wed, 22 Nov 2023 09:29:31 +0100 Subject: [PATCH 09/14] removed uaid --- .../user-assigned-identity/README.md | 445 ------------------ .../federated-identity-credential/README.md | 76 --- .../federated-identity-credential/main.bicep | 41 -- .../federated-identity-credential/main.json | 81 ---- .../user-assigned-identity/main.bicep | 156 ------ .../user-assigned-identity/main.json | 393 ---------------- .../tests/e2e/defaults/main.test.bicep | 46 -- .../tests/e2e/max/dependencies.bicep | 13 - .../tests/e2e/max/main.test.bicep | 82 ---- .../tests/e2e/waf-aligned/dependencies.bicep | 13 - .../tests/e2e/waf-aligned/main.test.bicep | 81 ---- .../user-assigned-identity/version.json | 7 - 12 files changed, 1434 deletions(-) delete mode 100644 avm/res/managed-identity/user-assigned-identity/README.md delete mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md delete mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json delete mode 100644 avm/res/managed-identity/user-assigned-identity/main.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/main.json delete mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep delete mode 100644 avm/res/managed-identity/user-assigned-identity/version.json diff --git a/avm/res/managed-identity/user-assigned-identity/README.md b/avm/res/managed-identity/user-assigned-identity/README.md deleted file mode 100644 index 5a1ddf0d848..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/README.md +++ /dev/null @@ -1,445 +0,0 @@ -# User Assigned Identities `[Microsoft.ManagedIdentity/userAssignedIdentities]` - -This module deploys a User Assigned Identity. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Usage examples](#Usage-examples) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| 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/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.ManagedIdentity/userAssignedIdentities` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities) | -| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | - -## 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-managedidentity-userassignedidentity:1.0.0`. - -- [Using only defaults](#example-1-using-only-defaults) -- [Using large parameter set](#example-2-using-large-parameter-set) -- [WAF-aligned](#example-3-waf-aligned) - -### Example 1: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. - - -
- -via Bicep module - -```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: '' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "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 userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -name: '${uniqueString(deployment().name, location)}-test-miauimax' - params: { - name: 'miuaimax001' - enableTelemetry: '' - location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-miuaimax-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: '' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: '' - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - 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": { - "enableTelemetry": { - "value": "" - }, - "federatedIdentityCredentials": { - "value": [ - { - "audiences": [ - "api://AzureADTokenExchange" - ], - "issuer": "", - "name": "test-fed-cred-miuaimax-001", - "subject": "system:serviceaccount:default:workload-identity-sa" - } - ] - }, - "location": { - "value": "" - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "name": { - "value": "miuaimax001" - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - }, - "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-pratices of the Well-Architectured-Framework. - - -

- -via Bicep module - -```bicep -module userAssignedIdentity 'br/public:avm-res-managedidentity-userassignedidentity:1.0.0' = { -name: '${uniqueString(deployment().name, location)}-test-miauiwaf' - params: { - name: 'miuaiwaf001' - location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-miuaiwaf-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: '' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: '' - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - 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": { - "federatedIdentityCredentials": { - "value": [ - { - "audiences": [ - "api://AzureADTokenExchange" - ], - "issuer": "", - "name": "test-fed-cred-miuaiwaf-001", - "subject": "system:serviceaccount:default:workload-identity-sa" - } - ] - }, - "location": { - "value": "" - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "name": { - "value": "miuaiwaf001" - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } -} -``` - -
-

- - -## Parameters - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`federatedIdentityCredentials`](#parameter-federatedidentitycredentials) | array | The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. | -| [`location`](#parameter-location) | string | Location for all resources. | -| [`lock`](#parameter-lock) | object | The lock settings of the service. | -| [`name`](#parameter-name) | string | Name of the User Assigned Identity. | -| [`roleAssignments`](#parameter-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'. | -| [`tags`](#parameter-tags) | object | Tags of the resource. | - -### Parameter: `enableTelemetry` - -Enable/Disable usage telemetry for module. -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `federatedIdentityCredentials` - -The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object. -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `location` - -Location for all resources. -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - -### Parameter: `lock` - -The lock settings of the service. -- Required: No -- Type: object - - -| Name | Required | Type | Description | -| :-- | :-- | :--| :-- | -| [`kind`](#parameter-lockkind) | No | string | Optional. Specify the type of lock. | -| [`name`](#parameter-lockname) | No | string | Optional. Specify the name of lock. | - -### Parameter: `lock.kind` - -Optional. Specify the type of lock. - -- Required: No -- Type: string -- Allowed: `[CanNotDelete, None, ReadOnly]` - -### Parameter: `lock.name` - -Optional. Specify the name of lock. - -- Required: No -- Type: string - -### Parameter: `name` - -Name of the User Assigned Identity. -- Required: No -- Type: string -- Default: `[guid(resourceGroup().id)]` - -### Parameter: `roleAssignments` - -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'. -- Required: No -- Type: array - - -| Name | Required | Type | Description | -| :-- | :-- | :--| :-- | -| [`condition`](#parameter-roleassignmentscondition) | No | string | 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`](#parameter-roleassignmentsconditionversion) | No | string | Optional. Version of the condition. | -| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | No | string | Optional. The Resource Id of the delegated managed identity resource. | -| [`description`](#parameter-roleassignmentsdescription) | No | string | Optional. The description of the role assignment. | -| [`principalId`](#parameter-roleassignmentsprincipalid) | Yes | string | Required. The principal ID of the principal (user/group/identity) to assign the role to. | -| [`principalType`](#parameter-roleassignmentsprincipaltype) | No | string | Optional. The principal type of the assigned principal ID. | -| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | Yes | string | Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. | - -### Parameter: `roleAssignments.condition` - -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" - -- Required: No -- Type: string - -### Parameter: `roleAssignments.conditionVersion` - -Optional. Version of the condition. - -- Required: No -- Type: string -- Allowed: `[2.0]` - -### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` - -Optional. The Resource Id of the delegated managed identity resource. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.description` - -Optional. The description of the role assignment. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.principalId` - -Required. The principal ID of the principal (user/group/identity) to assign the role to. - -- Required: Yes -- Type: string - -### Parameter: `roleAssignments.principalType` - -Optional. The principal type of the assigned principal ID. - -- Required: No -- Type: string -- Allowed: `[Device, ForeignGroup, Group, ServicePrincipal, User]` - -### Parameter: `roleAssignments.roleDefinitionIdOrName` - -Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead. - -- Required: Yes -- Type: string - -### Parameter: `tags` - -Tags of the resource. -- Required: No -- Type: object - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `clientId` | string | The client ID (application ID) of the user assigned identity. | -| `location` | string | The location the resource was deployed into. | -| `name` | string | The name of the user assigned identity. | -| `principalId` | string | The principal ID (object ID) of the user assigned identity. | -| `resourceGroupName` | string | The resource group the user assigned identity was deployed into. | -| `resourceId` | string | The resource ID of the user assigned identity. | - -## Cross-referenced modules - -_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md deleted file mode 100644 index c391846523b..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# User Assigned Identity Federated Identity Credential `[Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials]` - -This module deploys a User Assigned Identity Federated Identity Credential. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials` | [2023-01-31](https://learn.microsoft.com/en-us/azure/templates/Microsoft.ManagedIdentity/2023-01-31/userAssignedIdentities/federatedIdentityCredentials) | - -## Parameters - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`audiences`](#parameter-audiences) | array | The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. | -| [`issuer`](#parameter-issuer) | string | The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. | -| [`name`](#parameter-name) | string | The name of the secret. | -| [`subject`](#parameter-subject) | string | The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. | - -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`userAssignedIdentityName`](#parameter-userassignedidentityname) | string | The name of the parent user assigned identity. Required if the template is used in a standalone deployment. | - -### Parameter: `audiences` - -The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token. -- Required: Yes -- Type: array - -### Parameter: `issuer` - -The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged. -- Required: Yes -- Type: string - -### Parameter: `name` - -The name of the secret. -- Required: Yes -- Type: string - -### Parameter: `subject` - -The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD. -- Required: Yes -- Type: string - -### Parameter: `userAssignedIdentityName` - -The name of the parent user assigned identity. Required if the template is used in a standalone deployment. -- Required: Yes -- Type: string - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the federated identity credential. | -| `resourceGroupName` | string | The name of the resource group the federated identity credential was created in. | -| `resourceId` | string | The resource ID of the federated identity credential. | - -## Cross-referenced modules - -_None_ diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep deleted file mode 100644 index c229e10643b..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.bicep +++ /dev/null @@ -1,41 +0,0 @@ -metadata name = 'User Assigned Identity Federated Identity Credential' -metadata description = 'This module deploys a User Assigned Identity Federated Identity Credential.' -metadata owner = 'Azure/module-maintainers' - -@description('Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment.') -param userAssignedIdentityName string - -@description('Required. The name of the secret.') -param name string - -@description('Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token.') -param audiences array - -@description('Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged.') -param issuer string - -@description('Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD.') -param subject string - -resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { - name: userAssignedIdentityName -} - -resource federatedIdentityCredential 'Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials@2023-01-31' = { - name: name - parent: userAssignedIdentity - properties: { - audiences: audiences - issuer: issuer - subject: subject - } -} - -@description('The name of the federated identity credential.') -output name string = federatedIdentityCredential.name - -@description('The resource ID of the federated identity credential.') -output resourceId string = federatedIdentityCredential.id - -@description('The name of the resource group the federated identity credential was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json b/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json deleted file mode 100644 index daba95ce533..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/federated-identity-credential/main.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4906524580099045986" - }, - "name": "User Assigned Identity Federated Identity Credential", - "description": "This module deploys a User Assigned Identity Federated Identity Credential.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "userAssignedIdentityName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the secret." - } - }, - "audiences": { - "type": "array", - "metadata": { - "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." - } - }, - "issuer": { - "type": "string", - "metadata": { - "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." - } - }, - "subject": { - "type": "string", - "metadata": { - "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." - } - } - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", - "apiVersion": "2023-01-31", - "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", - "properties": { - "audiences": "[parameters('audiences')]", - "issuer": "[parameters('issuer')]", - "subject": "[parameters('subject')]" - } - } - ], - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the federated identity credential." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the federated identity credential." - }, - "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the resource group the federated identity credential was created in." - }, - "value": "[resourceGroup().name]" - } - } -} \ No newline at end of file diff --git a/avm/res/managed-identity/user-assigned-identity/main.bicep b/avm/res/managed-identity/user-assigned-identity/main.bicep deleted file mode 100644 index 07ea640d3ac..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/main.bicep +++ /dev/null @@ -1,156 +0,0 @@ -metadata name = 'User Assigned Identities' -metadata description = 'This module deploys a User Assigned Identity.' -metadata owner = 'Azure/module-maintainers' - -// ================ // -// Parameters // -// ================ // -@description('Optional. Name of the User Assigned Identity.') -param name string = guid(resourceGroup().id) - -@description('Optional. Location for all resources.') -param location string = resourceGroup().location - -@description('Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object.') -param federatedIdentityCredentials array = [] - -@description('Optional. The lock settings of the service.') -param lock lockType - -@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 roleAssignmentType - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. Enable/Disable usage telemetry for module.') -param enableTelemetry bool = true - -// =========== // -// Variables // -// =========== // - -var builtInRoleNames = { - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Managed Identity Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59') - 'Managed Identity Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830') - 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 (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') -} - -// ============ // -// Dependencies // -// ============ // - -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.managedidentity-userassignedidentity.${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 userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: name - location: location - tags: tags -} - -resource userMsi_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: userAssignedIdentity -} - -module userMsi_federatedIdentityCredentials 'federated-identity-credential/main.bicep' = [for (federatedIdentityCredential, index) in federatedIdentityCredentials: { - name: '${uniqueString(deployment().name, location)}-UserMSI-FederatedIdentityCredential-${index}' - params: { - name: federatedIdentityCredential.name - userAssignedIdentityName: userAssignedIdentity.name - audiences: federatedIdentityCredential.audiences - issuer: federatedIdentityCredential.issuer - subject: federatedIdentityCredential.subject - } -}] - -resource userMsi_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(userAssignedIdentity.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : 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: userAssignedIdentity -}] - -@description('The name of the user assigned identity.') -output name string = userAssignedIdentity.name - -@description('The resource ID of the user assigned identity.') -output resourceId string = userAssignedIdentity.id - -@description('The principal ID (object ID) of the user assigned identity.') -output principalId string = userAssignedIdentity.properties.principalId - -@description('The client ID (application ID) of the user assigned identity.') -output clientId string = userAssignedIdentity.properties.clientId - -@description('The resource group the user assigned identity was deployed into.') -output resourceGroupName string = resourceGroup().name - -@description('The location the resource was deployed into.') -output location string = userAssignedIdentity.location - -// =============== // -// Definitions // -// =============== // - -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 name of the role to assign. If it cannot be found you can specify the role definition ID instead.') - 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' | null)? - - @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/managed-identity/user-assigned-identity/main.json b/avm/res/managed-identity/user-assigned-identity/main.json deleted file mode 100644 index b1fbbaec327..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/main.json +++ /dev/null @@ -1,393 +0,0 @@ -{ - "$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.23.1.45101", - "templateHash": "17564684040391369711" - }, - "name": "User Assigned Identities", - "description": "This module deploys a User Assigned Identity.", - "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 name of the role to assign. If it cannot be found you can specify the role definition ID instead." - } - }, - "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", - "defaultValue": "[guid(resourceGroup().id)]", - "metadata": { - "description": "Optional. Name of the User Assigned Identity." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "federatedIdentityCredentials": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "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'." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - }, - "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')]", - "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", - "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", - "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 (Preview)": "[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.managedidentity-userassignedidentity.{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" - } - } - } - } - }, - "userAssignedIdentity": { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities", - "apiVersion": "2023-01-31", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]" - }, - "userMsi_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.ManagedIdentity/userAssignedIdentities/{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": [ - "userAssignedIdentity" - ] - }, - "userMsi_roleAssignments": { - "copy": { - "name": "userMsi_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" - }, - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 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], 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": [ - "userAssignedIdentity" - ] - }, - "userMsi_federatedIdentityCredentials": { - "copy": { - "name": "userMsi_federatedIdentityCredentials", - "count": "[length(parameters('federatedIdentityCredentials'))]" - }, - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-UserMSI-FederatedIdentityCredential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[parameters('federatedIdentityCredentials')[copyIndex()].name]" - }, - "userAssignedIdentityName": { - "value": "[parameters('name')]" - }, - "audiences": { - "value": "[parameters('federatedIdentityCredentials')[copyIndex()].audiences]" - }, - "issuer": { - "value": "[parameters('federatedIdentityCredentials')[copyIndex()].issuer]" - }, - "subject": { - "value": "[parameters('federatedIdentityCredentials')[copyIndex()].subject]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4906524580099045986" - }, - "name": "User Assigned Identity Federated Identity Credential", - "description": "This module deploys a User Assigned Identity Federated Identity Credential.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "userAssignedIdentityName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the secret." - } - }, - "audiences": { - "type": "array", - "metadata": { - "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." - } - }, - "issuer": { - "type": "string", - "metadata": { - "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." - } - }, - "subject": { - "type": "string", - "metadata": { - "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." - } - } - }, - "resources": [ - { - "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", - "apiVersion": "2023-01-31", - "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", - "properties": { - "audiences": "[parameters('audiences')]", - "issuer": "[parameters('issuer')]", - "subject": "[parameters('subject')]" - } - } - ], - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the federated identity credential." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the federated identity credential." - }, - "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the resource group the federated identity credential was created in." - }, - "value": "[resourceGroup().name]" - } - } - } - }, - "dependsOn": [ - "userAssignedIdentity" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the user assigned identity." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the user assigned identity." - }, - "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]" - }, - "principalId": { - "type": "string", - "metadata": { - "description": "The principal ID (object ID) of the user assigned identity." - }, - "value": "[reference('userAssignedIdentity').principalId]" - }, - "clientId": { - "type": "string", - "metadata": { - "description": "The client ID (application ID) of the user assigned identity." - }, - "value": "[reference('userAssignedIdentity').clientId]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group the user assigned identity was deployed into." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('userAssignedIdentity', '2023-01-31', 'full').location]" - } - } -} \ No newline at end of file diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep deleted file mode 100644 index 12e87cf4167..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/defaults/main.test.bicep +++ /dev/null @@ -1,46 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using only defaults' -metadata description = 'This instance deploys the module with the minimum set of required parameters.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-managedidentity.userassignedidentities-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimin' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -// ============== // -// Test Execution // -// ============== // - -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - } -} -] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep deleted file mode 100644 index a7f42aee7bd..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/dependencies.bicep +++ /dev/null @@ -1,13 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -@description('The principal ID of the created Managed Identity.') -output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep deleted file mode 100644 index c4edfe9f3d8..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/max/main.test.bicep +++ /dev/null @@ -1,82 +0,0 @@ -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}-managedidentity.userassignedidentities-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaimax' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - managedIdentityName: 'dep-${namePrefix}-msi-${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' - location: location - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-${serviceShort}-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } -} -] diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index a7f42aee7bd..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,13 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -@description('The principal ID of the created Managed Identity.') -output managedIdentityPrincipalId string = managedIdentity.properties.principalId diff --git a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep b/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep deleted file mode 100644 index 980f1590d66..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/tests/e2e/waf-aligned/main.test.bicep +++ /dev/null @@ -1,81 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'WAF-aligned' -metadata description = 'This instance deploys the module in alignment with the best-pratices of the Well-Architectured-Framework.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-managedidentity.userassignedidentities-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@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 = 'miuaiwaf' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - managedIdentityName: 'dep-${namePrefix}-msi-${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' - location: location - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - federatedIdentityCredentials: [ - { - name: 'test-fed-cred-${serviceShort}-001' - audiences: [ - 'api://AzureADTokenExchange' - ] - issuer: 'https://contoso.com/${subscription().tenantId}/${guid(deployment().name)}/' - subject: 'system:serviceaccount:default:workload-identity-sa' - } - ] - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } -} -] diff --git a/avm/res/managed-identity/user-assigned-identity/version.json b/avm/res/managed-identity/user-assigned-identity/version.json deleted file mode 100644 index 7fa401bdf78..00000000000 --- a/avm/res/managed-identity/user-assigned-identity/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", - "pathFilters": [ - "./main.json" - ] -} From 56de01102bd15edc923191722f86a56b77cd4c73 Mon Sep 17 00:00:00 2001 From: elisa anzelmo Date: Wed, 22 Nov 2023 13:40:10 +0100 Subject: [PATCH 10/14] Delete .github/workflows/avm.res.authorization.policyassignment.yml --- ...avm.res.authorization.policyassignment.yml | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 .github/workflows/avm.res.authorization.policyassignment.yml diff --git a/.github/workflows/avm.res.authorization.policyassignment.yml b/.github/workflows/avm.res.authorization.policyassignment.yml deleted file mode 100644 index 3a4b2329abf..00000000000 --- a/.github/workflows/avm.res.authorization.policyassignment.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: "avmres.authorization.policyassignment" - -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 - - push: - branches: - - main - paths: - - ".github/actions/templates/avm-**" - - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avmres.authorization.policyassignment" - - "avm/res/authorization/policyassignment/**" - - "avm/utilities/pipelines/**" - - "!*/**/README.md" - -env: - modulePath: "avm/res/authorization/policyassignment" - workflowPath: ".github/workflows/avm.res.authorization.policyassignment" - -concurrency: - group: ${{ github.workflow }} - -jobs: - ########################### - # Initialize pipeline # - ########################### - job_initialize_pipeline: - runs-on: ubuntu-20.04 - 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 parameter 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 }} - modulePath: "${{ env.modulePath }}" - - ############################## - # Call reusable workflow # - ############################## - call-workflow-passing-data: - name: "Module" - 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 }}" - modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" - secrets: inherit From 552285ba304bfe6be518799d35e7fca1b1003650 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Fri, 1 Dec 2023 16:21:34 +0100 Subject: [PATCH 11/14] draft --- .../automation/automation-account/README.md | 1704 ++++++++++ .../automation-account/job-schedule/README.md | 96 + .../job-schedule/main.bicep | 51 + .../automation-account/job-schedule/main.json | 95 + .../automation/automation-account/main.bicep | 555 +++ .../automation/automation-account/main.json | 2973 +++++++++++++++++ .../automation-account/module/README.md | 91 + .../automation-account/module/main.bicep | 50 + .../automation-account/module/main.json | 110 + .../automation-account/runbook/README.md | 145 + .../automation-account/runbook/main.bicep | 90 + .../automation-account/runbook/main.json | 170 + .../automation-account/schedule/README.md | 140 + .../automation-account/schedule/main.bicep | 73 + .../automation-account/schedule/main.json | 134 + .../software-update-configuration/README.md | 416 +++ .../software-update-configuration/main.bicep | 262 ++ .../software-update-configuration/main.json | 405 +++ .../tests/e2e/defaults/main.test.bicep | 46 + .../tests/e2e/encr/dependencies.bicep | 58 + .../tests/e2e/encr/main.test.bicep | 70 + .../tests/e2e/max/dependencies.bicep | 90 + .../tests/e2e/max/main.test.bicep | 261 ++ .../tests/e2e/waf-aligned/dependencies.bicep | 90 + .../tests/e2e/waf-aligned/main.test.bicep | 247 ++ .../automation-account/variable/README.md | 83 + .../automation-account/variable/main.bicep | 42 + .../automation-account/variable/main.json | 83 + .../automation-account/version.json | 7 + 29 files changed, 8637 insertions(+) create mode 100644 avm/res/automation/automation-account/README.md create mode 100644 avm/res/automation/automation-account/job-schedule/README.md create mode 100644 avm/res/automation/automation-account/job-schedule/main.bicep create mode 100644 avm/res/automation/automation-account/job-schedule/main.json create mode 100644 avm/res/automation/automation-account/main.bicep create mode 100644 avm/res/automation/automation-account/main.json create mode 100644 avm/res/automation/automation-account/module/README.md create mode 100644 avm/res/automation/automation-account/module/main.bicep create mode 100644 avm/res/automation/automation-account/module/main.json create mode 100644 avm/res/automation/automation-account/runbook/README.md create mode 100644 avm/res/automation/automation-account/runbook/main.bicep create mode 100644 avm/res/automation/automation-account/runbook/main.json create mode 100644 avm/res/automation/automation-account/schedule/README.md create mode 100644 avm/res/automation/automation-account/schedule/main.bicep create mode 100644 avm/res/automation/automation-account/schedule/main.json create mode 100644 avm/res/automation/automation-account/software-update-configuration/README.md create mode 100644 avm/res/automation/automation-account/software-update-configuration/main.bicep create mode 100644 avm/res/automation/automation-account/software-update-configuration/main.json create mode 100644 avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/max/main.test.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/automation/automation-account/variable/README.md create mode 100644 avm/res/automation/automation-account/variable/main.bicep create mode 100644 avm/res/automation/automation-account/variable/main.json create mode 100644 avm/res/automation/automation-account/version.json diff --git a/avm/res/automation/automation-account/README.md b/avm/res/automation/automation-account/README.md new file mode 100644 index 00000000000..e8a9bca4eeb --- /dev/null +++ b/avm/res/automation/automation-account/README.md @@ -0,0 +1,1704 @@ +# Automation Accounts `[Microsoft.Automation/automationAccounts]` + +This module deploys an Azure Automation Account. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| 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/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Automation/automationAccounts` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts) | +| `Microsoft.Automation/automationAccounts/jobSchedules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/jobSchedules) | +| `Microsoft.Automation/automationAccounts/modules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/modules) | +| `Microsoft.Automation/automationAccounts/runbooks` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/runbooks) | +| `Microsoft.Automation/automationAccounts/schedules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/schedules) | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | [2019-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) | +| `Microsoft.Automation/automationAccounts/variables` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/variables) | +| `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` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints) | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/privateEndpoints/privateDnsZoneGroups) | +| `Microsoft.OperationalInsights/workspaces/linkedServices` | [2020-08-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationalInsights/2020-08-01/workspaces/linkedServices) | +| `Microsoft.OperationsManagement/solutions` | [2015-11-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.OperationsManagement/2015-11-01-preview/solutions) | + +## 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/automation/automation-account:`. + +- [Using only defaults](#example-1-using-only-defaults) +- [Using encryption with Customer-Managed-Key](#example-2-using-encryption-with-customer-managed-key) +- [Using large parameter set](#example-3-using-large-parameter-set) +- [WAF-aligned](#example-4-waf-aligned) + +### Example 1: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module automationAccount 'br/public:avm/res/automation/automation-account:' = { + name: '${uniqueString(deployment().name, location)}-test-aamin' + params: { + // Required parameters + name: 'aamin001' + // 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": "aamin001" + }, + // Non-required parameters + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 2: _Using encryption with Customer-Managed-Key_ + +This instance deploys the module using Customer-Managed-Keys using a User-Assigned Identity to access the Customer-Managed-Key secret. + + +

+ +via Bicep module + +```bicep +module automationAccount 'br/public:avm/res/automation/automation-account:' = { + name: '${uniqueString(deployment().name, location)}-test-aaencr' + params: { + // Required parameters + name: 'aaencr001' + // Non-required parameters + customerManagedKey: { + keyName: '' + keyVaultResourceId: '' + userAssignedIdentityResourceId: '' + } + location: '' + managedIdentities: { + userAssignedResourceIds: [ + '' + ] + } + } +} +``` + +
+

+ +

+ +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": "aaencr001" + }, + // Non-required parameters + "customerManagedKey": { + "value": { + "keyName": "", + "keyVaultResourceId": "", + "userAssignedIdentityResourceId": "" + } + }, + "location": { + "value": "" + }, + "managedIdentities": { + "value": { + "userAssignedResourceIds": [ + "" + ] + } + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module automationAccount 'br/public:avm/res/automation/automation-account:' = { + name: '${uniqueString(deployment().name, location)}-test-aamax' + params: { + // Required parameters + name: 'aamax001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disableLocalAuth: true + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' + } + ] + linkedWorkspaceResourceId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'Webhook' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'DSCAndHybridWorker' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + isEncrypted: false + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } + ] + } +} +``` + +
+

+ +

+ +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": "aamax001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disableLocalAuth": { + "value": true + }, + "gallerySolutions": { + "value": [ + { + "name": "Updates", + "product": "OMSGallery", + "publisher": "Microsoft" + } + ] + }, + "jobSchedules": { + "value": [ + { + "runbookName": "TestRunbook", + "scheduleName": "TestSchedule" + } + ] + }, + "linkedWorkspaceResourceId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "modules": { + "value": [ + { + "name": "PSWindowsUpdate", + "uri": "https://www.powershellgallery.com/api/v2/package", + "version": "latest" + } + ] + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "Webhook", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "DSCAndHybridWorker", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "runbooks": { + "value": [ + { + "description": "Test runbook", + "name": "TestRunbook", + "type": "PowerShell", + "uri": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1", + "version": "1.0.0.0" + } + ] + }, + "schedules": { + "value": [ + { + "advancedSchedule": {}, + "expiryTime": "9999-12-31T13:00", + "frequency": "Hour", + "interval": 12, + "name": "TestSchedule", + "startTime": "", + "timeZone": "Europe/Berlin" + } + ] + }, + "softwareUpdateConfigurations": { + "value": [ + { + "excludeUpdates": [ + "123456" + ], + "frequency": "Month", + "includeUpdates": [ + "654321" + ], + "interval": 1, + "maintenanceWindow": "PT4H", + "monthlyOccurrences": [ + { + "day": "Friday", + "occurrence": 3 + } + ], + "name": "Windows_ZeroDay", + "operatingSystem": "Windows", + "rebootSetting": "IfRequired", + "scopeByTags": { + "Update": [ + "Automatic-Wave1" + ] + }, + "startTime": "22:00", + "updateClassifications": [ + "Critical", + "Definition", + "FeaturePack", + "Security", + "ServicePack", + "Tools", + "UpdateRollup", + "Updates" + ] + }, + { + "excludeUpdates": [ + "icacls" + ], + "frequency": "OneTime", + "includeUpdates": [ + "kernel" + ], + "maintenanceWindow": "PT4H", + "name": "Linux_ZeroDay", + "operatingSystem": "Linux", + "rebootSetting": "IfRequired", + "startTime": "22:00", + "updateClassifications": [ + "Critical", + "Other", + "Security" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "variables": { + "value": [ + { + "description": "TestStringDescription", + "name": "TestString", + "value": "\"TestString\"" + }, + { + "description": "TestIntegerDescription", + "name": "TestInteger", + "value": "500" + }, + { + "description": "TestBooleanDescription", + "name": "TestBoolean", + "value": "false" + }, + { + "description": "TestDateTimeDescription", + "isEncrypted": false, + "name": "TestDateTime", + "value": "\"\\/Date(1637934042656)\\/\"" + }, + { + "description": "TestEncryptedDescription", + "name": "TestEncryptedVariable", + "value": "\"TestEncryptedValue\"" + } + ] + } + } +} +``` + +
+

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

+ +via Bicep module + +```bicep +module automationAccount 'br/public:avm/res/automation/automation-account:' = { + name: '${uniqueString(deployment().name, location)}-test-aawaf' + params: { + // Required parameters + name: 'aawaf001' + // Non-required parameters + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + disableLocalAuth: true + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' + } + ] + linkedWorkspaceResourceId: '' + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'Webhook' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + '' + ] + service: 'DSCAndHybridWorker' + subnetResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + isEncrypted: false + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } + ] + } +} +``` + +
+

+ +

+ +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": "aawaf001" + }, + // Non-required parameters + "diagnosticSettings": { + "value": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ] + }, + "disableLocalAuth": { + "value": true + }, + "gallerySolutions": { + "value": [ + { + "name": "Updates", + "product": "OMSGallery", + "publisher": "Microsoft" + } + ] + }, + "jobSchedules": { + "value": [ + { + "runbookName": "TestRunbook", + "scheduleName": "TestSchedule" + } + ] + }, + "linkedWorkspaceResourceId": { + "value": "" + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "modules": { + "value": [ + { + "name": "PSWindowsUpdate", + "uri": "https://www.powershellgallery.com/api/v2/package", + "version": "latest" + } + ] + }, + "privateEndpoints": { + "value": [ + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "Webhook", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + { + "privateDnsZoneResourceIds": [ + "" + ], + "service": "DSCAndHybridWorker", + "subnetResourceId": "", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "runbooks": { + "value": [ + { + "description": "Test runbook", + "name": "TestRunbook", + "type": "PowerShell", + "uri": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1", + "version": "1.0.0.0" + } + ] + }, + "schedules": { + "value": [ + { + "advancedSchedule": {}, + "expiryTime": "9999-12-31T13:00", + "frequency": "Hour", + "interval": 12, + "name": "TestSchedule", + "startTime": "", + "timeZone": "Europe/Berlin" + } + ] + }, + "softwareUpdateConfigurations": { + "value": [ + { + "excludeUpdates": [ + "123456" + ], + "frequency": "Month", + "includeUpdates": [ + "654321" + ], + "interval": 1, + "maintenanceWindow": "PT4H", + "monthlyOccurrences": [ + { + "day": "Friday", + "occurrence": 3 + } + ], + "name": "Windows_ZeroDay", + "operatingSystem": "Windows", + "rebootSetting": "IfRequired", + "scopeByTags": { + "Update": [ + "Automatic-Wave1" + ] + }, + "startTime": "22:00", + "updateClassifications": [ + "Critical", + "Definition", + "FeaturePack", + "Security", + "ServicePack", + "Tools", + "UpdateRollup", + "Updates" + ] + }, + { + "excludeUpdates": [ + "icacls" + ], + "frequency": "OneTime", + "includeUpdates": [ + "kernel" + ], + "maintenanceWindow": "PT4H", + "name": "Linux_ZeroDay", + "operatingSystem": "Linux", + "rebootSetting": "IfRequired", + "startTime": "22:00", + "updateClassifications": [ + "Critical", + "Other", + "Security" + ] + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "variables": { + "value": [ + { + "description": "TestStringDescription", + "name": "TestString", + "value": "\"TestString\"" + }, + { + "description": "TestIntegerDescription", + "name": "TestInteger", + "value": "500" + }, + { + "description": "TestBooleanDescription", + "name": "TestBoolean", + "value": "false" + }, + { + "description": "TestDateTimeDescription", + "isEncrypted": false, + "name": "TestDateTime", + "value": "\"\\/Date(1637934042656)\\/\"" + }, + { + "description": "TestEncryptedDescription", + "name": "TestEncryptedVariable", + "value": "\"TestEncryptedValue\"" + } + ] + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Automation Account. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`customerManagedKey`](#parameter-customermanagedkey) | object | The customer managed key definition. | +| [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | +| [`disableLocalAuth`](#parameter-disablelocalauth) | bool | Disable local authentication profile used within the resource. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | +| [`gallerySolutions`](#parameter-gallerysolutions) | array | List of gallerySolutions to be created in the linked log analytics workspace. | +| [`jobSchedules`](#parameter-jobschedules) | array | List of jobSchedules to be created in the automation account. | +| [`linkedWorkspaceResourceId`](#parameter-linkedworkspaceresourceid) | string | ID of the log analytics workspace to be linked to the deployed automation account. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | +| [`modules`](#parameter-modules) | array | List of modules to be created in the automation account. | +| [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | +| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | 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. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`runbooks`](#parameter-runbooks) | array | List of runbooks to be created in the automation account. | +| [`schedules`](#parameter-schedules) | array | List of schedules to be created in the automation account. | +| [`skuName`](#parameter-skuname) | string | SKU name of the account. | +| [`softwareUpdateConfigurations`](#parameter-softwareupdateconfigurations) | array | List of softwareUpdateConfigurations to be created in the automation account. | +| [`tags`](#parameter-tags) | object | Tags of the Automation Account resource. | +| [`variables`](#parameter-variables) | array | List of variables to be created in the automation account. | + +### Parameter: `customerManagedKey` + +The customer managed key definition. +- Required: No +- Type: object + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`keyName`](#parameter-customermanagedkeykeyname) | Yes | string | Required. The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeykeyvaultresourceid) | Yes | string | Required. The resource ID of a key vault to reference a customer managed key for encryption from. | +| [`keyVersion`](#parameter-customermanagedkeykeyversion) | No | string | Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | No | string | Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | + +### Parameter: `customerManagedKey.keyName` + +Required. The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVaultResourceId` + +Required. The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVersion` + +Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'. + +- Required: No +- Type: string + +### Parameter: `customerManagedKey.userAssignedIdentityResourceId` + +Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings` + +The diagnostic settings of the service. +- Required: No +- Type: array + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`eventHubAuthorizationRuleResourceId`](#parameter-diagnosticsettingseventhubauthorizationruleresourceid) | No | string | Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| [`eventHubName`](#parameter-diagnosticsettingseventhubname) | No | string | Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`logAnalyticsDestinationType`](#parameter-diagnosticsettingsloganalyticsdestinationtype) | No | string | Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. | +| [`logCategoriesAndGroups`](#parameter-diagnosticsettingslogcategoriesandgroups) | No | array | Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`marketplacePartnerResourceId`](#parameter-diagnosticsettingsmarketplacepartnerresourceid) | No | string | Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. | +| [`metricCategories`](#parameter-diagnosticsettingsmetriccategories) | No | array | Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. | +| [`name`](#parameter-diagnosticsettingsname) | No | string | Optional. The name of diagnostic setting. | +| [`storageAccountResourceId`](#parameter-diagnosticsettingsstorageaccountresourceid) | No | string | Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | +| [`workspaceResourceId`](#parameter-diagnosticsettingsworkspaceresourceid) | No | string | Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | + +### Parameter: `diagnosticSettings.eventHubAuthorizationRuleResourceId` + +Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.eventHubName` + +Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logAnalyticsDestinationType` + +Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type. + +- Required: No +- Type: string +- Allowed: `[AzureDiagnostics, Dedicated]` + +### Parameter: `diagnosticSettings.logCategoriesAndGroups` + +Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`category`](#parameter-diagnosticsettingslogcategoriesandgroupscategory) | No | string | Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. | +| [`categoryGroup`](#parameter-diagnosticsettingslogcategoriesandgroupscategorygroup) | No | string | Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs. | + +### Parameter: `diagnosticSettings.logCategoriesAndGroups.category` + +Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.logCategoriesAndGroups.categoryGroup` + +Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs. + +- Required: No +- Type: string + + +### Parameter: `diagnosticSettings.marketplacePartnerResourceId` + +Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.metricCategories` + +Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to '' to disable log collection. + +- Required: No +- Type: array + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`category`](#parameter-diagnosticsettingsmetriccategoriescategory) | Yes | string | Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics. | + +### Parameter: `diagnosticSettings.metricCategories.category` + +Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics. + +- Required: Yes +- Type: string + + +### Parameter: `diagnosticSettings.name` + +Optional. The name of diagnostic setting. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.storageAccountResourceId` + +Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `diagnosticSettings.workspaceResourceId` + +Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. + +- Required: No +- Type: string + +### Parameter: `disableLocalAuth` + +Disable local authentication profile used within the resource. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableTelemetry` + +Enable/Disable usage telemetry for module. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `gallerySolutions` + +List of gallerySolutions to be created in the linked log analytics workspace. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `jobSchedules` + +List of jobSchedules to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `linkedWorkspaceResourceId` + +ID of the log analytics workspace to be linked to the deployed automation account. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `location` + +Location for all resources. +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. +- Required: No +- Type: object + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`kind`](#parameter-lockkind) | No | string | Optional. Specify the type of lock. | +| [`name`](#parameter-lockname) | No | string | Optional. Specify the name of lock. | + +### Parameter: `lock.kind` + +Optional. Specify the type of lock. + +- Required: No +- Type: string +- Allowed: `[CanNotDelete, None, ReadOnly]` + +### Parameter: `lock.name` + +Optional. Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `managedIdentities` + +The managed identity definition for this resource. +- Required: No +- Type: object + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | No | bool | Optional. Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | No | array | Optional. The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.systemAssigned` + +Optional. Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### Parameter: `managedIdentities.userAssignedResourceIds` + +Optional. The resource ID(s) to assign to the resource. + +- Required: No +- Type: array + +### Parameter: `modules` + +List of modules to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `name` + +Name of the Automation Account. +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints` + +Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. +- Required: No +- Type: array + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`applicationSecurityGroupResourceIds`](#parameter-privateendpointsapplicationsecuritygroupresourceids) | No | array | Optional. Application security groups in which the private endpoint IP configuration is included. | +| [`customDnsConfigs`](#parameter-privateendpointscustomdnsconfigs) | No | array | Optional. Custom DNS configurations. | +| [`customNetworkInterfaceName`](#parameter-privateendpointscustomnetworkinterfacename) | No | string | Optional. The custom name of the network interface attached to the private endpoint. | +| [`enableTelemetry`](#parameter-privateendpointsenabletelemetry) | No | bool | Optional. Enable/Disable usage telemetry for module. | +| [`ipConfigurations`](#parameter-privateendpointsipconfigurations) | No | array | Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. | +| [`location`](#parameter-privateendpointslocation) | No | string | Optional. The location to deploy the private endpoint to. | +| [`lock`](#parameter-privateendpointslock) | No | object | Optional. Specify the type of lock. | +| [`manualPrivateLinkServiceConnections`](#parameter-privateendpointsmanualprivatelinkserviceconnections) | No | array | Optional. Manual PrivateLink Service Connections. | +| [`name`](#parameter-privateendpointsname) | No | string | Optional. The name of the private endpoint. | +| [`privateDnsZoneGroupName`](#parameter-privateendpointsprivatednszonegroupname) | No | string | Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. | +| [`privateDnsZoneResourceIds`](#parameter-privateendpointsprivatednszoneresourceids) | No | array | Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. | +| [`roleAssignments`](#parameter-privateendpointsroleassignments) | No | array | Optional. Array of role assignments to create. | +| [`service`](#parameter-privateendpointsservice) | Yes | string | Required. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". | +| [`subnetResourceId`](#parameter-privateendpointssubnetresourceid) | Yes | string | Required. Resource ID of the subnet where the endpoint needs to be created. | +| [`tags`](#parameter-privateendpointstags) | No | object | Optional. Tags to be applied on all resources/resource groups in this deployment. | + +### Parameter: `privateEndpoints.applicationSecurityGroupResourceIds` + +Optional. Application security groups in which the private endpoint IP configuration is included. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.customDnsConfigs` + +Optional. Custom DNS configurations. + +- Required: No +- Type: array + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`fqdn`](#parameter-privateendpointscustomdnsconfigsfqdn) | No | string | Required. Fqdn that resolves to private endpoint ip address. | +| [`ipAddresses`](#parameter-privateendpointscustomdnsconfigsipaddresses) | Yes | array | Required. A list of private ip addresses of the private endpoint. | + +### Parameter: `privateEndpoints.customDnsConfigs.fqdn` + +Required. Fqdn that resolves to private endpoint ip address. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.customDnsConfigs.ipAddresses` + +Required. A list of private ip addresses of the private endpoint. + +- Required: Yes +- Type: array + + +### Parameter: `privateEndpoints.customNetworkInterfaceName` + +Optional. The custom name of the network interface attached to the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.enableTelemetry` + +Optional. Enable/Disable usage telemetry for module. + +- Required: No +- Type: bool + +### Parameter: `privateEndpoints.ipConfigurations` + +Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints. + +- Required: No +- Type: array + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`name`](#parameter-privateendpointsipconfigurationsname) | Yes | string | Required. The name of the resource that is unique within a resource group. | +| [`properties`](#parameter-privateendpointsipconfigurationsproperties) | Yes | object | Required. Properties of private endpoint IP configurations. | + +### Parameter: `privateEndpoints.ipConfigurations.name` + +Required. The name of the resource that is unique within a resource group. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties` + +Required. Properties of private endpoint IP configurations. + +- Required: Yes +- Type: object + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`groupId`](#parameter-privateendpointsipconfigurationspropertiesgroupid) | Yes | string | Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. | +| [`memberName`](#parameter-privateendpointsipconfigurationspropertiesmembername) | Yes | string | Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. | +| [`privateIPAddress`](#parameter-privateendpointsipconfigurationspropertiesprivateipaddress) | Yes | string | Required. A private ip address obtained from the private endpoint's subnet. | + +### Parameter: `privateEndpoints.ipConfigurations.properties.groupId` + +Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.memberName` + +Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.ipConfigurations.properties.privateIPAddress` + +Required. A private ip address obtained from the private endpoint's subnet. + +- Required: Yes +- Type: string + + + +### Parameter: `privateEndpoints.location` + +Optional. The location to deploy the private endpoint to. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.lock` + +Optional. Specify the type of lock. + +- Required: No +- Type: object + +### Parameter: `privateEndpoints.manualPrivateLinkServiceConnections` + +Optional. Manual PrivateLink Service Connections. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.name` + +Optional. The name of the private endpoint. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneGroupName` + +Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided. + +- Required: No +- Type: string + +### Parameter: `privateEndpoints.privateDnsZoneResourceIds` + +Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.roleAssignments` + +Optional. Array of role assignments to create. + +- Required: No +- Type: array + +### Parameter: `privateEndpoints.service` + +Required. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob". + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.subnetResourceId` + +Required. Resource ID of the subnet where the endpoint needs to be created. + +- Required: Yes +- Type: string + +### Parameter: `privateEndpoints.tags` + +Optional. Tags to be applied on all resources/resource groups in this deployment. + +- Required: No +- Type: object + +### Parameter: `publicNetworkAccess` + +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. +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Disabled' + 'Enabled' + ] + ``` + +### Parameter: `roleAssignments` + +Array of role assignments to create. +- Required: No +- Type: array + + +| Name | Required | Type | Description | +| :-- | :-- | :--| :-- | +| [`condition`](#parameter-roleassignmentscondition) | No | string | 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`](#parameter-roleassignmentsconditionversion) | No | string | Optional. Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | No | string | Optional. The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | No | string | Optional. The description of the role assignment. | +| [`principalId`](#parameter-roleassignmentsprincipalid) | Yes | string | Required. The principal ID of the principal (user/group/identity) to assign the role to. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | No | string | Optional. The principal type of the assigned principal ID. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | Yes | string | 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'. | + +### Parameter: `roleAssignments.condition` + +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" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Optional. Version of the condition. + +- Required: No +- Type: string +- Allowed: `[2.0]` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +Optional. The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +Optional. The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalId` + +Required. The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.principalType` + +Optional. The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: `[Device, ForeignGroup, Group, ServicePrincipal, User]` + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +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'. + +- Required: Yes +- Type: string + +### Parameter: `runbooks` + +List of runbooks to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `schedules` + +List of schedules to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `skuName` + +SKU name of the account. +- Required: No +- Type: string +- Default: `'Basic'` +- Allowed: + ```Bicep + [ + 'Basic' + 'Free' + ] + ``` + +### Parameter: `softwareUpdateConfigurations` + +List of softwareUpdateConfigurations to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `tags` + +Tags of the Automation Account resource. +- Required: No +- Type: object + +### Parameter: `variables` + +List of variables to be created in the automation account. +- Required: No +- Type: array +- Default: `[]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed automation account. | +| `resourceGroupName` | string | The resource group of the deployed automation account. | +| `resourceId` | string | The resource ID of the deployed automation account. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `res/operational-insights/workspace/linked-service` | Local reference | +| `br/public:avm/res/network/private-endpoint:0.3.1` | Remote reference | +| `br/public:avm/res/operations-management/solution:0.1.0` | Remote reference | diff --git a/avm/res/automation/automation-account/job-schedule/README.md b/avm/res/automation/automation-account/job-schedule/README.md new file mode 100644 index 00000000000..694802658a9 --- /dev/null +++ b/avm/res/automation/automation-account/job-schedule/README.md @@ -0,0 +1,96 @@ +# Automation Account Job Schedules `[Microsoft.Automation/automationAccounts/jobSchedules]` + +This module deploys an Azure Automation Account Job Schedule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/jobSchedules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/jobSchedules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`runbookName`](#parameter-runbookname) | string | The runbook property associated with the entity. | +| [`scheduleName`](#parameter-schedulename) | string | The schedule property associated with the entity. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`parameters`](#parameter-parameters) | object | List of job properties. | +| [`runOn`](#parameter-runon) | string | The hybrid worker group that the scheduled job should run on. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Automation Account job schedule. Must be a GUID and is autogenerated. No need to provide this value. | + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `name` + +Name of the Automation Account job schedule. Must be a GUID and is autogenerated. No need to provide this value. +- Required: No +- Type: string +- Default: `[newGuid()]` + +### Parameter: `parameters` + +List of job properties. +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `runbookName` + +The runbook property associated with the entity. +- Required: Yes +- Type: string + +### Parameter: `runOn` + +The hybrid worker group that the scheduled job should run on. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `scheduleName` + +The schedule property associated with the entity. +- Required: Yes +- Type: string + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed job schedule. | +| `resourceGroupName` | string | The resource group of the deployed job schedule. | +| `resourceId` | string | The resource ID of the deployed job schedule. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/job-schedule/main.bicep b/avm/res/automation/automation-account/job-schedule/main.bicep new file mode 100644 index 00000000000..1fc6e25d44f --- /dev/null +++ b/avm/res/automation/automation-account/job-schedule/main.bicep @@ -0,0 +1,51 @@ +metadata name = 'Automation Account Job Schedules' +metadata description = 'This module deploys an Azure Automation Account Job Schedule.' +metadata owner = 'Azure/module-maintainers' + +@description('Generated. Name of the Automation Account job schedule. Must be a GUID and is autogenerated. No need to provide this value.') +param name string = newGuid() + +@description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@description('Required. The runbook property associated with the entity.') +param runbookName string + +@description('Required. The schedule property associated with the entity.') +param scheduleName string + +@description('Optional. List of job properties.') +param parameters object = {} + +@description('Optional. The hybrid worker group that the scheduled job should run on.') +param runOn string = '' + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource jobSchedule 'Microsoft.Automation/automationAccounts/jobSchedules@2022-08-08' = { + // For each job schedule deployed with an ARM template, the GUID must be unique. Even if you're rescheduling an existing schedule, you'll need to change the GUID. This applies even if you've previously deleted an existing job schedule that was created with the same template. Reusing the same GUID results in a failed deployment. + #disable-next-line use-stable-resource-identifiers + name: name + parent: automationAccount + properties: { + parameters: parameters + runbook: { + name: runbookName + } + runOn: !empty(runOn) ? runOn : null + schedule: { + name: scheduleName + } + } +} + +@description('The name of the deployed job schedule.') +output name string = jobSchedule.name + +@description('The resource ID of the deployed job schedule.') +output resourceId string = jobSchedule.id + +@description('The resource group of the deployed job schedule.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/automation/automation-account/job-schedule/main.json b/avm/res/automation/automation-account/job-schedule/main.json new file mode 100644 index 00000000000..14f6d6b70aa --- /dev/null +++ b/avm/res/automation/automation-account/job-schedule/main.json @@ -0,0 +1,95 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "10635670071348763124" + }, + "name": "Automation Account Job Schedules", + "description": "This module deploys an Azure Automation Account Job Schedule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[newGuid()]", + "metadata": { + "description": "Generated. Name of the Automation Account job schedule. Must be a GUID and is autogenerated. No need to provide this value." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "runbookName": { + "type": "string", + "metadata": { + "description": "Required. The runbook property associated with the entity." + } + }, + "scheduleName": { + "type": "string", + "metadata": { + "description": "Required. The schedule property associated with the entity." + } + }, + "parameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. List of job properties." + } + }, + "runOn": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The hybrid worker group that the scheduled job should run on." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/jobSchedules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "parameters": "[parameters('parameters')]", + "runbook": { + "name": "[parameters('runbookName')]" + }, + "runOn": "[if(not(empty(parameters('runOn'))), parameters('runOn'), null())]", + "schedule": { + "name": "[parameters('scheduleName')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed job schedule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed job schedule." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/jobSchedules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed job schedule." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/main.bicep b/avm/res/automation/automation-account/main.bicep new file mode 100644 index 00000000000..cacca5bab14 --- /dev/null +++ b/avm/res/automation/automation-account/main.bicep @@ -0,0 +1,555 @@ +metadata name = 'Automation Accounts' +metadata description = 'This module deploys an Azure Automation Account.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Automation Account.') +param name string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. SKU name of the account.') +@allowed([ + 'Free' + 'Basic' +]) +param skuName string = 'Basic' + +@description('Optional. The customer managed key definition.') +param customerManagedKey customerManagedKeyType + +@description('Optional. List of modules to be created in the automation account.') +param modules array = [] + +@description('Optional. List of runbooks to be created in the automation account.') +param runbooks array = [] + +@description('Optional. List of schedules to be created in the automation account.') +param schedules array = [] + +@description('Optional. List of jobSchedules to be created in the automation account.') +param jobSchedules array = [] + +@description('Optional. List of variables to be created in the automation account.') +param variables array = [] + +@description('Optional. ID of the log analytics workspace to be linked to the deployed automation account.') +param linkedWorkspaceResourceId string = '' + +@description('Optional. List of gallerySolutions to be created in the linked log analytics workspace.') +param gallerySolutions array = [] + +@description('Optional. List of softwareUpdateConfigurations to be created in the automation account.') +param softwareUpdateConfigurations array = [] + +@description('Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set.') +@allowed([ + '' + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = '' + +@description('Optional. Disable local authentication profile used within the resource.') +param disableLocalAuth bool = true + +@description('Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible.') +param privateEndpoints privateEndpointType + +@description('Optional. The diagnostic settings of the service.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. The managed identity definition for this resource.') +param managedIdentities managedIdentitiesType + +@description('Optional. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Tags of the Automation Account resource.') +param tags object? + +@description('Optional. Enable/Disable usage telemetry for module.') +param enableTelemetry bool = true + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +var identity = !empty(managedIdentities) ? { + type: (managedIdentities.?systemAssigned ?? false) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + 'Automation Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867') + 'Automation Job Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f') + 'Automation Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404') + 'Automation Runbook Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5') + 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 (Preview)': 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.automation-automationaccount.${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 cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4]) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } +} + +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup(split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4]) +} + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' = { + name: name + location: location + tags: tags + identity: identity + properties: { + sku: { + name: skuName + } + encryption: !empty(customerManagedKey) ? { + keySource: 'Microsoft.KeyVault' + identity: !empty(customerManagedKey.?userAssignedIdentityResourceId) ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } : null + keyVaultProperties: { + keyName: customerManagedKey!.keyName + keyVaultUri: cMKKeyVault.properties.vaultUri + keyVersion: !empty(customerManagedKey.?keyVersion ?? '') ? customerManagedKey!.keyVersion : last(split(cMKKeyVault::cMKKey.properties.keyUriWithVersion, '/')) + } + } : null + publicNetworkAccess: !empty(publicNetworkAccess) ? (publicNetworkAccess == 'Disabled' ? false : true) : (!empty(privateEndpoints) ? false : null) + disableLocalAuth: disableLocalAuth + } +} + +module automationAccount_modules 'module/main.bicep' = [for (module, index) in modules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Module-${index}' + params: { + name: module.name + automationAccountName: automationAccount.name + version: module.version + uri: module.uri + location: location + tags: module.?tags ?? tags + } +}] + +module automationAccount_schedules 'schedule/main.bicep' = [for (schedule, index) in schedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Schedule-${index}' + params: { + name: schedule.name + automationAccountName: automationAccount.name + advancedSchedule: contains(schedule, 'advancedSchedule') ? schedule.advancedSchedule : null + description: contains(schedule, 'description') ? schedule.description : '' + expiryTime: contains(schedule, 'expiryTime') ? schedule.expiryTime : '' + frequency: contains(schedule, 'frequency') ? schedule.frequency : 'OneTime' + interval: contains(schedule, 'interval') ? schedule.interval : 0 + startTime: contains(schedule, 'startTime') ? schedule.startTime : '' + timeZone: contains(schedule, 'timeZone') ? schedule.timeZone : '' + } +}] + +module automationAccount_runbooks 'runbook/main.bicep' = [for (runbook, index) in runbooks: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Runbook-${index}' + params: { + name: runbook.name + automationAccountName: automationAccount.name + type: runbook.type + description: contains(runbook, 'description') ? runbook.description : '' + uri: contains(runbook, 'uri') ? runbook.uri : '' + version: contains(runbook, 'version') ? runbook.version : '' + sasTokenValidityLength: runbook.?sasTokenValidityLength + scriptStorageAccountResourceId: runbook.?scriptStorageAccountResourceId + location: location + tags: runbook.?tags ?? tags + } +}] + +module automationAccount_jobSchedules 'job-schedule/main.bicep' = [for (jobSchedule, index) in jobSchedules: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-JobSchedule-${index}' + params: { + automationAccountName: automationAccount.name + runbookName: jobSchedule.runbookName + scheduleName: jobSchedule.scheduleName + parameters: contains(jobSchedule, 'parameters') ? jobSchedule.parameters : {} + runOn: contains(jobSchedule, 'runOn') ? jobSchedule.runOn : '' + } + dependsOn: [ + automationAccount_schedules + automationAccount_runbooks + ] +}] + +module automationAccount_variables 'variable/main.bicep' = [for (variable, index) in variables: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Variable-${index}' + params: { + automationAccountName: automationAccount.name + name: variable.name + description: contains(variable, 'description') ? variable.description : '' + value: variable.value + isEncrypted: contains(variable, 'isEncrypted') ? variable.isEncrypted : true + } +}] + +module automationAccount_linkedService '../../operational-insights/workspace/linked-service/main.bicep' = if (!empty(linkedWorkspaceResourceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-LinkedService' + params: { + name: 'automation' + logAnalyticsWorkspaceName: last(split(linkedWorkspaceResourceId, '/'))! + resourceId: automationAccount.id + tags: tags + } + // This is to support linked services to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup((!empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) : subscription().subscriptionId), !empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) : resourceGroup().name) +} + +module automationAccount_solutions 'br/public:avm/res/operations-management/solution:0.1.0' = [for (gallerySolution, index) in gallerySolutions: if (!empty(linkedWorkspaceResourceId)) { + name: '${uniqueString(deployment().name, location)}-AutoAccount-Solution-${index}' + params: { + name: gallerySolution.name + location: location + logAnalyticsWorkspaceName: last(split(linkedWorkspaceResourceId, '/'))! + product: contains(gallerySolution, 'product') ? gallerySolution.product : 'OMSGallery' + publisher: contains(gallerySolution, 'publisher') ? gallerySolution.publisher : 'Microsoft' + enableTelemetry: enableTelemetry + } + // This is to support solution to law in different subscription and resource group than the automation account. + // The current scope is used by default if no linked service is intended to be created. + scope: resourceGroup((!empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '//'), '/')[2]) : subscription().subscriptionId), !empty(linkedWorkspaceResourceId) ? (split((!empty(linkedWorkspaceResourceId) ? linkedWorkspaceResourceId : '////'), '/')[4]) : resourceGroup().name) + dependsOn: [ + automationAccount_linkedService + ] +}] + +module automationAccount_softwareUpdateConfigurations 'software-update-configuration/main.bicep' = [for (softwareUpdateConfiguration, index) in softwareUpdateConfigurations: { + name: '${uniqueString(deployment().name, location)}-AutoAccount-SwUpdateConfig-${index}' + params: { + name: softwareUpdateConfiguration.name + automationAccountName: automationAccount.name + frequency: softwareUpdateConfiguration.frequency + operatingSystem: softwareUpdateConfiguration.operatingSystem + rebootSetting: softwareUpdateConfiguration.rebootSetting + azureVirtualMachines: contains(softwareUpdateConfiguration, 'azureVirtualMachines') ? softwareUpdateConfiguration.azureVirtualMachines : [] + excludeUpdates: contains(softwareUpdateConfiguration, 'excludeUpdates') ? softwareUpdateConfiguration.excludeUpdates : [] + expiryTime: contains(softwareUpdateConfiguration, 'expiryTime') ? softwareUpdateConfiguration.expiryTime : '' + expiryTimeOffsetMinutes: contains(softwareUpdateConfiguration, 'expiryTimeOffsetMinutes') ? softwareUpdateConfiguration.expiryTimeOffsetMinute : 0 + includeUpdates: contains(softwareUpdateConfiguration, 'includeUpdates') ? softwareUpdateConfiguration.includeUpdates : [] + interval: contains(softwareUpdateConfiguration, 'interval') ? softwareUpdateConfiguration.interval : 1 + isEnabled: contains(softwareUpdateConfiguration, 'isEnabled') ? softwareUpdateConfiguration.isEnabled : true + maintenanceWindow: contains(softwareUpdateConfiguration, 'maintenanceWindow') ? softwareUpdateConfiguration.maintenanceWindow : 'PT2H' + monthDays: contains(softwareUpdateConfiguration, 'monthDays') ? softwareUpdateConfiguration.monthDays : [] + monthlyOccurrences: contains(softwareUpdateConfiguration, 'monthlyOccurrences') ? softwareUpdateConfiguration.monthlyOccurrences : [] + nextRun: contains(softwareUpdateConfiguration, 'nextRun') ? softwareUpdateConfiguration.nextRun : '' + nextRunOffsetMinutes: contains(softwareUpdateConfiguration, 'nextRunOffsetMinutes') ? softwareUpdateConfiguration.nextRunOffsetMinutes : 0 + nonAzureComputerNames: contains(softwareUpdateConfiguration, 'nonAzureComputerNames') ? softwareUpdateConfiguration.nonAzureComputerNames : [] + nonAzureQueries: contains(softwareUpdateConfiguration, 'nonAzureQueries') ? softwareUpdateConfiguration.nonAzureQueries : [] + postTaskParameters: contains(softwareUpdateConfiguration, 'postTaskParameters') ? softwareUpdateConfiguration.postTaskParameters : {} + postTaskSource: contains(softwareUpdateConfiguration, 'postTaskSource') ? softwareUpdateConfiguration.postTaskSource : '' + preTaskParameters: contains(softwareUpdateConfiguration, 'preTaskParameters') ? softwareUpdateConfiguration.preTaskParameters : {} + preTaskSource: contains(softwareUpdateConfiguration, 'preTaskSource') ? softwareUpdateConfiguration.preTaskSource : '' + scheduleDescription: contains(softwareUpdateConfiguration, 'scheduleDescription') ? softwareUpdateConfiguration.scheduleDescription : '' + scopeByLocations: contains(softwareUpdateConfiguration, 'scopeByLocations') ? softwareUpdateConfiguration.scopeByLocations : [] + scopeByResources: contains(softwareUpdateConfiguration, 'scopeByResources') ? softwareUpdateConfiguration.scopeByResources : [ + subscription().id + ] + scopeByTags: contains(softwareUpdateConfiguration, 'scopeByTags') ? softwareUpdateConfiguration.scopeByTags : {} + scopeByTagsOperation: contains(softwareUpdateConfiguration, 'scopeByTagsOperation') ? softwareUpdateConfiguration.scopeByTagsOperation : 'All' + startTime: contains(softwareUpdateConfiguration, 'startTime') ? softwareUpdateConfiguration.startTime : '' + timeZone: contains(softwareUpdateConfiguration, 'timeZone') ? softwareUpdateConfiguration.timeZone : 'UTC' + updateClassifications: contains(softwareUpdateConfiguration, 'updateClassifications') ? softwareUpdateConfiguration.updateClassifications : [ + 'Critical' + 'Security' + ] + weekDays: contains(softwareUpdateConfiguration, 'weekDays') ? softwareUpdateConfiguration.weekDays : [] + } + dependsOn: [ + automationAccount_solutions + ] +}] + +resource automationAccount_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: automationAccount +} + +resource automationAccount_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = [for (diagnosticSetting, index) in (diagnosticSettings ?? []): { + name: diagnosticSetting.?name ?? '${name}-diagnosticSettings' + properties: { + storageAccountId: diagnosticSetting.?storageAccountResourceId + workspaceId: diagnosticSetting.?workspaceResourceId + eventHubAuthorizationRuleId: diagnosticSetting.?eventHubAuthorizationRuleResourceId + eventHubName: diagnosticSetting.?eventHubName + metrics: diagnosticSetting.?metricCategories ?? [ + { + category: 'AllMetrics' + timeGrain: null + enabled: true + } + ] + logs: diagnosticSetting.?logCategoriesAndGroups ?? [ + { + categoryGroup: 'AllLogs' + enabled: true + } + ] + marketplacePartnerId: diagnosticSetting.?marketplacePartnerResourceId + logAnalyticsDestinationType: diagnosticSetting.?logAnalyticsDestinationType + } + scope: automationAccount +}] + +module automationAccount_privateEndpoints 'br/public:avm/res/network/private-endpoint:0.3.1' = [for (privateEndpoint, index) in (privateEndpoints ?? []): { + name: '${uniqueString(deployment().name, location)}-automationAccount-PrivateEndpoint-${index}' + params: { + privateLinkServiceConnections: [ + { + name: name + properties: { + privateLinkServiceId: automationAccount.id + groupIds: [ + privateEndpoint.?service ?? 'automationaccount' + ] + } + } + ] + name: privateEndpoint.?name ?? 'pep-${last(split(automationAccount.id, '/'))}-${privateEndpoint.?service ?? privateEndpoint.service}-${index}' + subnetResourceId: privateEndpoint.subnetResourceId + location: privateEndpoint.?location ?? reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location + lock: privateEndpoint.?lock ?? lock + privateDnsZoneGroupName: privateEndpoint.?privateDnsZoneGroupName + privateDnsZoneResourceIds: privateEndpoint.?privateDnsZoneResourceIds + roleAssignments: privateEndpoint.?roleAssignments + tags: privateEndpoint.?tags ?? tags + manualPrivateLinkServiceConnections: privateEndpoint.?manualPrivateLinkServiceConnections + customDnsConfigs: privateEndpoint.?customDnsConfigs + ipConfigurations: privateEndpoint.?ipConfigurations + applicationSecurityGroupResourceIds: privateEndpoint.?applicationSecurityGroupResourceIds + customNetworkInterfaceName: privateEndpoint.?customNetworkInterfaceName + enableTelemetry: enableTelemetry + } +}] + +resource automationAccount_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(automationAccount.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: automationAccount +}] + +@description('The name of the deployed automation account.') +output name string = automationAccount.name + +@description('The resource ID of the deployed automation account.') +output resourceId string = automationAccount.id + +@description('The resource group of the deployed automation account.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(automationAccount.identity, 'principalId') ? automationAccount.identity.principalId : '' + +@description('The location the resource was deployed into.') +output location string = automationAccount.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? + + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[]? +}? + +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? +}[]? + +type privateEndpointType = { + @description('Optional. The name of the private endpoint.') + name: string? + + @description('Optional. The location to deploy the private endpoint to.') + location: string? + + @description('Required. The service (sub-) type to deploy the private endpoint for. For example "vault" or "blob".') + service: string + + @description('Required. Resource ID of the subnet where the endpoint needs to be created.') + subnetResourceId: string + + @description('Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided.') + privateDnsZoneGroupName: string? + + @description('Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones.') + privateDnsZoneResourceIds: string[]? + + @description('Optional. Custom DNS configurations.') + customDnsConfigs: { + @description('Required. Fqdn that resolves to private endpoint ip address.') + fqdn: string? + + @description('Required. A list of private ip addresses of the private endpoint.') + ipAddresses: string[] + }[]? + + @description('Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints.') + ipConfigurations: { + @description('Required. The name of the resource that is unique within a resource group.') + name: string + + @description('Required. Properties of private endpoint IP configurations.') + properties: { + @description('Required. The ID of a group obtained from the remote resource that this private endpoint should connect to.') + groupId: string + + @description('Required. The member name of a group obtained from the remote resource that this private endpoint should connect to.') + memberName: string + + @description('Required. A private ip address obtained from the private endpoint\'s subnet.') + privateIPAddress: string + } + }[]? + + @description('Optional. Application security groups in which the private endpoint IP configuration is included.') + applicationSecurityGroupResourceIds: string[]? + + @description('Optional. The custom name of the network interface attached to the private endpoint.') + customNetworkInterfaceName: string? + + @description('Optional. Specify the type of lock.') + lock: lockType + + @description('Optional. Array of role assignments to create.') + roleAssignments: roleAssignmentType + + @description('Optional. Tags to be applied on all resources/resource groups in this deployment.') + tags: object? + + @description('Optional. Manual PrivateLink Service Connections.') + manualPrivateLinkServiceConnections: array? + + @description('Optional. Enable/Disable usage telemetry for module.') + enableTelemetry: bool? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') + categoryGroup: string? + }[]? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + workspaceResourceId: string? + + @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + storageAccountResourceId: string? + + @description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') + eventHubAuthorizationRuleResourceId: string? + + @description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? + +type customerManagedKeyType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string + + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string + + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') + keyVersion: string? + + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? +}? diff --git a/avm/res/automation/automation-account/main.json b/avm/res/automation/automation-account/main.json new file mode 100644 index 00000000000..6678b3f01f1 --- /dev/null +++ b/avm/res/automation/automation-account/main.json @@ -0,0 +1,2973 @@ +{ + "$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.23.1.45101", + "templateHash": "3768407701498308451" + }, + "name": "Automation Accounts", + "description": "This module deploys an Azure Automation Account.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "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 + }, + "privateEndpointType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The service (sub-) type to deploy the private endpoint for. For example \"vault\" or \"blob\"." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "manualPrivateLinkServiceConnections": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Manual PrivateLink Service Connections." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Basic", + "allowedValues": [ + "Free", + "Basic" + ], + "metadata": { + "description": "Optional. SKU name of the account." + } + }, + "customerManagedKey": { + "$ref": "#/definitions/customerManagedKeyType", + "metadata": { + "description": "Optional. The customer managed key definition." + } + }, + "modules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of modules to be created in the automation account." + } + }, + "runbooks": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of runbooks to be created in the automation account." + } + }, + "schedules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of schedules to be created in the automation account." + } + }, + "jobSchedules": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of jobSchedules to be created in the automation account." + } + }, + "variables": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of variables to be created in the automation account." + } + }, + "linkedWorkspaceResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. ID of the log analytics workspace to be linked to the deployed automation account." + } + }, + "gallerySolutions": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of gallerySolutions to be created in the linked log analytics workspace." + } + }, + "softwareUpdateConfigurations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of softwareUpdateConfigurations to be created in the automation account." + } + }, + "publicNetworkAccess": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "", + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled. If not specified, it will be disabled by default if private endpoints are set." + } + }, + "disableLocalAuth": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Disable local authentication profile used within the resource." + } + }, + "privateEndpoints": { + "$ref": "#/definitions/privateEndpointType", + "metadata": { + "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Automation Account resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Automation Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f353d9bd-d4a6-484e-a77a-8050b599b867')]", + "Automation Job Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fe576fe-1146-4730-92eb-48519fa6bf9f')]", + "Automation Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd3881f73-407a-4167-8283-e981cbba0404')]", + "Automation Runbook Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5')]", + "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 (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "cMKKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKKeyVault" + ] + }, + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.automation-automationaccount.{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" + } + } + } + } + }, + "cMKKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKUserAssignedIdentity": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId')))]", + "existing": true, + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/'))]" + }, + "automationAccount": { + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "identity": "[variables('identity')]", + "properties": { + "sku": { + "name": "[parameters('skuName')]" + }, + "encryption": "[if(not(empty(parameters('customerManagedKey'))), createObject('keySource', 'Microsoft.KeyVault', 'identity', if(not(empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'))), createObject('userAssignedIdentity', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2], split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]), 'Microsoft.ManagedIdentity/userAssignedIdentities', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/')))), null()), 'keyVaultProperties', createObject('keyName', parameters('customerManagedKey').keyName, 'keyVaultUri', reference('cMKKeyVault').vaultUri, 'keyVersion', if(not(empty(coalesce(tryGet(parameters('customerManagedKey'), 'keyVersion'), ''))), parameters('customerManagedKey').keyVersion, last(split(reference('cMKKeyVault::cMKKey').keyUriWithVersion, '/'))))), null())]", + "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), if(equals(parameters('publicNetworkAccess'), 'Disabled'), false(), true()), if(not(empty(parameters('privateEndpoints'))), false(), null()))]", + "disableLocalAuth": "[parameters('disableLocalAuth')]" + }, + "dependsOn": [ + "cMKKeyVault", + "cMKUserAssignedIdentity" + ] + }, + "automationAccount_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.Automation/automationAccounts/{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": [ + "automationAccount" + ] + }, + "automationAccount_diagnosticSettings": { + "copy": { + "name": "automationAccount_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Automation/automationAccounts/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'AllLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_roleAssignments": { + "copy": { + "name": "automationAccount_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Automation/automationAccounts/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Automation/automationAccounts', 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": [ + "automationAccount" + ] + }, + "automationAccount_modules": { + "copy": { + "name": "automationAccount_modules", + "count": "[length(parameters('modules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-Module-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('modules')[copyIndex()].name]" + }, + "automationAccountName": { + "value": "[parameters('name')]" + }, + "version": { + "value": "[parameters('modules')[copyIndex()].version]" + }, + "uri": { + "value": "[parameters('modules')[copyIndex()].uri]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('modules')[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$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.23.1.45101", + "templateHash": "17367962996789020433" + }, + "name": "Automation Account Modules", + "description": "This module deploys an Azure Automation Account Module.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account module." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "uri": { + "type": "string", + "metadata": { + "description": "Required. Module package URI, e.g. https://www.powershellgallery.com/api/v2/package." + } + }, + "version": { + "type": "string", + "defaultValue": "latest", + "metadata": { + "description": "Optional. Module version or specify latest to get the latest version." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Automation Account resource." + } + } + }, + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "module": { + "type": "Microsoft.Automation/automationAccounts/modules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "contentLink": { + "uri": "[if(not(equals(parameters('version'), 'latest')), format('{0}/{1}/{2}', parameters('uri'), parameters('name'), parameters('version')), format('{0}/{1}', parameters('uri'), parameters('name')))]", + "version": "[if(not(equals(parameters('version'), 'latest')), parameters('version'), null())]" + } + }, + "dependsOn": [ + "automationAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed module." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed module." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/modules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed module." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('module', '2022-08-08', 'full').location]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_schedules": { + "copy": { + "name": "automationAccount_schedules", + "count": "[length(parameters('schedules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-Schedule-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('schedules')[copyIndex()].name]" + }, + "automationAccountName": { + "value": "[parameters('name')]" + }, + "advancedSchedule": "[if(contains(parameters('schedules')[copyIndex()], 'advancedSchedule'), createObject('value', parameters('schedules')[copyIndex()].advancedSchedule), createObject('value', null()))]", + "description": "[if(contains(parameters('schedules')[copyIndex()], 'description'), createObject('value', parameters('schedules')[copyIndex()].description), createObject('value', ''))]", + "expiryTime": "[if(contains(parameters('schedules')[copyIndex()], 'expiryTime'), createObject('value', parameters('schedules')[copyIndex()].expiryTime), createObject('value', ''))]", + "frequency": "[if(contains(parameters('schedules')[copyIndex()], 'frequency'), createObject('value', parameters('schedules')[copyIndex()].frequency), createObject('value', 'OneTime'))]", + "interval": "[if(contains(parameters('schedules')[copyIndex()], 'interval'), createObject('value', parameters('schedules')[copyIndex()].interval), createObject('value', 0))]", + "startTime": "[if(contains(parameters('schedules')[copyIndex()], 'startTime'), createObject('value', parameters('schedules')[copyIndex()].startTime), createObject('value', ''))]", + "timeZone": "[if(contains(parameters('schedules')[copyIndex()], 'timeZone'), createObject('value', parameters('schedules')[copyIndex()].timeZone), createObject('value', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "2599258461220838817" + }, + "name": "Automation Account Schedules", + "description": "This module deploys an Azure Automation Account Schedule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account schedule." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "advancedSchedule": { + "type": "object", + "defaultValue": {}, + "metadata": { + "monthDays": "Days of the month that the job should execute on. Must be between 1 and 31.", + "monthlyOccurrences": "Occurrences of days within a month.", + "weekDays": "Days of the week that the job should execute on.", + "description": "Optional. The properties of the create Advanced Schedule." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the schedule." + } + }, + "expiryTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end time of the schedule." + } + }, + "frequency": { + "type": "string", + "defaultValue": "OneTime", + "allowedValues": [ + "Day", + "Hour", + "Minute", + "Month", + "OneTime", + "Week" + ], + "metadata": { + "description": "Optional. The frequency of the schedule." + } + }, + "interval": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Anything." + } + }, + "startTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The start time of the schedule." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The time zone of the schedule." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Time used as a basis for e.g. the schedule start date." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/schedules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "advancedSchedule": "[if(not(empty(parameters('advancedSchedule'))), parameters('advancedSchedule'), null())]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "expiryTime": "[if(not(empty(parameters('expiryTime'))), parameters('expiryTime'), null())]", + "frequency": "[if(not(empty(parameters('frequency'))), parameters('frequency'), 'OneTime')]", + "interval": "[if(not(equals(parameters('interval'), 0)), parameters('interval'), null())]", + "startTime": "[if(not(empty(parameters('startTime'))), parameters('startTime'), dateTimeAdd(parameters('baseTime'), 'PT10M'))]", + "timeZone": "[if(not(empty(parameters('timeZone'))), parameters('timeZone'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed schedule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed schedule." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/schedules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed schedule." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_runbooks": { + "copy": { + "name": "automationAccount_runbooks", + "count": "[length(parameters('runbooks'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-Runbook-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('runbooks')[copyIndex()].name]" + }, + "automationAccountName": { + "value": "[parameters('name')]" + }, + "type": { + "value": "[parameters('runbooks')[copyIndex()].type]" + }, + "description": "[if(contains(parameters('runbooks')[copyIndex()], 'description'), createObject('value', parameters('runbooks')[copyIndex()].description), createObject('value', ''))]", + "uri": "[if(contains(parameters('runbooks')[copyIndex()], 'uri'), createObject('value', parameters('runbooks')[copyIndex()].uri), createObject('value', ''))]", + "version": "[if(contains(parameters('runbooks')[copyIndex()], 'version'), createObject('value', parameters('runbooks')[copyIndex()].version), createObject('value', ''))]", + "sasTokenValidityLength": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'sasTokenValidityLength')]" + }, + "scriptStorageAccountResourceId": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'scriptStorageAccountResourceId')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('runbooks')[copyIndex()], 'tags'), parameters('tags'))]" + } + }, + "template": { + "$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.23.1.45101", + "templateHash": "1364137745351676946" + }, + "name": "Automation Account Runbooks", + "description": "This module deploys an Azure Automation Account Runbook.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account runbook." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "Graph", + "GraphPowerShell", + "GraphPowerShellWorkflow", + "PowerShell", + "PowerShellWorkflow" + ], + "metadata": { + "description": "Required. The type of the runbook." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the runbook." + } + }, + "uri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The uri of the runbook content." + } + }, + "version": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The version of the runbook content." + } + }, + "scriptStorageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource Id of the runbook storage account." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Time used as a basis for e.g. the schedule start date." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Automation Account resource." + } + } + }, + "variables": { + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + } + }, + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "storageAccount": { + "condition": "[not(empty(parameters('scriptStorageAccountResourceId')))]", + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2022-09-01", + "subscriptionId": "[split(coalesce(parameters('scriptStorageAccountResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('scriptStorageAccountResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('scriptStorageAccountResourceId'), 'dummyVault'), '/'))]" + }, + "runbook": { + "type": "Microsoft.Automation/automationAccounts/runbooks", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "runbookType": "[parameters('type')]", + "description": "[parameters('description')]", + "publishContentLink": "[if(not(empty(parameters('uri'))), if(empty(parameters('uri')), null(), createObject('uri', if(not(empty(parameters('uri'))), if(empty(parameters('scriptStorageAccountResourceId')), parameters('uri'), format('{0}?{1}', parameters('uri'), listAccountSas(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('scriptStorageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('scriptStorageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('scriptStorageAccountResourceId'), 'dummyVault'), '/'))), '2021-04-01', variables('accountSasProperties')).accountSasToken)), null()), 'version', if(not(empty(parameters('version'))), parameters('version'), null()))), null())]" + }, + "dependsOn": [ + "automationAccount", + "storageAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed runbook." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed runbook." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/runbooks', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed runbook." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('runbook', '2022-08-08', 'full').location]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_jobSchedules": { + "copy": { + "name": "automationAccount_jobSchedules", + "count": "[length(parameters('jobSchedules'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-JobSchedule-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "automationAccountName": { + "value": "[parameters('name')]" + }, + "runbookName": { + "value": "[parameters('jobSchedules')[copyIndex()].runbookName]" + }, + "scheduleName": { + "value": "[parameters('jobSchedules')[copyIndex()].scheduleName]" + }, + "parameters": "[if(contains(parameters('jobSchedules')[copyIndex()], 'parameters'), createObject('value', parameters('jobSchedules')[copyIndex()].parameters), createObject('value', createObject()))]", + "runOn": "[if(contains(parameters('jobSchedules')[copyIndex()], 'runOn'), createObject('value', parameters('jobSchedules')[copyIndex()].runOn), createObject('value', ''))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "10635670071348763124" + }, + "name": "Automation Account Job Schedules", + "description": "This module deploys an Azure Automation Account Job Schedule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "defaultValue": "[newGuid()]", + "metadata": { + "description": "Generated. Name of the Automation Account job schedule. Must be a GUID and is autogenerated. No need to provide this value." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "runbookName": { + "type": "string", + "metadata": { + "description": "Required. The runbook property associated with the entity." + } + }, + "scheduleName": { + "type": "string", + "metadata": { + "description": "Required. The schedule property associated with the entity." + } + }, + "parameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. List of job properties." + } + }, + "runOn": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The hybrid worker group that the scheduled job should run on." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/jobSchedules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "parameters": "[parameters('parameters')]", + "runbook": { + "name": "[parameters('runbookName')]" + }, + "runOn": "[if(not(empty(parameters('runOn'))), parameters('runOn'), null())]", + "schedule": { + "name": "[parameters('scheduleName')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed job schedule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed job schedule." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/jobSchedules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed job schedule." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "automationAccount", + "automationAccount_runbooks", + "automationAccount_schedules" + ] + }, + "automationAccount_variables": { + "copy": { + "name": "automationAccount_variables", + "count": "[length(parameters('variables'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-Variable-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "automationAccountName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[parameters('variables')[copyIndex()].name]" + }, + "description": "[if(contains(parameters('variables')[copyIndex()], 'description'), createObject('value', parameters('variables')[copyIndex()].description), createObject('value', ''))]", + "value": { + "value": "[parameters('variables')[copyIndex()].value]" + }, + "isEncrypted": "[if(contains(parameters('variables')[copyIndex()], 'isEncrypted'), createObject('value', parameters('variables')[copyIndex()].isEncrypted), createObject('value', true()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "6672396434414300928" + }, + "name": "Automation Account Variables", + "description": "This module deploys an Azure Automation Account Variable.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the variable." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the variable. For security best practices, this value is always passed as a secure string as it could contain an encrypted value when the \"isEncrypted\" property is set to true." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the variable." + } + }, + "isEncrypted": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If the variable should be encrypted. For security reasons encryption of variables should be enabled." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/variables", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "isEncrypted": "[parameters('isEncrypted')]", + "value": "[parameters('value')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed variable." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed variable." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/variables', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed variable." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_linkedService": { + "condition": "[not(empty(parameters('linkedWorkspaceResourceId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-LinkedService', uniqueString(deployment().name, parameters('location')))]", + "subscriptionId": "[if(not(empty(parameters('linkedWorkspaceResourceId'))), split(if(not(empty(parameters('linkedWorkspaceResourceId'))), parameters('linkedWorkspaceResourceId'), '//'), '/')[2], subscription().subscriptionId)]", + "resourceGroup": "[if(not(empty(parameters('linkedWorkspaceResourceId'))), split(if(not(empty(parameters('linkedWorkspaceResourceId'))), parameters('linkedWorkspaceResourceId'), '////'), '/')[4], resourceGroup().name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "automation" + }, + "logAnalyticsWorkspaceName": { + "value": "[last(split(parameters('linkedWorkspaceResourceId'), '/'))]" + }, + "resourceId": { + "value": "[resourceId('Microsoft.Automation/automationAccounts', parameters('name'))]" + }, + "tags": { + "value": "[parameters('tags')]" + } + }, + "template": { + "$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.23.1.45101", + "templateHash": "14308828297239499350" + }, + "name": "Log Analytics Workspace Linked Services", + "description": "This module deploys a Log Analytics Workspace Linked Service.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the link." + } + }, + "resourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Required. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access." + } + }, + "writeAccessResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2022-10-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedService": { + "type": "Microsoft.OperationalInsights/workspaces/linkedServices", + "apiVersion": "2020-08-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resourceId": "[parameters('resourceId')]", + "writeAccessResourceId": "[if(empty(parameters('writeAccessResourceId')), null(), parameters('writeAccessResourceId'))]" + }, + "dependsOn": [ + "workspace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed linked service." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed linked service." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/linkedServices', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the linked service is deployed." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + }, + "automationAccount_solutions": { + "copy": { + "name": "automationAccount_solutions", + "count": "[length(parameters('gallerySolutions'))]" + }, + "condition": "[not(empty(parameters('linkedWorkspaceResourceId')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-Solution-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "subscriptionId": "[if(not(empty(parameters('linkedWorkspaceResourceId'))), split(if(not(empty(parameters('linkedWorkspaceResourceId'))), parameters('linkedWorkspaceResourceId'), '//'), '/')[2], subscription().subscriptionId)]", + "resourceGroup": "[if(not(empty(parameters('linkedWorkspaceResourceId'))), split(if(not(empty(parameters('linkedWorkspaceResourceId'))), parameters('linkedWorkspaceResourceId'), '////'), '/')[4], resourceGroup().name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('gallerySolutions')[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "logAnalyticsWorkspaceName": { + "value": "[last(split(parameters('linkedWorkspaceResourceId'), '/'))]" + }, + "product": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'product'), createObject('value', parameters('gallerySolutions')[copyIndex()].product), createObject('value', 'OMSGallery'))]", + "publisher": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'publisher'), createObject('value', parameters('gallerySolutions')[copyIndex()].publisher), createObject('value', 'Microsoft'))]", + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "18444780972506374592" + }, + "name": "Operations Management Solutions", + "description": "This module deploys an Operations Management Solution.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + } + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Log Analytics workspace where the solution will be deployed/enabled." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "product": { + "type": "string", + "defaultValue": "OMSGallery", + "metadata": { + "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." + } + }, + "publisher": { + "type": "string", + "defaultValue": "Microsoft", + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", + "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" + }, + "resources": [ + { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.1.0', '.', '-'), 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" + } + } + } + } + }, + { + "type": "Microsoft.OperationsManagement/solutions", + "apiVersion": "2015-11-01-preview", + "name": "[variables('solutionName')]", + "location": "[parameters('location')]", + "properties": { + "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" + }, + "plan": { + "name": "[variables('solutionName')]", + "promotionCode": "", + "product": "[variables('solutionProduct')]", + "publisher": "[parameters('publisher')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed solution." + }, + "value": "[variables('solutionName')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed solution." + }, + "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the solution is deployed." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + } + } + } + }, + "dependsOn": [ + "automationAccount_linkedService" + ] + }, + "automationAccount_softwareUpdateConfigurations": { + "copy": { + "name": "automationAccount_softwareUpdateConfigurations", + "count": "[length(parameters('softwareUpdateConfigurations'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-AutoAccount-SwUpdateConfig-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].name]" + }, + "automationAccountName": { + "value": "[parameters('name')]" + }, + "frequency": { + "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].frequency]" + }, + "operatingSystem": { + "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].operatingSystem]" + }, + "rebootSetting": { + "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].rebootSetting]" + }, + "azureVirtualMachines": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'azureVirtualMachines'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].azureVirtualMachines), createObject('value', createArray()))]", + "excludeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'excludeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].excludeUpdates), createObject('value', createArray()))]", + "expiryTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTime), createObject('value', ''))]", + "expiryTimeOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTimeOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTimeOffsetMinute), createObject('value', 0))]", + "includeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'includeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].includeUpdates), createObject('value', createArray()))]", + "interval": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'interval'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].interval), createObject('value', 1))]", + "isEnabled": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'isEnabled'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].isEnabled), createObject('value', true()))]", + "maintenanceWindow": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'maintenanceWindow'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].maintenanceWindow), createObject('value', 'PT2H'))]", + "monthDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthDays), createObject('value', createArray()))]", + "monthlyOccurrences": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthlyOccurrences'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthlyOccurrences), createObject('value', createArray()))]", + "nextRun": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRun'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRun), createObject('value', ''))]", + "nextRunOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRunOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRunOffsetMinutes), createObject('value', 0))]", + "nonAzureComputerNames": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureComputerNames'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureComputerNames), createObject('value', createArray()))]", + "nonAzureQueries": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureQueries'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureQueries), createObject('value', createArray()))]", + "postTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskParameters), createObject('value', createObject()))]", + "postTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskSource), createObject('value', ''))]", + "preTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskParameters), createObject('value', createObject()))]", + "preTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskSource), createObject('value', ''))]", + "scheduleDescription": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scheduleDescription'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scheduleDescription), createObject('value', ''))]", + "scopeByLocations": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByLocations'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByLocations), createObject('value', createArray()))]", + "scopeByResources": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByResources'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByResources), createObject('value', createArray(subscription().id)))]", + "scopeByTags": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTags'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTags), createObject('value', createObject()))]", + "scopeByTagsOperation": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTagsOperation'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTagsOperation), createObject('value', 'All'))]", + "startTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'startTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].startTime), createObject('value', ''))]", + "timeZone": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'timeZone'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].timeZone), createObject('value', 'UTC'))]", + "updateClassifications": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'updateClassifications'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].updateClassifications), createObject('value', createArray('Critical', 'Security')))]", + "weekDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'weekDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].weekDays), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "14279801215397466126" + }, + "name": "Automation Account Software Update Configurations", + "description": "This module deploys an Azure Automation Account Software Update Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Deployment schedule." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "operatingSystem": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The operating system to be configured by the deployment schedule." + } + }, + "rebootSetting": { + "type": "string", + "allowedValues": [ + "IfRequired", + "Never", + "RebootOnly", + "Always" + ], + "metadata": { + "description": "Required. Reboot setting for the deployment schedule." + } + }, + "frequency": { + "type": "string", + "allowedValues": [ + "OneTime", + "Hour", + "Day", + "Week", + "Month" + ], + "metadata": { + "description": "Required. The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided." + } + }, + "maintenanceWindow": { + "type": "string", + "defaultValue": "PT2H", + "metadata": { + "description": "Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601." + } + }, + "updateClassifications": { + "type": "array", + "defaultValue": [ + "Critical", + "Security" + ], + "allowedValues": [ + "Critical", + "Security", + "UpdateRollup", + "FeaturePack", + "ServicePack", + "Definition", + "Tools", + "Updates", + "Other" + ], + "metadata": { + "description": "Optional. Update classification included in the deployment schedule." + } + }, + "excludeUpdates": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. KB numbers or Linux packages excluded in the deployment schedule." + } + }, + "includeUpdates": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. KB numbers or Linux packages included in the deployment schedule." + } + }, + "scopeByResources": { + "type": "array", + "defaultValue": [ + "[subscription().id]" + ], + "metadata": { + "description": "Optional. Specify the resources to scope the deployment schedule to." + } + }, + "scopeByTags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specify tags to which to scope the deployment schedule to." + } + }, + "scopeByTagsOperation": { + "type": "string", + "defaultValue": "All", + "allowedValues": [ + "All", + "Any" + ], + "metadata": { + "description": "Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B)." + } + }, + "scopeByLocations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specify locations to which to scope the deployment schedule to." + } + }, + "preTaskParameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Parameters provided to the task running before the deployment schedule." + } + }, + "preTaskSource": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source of the task running before the deployment schedule." + } + }, + "postTaskParameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Parameters provided to the task running after the deployment schedule." + } + }, + "postTaskSource": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source of the task running after the deployment schedule." + } + }, + "interval": { + "type": "int", + "defaultValue": 1, + "maxValue": 100, + "metadata": { + "description": "Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc." + } + }, + "isEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enables the deployment schedule." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "UTC", + "metadata": { + "description": "Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID." + } + }, + "nonAzureQueries": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule." + } + }, + "azureVirtualMachines": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule." + } + }, + "nonAzureComputerNames": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of names of non-azure machines in scope for the deployment schedule." + } + }, + "weekDays": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" + ], + "metadata": { + "description": "Optional. Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule." + } + }, + "monthDays": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "metadata": { + "description": "Optional. Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule." + } + }, + "monthlyOccurrences": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule." + } + }, + "startTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00." + } + }, + "expiryTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00." + } + }, + "expiryTimeOffsetMinutes": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The expiry time's offset in minutes." + } + }, + "nextRun": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00." + } + }, + "nextRunOffsetMinutes": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The next run's offset in minutes." + } + }, + "scheduleDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The schedules description." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule." + } + } + }, + "variables": { + "updateClassificationsVar": "[replace(replace(replace(replace(string(parameters('updateClassifications')), ',', ', '), '[', ''), ']', ''), '\"', '')]" + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/softwareUpdateConfigurations", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "updateConfiguration": { + "operatingSystem": "[parameters('operatingSystem')]", + "duration": "[parameters('maintenanceWindow')]", + "linux": "[if(equals(parameters('operatingSystem'), 'Linux'), createObject('excludedPackageNameMasks', parameters('excludeUpdates'), 'includedPackageNameMasks', parameters('includeUpdates'), 'includedPackageClassifications', variables('updateClassificationsVar'), 'rebootSetting', parameters('rebootSetting')), null())]", + "windows": "[if(equals(parameters('operatingSystem'), 'Windows'), createObject('excludedKbNumbers', parameters('excludeUpdates'), 'includedKbNumbers', parameters('includeUpdates'), 'includedUpdateClassifications', variables('updateClassificationsVar'), 'rebootSetting', parameters('rebootSetting')), null())]", + "targets": { + "azureQueries": [ + { + "scope": "[parameters('scopeByResources')]", + "tagSettings": { + "tags": "[parameters('scopeByTags')]", + "filterOperator": "[parameters('scopeByTagsOperation')]" + }, + "locations": "[parameters('scopeByLocations')]" + } + ], + "nonAzureQueries": "[parameters('nonAzureQueries')]" + }, + "azureVirtualMachines": "[parameters('azureVirtualMachines')]", + "nonAzureComputerNames": "[parameters('nonAzureComputerNames')]" + }, + "tasks": { + "preTask": { + "parameters": "[if(empty(parameters('preTaskParameters')), null(), parameters('preTaskParameters'))]", + "source": "[if(empty(parameters('preTaskSource')), null(), parameters('preTaskSource'))]" + }, + "postTask": { + "parameters": "[if(empty(parameters('postTaskParameters')), null(), parameters('postTaskParameters'))]", + "source": "[if(empty(parameters('postTaskSource')), null(), parameters('postTaskSource'))]" + } + }, + "scheduleInfo": { + "interval": "[parameters('interval')]", + "frequency": "[parameters('frequency')]", + "isEnabled": "[parameters('isEnabled')]", + "timeZone": "[parameters('timeZone')]", + "advancedSchedule": { + "weekDays": "[if(empty(parameters('weekDays')), null(), parameters('weekDays'))]", + "monthDays": "[if(empty(parameters('monthDays')), null(), parameters('monthDays'))]", + "monthlyOccurrences": "[if(empty(parameters('monthlyOccurrences')), null(), parameters('monthlyOccurrences'))]" + }, + "startTime": "[if(empty(parameters('startTime')), dateTimeAdd(parameters('baseTime'), 'PT10M'), parameters('startTime'))]", + "expiryTime": "[parameters('expiryTime')]", + "expiryTimeOffsetMinutes": "[parameters('expiryTimeOffsetMinutes')]", + "nextRun": "[parameters('nextRun')]", + "nextRunOffsetMinutes": "[parameters('nextRunOffsetMinutes')]", + "description": "[parameters('scheduleDescription')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed softwareUpdateConfiguration." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed softwareUpdateConfiguration." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/softwareUpdateConfigurations', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed softwareUpdateConfiguration." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "automationAccount", + "automationAccount_solutions" + ] + }, + "automationAccount_privateEndpoints": { + "copy": { + "name": "automationAccount_privateEndpoints", + "count": "[length(coalesce(parameters('privateEndpoints'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-automationAccount-PrivateEndpoint-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "privateLinkServiceConnections": { + "value": [ + { + "name": "[parameters('name')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Automation/automationAccounts', parameters('name'))]", + "groupIds": [ + "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), 'automationaccount')]" + ] + } + } + ] + }, + "name": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'name'), format('pep-{0}-{1}-{2}', last(split(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), '/')), coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'service'), coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].service), copyIndex()))]" + }, + "subnetResourceId": { + "value": "[coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId]" + }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" + }, + "lock": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" + }, + "privateDnsZoneGroupName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" + }, + "privateDnsZoneResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" + }, + "tags": { + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'tags'), parameters('tags'))]" + }, + "manualPrivateLinkServiceConnections": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'manualPrivateLinkServiceConnections')]" + }, + "customDnsConfigs": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customDnsConfigs')]" + }, + "ipConfigurations": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'ipConfigurations')]" + }, + "applicationSecurityGroupResourceIds": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'applicationSecurityGroupResourceIds')]" + }, + "customNetworkInterfaceName": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'customNetworkInterfaceName')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + } + }, + "template": { + "$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.23.1.45101", + "templateHash": "2821141217598568122" + }, + "name": "Private Endpoints", + "description": "This module deploys a Private Endpoint.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "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 + }, + "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 + }, + "ipConfigurationsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private ip address obtained from the private endpoint's subnet." + } + } + }, + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + } + }, + "nullable": true + }, + "manualPrivateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "privateLinkServiceConnectionsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the private link service connection." + } + }, + "properties": { + "type": "object", + "properties": { + "groupIds": { + "type": "array", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateLinkServiceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of private link service." + } + }, + "requestMessage": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with this connection request. Restricted to 140 chars." + } + } + }, + "metadata": { + "description": "Required. Properties of private link service connection." + } + } + } + }, + "nullable": true + }, + "customDnsConfigType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "metadata": { + "description": "Required. Fqdn that resolves to private endpoint ip address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. A list of private ip addresses of the private endpoint." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the private endpoint resource to create." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "ipConfigurations": { + "$ref": "#/definitions/ipConfigurationsType", + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "privateDnsZoneGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." + } + }, + "privateDnsZoneResourceIds": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all Resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "customDnsConfigs": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "manualPrivateLinkServiceConnections": { + "$ref": "#/definitions/manualPrivateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource. Used when the network admin does not have access to approve connections to the remote resource." + } + }, + "privateLinkServiceConnections": { + "$ref": "#/definitions/privateLinkServiceConnectionsType", + "metadata": { + "description": "Optional. A grouping of information about the connection to the remote resource." + } + }, + "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')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.3.1', '.', '-'), 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" + } + } + } + } + }, + "privateEndpoint": { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "applicationSecurityGroups", + "count": "[length(coalesce(parameters('applicationSecurityGroupResourceIds'), createArray()))]", + "input": { + "id": "[coalesce(parameters('applicationSecurityGroupResourceIds'), createArray())[copyIndex('applicationSecurityGroups')]]" + } + } + ], + "customDnsConfigs": "[coalesce(parameters('customDnsConfigs'), createArray())]", + "customNetworkInterfaceName": "[coalesce(parameters('customNetworkInterfaceName'), '')]", + "ipConfigurations": "[coalesce(parameters('ipConfigurations'), createArray())]", + "manualPrivateLinkServiceConnections": "[coalesce(parameters('manualPrivateLinkServiceConnections'), createArray())]", + "privateLinkServiceConnections": "[coalesce(parameters('privateLinkServiceConnections'), createArray())]", + "subnet": { + "id": "[parameters('subnetResourceId')]" + } + } + }, + "privateEndpoint_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.Network/privateEndpoints/{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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_roleAssignments": { + "copy": { + "name": "privateEndpoint_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', 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": [ + "privateEndpoint" + ] + }, + "privateEndpoint_privateDnsZoneGroup": { + "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" + }, + "privateDNSResourceIds": { + "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + }, + "privateEndpointName": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "18168683629401652671" + }, + "name": "Private Endpoint Private DNS Zone Groups", + "description": "This module deploys a Private Endpoint Private DNS Zone Group.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "privateEndpointName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." + } + }, + "privateDNSResourceIds": { + "type": "array", + "minLength": 1, + "maxLength": 5, + "metadata": { + "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + } + }, + "name": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Optional. The name of the private DNS zone group." + } + } + }, + "variables": { + "copy": [ + { + "name": "privateDnsZoneConfigs", + "count": "[length(parameters('privateDNSResourceIds'))]", + "input": { + "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "properties": { + "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + } + } + } + ] + }, + "resources": [ + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2023-04-01", + "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", + "properties": { + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint DNS zone group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint DNS zone group." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints/privateDnsZoneGroups', parameters('privateEndpointName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint DNS zone group was deployed into." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "privateEndpoint" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the private endpoint was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the private endpoint." + }, + "value": "[resourceId('Microsoft.Network/privateEndpoints', parameters('name'))]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the private endpoint." + }, + "value": "[parameters('name')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "automationAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed automation account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed automation account." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed automation account." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('automationAccount', '2022-08-08', 'full').identity, 'principalId')), reference('automationAccount', '2022-08-08', 'full').identity.principalId, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('automationAccount', '2022-08-08', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/module/README.md b/avm/res/automation/automation-account/module/README.md new file mode 100644 index 00000000000..cdbed8c772a --- /dev/null +++ b/avm/res/automation/automation-account/module/README.md @@ -0,0 +1,91 @@ +# Automation Account Modules `[Microsoft.Automation/automationAccounts/modules]` + +This module deploys an Azure Automation Account Module. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/modules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/modules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Automation Account module. | +| [`uri`](#parameter-uri) | string | Module package URI, e.g. https://www.powershellgallery.com/api/v2/package. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`tags`](#parameter-tags) | object | Tags of the Automation Account resource. | +| [`version`](#parameter-version) | string | Module version or specify latest to get the latest version. | + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `location` + +Location for all resources. +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `name` + +Name of the Automation Account module. +- Required: Yes +- Type: string + +### Parameter: `tags` + +Tags of the Automation Account resource. +- Required: No +- Type: object + +### Parameter: `uri` + +Module package URI, e.g. https://www.powershellgallery.com/api/v2/package. +- Required: Yes +- Type: string + +### Parameter: `version` + +Module version or specify latest to get the latest version. +- Required: No +- Type: string +- Default: `'latest'` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed module. | +| `resourceGroupName` | string | The resource group of the deployed module. | +| `resourceId` | string | The resource ID of the deployed module. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/module/main.bicep b/avm/res/automation/automation-account/module/main.bicep new file mode 100644 index 00000000000..f43f11d9762 --- /dev/null +++ b/avm/res/automation/automation-account/module/main.bicep @@ -0,0 +1,50 @@ +metadata name = 'Automation Account Modules' +metadata description = 'This module deploys an Azure Automation Account Module.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the Automation Account module.') +param name string + +@description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@description('Required. Module package URI, e.g. https://www.powershellgallery.com/api/v2/package.') +param uri string + +@description('Optional. Module version or specify latest to get the latest version.') +param version string = 'latest' + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Tags of the Automation Account resource.') +param tags object? + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource module 'Microsoft.Automation/automationAccounts/modules@2022-08-08' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + contentLink: { + uri: version != 'latest' ? '${uri}/${name}/${version}' : '${uri}/${name}' + version: version != 'latest' ? version : null + } + } +} + +@description('The name of the deployed module.') +output name string = module.name + +@description('The resource ID of the deployed module.') +output resourceId string = module.id + +@description('The resource group of the deployed module.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = module.location diff --git a/avm/res/automation/automation-account/module/main.json b/avm/res/automation/automation-account/module/main.json new file mode 100644 index 00000000000..089ba3a8e51 --- /dev/null +++ b/avm/res/automation/automation-account/module/main.json @@ -0,0 +1,110 @@ +{ + "$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.23.1.45101", + "templateHash": "17367962996789020433" + }, + "name": "Automation Account Modules", + "description": "This module deploys an Azure Automation Account Module.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account module." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "uri": { + "type": "string", + "metadata": { + "description": "Required. Module package URI, e.g. https://www.powershellgallery.com/api/v2/package." + } + }, + "version": { + "type": "string", + "defaultValue": "latest", + "metadata": { + "description": "Optional. Module version or specify latest to get the latest version." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Automation Account resource." + } + } + }, + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "module": { + "type": "Microsoft.Automation/automationAccounts/modules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "contentLink": { + "uri": "[if(not(equals(parameters('version'), 'latest')), format('{0}/{1}/{2}', parameters('uri'), parameters('name'), parameters('version')), format('{0}/{1}', parameters('uri'), parameters('name')))]", + "version": "[if(not(equals(parameters('version'), 'latest')), parameters('version'), null())]" + } + }, + "dependsOn": [ + "automationAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed module." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed module." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/modules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed module." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('module', '2022-08-08', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/runbook/README.md b/avm/res/automation/automation-account/runbook/README.md new file mode 100644 index 00000000000..abd7ed483f9 --- /dev/null +++ b/avm/res/automation/automation-account/runbook/README.md @@ -0,0 +1,145 @@ +# Automation Account Runbooks `[Microsoft.Automation/automationAccounts/runbooks]` + +This module deploys an Azure Automation Account Runbook. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/runbooks` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/runbooks) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Automation Account runbook. | +| [`type`](#parameter-type) | string | The type of the runbook. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | The description of the runbook. | +| [`location`](#parameter-location) | string | Location for all resources. | +| [`sasTokenValidityLength`](#parameter-sastokenvaliditylength) | string | SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| [`scriptStorageAccountResourceId`](#parameter-scriptstorageaccountresourceid) | string | Resource Id of the runbook storage account. | +| [`tags`](#parameter-tags) | object | Tags of the Automation Account resource. | +| [`uri`](#parameter-uri) | string | The uri of the runbook content. | +| [`version`](#parameter-version) | string | The version of the runbook content. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`baseTime`](#parameter-basetime) | string | Time used as a basis for e.g. the schedule start date. | + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `baseTime` + +Time used as a basis for e.g. the schedule start date. +- Required: No +- Type: string +- Default: `[utcNow('u')]` + +### Parameter: `description` + +The description of the runbook. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `location` + +Location for all resources. +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `name` + +Name of the Automation Account runbook. +- Required: Yes +- Type: string + +### Parameter: `sasTokenValidityLength` + +SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. +- Required: No +- Type: string +- Default: `'PT8H'` + +### Parameter: `scriptStorageAccountResourceId` + +Resource Id of the runbook storage account. +- Required: No +- Type: string + +### Parameter: `tags` + +Tags of the Automation Account resource. +- Required: No +- Type: object + +### Parameter: `type` + +The type of the runbook. +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Graph' + 'GraphPowerShell' + 'GraphPowerShellWorkflow' + 'PowerShell' + 'PowerShellWorkflow' + ] + ``` + +### Parameter: `uri` + +The uri of the runbook content. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `version` + +The version of the runbook content. +- Required: No +- Type: string +- Default: `''` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the deployed runbook. | +| `resourceGroupName` | string | The resource group of the deployed runbook. | +| `resourceId` | string | The resource ID of the deployed runbook. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/runbook/main.bicep b/avm/res/automation/automation-account/runbook/main.bicep new file mode 100644 index 00000000000..ec1cd1ab8e1 --- /dev/null +++ b/avm/res/automation/automation-account/runbook/main.bicep @@ -0,0 +1,90 @@ +metadata name = 'Automation Account Runbooks' +metadata description = 'This module deploys an Azure Automation Account Runbook.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Required. Name of the Automation Account runbook.') +param name string + +@sys.description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@allowed([ + 'Graph' + 'GraphPowerShell' + 'GraphPowerShellWorkflow' + 'PowerShell' + 'PowerShellWorkflow' +]) +@sys.description('Required. The type of the runbook.') +param type string + +@sys.description('Optional. The description of the runbook.') +param description string = '' + +@sys.description('Optional. The uri of the runbook content.') +param uri string = '' + +@sys.description('Optional. The version of the runbook content.') +param version string = '' + +@sys.description('Optional. Resource Id of the runbook storage account.') +param scriptStorageAccountResourceId string? + +@sys.description('Generated. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +@sys.description('Optional. SAS token validity length. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@sys.description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@sys.description('Optional. Tags of the Automation Account resource.') +param tags object? + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' existing = if (!empty(scriptStorageAccountResourceId)) { + name: last(split((scriptStorageAccountResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup(split((scriptStorageAccountResourceId ?? '//'), '/')[2], split((scriptStorageAccountResourceId ?? '////'), '/')[4]) +} + +var publishContentLink = empty(uri) ? null : { + uri: !empty(uri) ? (empty(scriptStorageAccountResourceId) ? uri : '${uri}?${storageAccount.listAccountSas('2021-04-01', accountSasProperties).accountSasToken}') : null + version: !empty(version) ? version : null +} + +resource runbook 'Microsoft.Automation/automationAccounts/runbooks@2022-08-08' = { + name: name + parent: automationAccount + location: location + tags: tags + properties: { + runbookType: type + description: description + publishContentLink: !empty(uri) ? publishContentLink : null + } +} + +@sys.description('The name of the deployed runbook.') +output name string = runbook.name + +@sys.description('The resource ID of the deployed runbook.') +output resourceId string = runbook.id + +@sys.description('The resource group of the deployed runbook.') +output resourceGroupName string = resourceGroup().name + +@sys.description('The location the resource was deployed into.') +output location string = runbook.location diff --git a/avm/res/automation/automation-account/runbook/main.json b/avm/res/automation/automation-account/runbook/main.json new file mode 100644 index 00000000000..91edee1e92d --- /dev/null +++ b/avm/res/automation/automation-account/runbook/main.json @@ -0,0 +1,170 @@ +{ + "$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.23.1.45101", + "templateHash": "1364137745351676946" + }, + "name": "Automation Account Runbooks", + "description": "This module deploys an Azure Automation Account Runbook.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account runbook." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "Graph", + "GraphPowerShell", + "GraphPowerShellWorkflow", + "PowerShell", + "PowerShellWorkflow" + ], + "metadata": { + "description": "Required. The type of the runbook." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the runbook." + } + }, + "uri": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The uri of the runbook content." + } + }, + "version": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The version of the runbook content." + } + }, + "scriptStorageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource Id of the runbook storage account." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Time used as a basis for e.g. the schedule start date." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "description": "Optional. SAS token validity length. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the Automation Account resource." + } + } + }, + "variables": { + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + } + }, + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "storageAccount": { + "condition": "[not(empty(parameters('scriptStorageAccountResourceId')))]", + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2022-09-01", + "subscriptionId": "[split(coalesce(parameters('scriptStorageAccountResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(parameters('scriptStorageAccountResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(parameters('scriptStorageAccountResourceId'), 'dummyVault'), '/'))]" + }, + "runbook": { + "type": "Microsoft.Automation/automationAccounts/runbooks", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "runbookType": "[parameters('type')]", + "description": "[parameters('description')]", + "publishContentLink": "[if(not(empty(parameters('uri'))), if(empty(parameters('uri')), null(), createObject('uri', if(not(empty(parameters('uri'))), if(empty(parameters('scriptStorageAccountResourceId')), parameters('uri'), format('{0}?{1}', parameters('uri'), listAccountSas(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(parameters('scriptStorageAccountResourceId'), '//'), '/')[2], split(coalesce(parameters('scriptStorageAccountResourceId'), '////'), '/')[4]), 'Microsoft.Storage/storageAccounts', last(split(coalesce(parameters('scriptStorageAccountResourceId'), 'dummyVault'), '/'))), '2021-04-01', variables('accountSasProperties')).accountSasToken)), null()), 'version', if(not(empty(parameters('version'))), parameters('version'), null()))), null())]" + }, + "dependsOn": [ + "automationAccount", + "storageAccount" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed runbook." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed runbook." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/runbooks', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed runbook." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('runbook', '2022-08-08', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/schedule/README.md b/avm/res/automation/automation-account/schedule/README.md new file mode 100644 index 00000000000..560e7b214c1 --- /dev/null +++ b/avm/res/automation/automation-account/schedule/README.md @@ -0,0 +1,140 @@ +# Automation Account Schedules `[Microsoft.Automation/automationAccounts/schedules]` + +This module deploys an Azure Automation Account Schedule. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/schedules` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/schedules) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | Name of the Automation Account schedule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`advancedSchedule`](#parameter-advancedschedule) | object | The properties of the create Advanced Schedule. | +| [`description`](#parameter-description) | string | The description of the schedule. | +| [`expiryTime`](#parameter-expirytime) | string | The end time of the schedule. | +| [`frequency`](#parameter-frequency) | string | The frequency of the schedule. | +| [`interval`](#parameter-interval) | int | Anything. | +| [`startTime`](#parameter-starttime) | string | The start time of the schedule. | +| [`timeZone`](#parameter-timezone) | string | The time zone of the schedule. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`baseTime`](#parameter-basetime) | string | Time used as a basis for e.g. the schedule start date. | + +### Parameter: `advancedSchedule` + +The properties of the create Advanced Schedule. +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `baseTime` + +Time used as a basis for e.g. the schedule start date. +- Required: No +- Type: string +- Default: `[utcNow('u')]` + +### Parameter: `description` + +The description of the schedule. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `expiryTime` + +The end time of the schedule. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `frequency` + +The frequency of the schedule. +- Required: No +- Type: string +- Default: `'OneTime'` +- Allowed: + ```Bicep + [ + 'Day' + 'Hour' + 'Minute' + 'Month' + 'OneTime' + 'Week' + ] + ``` + +### Parameter: `interval` + +Anything. +- Required: No +- Type: int +- Default: `0` + +### Parameter: `name` + +Name of the Automation Account schedule. +- Required: Yes +- Type: string + +### Parameter: `startTime` + +The start time of the schedule. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `timeZone` + +The time zone of the schedule. +- Required: No +- Type: string +- Default: `''` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed schedule. | +| `resourceGroupName` | string | The resource group of the deployed schedule. | +| `resourceId` | string | The resource ID of the deployed schedule. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/schedule/main.bicep b/avm/res/automation/automation-account/schedule/main.bicep new file mode 100644 index 00000000000..3b591b0ca3a --- /dev/null +++ b/avm/res/automation/automation-account/schedule/main.bicep @@ -0,0 +1,73 @@ +metadata name = 'Automation Account Schedules' +metadata description = 'This module deploys an Azure Automation Account Schedule.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Required. Name of the Automation Account schedule.') +param name string + +@sys.description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@sys.description('Optional. The properties of the create Advanced Schedule.') +@metadata({ + monthDays: 'Days of the month that the job should execute on. Must be between 1 and 31.' + monthlyOccurrences: 'Occurrences of days within a month.' + weekDays: 'Days of the week that the job should execute on.' +}) +param advancedSchedule object = {} + +@sys.description('Optional. The description of the schedule.') +param description string = '' + +@sys.description('Optional. The end time of the schedule.') +param expiryTime string = '' + +@allowed([ + 'Day' + 'Hour' + 'Minute' + 'Month' + 'OneTime' + 'Week' +]) +@sys.description('Optional. The frequency of the schedule.') +param frequency string = 'OneTime' + +@sys.description('Optional. Anything.') +param interval int = 0 + +@sys.description('Optional. The start time of the schedule.') +param startTime string = '' + +@sys.description('Optional. The time zone of the schedule.') +param timeZone string = '' + +@sys.description('Generated. Time used as a basis for e.g. the schedule start date.') +param baseTime string = utcNow('u') + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource schedule 'Microsoft.Automation/automationAccounts/schedules@2022-08-08' = { + name: name + parent: automationAccount + properties: { + advancedSchedule: !empty(advancedSchedule) ? advancedSchedule : null + description: !empty(description) ? description : null + expiryTime: !empty(expiryTime) ? expiryTime : null + frequency: !empty(frequency) ? frequency : 'OneTime' + interval: (interval != 0) ? interval : null + startTime: !empty(startTime) ? startTime : dateTimeAdd(baseTime, 'PT10M') + timeZone: !empty(timeZone) ? timeZone : null + } +} + +@sys.description('The name of the deployed schedule.') +output name string = schedule.name + +@sys.description('The resource ID of the deployed schedule.') +output resourceId string = schedule.id + +@sys.description('The resource group of the deployed schedule.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/automation/automation-account/schedule/main.json b/avm/res/automation/automation-account/schedule/main.json new file mode 100644 index 00000000000..e799523e702 --- /dev/null +++ b/avm/res/automation/automation-account/schedule/main.json @@ -0,0 +1,134 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "2599258461220838817" + }, + "name": "Automation Account Schedules", + "description": "This module deploys an Azure Automation Account Schedule.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account schedule." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "advancedSchedule": { + "type": "object", + "defaultValue": {}, + "metadata": { + "monthDays": "Days of the month that the job should execute on. Must be between 1 and 31.", + "monthlyOccurrences": "Occurrences of days within a month.", + "weekDays": "Days of the week that the job should execute on.", + "description": "Optional. The properties of the create Advanced Schedule." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the schedule." + } + }, + "expiryTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end time of the schedule." + } + }, + "frequency": { + "type": "string", + "defaultValue": "OneTime", + "allowedValues": [ + "Day", + "Hour", + "Minute", + "Month", + "OneTime", + "Week" + ], + "metadata": { + "description": "Optional. The frequency of the schedule." + } + }, + "interval": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. Anything." + } + }, + "startTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The start time of the schedule." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The time zone of the schedule." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Time used as a basis for e.g. the schedule start date." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/schedules", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "advancedSchedule": "[if(not(empty(parameters('advancedSchedule'))), parameters('advancedSchedule'), null())]", + "description": "[if(not(empty(parameters('description'))), parameters('description'), null())]", + "expiryTime": "[if(not(empty(parameters('expiryTime'))), parameters('expiryTime'), null())]", + "frequency": "[if(not(empty(parameters('frequency'))), parameters('frequency'), 'OneTime')]", + "interval": "[if(not(equals(parameters('interval'), 0)), parameters('interval'), null())]", + "startTime": "[if(not(empty(parameters('startTime'))), parameters('startTime'), dateTimeAdd(parameters('baseTime'), 'PT10M'))]", + "timeZone": "[if(not(empty(parameters('timeZone'))), parameters('timeZone'), null())]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed schedule." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed schedule." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/schedules', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed schedule." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/software-update-configuration/README.md b/avm/res/automation/automation-account/software-update-configuration/README.md new file mode 100644 index 00000000000..e1c550e23a7 --- /dev/null +++ b/avm/res/automation/automation-account/software-update-configuration/README.md @@ -0,0 +1,416 @@ +# Automation Account Software Update Configurations `[Microsoft.Automation/automationAccounts/softwareUpdateConfigurations]` + +This module deploys an Azure Automation Account Software Update Configuration. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/softwareUpdateConfigurations` | [2019-06-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2019-06-01/automationAccounts/softwareUpdateConfigurations) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`frequency`](#parameter-frequency) | string | The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided. | +| [`name`](#parameter-name) | string | The name of the Deployment schedule. | +| [`operatingSystem`](#parameter-operatingsystem) | string | The operating system to be configured by the deployment schedule. | +| [`rebootSetting`](#parameter-rebootsetting) | string | Reboot setting for the deployment schedule. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`azureVirtualMachines`](#parameter-azurevirtualmachines) | array | List of azure resource IDs for azure virtual machines in scope for the deployment schedule. | +| [`excludeUpdates`](#parameter-excludeupdates) | array | KB numbers or Linux packages excluded in the deployment schedule. | +| [`expiryTime`](#parameter-expirytime) | string | The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. | +| [`expiryTimeOffsetMinutes`](#parameter-expirytimeoffsetminutes) | int | The expiry time's offset in minutes. | +| [`includeUpdates`](#parameter-includeupdates) | array | KB numbers or Linux packages included in the deployment schedule. | +| [`interval`](#parameter-interval) | int | The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc. | +| [`isEnabled`](#parameter-isenabled) | bool | Enables the deployment schedule. | +| [`maintenanceWindow`](#parameter-maintenancewindow) | string | Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601. | +| [`monthDays`](#parameter-monthdays) | array | Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule. | +| [`monthlyOccurrences`](#parameter-monthlyoccurrences) | array | Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule. | +| [`nextRun`](#parameter-nextrun) | string | The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. | +| [`nextRunOffsetMinutes`](#parameter-nextrunoffsetminutes) | int | The next run's offset in minutes. | +| [`nonAzureComputerNames`](#parameter-nonazurecomputernames) | array | List of names of non-azure machines in scope for the deployment schedule. | +| [`nonAzureQueries`](#parameter-nonazurequeries) | array | Array of functions from a Log Analytics workspace, used to scope the deployment schedule. | +| [`postTaskParameters`](#parameter-posttaskparameters) | object | Parameters provided to the task running after the deployment schedule. | +| [`postTaskSource`](#parameter-posttasksource) | string | The source of the task running after the deployment schedule. | +| [`preTaskParameters`](#parameter-pretaskparameters) | object | Parameters provided to the task running before the deployment schedule. | +| [`preTaskSource`](#parameter-pretasksource) | string | The source of the task running before the deployment schedule. | +| [`scheduleDescription`](#parameter-scheduledescription) | string | The schedules description. | +| [`scopeByLocations`](#parameter-scopebylocations) | array | Specify locations to which to scope the deployment schedule to. | +| [`scopeByResources`](#parameter-scopebyresources) | array | Specify the resources to scope the deployment schedule to. | +| [`scopeByTags`](#parameter-scopebytags) | object | Specify tags to which to scope the deployment schedule to. | +| [`scopeByTagsOperation`](#parameter-scopebytagsoperation) | string | Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B). | +| [`startTime`](#parameter-starttime) | string | The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00. | +| [`timeZone`](#parameter-timezone) | string | Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID. | +| [`updateClassifications`](#parameter-updateclassifications) | array | Update classification included in the deployment schedule. | +| [`weekDays`](#parameter-weekdays) | array | Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`baseTime`](#parameter-basetime) | string | Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule. | + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `azureVirtualMachines` + +List of azure resource IDs for azure virtual machines in scope for the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `baseTime` + +Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule. +- Required: No +- Type: string +- Default: `[utcNow('u')]` + +### Parameter: `excludeUpdates` + +KB numbers or Linux packages excluded in the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `expiryTime` + +The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `expiryTimeOffsetMinutes` + +The expiry time's offset in minutes. +- Required: No +- Type: int +- Default: `0` + +### Parameter: `frequency` + +The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided. +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Day' + 'Hour' + 'Month' + 'OneTime' + 'Week' + ] + ``` + +### Parameter: `includeUpdates` + +KB numbers or Linux packages included in the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `interval` + +The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc. +- Required: No +- Type: int +- Default: `1` + +### Parameter: `isEnabled` + +Enables the deployment schedule. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `maintenanceWindow` + +Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601. +- Required: No +- Type: string +- Default: `'PT2H'` + +### Parameter: `monthDays` + +Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule. +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + ] + ``` + +### Parameter: `monthlyOccurrences` + +Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `name` + +The name of the Deployment schedule. +- Required: Yes +- Type: string + +### Parameter: `nextRun` + +The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `nextRunOffsetMinutes` + +The next run's offset in minutes. +- Required: No +- Type: int +- Default: `0` + +### Parameter: `nonAzureComputerNames` + +List of names of non-azure machines in scope for the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `nonAzureQueries` + +Array of functions from a Log Analytics workspace, used to scope the deployment schedule. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `operatingSystem` + +The operating system to be configured by the deployment schedule. +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `postTaskParameters` + +Parameters provided to the task running after the deployment schedule. +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `postTaskSource` + +The source of the task running after the deployment schedule. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `preTaskParameters` + +Parameters provided to the task running before the deployment schedule. +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `preTaskSource` + +The source of the task running before the deployment schedule. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `rebootSetting` + +Reboot setting for the deployment schedule. +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Always' + 'IfRequired' + 'Never' + 'RebootOnly' + ] + ``` + +### Parameter: `scheduleDescription` + +The schedules description. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `scopeByLocations` + +Specify locations to which to scope the deployment schedule to. +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `scopeByResources` + +Specify the resources to scope the deployment schedule to. +- Required: No +- Type: array +- Default: + ```Bicep + [ + '[subscription().id]' + ] + ``` + +### Parameter: `scopeByTags` + +Specify tags to which to scope the deployment schedule to. +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `scopeByTagsOperation` + +Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B). +- Required: No +- Type: string +- Default: `'All'` +- Allowed: + ```Bicep + [ + 'All' + 'Any' + ] + ``` + +### Parameter: `startTime` + +The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `timeZone` + +Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID. +- Required: No +- Type: string +- Default: `'UTC'` + +### Parameter: `updateClassifications` + +Update classification included in the deployment schedule. +- Required: No +- Type: array +- Default: + ```Bicep + [ + 'Critical' + 'Security' + ] + ``` +- Allowed: + ```Bicep + [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Other' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + ``` + +### Parameter: `weekDays` + +Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule. +- Required: No +- Type: array +- Default: `[]` +- Allowed: + ```Bicep + [ + 'Friday' + 'Monday' + 'Saturday' + 'Sunday' + 'Thursday' + 'Tuesday' + 'Wednesday' + ] + ``` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed softwareUpdateConfiguration. | +| `resourceGroupName` | string | The resource group of the deployed softwareUpdateConfiguration. | +| `resourceId` | string | The resource ID of the deployed softwareUpdateConfiguration. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/software-update-configuration/main.bicep b/avm/res/automation/automation-account/software-update-configuration/main.bicep new file mode 100644 index 00000000000..6354fa6b3eb --- /dev/null +++ b/avm/res/automation/automation-account/software-update-configuration/main.bicep @@ -0,0 +1,262 @@ +metadata name = 'Automation Account Software Update Configurations' +metadata description = 'This module deploys an Azure Automation Account Software Update Configuration.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. The name of the Deployment schedule.') +param name string + +@description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@description('Required. The operating system to be configured by the deployment schedule.') +@allowed([ + 'Windows' + 'Linux' +]) +param operatingSystem string + +@description('Required. Reboot setting for the deployment schedule.') +@allowed([ + 'IfRequired' + 'Never' + 'RebootOnly' + 'Always' +]) +param rebootSetting string + +@description('Required. The frequency of the deployment schedule. When using \'Hour\', \'Day\', \'Week\' or \'Month\', an interval needs to be provided.') +@allowed([ + 'OneTime' + 'Hour' + 'Day' + 'Week' + 'Month' +]) +param frequency string + +@description('Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601.') +param maintenanceWindow string = 'PT2H' + +@description('Optional. Update classification included in the deployment schedule.') +@allowed([ + 'Critical' + 'Security' + 'UpdateRollup' + 'FeaturePack' + 'ServicePack' + 'Definition' + 'Tools' + 'Updates' + 'Other' +]) +param updateClassifications array = [ + 'Critical' + 'Security' +] + +@description('Optional. KB numbers or Linux packages excluded in the deployment schedule.') +param excludeUpdates array = [] + +@description('Optional. KB numbers or Linux packages included in the deployment schedule.') +param includeUpdates array = [] + +@description('Optional. Specify the resources to scope the deployment schedule to.') +param scopeByResources array = [ + subscription().id +] + +@description('Optional. Specify tags to which to scope the deployment schedule to.') +param scopeByTags object = {} + +@description('Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B).') +@allowed([ + 'All' + 'Any' +]) +param scopeByTagsOperation string = 'All' + +@description('Optional. Specify locations to which to scope the deployment schedule to.') +param scopeByLocations array = [] + +@description('Optional. Parameters provided to the task running before the deployment schedule.') +param preTaskParameters object = {} + +@description('Optional. The source of the task running before the deployment schedule.') +param preTaskSource string = '' + +@description('Optional. Parameters provided to the task running after the deployment schedule.') +param postTaskParameters object = {} + +@description('Optional. The source of the task running after the deployment schedule.') +param postTaskSource string = '' + +@description('Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc.') +@maxValue(100) +param interval int = 1 + +@description('Optional. Enables the deployment schedule.') +param isEnabled bool = true + +@description('Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID.') +param timeZone string = 'UTC' + +@description('Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule.') +param nonAzureQueries array = [] + +@description('Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule.') +param azureVirtualMachines array = [] + +@description('Optional. List of names of non-azure machines in scope for the deployment schedule.') +param nonAzureComputerNames array = [] + +@description('Optional. Required when used with frequency \'Week\'. Specified the day of the week to run the deployment schedule.') +@allowed([ + 'Monday' + 'Tuesday' + 'Wednesday' + 'Thursday' + 'Friday' + 'Saturday' + 'Sunday' +]) +param weekDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the specific days of the month to run the deployment schedule.') +@allowed([ + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 +]) +param monthDays array = [] + +@description('Optional. Can be used with frequency \'Month\'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule.') +param monthlyOccurrences array = [] + +@description('Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00.') +param startTime string = '' + +@description('Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00.') +param expiryTime string = '' + +@description('Optional. The expiry time\'s offset in minutes.') +param expiryTimeOffsetMinutes int = 0 + +@description('Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00.') +param nextRun string = '' + +@description('Optional. The next run\'s offset in minutes.') +param nextRunOffsetMinutes int = 0 + +@description('Optional. The schedules description.') +param scheduleDescription string = '' + +@description('Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule.') +param baseTime string = utcNow('u') + +var updateClassificationsVar = replace(replace(replace(replace(string(updateClassifications), ',', ', '), '[', ''), ']', ''), '"', '') + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource softwareUpdateConfiguration 'Microsoft.Automation/automationAccounts/softwareUpdateConfigurations@2019-06-01' = { + name: name + parent: automationAccount + properties: { + updateConfiguration: { + operatingSystem: operatingSystem + duration: maintenanceWindow + linux: ((operatingSystem == 'Linux') ? { + excludedPackageNameMasks: excludeUpdates + includedPackageNameMasks: includeUpdates + includedPackageClassifications: updateClassificationsVar + rebootSetting: rebootSetting + } : null) + windows: ((operatingSystem == 'Windows') ? { + excludedKbNumbers: excludeUpdates + includedKbNumbers: includeUpdates + includedUpdateClassifications: updateClassificationsVar + rebootSetting: rebootSetting + } : null) + targets: { + azureQueries: [ + { + scope: scopeByResources + tagSettings: { + tags: scopeByTags + filterOperator: scopeByTagsOperation + } + locations: scopeByLocations + } + ] + nonAzureQueries: nonAzureQueries + } + azureVirtualMachines: azureVirtualMachines + nonAzureComputerNames: nonAzureComputerNames + } + tasks: { + preTask: { + parameters: (empty(preTaskParameters) ? null : preTaskParameters) + source: (empty(preTaskSource) ? null : preTaskSource) + } + postTask: { + parameters: (empty(postTaskParameters) ? null : postTaskParameters) + source: (empty(postTaskSource) ? null : postTaskSource) + } + } + scheduleInfo: { + interval: interval + frequency: frequency + isEnabled: isEnabled + timeZone: timeZone + advancedSchedule: { + weekDays: (empty(weekDays) ? null : weekDays) + monthDays: (empty(monthDays) ? null : monthDays) + monthlyOccurrences: (empty(monthlyOccurrences) ? null : monthlyOccurrences) + } + startTime: (empty(startTime) ? dateTimeAdd(baseTime, 'PT10M') : startTime) + expiryTime: expiryTime + expiryTimeOffsetMinutes: expiryTimeOffsetMinutes + nextRun: nextRun + nextRunOffsetMinutes: nextRunOffsetMinutes + description: scheduleDescription + } + } +} + +@description('The name of the deployed softwareUpdateConfiguration.') +output name string = softwareUpdateConfiguration.name + +@description('The resource ID of the deployed softwareUpdateConfiguration.') +output resourceId string = softwareUpdateConfiguration.id + +@description('The resource group of the deployed softwareUpdateConfiguration.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/automation/automation-account/software-update-configuration/main.json b/avm/res/automation/automation-account/software-update-configuration/main.json new file mode 100644 index 00000000000..fa5d1a9edc5 --- /dev/null +++ b/avm/res/automation/automation-account/software-update-configuration/main.json @@ -0,0 +1,405 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "14279801215397466126" + }, + "name": "Automation Account Software Update Configurations", + "description": "This module deploys an Azure Automation Account Software Update Configuration.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Deployment schedule." + } + }, + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "operatingSystem": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The operating system to be configured by the deployment schedule." + } + }, + "rebootSetting": { + "type": "string", + "allowedValues": [ + "IfRequired", + "Never", + "RebootOnly", + "Always" + ], + "metadata": { + "description": "Required. Reboot setting for the deployment schedule." + } + }, + "frequency": { + "type": "string", + "allowedValues": [ + "OneTime", + "Hour", + "Day", + "Week", + "Month" + ], + "metadata": { + "description": "Required. The frequency of the deployment schedule. When using 'Hour', 'Day', 'Week' or 'Month', an interval needs to be provided." + } + }, + "maintenanceWindow": { + "type": "string", + "defaultValue": "PT2H", + "metadata": { + "description": "Optional. Maximum time allowed for the deployment schedule to run. Duration needs to be specified using the format PT[n]H[n]M[n]S as per ISO8601." + } + }, + "updateClassifications": { + "type": "array", + "defaultValue": [ + "Critical", + "Security" + ], + "allowedValues": [ + "Critical", + "Security", + "UpdateRollup", + "FeaturePack", + "ServicePack", + "Definition", + "Tools", + "Updates", + "Other" + ], + "metadata": { + "description": "Optional. Update classification included in the deployment schedule." + } + }, + "excludeUpdates": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. KB numbers or Linux packages excluded in the deployment schedule." + } + }, + "includeUpdates": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. KB numbers or Linux packages included in the deployment schedule." + } + }, + "scopeByResources": { + "type": "array", + "defaultValue": [ + "[subscription().id]" + ], + "metadata": { + "description": "Optional. Specify the resources to scope the deployment schedule to." + } + }, + "scopeByTags": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Specify tags to which to scope the deployment schedule to." + } + }, + "scopeByTagsOperation": { + "type": "string", + "defaultValue": "All", + "allowedValues": [ + "All", + "Any" + ], + "metadata": { + "description": "Optional. Enables the scopeByTags to require All (Tag A and Tag B) or Any (Tag A or Tag B)." + } + }, + "scopeByLocations": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specify locations to which to scope the deployment schedule to." + } + }, + "preTaskParameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Parameters provided to the task running before the deployment schedule." + } + }, + "preTaskSource": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source of the task running before the deployment schedule." + } + }, + "postTaskParameters": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Parameters provided to the task running after the deployment schedule." + } + }, + "postTaskSource": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The source of the task running after the deployment schedule." + } + }, + "interval": { + "type": "int", + "defaultValue": 1, + "maxValue": 100, + "metadata": { + "description": "Optional. The interval of the frequency for the deployment schedule. 1 Hour is every hour, 2 Day is every second day, etc." + } + }, + "isEnabled": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enables the deployment schedule." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "UTC", + "metadata": { + "description": "Optional. Time zone for the deployment schedule. IANA ID or a Windows Time Zone ID." + } + }, + "nonAzureQueries": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Array of functions from a Log Analytics workspace, used to scope the deployment schedule." + } + }, + "azureVirtualMachines": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of azure resource IDs for azure virtual machines in scope for the deployment schedule." + } + }, + "nonAzureComputerNames": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of names of non-azure machines in scope for the deployment schedule." + } + }, + "weekDays": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" + ], + "metadata": { + "description": "Optional. Required when used with frequency 'Week'. Specified the day of the week to run the deployment schedule." + } + }, + "monthDays": { + "type": "array", + "defaultValue": [], + "allowedValues": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31 + ], + "metadata": { + "description": "Optional. Can be used with frequency 'Month'. Provides the specific days of the month to run the deployment schedule." + } + }, + "monthlyOccurrences": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule." + } + }, + "startTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The start time of the deployment schedule in ISO 8601 format. To specify a specific time use YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00. For schedules where we want to start the deployment as soon as possible, specify the time segment only in 24 hour format, HH:MM, 22:00." + } + }, + "expiryTime": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The end time of the deployment schedule in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00." + } + }, + "expiryTimeOffsetMinutes": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The expiry time's offset in minutes." + } + }, + "nextRun": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The next time the deployment schedule runs in ISO 8601 format. YYYY-MM-DDTHH:MM:SS, 2021-12-31T23:00:00." + } + }, + "nextRunOffsetMinutes": { + "type": "int", + "defaultValue": 0, + "metadata": { + "description": "Optional. The next run's offset in minutes." + } + }, + "scheduleDescription": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The schedules description." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not touch. Is used to provide the base time for time comparison for startTime. If startTime is specified in HH:MM format, baseTime is used to check if the provided startTime has passed, adding one day before setting the deployment schedule." + } + } + }, + "variables": { + "updateClassificationsVar": "[replace(replace(replace(replace(string(parameters('updateClassifications')), ',', ', '), '[', ''), ']', ''), '\"', '')]" + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/softwareUpdateConfigurations", + "apiVersion": "2019-06-01", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "updateConfiguration": { + "operatingSystem": "[parameters('operatingSystem')]", + "duration": "[parameters('maintenanceWindow')]", + "linux": "[if(equals(parameters('operatingSystem'), 'Linux'), createObject('excludedPackageNameMasks', parameters('excludeUpdates'), 'includedPackageNameMasks', parameters('includeUpdates'), 'includedPackageClassifications', variables('updateClassificationsVar'), 'rebootSetting', parameters('rebootSetting')), null())]", + "windows": "[if(equals(parameters('operatingSystem'), 'Windows'), createObject('excludedKbNumbers', parameters('excludeUpdates'), 'includedKbNumbers', parameters('includeUpdates'), 'includedUpdateClassifications', variables('updateClassificationsVar'), 'rebootSetting', parameters('rebootSetting')), null())]", + "targets": { + "azureQueries": [ + { + "scope": "[parameters('scopeByResources')]", + "tagSettings": { + "tags": "[parameters('scopeByTags')]", + "filterOperator": "[parameters('scopeByTagsOperation')]" + }, + "locations": "[parameters('scopeByLocations')]" + } + ], + "nonAzureQueries": "[parameters('nonAzureQueries')]" + }, + "azureVirtualMachines": "[parameters('azureVirtualMachines')]", + "nonAzureComputerNames": "[parameters('nonAzureComputerNames')]" + }, + "tasks": { + "preTask": { + "parameters": "[if(empty(parameters('preTaskParameters')), null(), parameters('preTaskParameters'))]", + "source": "[if(empty(parameters('preTaskSource')), null(), parameters('preTaskSource'))]" + }, + "postTask": { + "parameters": "[if(empty(parameters('postTaskParameters')), null(), parameters('postTaskParameters'))]", + "source": "[if(empty(parameters('postTaskSource')), null(), parameters('postTaskSource'))]" + } + }, + "scheduleInfo": { + "interval": "[parameters('interval')]", + "frequency": "[parameters('frequency')]", + "isEnabled": "[parameters('isEnabled')]", + "timeZone": "[parameters('timeZone')]", + "advancedSchedule": { + "weekDays": "[if(empty(parameters('weekDays')), null(), parameters('weekDays'))]", + "monthDays": "[if(empty(parameters('monthDays')), null(), parameters('monthDays'))]", + "monthlyOccurrences": "[if(empty(parameters('monthlyOccurrences')), null(), parameters('monthlyOccurrences'))]" + }, + "startTime": "[if(empty(parameters('startTime')), dateTimeAdd(parameters('baseTime'), 'PT10M'), parameters('startTime'))]", + "expiryTime": "[parameters('expiryTime')]", + "expiryTimeOffsetMinutes": "[parameters('expiryTimeOffsetMinutes')]", + "nextRun": "[parameters('nextRun')]", + "nextRunOffsetMinutes": "[parameters('nextRunOffsetMinutes')]", + "description": "[parameters('scheduleDescription')]" + } + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed softwareUpdateConfiguration." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed softwareUpdateConfiguration." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/softwareUpdateConfigurations', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed softwareUpdateConfiguration." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep new file mode 100644 index 00000000000..2059e33b554 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/defaults/main.test.bicep @@ -0,0 +1,46 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-automation.account-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'aamin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +// ============== // +// 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/automation/automation-account/tests/e2e/encr/dependencies.bicep b/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep new file mode 100644 index 00000000000..c0fbbed613e --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/encr/dependencies.bicep @@ -0,0 +1,58 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + softDeleteRetentionInDays: 7 + enablePurgeProtection: true + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The name of the Key Vault Encryption Key.') +output keyVaultEncryptionKeyName string = keyVault::key.name + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep new file mode 100644 index 00000000000..060aa9cb622 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/encr/main.test.bicep @@ -0,0 +1,70 @@ +targetScope = 'subscription' + +metadata name = 'Using encryption with Customer-Managed-Key' +metadata description = 'This instance deploys the module using Customer-Managed-Keys using a User-Assigned Identity to access the Customer-Managed-Key secret.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-automation.account-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'aaencr' + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location + } +} + +// ============== // +// 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' + customerManagedKey: { + keyName: nestedDependencies.outputs.keyVaultEncryptionKeyName + keyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + userAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } + managedIdentities: { + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + location: location + } +}] diff --git a/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep b/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep new file mode 100644 index 00000000000..3a979dc83b0 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/max/dependencies.bicep @@ -0,0 +1,90 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azure-automation.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep new file mode 100644 index 00000000000..7921104e288 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/max/main.test.bicep @@ -0,0 +1,261 @@ +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}-automation.account-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'aamax' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// 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' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' + } + ] + disableLocalAuth: true + linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + location: location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'DSCAndHybridWorker' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + 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' + } + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + isEncrypted: false + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 00000000000..3a979dc83b0 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,90 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azure-automation.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 00000000000..77060749ab9 --- /dev/null +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,247 @@ +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}-automation.account-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@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 = 'aawaf' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + location: location + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// 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' + diagnosticSettings: [ + { + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + gallerySolutions: [ + { + name: 'Updates' + product: 'OMSGallery' + publisher: 'Microsoft' + } + ] + jobSchedules: [ + { + runbookName: 'TestRunbook' + scheduleName: 'TestSchedule' + } + ] + disableLocalAuth: true + linkedWorkspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + location: location + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + modules: [ + { + name: 'PSWindowsUpdate' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: 'latest' + } + ] + privateEndpoints: [ + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'Webhook' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + { + privateDnsZoneResourceIds: [ + nestedDependencies.outputs.privateDNSZoneResourceId + ] + service: 'DSCAndHybridWorker' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + runbooks: [ + { + description: 'Test runbook' + name: 'TestRunbook' + type: 'PowerShell' + uri: 'https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/quickstarts/microsoft.automation/101-automation/scripts/AzureAutomationTutorial.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + advancedSchedule: {} + expiryTime: '9999-12-31T13:00' + frequency: 'Hour' + interval: 12 + name: 'TestSchedule' + startTime: '' + timeZone: 'Europe/Berlin' + } + ] + softwareUpdateConfigurations: [ + { + excludeUpdates: [ + '123456' + ] + frequency: 'Month' + includeUpdates: [ + '654321' + ] + interval: 1 + maintenanceWindow: 'PT4H' + monthlyOccurrences: [ + { + day: 'Friday' + occurrence: 3 + } + ] + name: 'Windows_ZeroDay' + operatingSystem: 'Windows' + rebootSetting: 'IfRequired' + scopeByTags: { + Update: [ + 'Automatic-Wave1' + ] + } + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Definition' + 'FeaturePack' + 'Security' + 'ServicePack' + 'Tools' + 'UpdateRollup' + 'Updates' + ] + } + { + excludeUpdates: [ + 'icacls' + ] + frequency: 'OneTime' + includeUpdates: [ + 'kernel' + ] + maintenanceWindow: 'PT4H' + name: 'Linux_ZeroDay' + operatingSystem: 'Linux' + rebootSetting: 'IfRequired' + startTime: '22:00' + updateClassifications: [ + 'Critical' + 'Other' + 'Security' + ] + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + variables: [ + { + description: 'TestStringDescription' + name: 'TestString' + value: '\'TestString\'' + } + { + description: 'TestIntegerDescription' + name: 'TestInteger' + value: '500' + } + { + description: 'TestBooleanDescription' + name: 'TestBoolean' + value: 'false' + } + { + description: 'TestDateTimeDescription' + isEncrypted: false + name: 'TestDateTime' + value: '\'\\/Date(1637934042656)\\/\'' + } + { + description: 'TestEncryptedDescription' + name: 'TestEncryptedVariable' + value: '\'TestEncryptedValue\'' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/automation/automation-account/variable/README.md b/avm/res/automation/automation-account/variable/README.md new file mode 100644 index 00000000000..60e939051d9 --- /dev/null +++ b/avm/res/automation/automation-account/variable/README.md @@ -0,0 +1,83 @@ +# Automation Account Variables `[Microsoft.Automation/automationAccounts/variables]` + +This module deploys an Azure Automation Account Variable. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Automation/automationAccounts/variables` | [2022-08-08](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Automation/2022-08-08/automationAccounts/variables) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`name`](#parameter-name) | string | The name of the variable. | +| [`value`](#parameter-value) | securestring | The value of the variable. For security best practices, this value is always passed as a secure string as it could contain an encrypted value when the "isEncrypted" property is set to true. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`automationAccountName`](#parameter-automationaccountname) | string | The name of the parent Automation Account. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`description`](#parameter-description) | string | The description of the variable. | +| [`isEncrypted`](#parameter-isencrypted) | bool | If the variable should be encrypted. For security reasons encryption of variables should be enabled. | + +### Parameter: `automationAccountName` + +The name of the parent Automation Account. Required if the template is used in a standalone deployment. +- Required: Yes +- Type: string + +### Parameter: `description` + +The description of the variable. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `isEncrypted` + +If the variable should be encrypted. For security reasons encryption of variables should be enabled. +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `name` + +The name of the variable. +- Required: Yes +- Type: string + +### Parameter: `value` + +The value of the variable. For security best practices, this value is always passed as a secure string as it could contain an encrypted value when the "isEncrypted" property is set to true. +- Required: Yes +- Type: securestring + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the deployed variable. | +| `resourceGroupName` | string | The resource group of the deployed variable. | +| `resourceId` | string | The resource ID of the deployed variable. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/automation/automation-account/variable/main.bicep b/avm/res/automation/automation-account/variable/main.bicep new file mode 100644 index 00000000000..a96c274d326 --- /dev/null +++ b/avm/res/automation/automation-account/variable/main.bicep @@ -0,0 +1,42 @@ +metadata name = 'Automation Account Variables' +metadata description = 'This module deploys an Azure Automation Account Variable.' +metadata owner = 'Azure/module-maintainers' + +@sys.description('Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment.') +param automationAccountName string + +@sys.description('Required. The name of the variable.') +param name string + +@secure() +@sys.description('Required. The value of the variable. For security best practices, this value is always passed as a secure string as it could contain an encrypted value when the "isEncrypted" property is set to true.') +param value string + +@sys.description('Optional. The description of the variable.') +param description string = '' + +@sys.description('Optional. If the variable should be encrypted. For security reasons encryption of variables should be enabled.') +param isEncrypted bool = true + +resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = { + name: automationAccountName +} + +resource variable 'Microsoft.Automation/automationAccounts/variables@2022-08-08' = { + name: name + parent: automationAccount + properties: { + description: description + isEncrypted: isEncrypted + value: value + } +} + +@sys.description('The name of the deployed variable.') +output name string = variable.name + +@sys.description('The resource ID of the deployed variable.') +output resourceId string = variable.id + +@sys.description('The resource group of the deployed variable.') +output resourceGroupName string = resourceGroup().name diff --git a/avm/res/automation/automation-account/variable/main.json b/avm/res/automation/automation-account/variable/main.json new file mode 100644 index 00000000000..945b0c029d3 --- /dev/null +++ b/avm/res/automation/automation-account/variable/main.json @@ -0,0 +1,83 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "6672396434414300928" + }, + "name": "Automation Account Variables", + "description": "This module deploys an Azure Automation Account Variable.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "automationAccountName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the variable." + } + }, + "value": { + "type": "securestring", + "metadata": { + "description": "Required. The value of the variable. For security best practices, this value is always passed as a secure string as it could contain an encrypted value when the \"isEncrypted\" property is set to true." + } + }, + "description": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The description of the variable." + } + }, + "isEncrypted": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. If the variable should be encrypted. For security reasons encryption of variables should be enabled." + } + } + }, + "resources": [ + { + "type": "Microsoft.Automation/automationAccounts/variables", + "apiVersion": "2022-08-08", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", + "properties": { + "description": "[parameters('description')]", + "isEncrypted": "[parameters('isEncrypted')]", + "value": "[parameters('value')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed variable." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed variable." + }, + "value": "[resourceId('Microsoft.Automation/automationAccounts/variables', parameters('automationAccountName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed variable." + }, + "value": "[resourceGroup().name]" + } + } +} \ No newline at end of file diff --git a/avm/res/automation/automation-account/version.json b/avm/res/automation/automation-account/version.json new file mode 100644 index 00000000000..83083db6945 --- /dev/null +++ b/avm/res/automation/automation-account/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} \ No newline at end of file From 499a5f6013ac9a9da96d2d8eabb33ee47b44d321 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Fri, 1 Dec 2023 16:25:14 +0100 Subject: [PATCH 12/14] workflow file --- .../avm.res.automation.automation-account.yml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/avm.res.automation.automation-account.yml diff --git a/.github/workflows/avm.res.automation.automation-account.yml b/.github/workflows/avm.res.automation.automation-account.yml new file mode 100644 index 00000000000..77620330016 --- /dev/null +++ b/.github/workflows/avm.res.automation.automation-account.yml @@ -0,0 +1,83 @@ +name: "avm.res.automation.automation-account" + +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 + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.automation.automation-account.yml" + - "avm/res/automation/automation-account/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/automation/automation-account" + workflowPath: ".github/workflows/avm.res.automation.automation-account.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + 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: "Module" + 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 From 571feba73f18401c1c8318e8436bf01661aefc2f Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Fri, 1 Dec 2023 17:23:06 +0100 Subject: [PATCH 13/14] log for waf --- .../tests/e2e/waf-aligned/main.test.bicep | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep index 77060749ab9..4446e000c09 100644 --- a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep @@ -72,6 +72,16 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + metricCategories: [ + { + category: 'AllMetrics' + } + ] + logCategoriesAndGroups: [ + { + categoryGroup: 'AllLogs' + } + ] } ] gallerySolutions: [ From 2be97e4aad37031e62d49d66bc642935b45f0258 Mon Sep 17 00:00:00 2001 From: Elisa Anzelmo Date: Fri, 1 Dec 2023 17:36:32 +0100 Subject: [PATCH 14/14] specific categories audit --- .../tests/e2e/waf-aligned/main.test.bicep | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep index 4446e000c09..a8c49a95274 100644 --- a/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep +++ b/avm/res/automation/automation-account/tests/e2e/waf-aligned/main.test.bicep @@ -79,7 +79,13 @@ module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ] logCategoriesAndGroups: [ { - categoryGroup: 'AllLogs' + category: 'JobLogs' + } + { + category: 'JobStreams' + } + { + category: 'DSCNodeStatus' } ] }