From d9714ff12a2053db6093a8bbed035bf5607486ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Harjam=C3=A4ki?= Date: Fri, 3 Jul 2026 19:31:25 +0300 Subject: [PATCH] fix: secure observability public network access by default Parameterize public network access for Log Analytics and Application Insights instead of hardcoding 'Enabled'. Introduces bool param allowPublicNetworkAccess (default false) in the observability module, mapping to Enabled/Disabled for both ingestion and query on the workspace and the App Insights component. DisableLocalAuth and enableLogAccessUsingOnlyResourcePermissions are preserved. Wire allowObservabilityPublicNetworkAccess through main.bicep and the per-environment .bicepparam files: dev overrides to true, test and prod keep the secure default of false. Expand bicepconfig.json to production linter defaults: core analyzers enabled, secret/security rules at error, style/correctness rules at warning, no-hardcoded-env-urls at error, and use-recent-api-versions disabled to avoid churn. Co-Authored-By: Claude Opus 4.8 --- bicepconfig.json | 37 +++++++++++++++++++++++++++---- infra/main.bicep | 4 ++++ infra/modules/observability.bicep | 13 +++++++---- infra/parameters/dev.bicepparam | 1 + infra/parameters/prod.bicepparam | 1 + infra/parameters/test.bicepparam | 1 + 6 files changed, 49 insertions(+), 8 deletions(-) diff --git a/bicepconfig.json b/bicepconfig.json index 4afe4c1..7b7be46 100644 --- a/bicepconfig.json +++ b/bicepconfig.json @@ -2,16 +2,45 @@ "analyzers": { "core": { "enabled": true, + "verbose": false, "rules": { "adminusername-should-not-be-literal": { "level": "error" }, - "no-hardcoded-env-urls": { "level": "warning" }, + "artifacts-parameters": { "level": "warning" }, + "decompiler-cleanup": { "level": "warning" }, + "explicit-values-for-loc-params": { "level": "warning" }, + "max-asserts": { "level": "warning" }, + "max-outputs": { "level": "warning" }, + "max-params": { "level": "warning" }, + "max-resources": { "level": "warning" }, + "max-variables": { "level": "warning" }, + "nested-deployment-template-scoping": { "level": "error" }, + "no-conflicting-metadata": { "level": "warning" }, + "no-deployments-resources": { "level": "warning" }, + "no-hardcoded-env-urls": { "level": "error" }, + "no-hardcoded-location": { "level": "warning" }, + "no-loc-expr-outside-params": { "level": "warning" }, "no-unnecessary-dependson": { "level": "warning" }, + "no-unused-existing-resources": { "level": "warning" }, + "no-unused-params": { "level": "warning" }, + "no-unused-vars": { "level": "warning" }, "outputs-should-not-contain-secrets": { "level": "error" }, + "prefer-interpolation": { "level": "warning" }, + "prefer-unquoted-property-names": { "level": "warning" }, + "protect-commandtoexecute-secrets": { "level": "error" }, "secure-parameter-default": { "level": "error" }, - "use-recent-api-versions": { "level": "warning" }, - "use-resource-id-functions": { "level": "warning" } + "secure-params-in-nested-deploy": { "level": "error" }, + "secure-secrets-in-params": { "level": "error" }, + "simplify-interpolation": { "level": "warning" }, + "simplify-json-null": { "level": "warning" }, + "use-parent-property": { "level": "warning" }, + "use-recent-api-versions": { "level": "off" }, + "use-resource-id-functions": { "level": "warning" }, + "use-resource-symbol-reference": { "level": "warning" }, + "use-safe-access": { "level": "warning" }, + "use-secure-value-for-secure-inputs": { "level": "error" }, + "use-stable-resource-identifiers": { "level": "warning" }, + "use-stable-vm-image": { "level": "warning" } } } } } - diff --git a/infra/main.bicep b/infra/main.bicep index 7e61962..988ea68 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -59,6 +59,9 @@ param enableExternalIngress bool = false @minValue(30) param logRetentionDays int = 30 +@description('Allow public network access to Log Analytics and Application Insights ingestion/query. Secure default is false; lower environments (for example dev) may override to true.') +param allowObservabilityPublicNetworkAccess bool = false + @description('Optional monthly resource-group budget. Set to zero to disable.') @minValue(0) param monthlyBudget int = 0 @@ -94,6 +97,7 @@ module observability './modules/observability.bicep' = { location: location suffix: suffix retentionDays: logRetentionDays + allowPublicNetworkAccess: allowObservabilityPublicNetworkAccess tags: tags } } diff --git a/infra/modules/observability.bicep b/infra/modules/observability.bicep index cbf229c..5dd800a 100644 --- a/infra/modules/observability.bicep +++ b/infra/modules/observability.bicep @@ -18,6 +18,11 @@ param retentionDays int @description('Common Azure resource tags.') param tags object +@description('Allow public network access for observability ingestion and query. Secure default is false; individual environments (for example dev) may override to true.') +param allowPublicNetworkAccess bool = false + +var publicNetworkAccess = allowPublicNetworkAccess ? 'Enabled' : 'Disabled' + resource workspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: 'log-${workloadName}-${environment}-${suffix}' location: location @@ -27,8 +32,8 @@ resource workspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { features: { enableLogAccessUsingOnlyResourcePermissions: true } - publicNetworkAccessForIngestion: 'Enabled' - publicNetworkAccessForQuery: 'Enabled' + publicNetworkAccessForIngestion: publicNetworkAccess + publicNetworkAccessForQuery: publicNetworkAccess } } @@ -42,8 +47,8 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { WorkspaceResourceId: workspace.id DisableLocalAuth: true IngestionMode: 'LogAnalytics' - publicNetworkAccessForIngestion: 'Enabled' - publicNetworkAccessForQuery: 'Enabled' + publicNetworkAccessForIngestion: publicNetworkAccess + publicNetworkAccessForQuery: publicNetworkAccess } } diff --git a/infra/parameters/dev.bicepparam b/infra/parameters/dev.bicepparam index 393d9f9..bc9752d 100644 --- a/infra/parameters/dev.bicepparam +++ b/infra/parameters/dev.bicepparam @@ -13,5 +13,6 @@ param foundryProjectResourceId = '' param foundryRoleDefinitionResourceId = '' param enableExternalIngress = false param logRetentionDays = 30 +param allowObservabilityPublicNetworkAccess = true param monthlyBudget = 0 param budgetContactEmails = [] diff --git a/infra/parameters/prod.bicepparam b/infra/parameters/prod.bicepparam index 57484ad..6231d94 100644 --- a/infra/parameters/prod.bicepparam +++ b/infra/parameters/prod.bicepparam @@ -13,5 +13,6 @@ param foundryProjectResourceId = '' param foundryRoleDefinitionResourceId = '' param enableExternalIngress = false param logRetentionDays = 90 +param allowObservabilityPublicNetworkAccess = false param monthlyBudget = 0 param budgetContactEmails = [] diff --git a/infra/parameters/test.bicepparam b/infra/parameters/test.bicepparam index 702648b..4c21407 100644 --- a/infra/parameters/test.bicepparam +++ b/infra/parameters/test.bicepparam @@ -13,5 +13,6 @@ param foundryProjectResourceId = '' param foundryRoleDefinitionResourceId = '' param enableExternalIngress = false param logRetentionDays = 30 +param allowObservabilityPublicNetworkAccess = false param monthlyBudget = 0 param budgetContactEmails = []