Skip to content

Commit cbc17d0

Browse files
Merge pull request #244 from microsoft/psl-sw/43311-sfi-security-fixes
fix(infra): address SFI security compliance issues
2 parents e977522 + 9280da7 commit cbc17d0

4 files changed

Lines changed: 1676 additions & 12 deletions

File tree

infra/main.bicep

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,10 @@ module jumpboxVM 'br/public:avm/res/compute/virtual-machine:0.15.0' = if (enable
363363
adminPassword: vmAdminPassword ?? 'JumpboxAdminP@ssw0rd1234!'
364364
tags: allTags
365365
zone: 0
366+
// SFI: enable system-assigned managed identity on the jumpbox VM. Required so
367+
// the Azure Monitor Agent can authenticate to the Log Analytics workspace and
368+
// honor the SecurityAuditEvents data collection rule association.
369+
managedIdentities: { systemAssigned: true }
366370
imageReference: {
367371
offer: 'WindowsServer'
368372
publisher: 'MicrosoftWindowsServer'
@@ -409,6 +413,148 @@ module jumpboxVM 'br/public:avm/res/compute/virtual-machine:0.15.0' = if (enable
409413
}
410414
]
411415
enableTelemetry: enableTelemetry
416+
// SFI: associate the SecurityAuditEvents data collection rule with the
417+
// jumpbox VM via the Azure Monitor Agent extension. Routes Windows audit
418+
// success / audit failure events to Log Analytics. Gated on the same
419+
// (enablePrivateNetworking && enableMonitoring) expression as the DCR
420+
// module so the dereference of windowsVmDataCollectionRules!.outputs
421+
// stays safe even if the outer jumpbox VM gate ever changes.
422+
extensionMonitoringAgentConfig: (enablePrivateNetworking && enableMonitoring)
423+
? {
424+
enabled: true
425+
tags: allTags
426+
dataCollectionRuleAssociations: [
427+
{
428+
name: 'send-${logAnalyticsWorkspaceResourceName}'
429+
dataCollectionRuleResourceId: windowsVmDataCollectionRules!.outputs.resourceId
430+
}
431+
]
432+
}
433+
: null
434+
}
435+
}
436+
437+
// SFI: data collection rule that captures Windows Security audit success and
438+
// audit failure events from the jumpbox VM and routes them to Log Analytics
439+
// via the Microsoft-Event stream. The xPath filter uses the Windows
440+
// audit Keywords bitmask (0x30000000000000 = AuditSuccess|AuditFailure) and
441+
// excludes EventID 4624 (successful logon) because it is extremely
442+
// high-volume. Also collects a small set of Windows performance counters via
443+
// Microsoft-Perf for the jumpbox so the same DCR provides basic VM health
444+
// signal. The SecurityEvent / Perf tables are auto-provisioned by Azure
445+
// Monitor on first ingestion via the DCR; no legacy OMSGallery/Security
446+
// solution is needed.
447+
var dataCollectionRulesResourceName = 'dcr-${solutionSuffix}'
448+
var dataCollectionRulesLocation = useExistingLogAnalytics
449+
? existingLogAnalyticsWorkspace!.location
450+
: logAnalyticsWorkspace!.outputs.location
451+
var dcrLogAnalyticsDestinationName = 'la-${logAnalyticsWorkspaceResourceName}-destination'
452+
module windowsVmDataCollectionRules 'br/public:avm/res/insights/data-collection-rule:0.11.0' = if (enablePrivateNetworking && enableMonitoring) {
453+
name: take('avm.res.insights.data-collection-rule.${dataCollectionRulesResourceName}', 64)
454+
params: {
455+
name: dataCollectionRulesResourceName
456+
tags: allTags
457+
enableTelemetry: enableTelemetry
458+
location: dataCollectionRulesLocation
459+
dataCollectionRuleProperties: {
460+
kind: 'Windows'
461+
dataSources: {
462+
windowsEventLogs: [
463+
{
464+
name: 'SecurityAuditEvents'
465+
streams: [
466+
'Microsoft-Event'
467+
]
468+
xPathQueries: [
469+
'Security!*[System[(band(Keywords,13510798882111488)) and (EventID != 4624)]]'
470+
]
471+
}
472+
]
473+
performanceCounters: [
474+
{
475+
name: 'perfCounterDataSource60'
476+
streams: [
477+
'Microsoft-Perf'
478+
]
479+
samplingFrequencyInSeconds: 60
480+
counterSpecifiers: [
481+
'\\Processor Information(_Total)\\% Processor Time'
482+
'\\Processor Information(_Total)\\% Privileged Time'
483+
'\\Processor Information(_Total)\\% User Time'
484+
'\\Processor Information(_Total)\\Processor Frequency'
485+
'\\System\\Processes'
486+
'\\Process(_Total)\\Thread Count'
487+
'\\Process(_Total)\\Handle Count'
488+
'\\System\\System Up Time'
489+
'\\System\\Context Switches/sec'
490+
'\\System\\Processor Queue Length'
491+
'\\Memory\\% Committed Bytes In Use'
492+
'\\Memory\\Available Bytes'
493+
'\\Memory\\Committed Bytes'
494+
'\\Memory\\Cache Bytes'
495+
'\\Memory\\Pool Paged Bytes'
496+
'\\Memory\\Pool Nonpaged Bytes'
497+
'\\Memory\\Pages/sec'
498+
'\\Memory\\Page Faults/sec'
499+
'\\Process(_Total)\\Working Set'
500+
'\\Process(_Total)\\Working Set - Private'
501+
'\\LogicalDisk(_Total)\\% Disk Time'
502+
'\\LogicalDisk(_Total)\\% Disk Read Time'
503+
'\\LogicalDisk(_Total)\\% Disk Write Time'
504+
'\\LogicalDisk(_Total)\\% Idle Time'
505+
'\\LogicalDisk(_Total)\\Disk Bytes/sec'
506+
'\\LogicalDisk(_Total)\\Disk Read Bytes/sec'
507+
'\\LogicalDisk(_Total)\\Disk Write Bytes/sec'
508+
'\\LogicalDisk(_Total)\\Disk Transfers/sec'
509+
'\\LogicalDisk(_Total)\\Disk Reads/sec'
510+
'\\LogicalDisk(_Total)\\Disk Writes/sec'
511+
'\\LogicalDisk(_Total)\\Avg. Disk sec/Transfer'
512+
'\\LogicalDisk(_Total)\\Avg. Disk sec/Read'
513+
'\\LogicalDisk(_Total)\\Avg. Disk sec/Write'
514+
'\\LogicalDisk(_Total)\\Avg. Disk Queue Length'
515+
'\\LogicalDisk(_Total)\\Avg. Disk Read Queue Length'
516+
'\\LogicalDisk(_Total)\\Avg. Disk Write Queue Length'
517+
'\\LogicalDisk(_Total)\\% Free Space'
518+
'\\LogicalDisk(_Total)\\Free Megabytes'
519+
'\\Network Interface(*)\\Bytes Total/sec'
520+
'\\Network Interface(*)\\Bytes Sent/sec'
521+
'\\Network Interface(*)\\Bytes Received/sec'
522+
'\\Network Interface(*)\\Packets/sec'
523+
'\\Network Interface(*)\\Packets Sent/sec'
524+
'\\Network Interface(*)\\Packets Received/sec'
525+
'\\Network Interface(*)\\Packets Outbound Errors'
526+
'\\Network Interface(*)\\Packets Received Errors'
527+
]
528+
}
529+
]
530+
}
531+
destinations: {
532+
logAnalytics: [
533+
{
534+
workspaceResourceId: logAnalyticsWorkspaceResourceId
535+
name: dcrLogAnalyticsDestinationName
536+
}
537+
]
538+
}
539+
dataFlows: [
540+
{
541+
streams: [
542+
'Microsoft-Event'
543+
]
544+
destinations: [
545+
dcrLogAnalyticsDestinationName
546+
]
547+
}
548+
{
549+
streams: [
550+
'Microsoft-Perf'
551+
]
552+
destinations: [
553+
dcrLogAnalyticsDestinationName
554+
]
555+
}
556+
]
557+
}
412558
}
413559
}
414560

