diff --git a/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.json b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.json new file mode 100644 index 00000000..84f9bbdf --- /dev/null +++ b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.json @@ -0,0 +1,159 @@ +{ + "name": "b5f9e3d2-2c34-4d8b-ae6f-4a7b8c9d0e12", + "type": "Microsoft.Authorization/policyDefinitions", + "properties": { + "displayName": "Configure Log Analytics table data retention (analytics and total retention)", + "mode": "All", + "description": "Configures analytics (retentionInDays) and total (totalRetentionInDays) retention of Log Analytics tables via DeployIfNotExists; App* tables are excluded. Filter with tableNameLike/tableNameNotLike; create a remediation task to fix existing tables. Requires a managed identity with Log Analytics Contributor. Part of the Log Analytics data retention guardrails set (workspace, table, and App Insights policies); initiative + one-click deploy: https://github.com/claestom/law-retention-guardrails", + "metadata": { + "category": "Monitoring", + "version": "2.0.0", + "source": "https://learn.microsoft.com/azure/azure-monitor/logs/data-retention-configure" + }, + "parameters": { + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "The policy effect. DeployIfNotExists remediates non-compliant tables, AuditIfNotExists only reports them, Disabled turns the policy off." + }, + "allowedValues": [ + "DeployIfNotExists", + "AuditIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "tableRetentionInDays": { + "type": "Integer", + "metadata": { + "displayName": "Table analytics retention (days)", + "description": "Analytics (interactive) retention in days for each table. Allowed range is 4-730. Defaults to 30. Keep this low to control cost; use total retention for long-term storage." + }, + "defaultValue": 30 + }, + "tableTotalRetentionInDays": { + "type": "Integer", + "metadata": { + "displayName": "Table total retention (days)", + "description": "Total retention in days (analytics + long-term) for each table. Valid values are 4-730, or 1095, 1460, 1826, 2191, 2556, 2922, 3288, 3653, 4018, 4383. Defaults to 30." + }, + "defaultValue": 30 + }, + "tableNameLike": { + "type": "String", + "metadata": { + "displayName": "Table name include pattern", + "description": "Only tables whose name matches this wildcard pattern are governed. '*' = all tables, 'App*' = Application Insights tables, '*_CL' = custom-log tables. Defaults to '*'." + }, + "defaultValue": "*" + }, + "tableNameNotLike": { + "type": "String", + "metadata": { + "displayName": "Table name exclude pattern", + "description": "Tables whose name matches this wildcard pattern are skipped. E.g. 'App*' excludes Application Insights tables so a second assignment can target them at a different retention. Defaults to a value that matches nothing (exclude none)." + }, + "defaultValue": "~noexclude~" + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.OperationalInsights/workspaces/tables" + }, + { + "field": "name", + "like": "[parameters('tableNameLike')]" + }, + { + "field": "name", + "notLike": "[parameters('tableNameNotLike')]" + }, + { + "field": "name", + "notIn": [ + "AppAvailabilityResults", + "AppBrowserTimings", + "AppDependencies", + "AppEvents", + "AppExceptions", + "AppMetrics", + "AppPageViews", + "AppPerformanceCounters", + "AppRequests", + "AppSystemEvents", + "AppTraces" + ] + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "name": "[field('fullName')]", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293" + ], + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.OperationalInsights/workspaces/tables/retentionInDays", + "equals": "[parameters('tableRetentionInDays')]" + }, + { + "field": "Microsoft.OperationalInsights/workspaces/tables/totalRetentionInDays", + "equals": "[parameters('tableTotalRetentionInDays')]" + } + ] + }, + "deployment": { + "properties": { + "mode": "incremental", + "parameters": { + "tableFullName": { + "value": "[field('fullName')]" + }, + "retentionInDays": { + "value": "[parameters('tableRetentionInDays')]" + }, + "totalRetentionInDays": { + "value": "[parameters('tableTotalRetentionInDays')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "tableFullName": { + "type": "string" + }, + "retentionInDays": { + "type": "int" + }, + "totalRetentionInDays": { + "type": "int" + } + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "apiVersion": "2022-10-01", + "name": "[parameters('tableFullName')]", + "properties": { + "retentionInDays": "[parameters('retentionInDays')]", + "totalRetentionInDays": "[parameters('totalRetentionInDays')]" + } + } + ] + } + } + } + } + } + } + } +} diff --git a/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.parameters.json b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.parameters.json new file mode 100644 index 00000000..c329d6ae --- /dev/null +++ b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.parameters.json @@ -0,0 +1,47 @@ +{ + "effect": { + "type": "String", + "metadata": { + "displayName": "Effect", + "description": "The policy effect. DeployIfNotExists remediates non-compliant tables, AuditIfNotExists only reports them, Disabled turns the policy off." + }, + "allowedValues": [ + "DeployIfNotExists", + "AuditIfNotExists", + "Disabled" + ], + "defaultValue": "DeployIfNotExists" + }, + "tableRetentionInDays": { + "type": "Integer", + "metadata": { + "displayName": "Table analytics retention (days)", + "description": "Analytics (interactive) retention in days for each table. Allowed range is 4-730. Defaults to 30. Keep this low to control cost; use total retention for long-term storage." + }, + "defaultValue": 30 + }, + "tableTotalRetentionInDays": { + "type": "Integer", + "metadata": { + "displayName": "Table total retention (days)", + "description": "Total retention in days (analytics + long-term) for each table. Valid values are 4-730, or 1095, 1460, 1826, 2191, 2556, 2922, 3288, 3653, 4018, 4383. Defaults to 30." + }, + "defaultValue": 30 + }, + "tableNameLike": { + "type": "String", + "metadata": { + "displayName": "Table name include pattern", + "description": "Only tables whose name matches this wildcard pattern are governed. '*' = all tables, 'App*' = Application Insights tables, '*_CL' = custom-log tables. Defaults to '*'." + }, + "defaultValue": "*" + }, + "tableNameNotLike": { + "type": "String", + "metadata": { + "displayName": "Table name exclude pattern", + "description": "Tables whose name matches this wildcard pattern are skipped. E.g. 'App*' excludes Application Insights tables so a second assignment can target them at a different retention. Defaults to a value that matches nothing (exclude none)." + }, + "defaultValue": "~noexclude~" + } +} diff --git a/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.rules.json b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.rules.json new file mode 100644 index 00000000..120373bc --- /dev/null +++ b/policyDefinitions/Monitoring/configure-law-table-retention/azurepolicy.rules.json @@ -0,0 +1,98 @@ +{ + "if": { + "allOf": [ + { + "field": "type", + "equals": "Microsoft.OperationalInsights/workspaces/tables" + }, + { + "field": "name", + "like": "[parameters('tableNameLike')]" + }, + { + "field": "name", + "notLike": "[parameters('tableNameNotLike')]" + }, + { + "field": "name", + "notIn": [ + "AppAvailabilityResults", + "AppBrowserTimings", + "AppDependencies", + "AppEvents", + "AppExceptions", + "AppMetrics", + "AppPageViews", + "AppPerformanceCounters", + "AppRequests", + "AppSystemEvents", + "AppTraces" + ] + } + ] + }, + "then": { + "effect": "[parameters('effect')]", + "details": { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "name": "[field('fullName')]", + "roleDefinitionIds": [ + "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293" + ], + "existenceCondition": { + "allOf": [ + { + "field": "Microsoft.OperationalInsights/workspaces/tables/retentionInDays", + "equals": "[parameters('tableRetentionInDays')]" + }, + { + "field": "Microsoft.OperationalInsights/workspaces/tables/totalRetentionInDays", + "equals": "[parameters('tableTotalRetentionInDays')]" + } + ] + }, + "deployment": { + "properties": { + "mode": "incremental", + "parameters": { + "tableFullName": { + "value": "[field('fullName')]" + }, + "retentionInDays": { + "value": "[parameters('tableRetentionInDays')]" + }, + "totalRetentionInDays": { + "value": "[parameters('tableTotalRetentionInDays')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "tableFullName": { + "type": "string" + }, + "retentionInDays": { + "type": "int" + }, + "totalRetentionInDays": { + "type": "int" + } + }, + "resources": [ + { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "apiVersion": "2022-10-01", + "name": "[parameters('tableFullName')]", + "properties": { + "retentionInDays": "[parameters('retentionInDays')]", + "totalRetentionInDays": "[parameters('totalRetentionInDays')]" + } + } + ] + } + } + } + } + } +}