diff --git a/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml b/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml new file mode 100644 index 0000000000..79d0138395 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml @@ -0,0 +1,52 @@ +name: 'EventGrid - System Topics' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.eventgrid.systemtopics.yml' + - '/.azuredevops/pipelineTemplates/module.*.yml' + - '/arm/Microsoft.EventGrid/systemTopics/*' + exclude: + - '/**/*.md' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/arm/Microsoft.EventGrid/systemTopics' + +stages: + - stage: Validation + displayName: Pester tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModulePester.yml + + - stage: Deployment + displayName: Deployment tests + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.validateModuleDeployment.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + deploymentBlocks: + - path: $(modulePath)/.parameters/min.parameters.json + - path: $(modulePath)/.parameters/parameters.json + + - stage: Publishing + displayName: Publish module + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq('${{ parameters.prerelease }}', 'true'))) + jobs: + - template: /.azuredevops/pipelineTemplates/jobs.publishModule.yml diff --git a/.github/workflows/ms.eventgrid.systemtopics.yml b/.github/workflows/ms.eventgrid.systemtopics.yml new file mode 100644 index 0000000000..1fe703b874 --- /dev/null +++ b/.github/workflows/ms.eventgrid.systemtopics.yml @@ -0,0 +1,135 @@ +name: 'EventGrid: System Topics' + +on: + workflow_dispatch: + inputs: + removeDeployment: + type: boolean + description: 'Remove deployed module' + required: false + default: 'true' + prerelease: + type: boolean + description: 'Publish prerelease module' + required: false + default: 'false' + push: + branches: + - main + paths: + - '.github/actions/templates/**' + - '.github/workflows/ms.eventgrid.systemtopics.yml' + - 'arm/Microsoft.EventGrid/systemTopics/**' + - '!*/**/readme.md' + - 'utilities/pipelines/**' + - '!utilities/pipelines/dependencies/**' + +env: + modulePath: 'arm/Microsoft.EventGrid/systemTopics' + workflowPath: '.github/workflows/ms.eventgrid.systemtopics.yml' + AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} + ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' + ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' + DEPLOYMENT_SP_ID: '${{ secrets.DEPLOYMENT_SP_ID }}' + +jobs: + ############################ + # SET INPUT PARAMETERS # + ############################ + job_set_workflow_param: + runs-on: ubuntu-20.04 + name: 'Set input parameters to output variables' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: 'Set input parameters' + id: get-workflow-param + uses: ./.github/actions/templates/getWorkflowInput + with: + workflowPath: '${{ env.workflowPath}}' + outputs: + removeDeployment: ${{ steps.get-workflow-param.outputs.removeDeployment }} + + #################### + # Pester Tests # + #################### + job_module_pester_validation: + runs-on: ubuntu-20.04 + name: 'Pester tests' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: 'Run tests' + uses: ./.github/actions/templates/validateModulePester + with: + modulePath: '${{ env.modulePath }}' + + #################### + # Deployment tests # + #################### + job_module_deploy_validation: + runs-on: ubuntu-20.04 + name: 'Deployment tests' + needs: + - job_set_workflow_param + - job_module_pester_validation + strategy: + fail-fast: false + matrix: + parameterFilePaths: ['min.parameters.json', 'parameters.json'] + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: deep-mm/set-variables@v1.0 + with: + variableFileName: 'global.variables' + - name: 'Using parameter file [${{ matrix.parameterFilePaths }}]' + uses: ./.github/actions/templates/validateModuleDeployment + with: + templateFilePath: '${{ env.modulePath }}/deploy.bicep' + parameterFilePath: '${{ env.modulePath }}/.parameters/${{ matrix.parameterFilePaths }}' + location: '${{ env.defaultLocation }}' + resourceGroupName: '${{ env.resourceGroupName }}' + subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' + removeDeployment: '${{ needs.job_set_workflow_param.outputs.removeDeployment }}' + + ############### + # PUBLISH # + ############### + job_publish_module: + name: 'Publish module' + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' + runs-on: ubuntu-20.04 + needs: + - job_set_workflow_param + - job_module_deploy_validation + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: deep-mm/set-variables@v1.0 + with: + variableFileName: 'global.variables' + - name: 'Publish module' + uses: ./.github/actions/templates/publishModule + with: + templateFilePath: '${{ env.modulePath }}/deploy.bicep' + templateSpecsRGName: '${{ env.templateSpecsRGName }}' + templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' + templateSpecsDescription: '${{ env.templateSpecsDescription }}' + templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' + bicepRegistryName: '${{ env.bicepRegistryName }}' + bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' + bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' diff --git a/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_cuaId.bicep @@ -0,0 +1 @@ + diff --git a/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep new file mode 100644 index 0000000000..82ab478cd6 --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_privateEndpoint.bicep @@ -0,0 +1,52 @@ +param privateEndpointResourceId string +param privateEndpointVnetLocation string +param privateEndpointObj object +param tags object + +var privateEndpointResourceName = last(split(privateEndpointResourceId, '/')) +var privateEndpoint_var = { + name: (contains(privateEndpointObj, 'name') ? (empty(privateEndpointObj.name) ? '${privateEndpointResourceName}-${privateEndpointObj.service}' : privateEndpointObj.name) : '${privateEndpointResourceName}-${privateEndpointObj.service}') + subnetResourceId: privateEndpointObj.subnetResourceId + service: [ + privateEndpointObj.service + ] + privateDnsZoneResourceIds: (contains(privateEndpointObj, 'privateDnsZoneResourceIds') ? (empty(privateEndpointObj.privateDnsZoneResourceIds) ? [] : privateEndpointObj.privateDnsZoneResourceIds) : []) + customDnsConfigs: (contains(privateEndpointObj, 'customDnsConfigs') ? (empty(privateEndpointObj.customDnsConfigs) ? null : privateEndpointObj.customDnsConfigs) : null) +} + +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-05-01' = { + name: privateEndpoint_var.name + location: privateEndpointVnetLocation + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: privateEndpoint_var.name + properties: { + privateLinkServiceId: privateEndpointResourceId + groupIds: privateEndpoint_var.service + } + } + ] + manualPrivateLinkServiceConnections: [] + subnet: { + id: privateEndpoint_var.subnetResourceId + } + customDnsConfigs: privateEndpoint_var.customDnsConfigs + } +} + +resource privateDnsZoneGroups 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2021-02-01' = if (!empty(privateEndpoint_var.privateDnsZoneResourceIds)) { + name: '${privateEndpoint_var.name}/default' + properties: { + privateDnsZoneConfigs: [for j in range(0, length(privateEndpoint_var.privateDnsZoneResourceIds)): { + name: last(split(privateEndpoint_var.privateDnsZoneResourceIds[j], '/')) + properties: { + privateDnsZoneId: privateEndpoint_var.privateDnsZoneResourceIds[j] + } + }] + } + dependsOn: [ + privateEndpoint + ] +} diff --git a/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep new file mode 100644 index 0000000000..af15c17cde --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/.bicep/nested_rbac.bicep @@ -0,0 +1,34 @@ +param principalIds array +param roleDefinitionIdOrName string +param resourceId string + +var builtInRoleNames = { + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'EventGrid Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1e241071-0855-49ea-94dc-649edcd759de') + 'EventGrid Data Sender': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd5a91429-5739-47e2-a06b-3470a27159e7') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Metrics Publisher': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3913510d-42f4-4e42-8a64-420c390055eb') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2021-04-01-preview' = [for principalId in principalIds: { + name: guid(systemTopic.name, principalId, roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + } + scope: systemTopic +}] diff --git a/arm/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json b/arm/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json new file mode 100644 index 0000000000..87be2f37f1 --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/.parameters/min.parameters.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egstn-x-002" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + } + } +} diff --git a/arm/Microsoft.EventGrid/systemTopics/.parameters/parameters.json b/arm/Microsoft.EventGrid/systemTopics/.parameters/parameters.json new file mode 100644 index 0000000000..46728a6924 --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/.parameters/parameters.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-egstn-x-001" + }, + "source": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "topicType": { + "value": "Microsoft.Storage.StorageAccounts" + }, + "roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "<>" + ] + } + ] + }, + "diagnosticLogsRetentionInDays": { + "value": 7 + }, + "diagnosticStorageAccountId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + }, + "diagnosticWorkspaceId": { + "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + }, + "diagnosticEventHubAuthorizationRuleId": { + "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + }, + "diagnosticEventHubName": { + "value": "adp-<>-az-evh-x-001" + } + } +} diff --git a/arm/Microsoft.EventGrid/systemTopics/deploy.bicep b/arm/Microsoft.EventGrid/systemTopics/deploy.bicep new file mode 100644 index 0000000000..53996c3bff --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/deploy.bicep @@ -0,0 +1,165 @@ +@description('Required. The name of the Event Grid Topic') +param name string + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Required. Source for the system topic.') +param source string + +@description('Required. TopicType for the system topic.') +param topicType string + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId 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.') +param diagnosticEventHubAuthorizationRuleId 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.') +param diagnosticEventHubName string = '' + +@description('Optional. Configuration Details for private endpoints.') +param privateEndpoints array = [] + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'') +param roleAssignments array = [] + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') +param cuaId string = '' + +var identityType = systemAssignedIdentity ? (!empty(userAssignedIdentities) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(userAssignedIdentities) ? 'UserAssigned' : 'None') + +var identity = identityType != 'None' ? { + type: identityType + userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null +} : null + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DeliveryFailures' +]) +param logsToEnable array = [ + 'DeliveryFailures' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param metricsToEnable array = [ + 'AllMetrics' +] + +var diagnosticsLogs = [for log in logsToEnable: { + category: log + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsMetrics = [for metric in metricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { + name: 'pid-${cuaId}' + params: {} +} + +resource systemTopic 'Microsoft.EventGrid/systemTopics@2021-12-01' = { + name: name + location: location + identity: identity + tags: tags + properties: { + source: source + topicType: topicType + } +} + +resource systemTopic_lock 'Microsoft.Authorization/locks@2017-04-01' = if (lock != 'NotSpecified') { + name: '${systemTopic.name}-${lock}-lock' + properties: { + level: lock + notes: (lock == 'CanNotDelete') ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: systemTopic +} + +resource systemTopic_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: '${systemTopic.name}-diagnosticSettings' + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: systemTopic +} + +module systemTopic_privateEndpoints '.bicep/nested_privateEndpoint.bicep' = [for (privateEndpoint, index) in privateEndpoints: if (!empty(privateEndpoints)) { + name: '${uniqueString(deployment().name, location)}-EventGrid-PrivateEndpoint-${index}' + params: { + privateEndpointResourceId: systemTopic.id + privateEndpointVnetLocation: (empty(privateEndpoints) ? 'dummy' : reference(split(privateEndpoint.subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location) + privateEndpointObj: privateEndpoint + tags: tags + } +}] + +module systemTopic_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-EventGrid-Rbac-${index}' + params: { + principalIds: roleAssignment.principalIds + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + resourceId: systemTopic.id + } +}] + +@description('The name of the event grid system topic') +output name string = systemTopic.name + +@description('The resource ID of the event grid system topic') +output resourceId string = systemTopic.id + +@description('The name of the resource group the event grid system topic was deployed into') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedPrincipalId string = systemAssignedIdentity && contains(systemTopic.identity, 'principalId') ? systemTopic.identity.principalId : '' diff --git a/arm/Microsoft.EventGrid/systemTopics/readme.md b/arm/Microsoft.EventGrid/systemTopics/readme.md new file mode 100644 index 0000000000..6a42a7441f --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/readme.md @@ -0,0 +1,143 @@ +# Event Grid Topics `[Microsoft.EventGrid/systemTopics]` + +This module deploys an event grid topic. + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | 2017-04-01 | +| `Microsoft.Authorization/roleAssignments` | 2021-04-01-preview | +| `Microsoft.EventGrid/systemTopics` | 2021-12-01 | +| `Microsoft.Insights/diagnosticSettings` | 2021-05-01-preview | +| `Microsoft.Network/privateEndpoints` | 2021-05-01 | +| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | 2021-02-01 | + +## Parameters + +| Parameter Name | Type | Default Value | Possible Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `diagnosticEventHubAuthorizationRuleId` | 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. | +| `diagnosticEventHubName` | 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. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | | | Optional. Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | | | Optional. Resource ID of the diagnostic log analytics workspace. | +| `location` | string | `[resourceGroup().location]` | | Optional. Location for all Resources. | +| `lock` | string | `NotSpecified` | `[CanNotDelete, NotSpecified, ReadOnly]` | Optional. Specify the type of lock. | +| `logsToEnable` | array | `[DeliveryFailures]` | `[DeliveryFailures]` | Optional. The name of logs that will be streamed. | +| `metricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | Optional. The name of metrics that will be streamed. | +| `name` | string | | | Required. The name of the Event Grid Topic | +| `privateEndpoints` | array | `[]` | | Optional. Configuration Details for private endpoints. | +| `roleAssignments` | array | `[]` | | 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' | +| `source` | string | | | Required. Source for the system topic. | +| `systemAssignedIdentity` | bool | | | Optional. Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Optional. Tags of the resource. | +| `topicType` | string | | | Required. TopicType for the system topic. | +| `userAssignedIdentities` | object | `{object}` | | Optional. The ID(s) to assign to the resource. | + +### Parameter Usage: `privateEndpoints` + +To use Private Endpoint the following dependencies must be deployed: + +- Destination subnet must be created with the following configuration option - `"privateEndpointNetworkPolicies": "Disabled"`. Setting this option acknowledges that NSG rules are not applied to Private Endpoints (this capability is coming soon). A full example is available in the Virtual Network Module. +- Although not strictly required, it is highly recommended to first create a private DNS Zone to host Private Endpoint DNS records. See [Azure Private Endpoint DNS configuration](https://docs.microsoft.com/en-us/azure/private-link/private-endpoint-dns) for more information. + +```json +"privateEndpoints": { + "value": [ + // Example showing all available fields + { + "name": "sxx-az-pe", // Optional: Name will be automatically generated if one is not provided here + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "blob", + "privateDnsZoneResourceIds": [ // Optional: No DNS record will be created if a private DNS zone Resource ID is not specified + "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net" + ], + "customDnsConfigs": [ // Optional + { + "fqdn": "customname.test.local", + "ipAddresses": [ + "10.10.10.10" + ] + } + ] + }, + // Example showing only mandatory fields + { + "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/sxx-az-vnet-x-001/subnets/sxx-az-subnet-x-001", + "service": "file" + } + ] +} +``` + +### Parameter Usage: `roleAssignments` + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ] + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the event grid system topic | +| `resourceGroupName` | string | The name of the resource group the event grid system topic was deployed into | +| `resourceId` | string | The resource ID of the event grid system topic | +| `systemAssignedPrincipalId` | string | The principal ID of the system assigned identity. | + +## Template references + +- [Diagnosticsettings](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) +- [Locks](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) +- [Privateendpoints](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/privateEndpoints) +- [Privateendpoints/Privatednszonegroups](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-02-01/privateEndpoints/privateDnsZoneGroups) +- [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/roleAssignments) +- [Systemtopics](https://docs.microsoft.com/en-us/azure/templates/Microsoft.EventGrid/2021-12-01/systemTopics) diff --git a/arm/Microsoft.EventGrid/systemTopics/version.json b/arm/Microsoft.EventGrid/systemTopics/version.json new file mode 100644 index 0000000000..56f8d9ca40 --- /dev/null +++ b/arm/Microsoft.EventGrid/systemTopics/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.4" +}