@@ -480,6 +626,8 @@ module storageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
480626
location: solutionLocation
481627
managedIdentities: { systemAssigned: true }
482628
minimumTlsVersion: 'TLS1_2'
629+
// SFI: enable infrastructure (double) encryption at rest
630+
requireInfrastructureEncryption: true
483631
enableTelemetry: enableTelemetry
484632
tags: allTags
485633
accessTier: 'Hot'
@@ -598,6 +746,8 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
598746
location: cosmosLocation
599747
tags: allTags
600748
enableTelemetry: enableTelemetry
749+
// SFI: enable system-assigned managed identity for Cosmos DB account
750+
managedIdentities: { systemAssigned: true }
601751
sqlDatabases: [
602752
{
603753
name: cosmosDatabaseName
@@ -1147,6 +1297,11 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
11471297
]
11481298
enableTelemetry: enableTelemetry
11491299
publicNetworkAccess: 'Enabled' // Always enabled for Container Apps Environment
1300+
// SFI: enable mTLS / end-to-end encryption between revisions within the
1301+
// Container Apps environment (Container Apps equivalent of App Service's
1302+
// endToEndEncryptionEnabled). Applies to Microsoft.App/managedEnvironments
1303+
// peerTrafficConfiguration.encryption.enabled.
1304+
peerTrafficEncryption: true
11501305

11511306
// <========== WAF related parameters
11521307

0 commit comments

Comments
 (0)