diff --git a/docs/changelog.md b/docs/changelog.md index 4cd4191af3..bf88b94eb0 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -45,6 +45,9 @@ What's changed since v1.45.2: - Includes rules released before or during September 2025. - Marked `Azure.GA_2025_06` and `Azure.Preview_2025_06` baselines as obsolete. - New rules: + - Azure Container Registry: + - Check that audit diagnostic logs are enabled for Container Registry by @copilot. + [#3536](https://github.com/Azure/PSRule.Rules.Azure/issues/3536) - Azure Cache for Redis: - Check that Entra ID is required for all authentication of cache instances by @BernieWhite. [#3113](https://github.com/Azure/PSRule.Rules.Azure/issues/3113) diff --git a/docs/en/rules/Azure.ACR.Logs.md b/docs/en/rules/Azure.ACR.Logs.md new file mode 100644 index 0000000000..0fdb4be8d4 --- /dev/null +++ b/docs/en/rules/Azure.ACR.Logs.md @@ -0,0 +1,156 @@ +--- +severity: Important +pillar: Security +category: SE:10 Monitoring and threat detection +resource: Container Registry +resourceType: Microsoft.ContainerRegistry/registries,Microsoft.Insights/diagnosticSettings +online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ACR.Logs/ +--- + +# Audit Container Registry access + +## SYNOPSIS + +Ensure container registry audit diagnostic logs are enabled. + +## DESCRIPTION + +Azure Container Registry (ACR) provides diagnostic logs that can be used to monitor and audit access to container images. +Enabling audit logs helps you track who accesses your registry and when, which is important for security and compliance. + +The following log categories should be enabled: + +- `ContainerRegistryLoginEvents` - Captures authentication events to the registry. +- `ContainerRegistryRepositoryEvents` - Captures push and pull operations for container images. + +Alternatively, you can enable the `audit` or `allLogs` category group to capture these and other audit events. + +## RECOMMENDATION + +Consider configuring diagnostic settings to capture container registry audit logs for security investigation. + +## EXAMPLES + +### Configure with Azure template + +To deploy container registries that pass this rule: + +- Deploy a diagnostic settings sub-resource (extension resource). +- Enable `ContainerRegistryLoginEvents` and `ContainerRegistryRepositoryEvents` categories or `audit` category group or `allLogs` category group. + +For example: + +```json +{ + "type": "Microsoft.ContainerRegistry/registries", + "apiVersion": "2023-11-01-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "sku": { + "name": "Premium" + }, + "properties": { + "adminUserEnabled": false, + "policies": { + "quarantinePolicy": { + "status": "enabled" + } + } + }, + "resources": [ + { + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.ContainerRegistry/registries/{0}', parameters('name'))]", + "name": "logs", + "properties": { + "workspaceId": "[parameters('workspaceId')]", + "logs": [ + { + "category": "ContainerRegistryLoginEvents", + "enabled": true + }, + { + "category": "ContainerRegistryRepositoryEvents", + "enabled": true + } + ] + }, + "dependsOn": [ + "[parameters('name')]" + ] + } + ] +} +``` + +### Configure with Bicep + +To deploy container registries that pass this rule: + +- Deploy a diagnostic settings sub-resource (extension resource). +- Enable `ContainerRegistryLoginEvents` and `ContainerRegistryRepositoryEvents` categories or `audit` category group or `allLogs` category group. + +For example: + +```bicep +resource registry 'Microsoft.ContainerRegistry/registries@2023-11-01-preview' = { + name: name + location: location + sku: { + name: 'Premium' + } + properties: { + adminUserEnabled: false + policies: { + quarantinePolicy: { + status: 'enabled' + } + } + } +} + +resource logs 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: 'logs' + scope: registry + properties: { + workspaceId: workspaceId + logs: [ + { + category: 'ContainerRegistryLoginEvents' + enabled: true + } + { + category: 'ContainerRegistryRepositoryEvents' + enabled: true + } + ] + } +} +``` + +Alternatively, you can use category groups: + +```bicep +resource logs 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: 'logs' + scope: registry + properties: { + workspaceId: workspaceId + logs: [ + { + categoryGroup: 'audit' + enabled: true + } + ] + } +} +``` + +## LINKS + +- [SE:10 Monitoring and threat detection](https://learn.microsoft.com/azure/well-architected/security/monitor-threats) +- [LT-4: Enable logging for security investigation](https://learn.microsoft.com/security/benchmark/azure/baselines/container-registry-security-baseline#lt-4-enable-logging-for-security-investigation) +- [Monitor Azure Container Registry](https://learn.microsoft.com/azure/container-registry/monitor-container-registry) +- [Container Registry resource logs](https://learn.microsoft.com/azure/container-registry/monitor-container-registry-reference#resource-logs) +- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.containerregistry/registries) diff --git a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 index 7791b83b37..7f6bba0b09 100644 --- a/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 +++ b/src/PSRule.Rules.Azure/en/PSRule-rules.psd1 @@ -76,6 +76,7 @@ VMSSPublicKey = "The virtual machine scale set '{0}' should have password authentication disabled." ACRSoftDeletePolicy = "The container registry '{0}' should have soft delete policy enabled." ACRSoftDeletePolicyRetention = "The container registry '{0}' should have retention period value between one to 90 days for the soft delete policy." + ContainerRegistryAuditDiagnosticSetting = "Minimum one diagnostic setting should have ({0}) configured or category group ({1}) configured." AppConfigStoresDiagnosticSetting = "Minimum one diagnostic setting should have ({0}) configured or category group ({1}) configured." AppConfigPurgeProtection = "The app configuration store '{0}' should have purge protection enabled." diff --git a/src/PSRule.Rules.Azure/rules/Azure.ACR.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.ACR.Rule.ps1 index a4186fb73f..dcf6e0e849 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.ACR.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.ACR.Rule.ps1 @@ -75,6 +75,24 @@ Rule 'Azure.ACR.ReplicaLocation' -Ref 'AZR-000494' -Type 'Microsoft.ContainerReg } } +# Synopsis: Ensure container registry audit diagnostic logs are enabled. +Rule 'Azure.ACR.Logs' -Ref 'AZR-000498' -Type 'Microsoft.ContainerRegistry/registries' -Tag @{ release = 'GA'; ruleSet = '2025_12'; 'Azure.WAF/pillar' = 'Security'; } -Labels @{ 'Azure.MCSB.v1/control' = 'LT-4'; 'Azure.WAF/maturity' = 'L1'; } { + $logCategoryGroups = 'audit', 'allLogs' + $joinedLogCategoryGroups = $logCategoryGroups -join ', ' + $diagnostics = @(GetSubResources -ResourceType 'Microsoft.Insights/diagnosticSettings', 'Microsoft.ContainerRegistry/registries/providers/diagnosticSettings' | + ForEach-Object { $_.properties.logs | + Where-Object { + ($_.category -in 'ContainerRegistryLoginEvents', 'ContainerRegistryRepositoryEvents' -or $_.categoryGroup -in $logCategoryGroups) -and $_.enabled + } + }) + + $Assert.Greater($diagnostics, '.', 0).Reason( + $LocalizedData.ContainerRegistryAuditDiagnosticSetting, + 'ContainerRegistryLoginEvents, ContainerRegistryRepositoryEvents', + $joinedLogCategoryGroups + ).PathPrefix('resources') +} + #endregion Rules #region Helper functions diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.ACR.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.ACR.Tests.ps1 index f747fbd08a..98b57b5fdb 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.ACR.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.ACR.Tests.ps1 @@ -53,8 +53,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-B', 'registry-C', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 11; + $ruleResult.TargetName | Should -BeIn 'registry-B', 'registry-C', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 17; } It 'Azure.ACR.MinSku' { @@ -70,8 +70,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 12; + $ruleResult.TargetName | Should -BeIn 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 18; } It 'Azure.ACR.Quarantine' { @@ -80,9 +80,9 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; $ruleResult.Detail.Reason.Path | Should -BeIn 'Properties.policies.quarantinePolicy.status'; - $ruleResult.Length | Should -Be 11; + $ruleResult.Length | Should -Be 17; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); @@ -97,9 +97,9 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-K', 'registry-L', 'registry-M'; + $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; $ruleResult.Detail.Reason.Path | Should -BeIn 'properties.policies.trustPolicy.status'; - $ruleResult.Length | Should -Be 4; + $ruleResult.Length | Should -Be 10; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); @@ -120,8 +120,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-J', 'registry-I', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 6; + $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-J', 'registry-I', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 12; $ruleResult.Detail.Reason.Path | Should -BeIn 'properties.policies.retentionPolicy.status'; # Pass @@ -150,8 +150,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-C', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 11; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-C', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 17; } It 'Azure.ACR.ContainerScan' { @@ -160,8 +160,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 10; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 16; # TODO: $ruleResult.Detail.Reason.Path | Should -BeIn 'resources'; $ruleResult[0].Reason | Should -Not -BeNullOrEmpty; @@ -196,8 +196,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # None $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'None' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 10; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; + $ruleResult.Length | Should -Be 16; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; } It 'Azure.ACR.GeoReplica' { @@ -206,8 +206,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 9; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 15; # TODO: $ruleResult.Detail.Reason.Path | Should -BeIn ''; $ruleResult[0].Reason | Should -Not -BeNullOrEmpty; @@ -226,8 +226,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-H', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 5; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-D', 'registry-H', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 11; $ruleResult[0].Reason | Should -BeExactly "The container registry 'registry-A' should have soft delete policy enabled.", "The container registry 'registry-A' should have retention period value between one to 90 days for the soft delete policy."; $ruleResult[1].Reason | Should -BeExactly "The container registry 'registry-D' should have soft delete policy enabled.", "The container registry 'registry-D' should have retention period value between one to 90 days for the soft delete policy."; @@ -253,8 +253,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Pass - registries with replicas in allowed regions or no replicas $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 12; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 18; } It 'Azure.ACR.AnonymousAccess' { @@ -268,8 +268,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); - $ruleResult.TargetName | Should -BeIn 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M'; - $ruleResult.Length | Should -Be 11; + $ruleResult.TargetName | Should -BeIn 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 17; # None $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'None' }); @@ -282,8 +282,8 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); - $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-E', 'registry-K', 'registry-L'; - $ruleResult.Length | Should -Be 4; + $ruleResult.TargetName | Should -BeIn 'registry-D', 'registry-E', 'registry-K', 'registry-L', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; + $ruleResult.Length | Should -Be 10; $ruleResult.Detail.Reason.Path | Should -BeIn 'properties.publicNetworkAccess', 'properties.networkRuleSet.defaultAction'; # Pass @@ -303,9 +303,9 @@ Describe 'Azure.ACR' -Tag 'ACR' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L'; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-N', 'registry-O', 'registry-P', 'registry-Q', 'registry-R', 'registry-S'; $ruleResult.Detail.Reason.Path | Should -BeIn 'properties.policies.exportPolicy.status', 'properties.publicNetworkAccess'; - $ruleResult.Length | Should -Be 12; + $ruleResult.Length | Should -Be 18; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); @@ -313,6 +313,24 @@ Describe 'Azure.ACR' -Tag 'ACR' { $ruleResult.TargetName | Should -BeIn 'registry-M'; $ruleResult.Length | Should -Be 1; } + + It 'Azure.ACR.Logs' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.ACR.Logs' }; + + # Fail - no diagnostic settings or disabled logs + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 15; + $ruleResult.TargetName | Should -BeIn 'registry-A', 'registry-B', 'registry-C', 'registry-D', 'registry-E', 'registry-F', 'registry-G', 'registry-H', 'registry-I', 'registry-J', 'registry-K', 'registry-L', 'registry-M', 'registry-O', 'registry-R'; + + $ruleResult[0].Reason | Should -BeExactly "Minimum one diagnostic setting should have (ContainerRegistryLoginEvents, ContainerRegistryRepositoryEvents) configured or category group (audit, allLogs) configured."; + + # Pass - diagnostic settings with specific categories or category groups + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 4; + $ruleResult.TargetName | Should -BeIn 'registry-N', 'registry-P', 'registry-Q', 'registry-S'; + } } Context 'Resource name' { diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.ACR.json b/tests/PSRule.Rules.Azure.Tests/Resources.ACR.json index d4f7bc0ca3..88460748d5 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.ACR.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.ACR.json @@ -705,5 +705,214 @@ "Capacity": null }, "SubscriptionId": "00000000-0000-0000-0000-000000000000" + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-N", + "Location": "region", + "Name": "registry-N", + "Properties": { + "loginServer": "registry-N.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-N/providers/microsoft.insights/diagnosticSettings/logs", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-N/providers/microsoft.insights/diagnosticSettings/logs", + "Name": "logs", + "ExtensionResourceName": "logs", + "properties": { + "workspaceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/microsoft.operationalinsights/workspaces/workspace-A", + "logs": [ + { + "category": "ContainerRegistryLoginEvents", + "enabled": true + }, + { + "category": "ContainerRegistryRepositoryEvents", + "enabled": true + } + ] + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "ExtensionResourceType": "microsoft.insights/diagnosticSettings", + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + } + ] + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-O", + "Location": "region", + "Name": "registry-O", + "Properties": { + "loginServer": "registry-O.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-O/providers/microsoft.insights/diagnosticSettings/logs", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-O/providers/microsoft.insights/diagnosticSettings/logs", + "Name": "logs", + "ExtensionResourceName": "logs", + "properties": { + "workspaceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/microsoft.operationalinsights/workspaces/workspace-A", + "logs": [ + { + "category": "ContainerRegistryLoginEvents", + "enabled": false + }, + { + "category": "ContainerRegistryRepositoryEvents", + "enabled": false + } + ] + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "ExtensionResourceType": "microsoft.insights/diagnosticSettings", + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + } + ] + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-P", + "Location": "region", + "Name": "registry-P", + "Properties": { + "loginServer": "registry-P.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-P/providers/microsoft.insights/diagnosticSettings/logs", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-P/providers/microsoft.insights/diagnosticSettings/logs", + "Name": "logs", + "ExtensionResourceName": "logs", + "properties": { + "workspaceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/microsoft.operationalinsights/workspaces/workspace-A", + "logs": [ + { + "categoryGroup": "audit", + "enabled": true + } + ] + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "ExtensionResourceType": "microsoft.insights/diagnosticSettings", + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + } + ] + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-Q", + "Location": "region", + "Name": "registry-Q", + "Properties": { + "loginServer": "registry-Q.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-Q/providers/microsoft.insights/diagnosticSettings/logs", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-Q/providers/microsoft.insights/diagnosticSettings/logs", + "Name": "logs", + "ExtensionResourceName": "logs", + "properties": { + "workspaceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/microsoft.operationalinsights/workspaces/workspace-A", + "logs": [ + { + "categoryGroup": "allLogs", + "enabled": true + } + ] + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "ExtensionResourceType": "microsoft.insights/diagnosticSettings", + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + } + ] + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-R", + "Location": "region", + "Name": "registry-R", + "Properties": { + "loginServer": "registry-R.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + }, + { + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-S", + "Location": "region", + "Name": "registry-S", + "Properties": { + "loginServer": "registry-S.azurecr.io", + "adminUserEnabled": false + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "Sku": { + "Name": "Premium", + "Tier": "Premium" + }, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-S/providers/microsoft.insights/diagnosticSettings/logs", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/Microsoft.ContainerRegistry/registries/registry-S/providers/microsoft.insights/diagnosticSettings/logs", + "Name": "logs", + "ExtensionResourceName": "logs", + "properties": { + "workspaceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/test-rg/providers/microsoft.operationalinsights/workspaces/workspace-A", + "logs": [ + { + "category": "ContainerRegistryLoginEvents", + "enabled": true + } + ] + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.ContainerRegistry/registries", + "ExtensionResourceType": "microsoft.insights/diagnosticSettings", + "SubscriptionId": "00000000-0000-0000-0000-000000000000" + } + ] } ]