fedramp-20x-mcp 0.4.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fedramp_20x_mcp/__init__.py +14 -0
- fedramp_20x_mcp/__main__.py +12 -0
- fedramp_20x_mcp/data_loader.py +673 -0
- fedramp_20x_mcp/prompts/__init__.py +62 -0
- fedramp_20x_mcp/prompts/api_design_guide.txt +432 -0
- fedramp_20x_mcp/prompts/ato_package_checklist.txt +75 -0
- fedramp_20x_mcp/prompts/audit_preparation.txt +592 -0
- fedramp_20x_mcp/prompts/authorization_boundary_review.txt +76 -0
- fedramp_20x_mcp/prompts/azure_ksi_automation.txt +997 -0
- fedramp_20x_mcp/prompts/continuous_monitoring_setup.txt +61 -0
- fedramp_20x_mcp/prompts/documentation_generator.txt +499 -0
- fedramp_20x_mcp/prompts/gap_analysis.txt +25 -0
- fedramp_20x_mcp/prompts/initial_assessment_roadmap.txt +202 -0
- fedramp_20x_mcp/prompts/ksi_implementation_priorities.txt +283 -0
- fedramp_20x_mcp/prompts/migration_from_rev5.txt +440 -0
- fedramp_20x_mcp/prompts/quarterly_review_checklist.txt +231 -0
- fedramp_20x_mcp/prompts/significant_change_assessment.txt +50 -0
- fedramp_20x_mcp/prompts/vendor_evaluation.txt +349 -0
- fedramp_20x_mcp/prompts/vulnerability_remediation_timeline.txt +45 -0
- fedramp_20x_mcp/server.py +270 -0
- fedramp_20x_mcp/templates/__init__.py +75 -0
- fedramp_20x_mcp/templates/bicep/afr.txt +33 -0
- fedramp_20x_mcp/templates/bicep/cna.txt +48 -0
- fedramp_20x_mcp/templates/bicep/generic.txt +47 -0
- fedramp_20x_mcp/templates/bicep/iam.txt +211 -0
- fedramp_20x_mcp/templates/bicep/mla.txt +82 -0
- fedramp_20x_mcp/templates/bicep/rpl.txt +44 -0
- fedramp_20x_mcp/templates/bicep/svc.txt +54 -0
- fedramp_20x_mcp/templates/code/generic_csharp.txt +65 -0
- fedramp_20x_mcp/templates/code/generic_powershell.txt +65 -0
- fedramp_20x_mcp/templates/code/generic_python.txt +63 -0
- fedramp_20x_mcp/templates/code/iam_csharp.txt +150 -0
- fedramp_20x_mcp/templates/code/iam_powershell.txt +162 -0
- fedramp_20x_mcp/templates/code/iam_python.txt +224 -0
- fedramp_20x_mcp/templates/code/mla_python.txt +124 -0
- fedramp_20x_mcp/templates/terraform/afr.txt +29 -0
- fedramp_20x_mcp/templates/terraform/cna.txt +50 -0
- fedramp_20x_mcp/templates/terraform/generic.txt +40 -0
- fedramp_20x_mcp/templates/terraform/iam.txt +219 -0
- fedramp_20x_mcp/templates/terraform/mla.txt +29 -0
- fedramp_20x_mcp/templates/terraform/rpl.txt +32 -0
- fedramp_20x_mcp/templates/terraform/svc.txt +46 -0
- fedramp_20x_mcp/tools/__init__.py +167 -0
- fedramp_20x_mcp/tools/definitions.py +154 -0
- fedramp_20x_mcp/tools/documentation.py +155 -0
- fedramp_20x_mcp/tools/enhancements.py +2256 -0
- fedramp_20x_mcp/tools/evidence.py +701 -0
- fedramp_20x_mcp/tools/export.py +753 -0
- fedramp_20x_mcp/tools/ksi.py +90 -0
- fedramp_20x_mcp/tools/requirements.py +163 -0
- fedramp_20x_mcp-0.4.8.dist-info/METADATA +877 -0
- fedramp_20x_mcp-0.4.8.dist-info/RECORD +55 -0
- fedramp_20x_mcp-0.4.8.dist-info/WHEEL +4 -0
- fedramp_20x_mcp-0.4.8.dist-info/entry_points.txt +2 -0
- fedramp_20x_mcp-0.4.8.dist-info/licenses/LICENSE +27 -0
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
I'll help you implement FedRAMP 20x KSI automation using Microsoft, Azure, and M365 services.
|
|
2
|
+
|
|
3
|
+
# Azure/M365 KSI Automation Guide
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This guide maps all 72 FedRAMP 20x Key Security Indicators to specific Microsoft services and provides automation approaches for evidence collection.
|
|
8
|
+
|
|
9
|
+
**Key Microsoft Services for FedRAMP 20x:**
|
|
10
|
+
- **Microsoft Sentinel** - SIEM/SOAR (KSI-MLA)
|
|
11
|
+
- **Microsoft Defender for Cloud** - Security posture management (KSI-AFR, KSI-CNA)
|
|
12
|
+
- **Microsoft Entra ID** (formerly Azure AD) - Identity & Access (KSI-IAM)
|
|
13
|
+
- **Azure Policy** - Configuration compliance (KSI-PIY, KSI-CMT)
|
|
14
|
+
- **Azure Monitor & Log Analytics** - Logging & monitoring (KSI-MLA)
|
|
15
|
+
- **Microsoft Purview** - Data governance (KSI-TPR, KSI-PIY)
|
|
16
|
+
- **Azure DevOps / GitHub Advanced Security** - CI/CD & security scanning (KSI-CMT)
|
|
17
|
+
- **Microsoft Defender suite** - Endpoint, Cloud Apps, Office 365 (various KSIs)
|
|
18
|
+
|
|
19
|
+
## KSI Family Automation
|
|
20
|
+
|
|
21
|
+
### KSI-IAM: Identity & Access Management (7 KSIs)
|
|
22
|
+
|
|
23
|
+
**KSI-IAM-01: Phishing-Resistant MFA**
|
|
24
|
+
|
|
25
|
+
**Azure Services:**
|
|
26
|
+
- Microsoft Entra ID with Conditional Access
|
|
27
|
+
- FIDO2 security keys or Windows Hello for Business
|
|
28
|
+
- Microsoft Authenticator (passwordless)
|
|
29
|
+
|
|
30
|
+
**Automation:**
|
|
31
|
+
```powershell
|
|
32
|
+
# Connect to Microsoft Graph
|
|
33
|
+
Connect-MgGraph -Scopes "UserAuthenticationMethod.Read.All", "Policy.Read.All"
|
|
34
|
+
|
|
35
|
+
# Get MFA status for all users
|
|
36
|
+
$users = Get-MgUser -All
|
|
37
|
+
$mfaReport = @()
|
|
38
|
+
|
|
39
|
+
foreach ($user in $users) {
|
|
40
|
+
$authMethods = Get-MgUserAuthenticationMethod -UserId $user.Id
|
|
41
|
+
$hasFIDO2 = $authMethods | Where-Object { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.fido2AuthenticationMethod' }
|
|
42
|
+
|
|
43
|
+
$mfaReport += [PSCustomObject]@{
|
|
44
|
+
UserPrincipalName = $user.UserPrincipalName
|
|
45
|
+
HasFIDO2 = ($hasFIDO2 -ne $null)
|
|
46
|
+
MFAEnabled = $authMethods.Count -gt 1
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Generate compliance report
|
|
51
|
+
$mfaReport | Export-Csv "mfa-compliance-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Evidence Collection:**
|
|
55
|
+
- Microsoft Entra ID sign-in logs (Graph API)
|
|
56
|
+
- Authentication methods report
|
|
57
|
+
- Conditional Access policy export
|
|
58
|
+
- Store in Azure Blob Storage with immutability
|
|
59
|
+
|
|
60
|
+
**KSI-IAM-02 through IAM-07**
|
|
61
|
+
|
|
62
|
+
**Automation via Microsoft Graph API:**
|
|
63
|
+
```powershell
|
|
64
|
+
# IAM-02: Passwordless authentication
|
|
65
|
+
Get-MgBetaReportAuthenticationMethodUserRegistrationDetail |
|
|
66
|
+
Where-Object { $_.IsPasswordlessCapable -eq $true }
|
|
67
|
+
|
|
68
|
+
# IAM-05: Least privilege (Privileged Identity Management)
|
|
69
|
+
Get-MgRoleManagementDirectoryRoleAssignment |
|
|
70
|
+
Where-Object { $_.PrincipalType -eq "User" }
|
|
71
|
+
|
|
72
|
+
# IAM-06: Suspicious activity detection
|
|
73
|
+
# Configure Microsoft Entra ID Protection
|
|
74
|
+
$riskDetections = Get-MgRiskDetection -Top 100
|
|
75
|
+
$riskDetections | Export-Csv "risk-detections-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Automated Evidence:**
|
|
79
|
+
- Use Azure Logic Apps to collect daily reports
|
|
80
|
+
- Store in Azure Storage with compliance tags
|
|
81
|
+
- Integrate with Sentinel for alerting
|
|
82
|
+
|
|
83
|
+
### KSI-MLA: Monitoring, Logging & Analysis (5 KSIs)
|
|
84
|
+
|
|
85
|
+
**KSI-MLA-01: Centralized Logging (SIEM)**
|
|
86
|
+
|
|
87
|
+
**Azure Services:**
|
|
88
|
+
- Microsoft Sentinel (Azure-native SIEM)
|
|
89
|
+
- Log Analytics Workspace
|
|
90
|
+
- Azure Monitor Agent
|
|
91
|
+
|
|
92
|
+
**Automation:**
|
|
93
|
+
```bash
|
|
94
|
+
# Deploy Sentinel workspace with Azure CLI
|
|
95
|
+
az sentinel workspace create \
|
|
96
|
+
--resource-group rg-fedramp \
|
|
97
|
+
--name sentinel-fedramp \
|
|
98
|
+
--location eastus
|
|
99
|
+
|
|
100
|
+
# Enable all data connectors
|
|
101
|
+
az sentinel data-connector create \
|
|
102
|
+
--resource-group rg-fedramp \
|
|
103
|
+
--workspace-name sentinel-fedramp \
|
|
104
|
+
--kind AzureActiveDirectory
|
|
105
|
+
|
|
106
|
+
# Configure log retention (1 year minimum for FedRAMP)
|
|
107
|
+
az monitor log-analytics workspace update \
|
|
108
|
+
--resource-group rg-fedramp \
|
|
109
|
+
--workspace-name sentinel-fedramp \
|
|
110
|
+
--retention-time 365
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Evidence Collection via KQL:**
|
|
114
|
+
```kusto
|
|
115
|
+
// Daily log ingestion report
|
|
116
|
+
Usage
|
|
117
|
+
| where TimeGenerated > ago(1d)
|
|
118
|
+
| where IsBillable == true
|
|
119
|
+
| summarize TotalGB = sum(Quantity) / 1000 by DataType
|
|
120
|
+
| order by TotalGB desc
|
|
121
|
+
|
|
122
|
+
// Store results in Azure Data Explorer for historical tracking
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**KSI-MLA-02: Audit Logging**
|
|
126
|
+
|
|
127
|
+
**Automation:**
|
|
128
|
+
```powershell
|
|
129
|
+
# Enable diagnostic settings for all Azure resources
|
|
130
|
+
$resources = Get-AzResource
|
|
131
|
+
|
|
132
|
+
foreach ($resource in $resources) {
|
|
133
|
+
$diagnosticSettings = @{
|
|
134
|
+
Name = "fedramp-logging"
|
|
135
|
+
ResourceId = $resource.ResourceId
|
|
136
|
+
WorkspaceId = "/subscriptions/.../workspaces/sentinel-fedramp"
|
|
137
|
+
Enabled = $true
|
|
138
|
+
Category = @("AuditEvent", "Administrative", "Security")
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Set-AzDiagnosticSetting @diagnosticSettings
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**KSI-MLA-05: Infrastructure as Code**
|
|
146
|
+
|
|
147
|
+
**Azure Services:**
|
|
148
|
+
- Azure Repos (for Bicep/ARM/Terraform)
|
|
149
|
+
- Azure DevOps Pipelines
|
|
150
|
+
- Azure Policy for IaC validation
|
|
151
|
+
|
|
152
|
+
**Automation:**
|
|
153
|
+
```yaml
|
|
154
|
+
# Azure Pipeline to validate IaC compliance
|
|
155
|
+
trigger:
|
|
156
|
+
- main
|
|
157
|
+
|
|
158
|
+
pool:
|
|
159
|
+
vmImage: 'ubuntu-latest'
|
|
160
|
+
|
|
161
|
+
steps:
|
|
162
|
+
- task: AzureCLI@2
|
|
163
|
+
inputs:
|
|
164
|
+
azureSubscription: 'fedramp-connection'
|
|
165
|
+
scriptType: 'bash'
|
|
166
|
+
scriptLocation: 'inlineScript'
|
|
167
|
+
inlineScript: |
|
|
168
|
+
# Scan Bicep files
|
|
169
|
+
az bicep build --file main.bicep
|
|
170
|
+
|
|
171
|
+
# Run Azure Policy compliance check
|
|
172
|
+
az policy state list --resource-group rg-fedramp \
|
|
173
|
+
--query "[?complianceState=='NonCompliant']" > compliance-report.json
|
|
174
|
+
|
|
175
|
+
# Upload to evidence storage
|
|
176
|
+
az storage blob upload \
|
|
177
|
+
--account-name fedrampevidence \
|
|
178
|
+
--container-name iac-compliance \
|
|
179
|
+
--name "compliance-$(date +%Y-%m-%d).json" \
|
|
180
|
+
--file compliance-report.json
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### KSI-AFR: Automated Findings & Remediation (5 KSIs)
|
|
184
|
+
|
|
185
|
+
**KSI-AFR-01: Vulnerability Scanning**
|
|
186
|
+
|
|
187
|
+
**Azure Services:**
|
|
188
|
+
- Microsoft Defender for Cloud
|
|
189
|
+
- Microsoft Defender for Containers
|
|
190
|
+
- GitHub Advanced Security (for code)
|
|
191
|
+
|
|
192
|
+
**Automation:**
|
|
193
|
+
```powershell
|
|
194
|
+
# Get vulnerability assessment findings from Defender for Cloud
|
|
195
|
+
$vulnerabilities = Get-AzSecurityTask | Where-Object {
|
|
196
|
+
$_.SecurityTaskParameters.Name -match "Vulnerability"
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# Generate FedRAMP-compliant report
|
|
200
|
+
$vulnReport = $vulnerabilities | Select-Object @{
|
|
201
|
+
Name = 'FindingId'; Expression = { $_.Name }
|
|
202
|
+
}, @{
|
|
203
|
+
Name = 'Severity'; Expression = { $_.SecurityTaskParameters.Severity }
|
|
204
|
+
}, @{
|
|
205
|
+
Name = 'Resource'; Expression = { $_.ResourceId }
|
|
206
|
+
}, @{
|
|
207
|
+
Name = 'DetectedDate'; Expression = { $_.TimeGenerated }
|
|
208
|
+
}, @{
|
|
209
|
+
Name = 'DueDate'; Expression = {
|
|
210
|
+
# Calculate based on FRR-VDR timeframes
|
|
211
|
+
$days = switch ($_.SecurityTaskParameters.Severity) {
|
|
212
|
+
'Critical' { 7 }
|
|
213
|
+
'High' { 15 }
|
|
214
|
+
'Medium' { 30 }
|
|
215
|
+
default { 90 }
|
|
216
|
+
}
|
|
217
|
+
(Get-Date).AddDays($days)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
$vulnReport | Export-Csv "vuln-report-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Automated Remediation:**
|
|
225
|
+
```powershell
|
|
226
|
+
# Enable automatic remediation in Defender for Cloud
|
|
227
|
+
Update-AzSecurityAutoProvisioningSetting -Name "default" -EnableAutoProvision
|
|
228
|
+
|
|
229
|
+
# Create Azure Logic App for ticket creation
|
|
230
|
+
# When new vulnerability detected -> Create Azure DevOps work item
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**KSI-AFR-04: Continuous Scanning**
|
|
234
|
+
|
|
235
|
+
**Automation:**
|
|
236
|
+
```bash
|
|
237
|
+
# Enable Defender for Cloud on all subscriptions
|
|
238
|
+
az security pricing create \
|
|
239
|
+
--name VirtualMachines \
|
|
240
|
+
--tier Standard
|
|
241
|
+
|
|
242
|
+
az security pricing create \
|
|
243
|
+
--name Containers \
|
|
244
|
+
--tier Standard
|
|
245
|
+
|
|
246
|
+
# Configure continuous export to Log Analytics
|
|
247
|
+
az security automation create \
|
|
248
|
+
--resource-group rg-fedramp \
|
|
249
|
+
--name export-vulnerabilities \
|
|
250
|
+
--location eastus \
|
|
251
|
+
--scopes "/subscriptions/{subscription-id}" \
|
|
252
|
+
--sources "Assessments" \
|
|
253
|
+
--actions '[{
|
|
254
|
+
"actionType": "LogAnalytics",
|
|
255
|
+
"workspaceResourceId": "/subscriptions/.../workspaces/sentinel-fedramp"
|
|
256
|
+
}]'
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### KSI-CMT: Change Management & Testing (4 KSIs)
|
|
260
|
+
|
|
261
|
+
**KSI-CMT-01: Track Changes**
|
|
262
|
+
|
|
263
|
+
**Azure Services:**
|
|
264
|
+
- Azure DevOps (change tracking)
|
|
265
|
+
- Azure Repos (version control)
|
|
266
|
+
- Azure Resource Graph (infrastructure changes)
|
|
267
|
+
|
|
268
|
+
**Automation:**
|
|
269
|
+
```kusto
|
|
270
|
+
// Query all Azure resource changes in last 30 days
|
|
271
|
+
resourcechanges
|
|
272
|
+
| where timestamp > ago(30d)
|
|
273
|
+
| extend changeType = properties.changeType
|
|
274
|
+
| extend changedBy = properties.changeAttributes.changedBy
|
|
275
|
+
| project timestamp, changeType, changedBy, resourceId = id, changes = properties.changes
|
|
276
|
+
| order by timestamp desc
|
|
277
|
+
|
|
278
|
+
// Export to CSV for evidence
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Change Notification Automation:**
|
|
282
|
+
```powershell
|
|
283
|
+
# Monitor Azure Activity Log for significant changes
|
|
284
|
+
$activityLogs = Get-AzActivityLog -StartTime (Get-Date).AddDays(-1)
|
|
285
|
+
|
|
286
|
+
$significantChanges = $activityLogs | Where-Object {
|
|
287
|
+
$_.OperationName.Value -in @(
|
|
288
|
+
'Microsoft.Compute/virtualMachines/write',
|
|
289
|
+
'Microsoft.Network/networkSecurityGroups/write',
|
|
290
|
+
'Microsoft.KeyVault/vaults/write'
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
# Send to Teams channel via webhook
|
|
295
|
+
foreach ($change in $significantChanges) {
|
|
296
|
+
$body = @{
|
|
297
|
+
text = "Significant Change Detected: $($change.OperationName.Value) by $($change.Caller)"
|
|
298
|
+
} | ConvertTo-Json
|
|
299
|
+
|
|
300
|
+
Invoke-RestMethod -Uri $env:TEAMS_WEBHOOK_URL -Method Post -Body $body -ContentType 'application/json'
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**KSI-CMT-03: Automated Testing**
|
|
305
|
+
|
|
306
|
+
**Azure DevOps Pipeline:**
|
|
307
|
+
```yaml
|
|
308
|
+
# Complete FedRAMP testing pipeline
|
|
309
|
+
stages:
|
|
310
|
+
- stage: SecurityScanning
|
|
311
|
+
jobs:
|
|
312
|
+
- job: SAST
|
|
313
|
+
steps:
|
|
314
|
+
- task: GitHubAdvancedSecurity@1
|
|
315
|
+
displayName: 'Run SAST'
|
|
316
|
+
|
|
317
|
+
- job: ContainerScan
|
|
318
|
+
steps:
|
|
319
|
+
- task: AzureContainerRegistry@2
|
|
320
|
+
displayName: 'Scan container images'
|
|
321
|
+
|
|
322
|
+
- job: IaCValidation
|
|
323
|
+
steps:
|
|
324
|
+
- task: AzureCLI@2
|
|
325
|
+
displayName: 'Validate Bicep/Terraform'
|
|
326
|
+
inputs:
|
|
327
|
+
scriptType: 'bash'
|
|
328
|
+
inlineScript: |
|
|
329
|
+
az bicep build --file main.bicep
|
|
330
|
+
terraform validate
|
|
331
|
+
|
|
332
|
+
- stage: Deploy
|
|
333
|
+
dependsOn: SecurityScanning
|
|
334
|
+
condition: succeeded()
|
|
335
|
+
jobs:
|
|
336
|
+
- deployment: DeployToStaging
|
|
337
|
+
environment: staging
|
|
338
|
+
strategy:
|
|
339
|
+
runOnce:
|
|
340
|
+
deploy:
|
|
341
|
+
steps:
|
|
342
|
+
- task: AzureResourceManagerTemplateDeployment@3
|
|
343
|
+
|
|
344
|
+
- stage: IntegrationTests
|
|
345
|
+
jobs:
|
|
346
|
+
- job: RunTests
|
|
347
|
+
steps:
|
|
348
|
+
- task: AzureCLI@2
|
|
349
|
+
displayName: 'Run integration tests'
|
|
350
|
+
|
|
351
|
+
# Store test results in Azure Blob
|
|
352
|
+
- task: PublishPipelineArtifact@1
|
|
353
|
+
inputs:
|
|
354
|
+
targetPath: 'test-results'
|
|
355
|
+
artifact: 'fedramp-test-evidence'
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### KSI-CNA: Cloud-Native Architecture (8 KSIs)
|
|
359
|
+
|
|
360
|
+
**KSI-CNA-01: Restrict Network Traffic**
|
|
361
|
+
|
|
362
|
+
**Azure Services:**
|
|
363
|
+
- Network Security Groups (NSGs)
|
|
364
|
+
- Azure Firewall
|
|
365
|
+
- Azure Policy
|
|
366
|
+
|
|
367
|
+
**Automation:**
|
|
368
|
+
```powershell
|
|
369
|
+
# Audit NSG rules for compliance
|
|
370
|
+
$nsgs = Get-AzNetworkSecurityGroup
|
|
371
|
+
|
|
372
|
+
$nonCompliantRules = @()
|
|
373
|
+
foreach ($nsg in $nsgs) {
|
|
374
|
+
foreach ($rule in $nsg.SecurityRules) {
|
|
375
|
+
if ($rule.SourceAddressPrefix -eq "*" -and $rule.Direction -eq "Inbound") {
|
|
376
|
+
$nonCompliantRules += [PSCustomObject]@{
|
|
377
|
+
NSG = $nsg.Name
|
|
378
|
+
Rule = $rule.Name
|
|
379
|
+
Issue = "Allows traffic from any source"
|
|
380
|
+
Severity = "High"
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
$nonCompliantRules | Export-Csv "nsg-audit-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**Azure Policy for Network Compliance:**
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"policyRule": {
|
|
393
|
+
"if": {
|
|
394
|
+
"allOf": [
|
|
395
|
+
{
|
|
396
|
+
"field": "type",
|
|
397
|
+
"equals": "Microsoft.Network/networkSecurityGroups/securityRules"
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
"field": "Microsoft.Network/networkSecurityGroups/securityRules/sourceAddressPrefix",
|
|
401
|
+
"equals": "*"
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"field": "Microsoft.Network/networkSecurityGroups/securityRules/access",
|
|
405
|
+
"equals": "Allow"
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
},
|
|
409
|
+
"then": {
|
|
410
|
+
"effect": "deny"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
**KSI-CNA-04: Immutable Infrastructure**
|
|
417
|
+
|
|
418
|
+
**Azure Services:**
|
|
419
|
+
- Azure VM Image Builder
|
|
420
|
+
- Azure Container Registry with image immutability
|
|
421
|
+
- Azure Kubernetes Service (AKS) with node pools
|
|
422
|
+
|
|
423
|
+
**Automation:**
|
|
424
|
+
```bash
|
|
425
|
+
# Enable ACR image immutability
|
|
426
|
+
az acr config retention update \
|
|
427
|
+
--registry fedrampregistry \
|
|
428
|
+
--status enabled \
|
|
429
|
+
--days 365 \
|
|
430
|
+
--type UntaggedManifests
|
|
431
|
+
|
|
432
|
+
# Configure AKS for immutable nodes
|
|
433
|
+
az aks nodepool update \
|
|
434
|
+
--resource-group rg-fedramp \
|
|
435
|
+
--cluster-name aks-fedramp \
|
|
436
|
+
--name nodepool1 \
|
|
437
|
+
--mode System \
|
|
438
|
+
--enable-node-public-ip false
|
|
439
|
+
|
|
440
|
+
# Evidence: Daily snapshot of infrastructure state
|
|
441
|
+
az resource list --query "[].{Name:name, Type:type, Location:location}" \
|
|
442
|
+
-o json > "infrastructure-state-$(date +%Y-%m-%d).json"
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### KSI-INR: Incident Notification & Response (3 KSIs)
|
|
446
|
+
|
|
447
|
+
**Azure Services:**
|
|
448
|
+
- Microsoft Sentinel (SIEM/SOAR)
|
|
449
|
+
- Azure Logic Apps (automation)
|
|
450
|
+
- Microsoft Teams (notifications)
|
|
451
|
+
|
|
452
|
+
**Automation:**
|
|
453
|
+
```powershell
|
|
454
|
+
# Create Sentinel Analytics Rule for incident detection
|
|
455
|
+
$rule = @{
|
|
456
|
+
DisplayName = "Suspicious Sign-in Activity"
|
|
457
|
+
Query = @"
|
|
458
|
+
SigninLogs
|
|
459
|
+
| where ResultType != 0
|
|
460
|
+
| where TimeGenerated > ago(1h)
|
|
461
|
+
| summarize FailedAttempts = count() by UserPrincipalName, IPAddress
|
|
462
|
+
| where FailedAttempts > 5
|
|
463
|
+
"@
|
|
464
|
+
Severity = "High"
|
|
465
|
+
Enabled = $true
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
New-AzSentinelAlertRule @rule -WorkspaceName "sentinel-fedramp"
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Automated Incident Response Playbook:**
|
|
472
|
+
```json
|
|
473
|
+
{
|
|
474
|
+
"type": "Microsoft.Logic/workflows",
|
|
475
|
+
"properties": {
|
|
476
|
+
"definition": {
|
|
477
|
+
"triggers": {
|
|
478
|
+
"When_Sentinel_Incident_Created": {
|
|
479
|
+
"type": "ApiConnection",
|
|
480
|
+
"inputs": {
|
|
481
|
+
"host": {
|
|
482
|
+
"connection": {
|
|
483
|
+
"name": "@parameters('$connections')['azuresentinel']"
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
"actions": {
|
|
490
|
+
"Post_to_Teams": {
|
|
491
|
+
"type": "ApiConnection",
|
|
492
|
+
"inputs": {
|
|
493
|
+
"host": {
|
|
494
|
+
"connection": {
|
|
495
|
+
"name": "@parameters('$connections')['teams']"
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
"method": "post",
|
|
499
|
+
"body": {
|
|
500
|
+
"message": "New Security Incident: @{triggerBody()?['title']}"
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
},
|
|
504
|
+
"Create_ServiceNow_Ticket": {
|
|
505
|
+
"type": "ApiConnection",
|
|
506
|
+
"runAfter": {
|
|
507
|
+
"Post_to_Teams": ["Succeeded"]
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
"Store_Incident_Evidence": {
|
|
511
|
+
"type": "ApiConnection",
|
|
512
|
+
"inputs": {
|
|
513
|
+
"host": {
|
|
514
|
+
"connection": {
|
|
515
|
+
"name": "@parameters('$connections')['azureblob']"
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
"method": "put",
|
|
519
|
+
"path": "/evidence/incident-@{triggerBody()?['incidentNumber']}.json",
|
|
520
|
+
"body": "@triggerBody()"
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
### KSI-RPL: Recovery Planning (3 KSIs)
|
|
530
|
+
|
|
531
|
+
**KSI-RPL-03: Backup Testing**
|
|
532
|
+
|
|
533
|
+
**Azure Services:**
|
|
534
|
+
- Azure Backup
|
|
535
|
+
- Azure Site Recovery
|
|
536
|
+
- Azure Automation
|
|
537
|
+
|
|
538
|
+
**Automation:**
|
|
539
|
+
```powershell
|
|
540
|
+
# Automated backup verification
|
|
541
|
+
$vaults = Get-AzRecoveryServicesVault
|
|
542
|
+
|
|
543
|
+
$backupReport = @()
|
|
544
|
+
foreach ($vault in $vaults) {
|
|
545
|
+
Set-AzRecoveryServicesVaultContext -Vault $vault
|
|
546
|
+
|
|
547
|
+
$containers = Get-AzRecoveryServicesBackupContainer -ContainerType AzureVM
|
|
548
|
+
|
|
549
|
+
foreach ($container in $containers) {
|
|
550
|
+
$items = Get-AzRecoveryServicesBackupItem -Container $container -WorkloadType AzureVM
|
|
551
|
+
|
|
552
|
+
foreach ($item in $items) {
|
|
553
|
+
$rp = Get-AzRecoveryServicesBackupRecoveryPoint -Item $item | Select-Object -First 1
|
|
554
|
+
|
|
555
|
+
$backupReport += [PSCustomObject]@{
|
|
556
|
+
VM = $item.Name
|
|
557
|
+
LastBackup = $rp.RecoveryPointTime
|
|
558
|
+
Status = $item.ProtectionStatus
|
|
559
|
+
DaysSinceBackup = ((Get-Date) - $rp.RecoveryPointTime).Days
|
|
560
|
+
Compliant = ((Get-Date) - $rp.RecoveryPointTime).Days -le 1
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
$backupReport | Export-Csv "backup-compliance-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
567
|
+
|
|
568
|
+
# Alert if backups are stale
|
|
569
|
+
$staleBackups = $backupReport | Where-Object { -not $_.Compliant }
|
|
570
|
+
if ($staleBackups) {
|
|
571
|
+
# Send alert via Teams/Email
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Automated DR Testing:**
|
|
576
|
+
```bash
|
|
577
|
+
# Schedule quarterly DR test with Azure Automation
|
|
578
|
+
az automation runbook create \
|
|
579
|
+
--resource-group rg-fedramp \
|
|
580
|
+
--automation-account-name automation-fedramp \
|
|
581
|
+
--name "QuarterlyDRTest" \
|
|
582
|
+
--type PowerShell \
|
|
583
|
+
--location eastus
|
|
584
|
+
|
|
585
|
+
# Create schedule for quarterly execution
|
|
586
|
+
az automation schedule create \
|
|
587
|
+
--resource-group rg-fedramp \
|
|
588
|
+
--automation-account-name automation-fedramp \
|
|
589
|
+
--name "QuarterlyDRSchedule" \
|
|
590
|
+
--frequency Quarter \
|
|
591
|
+
--interval 1
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### KSI-PIY: Platform Investment (10 KSIs)
|
|
595
|
+
|
|
596
|
+
**KSI-PIY-01: Automated Inventory**
|
|
597
|
+
|
|
598
|
+
**Azure Services:**
|
|
599
|
+
- Azure Resource Graph
|
|
600
|
+
- Microsoft Defender for Cloud
|
|
601
|
+
- Azure Policy
|
|
602
|
+
|
|
603
|
+
**Automation:**
|
|
604
|
+
```kusto
|
|
605
|
+
// Complete Azure resource inventory
|
|
606
|
+
Resources
|
|
607
|
+
| project
|
|
608
|
+
ResourceId = id,
|
|
609
|
+
Name = name,
|
|
610
|
+
Type = type,
|
|
611
|
+
Location = location,
|
|
612
|
+
ResourceGroup = resourceGroup,
|
|
613
|
+
SubscriptionId = subscriptionId,
|
|
614
|
+
Tags = tags,
|
|
615
|
+
CreatedDate = properties.createdTime,
|
|
616
|
+
ModifiedDate = properties.changedTime
|
|
617
|
+
| join kind=leftouter (
|
|
618
|
+
SecurityResources
|
|
619
|
+
| where type == "microsoft.security/assessments"
|
|
620
|
+
| project ResourceId = id, SecurityScore = properties.status.code
|
|
621
|
+
) on ResourceId
|
|
622
|
+
| order by ModifiedDate desc
|
|
623
|
+
|
|
624
|
+
// Export daily to Blob Storage
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
**Automated Configuration Baseline:**
|
|
628
|
+
```powershell
|
|
629
|
+
# Use Azure Policy Guest Configuration
|
|
630
|
+
$guestConfig = @{
|
|
631
|
+
Name = "FedRAMP-Baseline-Windows"
|
|
632
|
+
PolicyDefinitionId = "/providers/Microsoft.Authorization/policyDefinitions/..."
|
|
633
|
+
Scope = "/subscriptions/{subscription-id}"
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
New-AzPolicyAssignment @guestConfig
|
|
637
|
+
|
|
638
|
+
# Daily compliance report
|
|
639
|
+
Get-AzPolicyState -PolicyAssignmentName "FedRAMP-Baseline-Windows" |
|
|
640
|
+
Select-Object ResourceId, ComplianceState, PolicyDefinitionAction |
|
|
641
|
+
Export-Csv "config-compliance-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
### KSI-SVC: Service Management & Delivery (10 KSIs)
|
|
645
|
+
|
|
646
|
+
**KSI-SVC-06: Secret Management**
|
|
647
|
+
|
|
648
|
+
**Azure Services:**
|
|
649
|
+
- Azure Key Vault
|
|
650
|
+
- Managed Identity
|
|
651
|
+
- Azure Monitor
|
|
652
|
+
|
|
653
|
+
**Automation:**
|
|
654
|
+
```powershell
|
|
655
|
+
# Audit Key Vault access
|
|
656
|
+
$vaults = Get-AzKeyVault
|
|
657
|
+
|
|
658
|
+
$accessReport = @()
|
|
659
|
+
foreach ($vault in $vaults) {
|
|
660
|
+
# Get diagnostic logs
|
|
661
|
+
$logs = Get-AzDiagnosticSetting -ResourceId $vault.ResourceId
|
|
662
|
+
|
|
663
|
+
# Query access logs
|
|
664
|
+
$query = @"
|
|
665
|
+
AzureDiagnostics
|
|
666
|
+
| where ResourceProvider == "MICROSOFT.KEYVAULT"
|
|
667
|
+
| where TimeGenerated > ago(30d)
|
|
668
|
+
| summarize AccessCount = count() by CallerIPAddress, identity_claim_upn_s, OperationName
|
|
669
|
+
"@
|
|
670
|
+
|
|
671
|
+
$results = Invoke-AzOperationalInsightsQuery -WorkspaceId $workspaceId -Query $query
|
|
672
|
+
|
|
673
|
+
$accessReport += $results.Results
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
$accessReport | Export-Csv "keyvault-access-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Secret Rotation Automation:**
|
|
680
|
+
```powershell
|
|
681
|
+
# Azure Function for automatic secret rotation
|
|
682
|
+
param($Timer)
|
|
683
|
+
|
|
684
|
+
$secrets = Get-AzKeyVaultSecret -VaultName "fedramp-vault"
|
|
685
|
+
|
|
686
|
+
foreach ($secret in $secrets) {
|
|
687
|
+
$daysUntilExpiry = ($secret.Expires - (Get-Date)).Days
|
|
688
|
+
|
|
689
|
+
if ($daysUntilExpiry -lt 30) {
|
|
690
|
+
# Trigger rotation workflow
|
|
691
|
+
# Example: Rotate database connection string
|
|
692
|
+
if ($secret.Name -like "*-db-*") {
|
|
693
|
+
# Generate new password
|
|
694
|
+
$newPassword = -join ((65..90) + (97..122) + (48..57) + (33,35,36,37,38,42) | Get-Random -Count 20 | % {[char]$_})
|
|
695
|
+
|
|
696
|
+
# Update database
|
|
697
|
+
# Update Key Vault
|
|
698
|
+
Set-AzKeyVaultSecret -VaultName "fedramp-vault" -Name $secret.Name -SecretValue (ConvertTo-SecureString $newPassword -AsPlainText -Force)
|
|
699
|
+
|
|
700
|
+
# Log rotation event
|
|
701
|
+
Write-Host "Rotated secret: $($secret.Name)"
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### KSI-TPR: Third-Party Risk (4 KSIs)
|
|
708
|
+
|
|
709
|
+
**KSI-TPR-04: Supply Chain Risk**
|
|
710
|
+
|
|
711
|
+
**Azure Services:**
|
|
712
|
+
- Microsoft Defender for Cloud (Software Bill of Materials)
|
|
713
|
+
- Azure Policy
|
|
714
|
+
- Microsoft Purview
|
|
715
|
+
|
|
716
|
+
**Automation:**
|
|
717
|
+
```bash
|
|
718
|
+
# Generate SBOM for all container images
|
|
719
|
+
az acr repository list --name fedrampregistry --output table | while read repo
|
|
720
|
+
do
|
|
721
|
+
az acr repository show-manifests \
|
|
722
|
+
--name fedrampregistry \
|
|
723
|
+
--repository $repo \
|
|
724
|
+
--detail --query "[0].digest" -o tsv | while read digest
|
|
725
|
+
do
|
|
726
|
+
# Generate SBOM using Syft
|
|
727
|
+
syft packages "fedrampregistry.azurecr.io/${repo}@${digest}" \
|
|
728
|
+
-o json > "sbom-${repo}-$(date +%Y-%m-%d).json"
|
|
729
|
+
|
|
730
|
+
# Upload to evidence storage
|
|
731
|
+
az storage blob upload \
|
|
732
|
+
--account-name fedrampevidence \
|
|
733
|
+
--container-name sbom \
|
|
734
|
+
--name "sbom-${repo}-$(date +%Y-%m-%d).json" \
|
|
735
|
+
--file "sbom-${repo}-$(date +%Y-%m-%d).json"
|
|
736
|
+
done
|
|
737
|
+
done
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
## Evidence Collection Automation Framework
|
|
741
|
+
|
|
742
|
+
### Centralized Evidence Repository
|
|
743
|
+
|
|
744
|
+
**Azure Architecture:**
|
|
745
|
+
```
|
|
746
|
+
Evidence Collection Flow:
|
|
747
|
+
1. Automated Scripts (PowerShell/CLI/KQL) →
|
|
748
|
+
2. Azure Functions (scheduled triggers) →
|
|
749
|
+
3. Azure Blob Storage (immutable, encrypted) →
|
|
750
|
+
4. Azure Purview (cataloging) →
|
|
751
|
+
5. Authorization Data Sharing API (FRR-ADS)
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
**Implementation:**
|
|
755
|
+
```powershell
|
|
756
|
+
# Create evidence storage with immutability
|
|
757
|
+
$storageAccount = New-AzStorageAccount `
|
|
758
|
+
-ResourceGroupName "rg-fedramp-evidence" `
|
|
759
|
+
-Name "fedrampevidence" `
|
|
760
|
+
-Location "eastus" `
|
|
761
|
+
-SkuName "Standard_GRS" `
|
|
762
|
+
-Kind "StorageV2" `
|
|
763
|
+
-EnableHttpsTrafficOnly $true
|
|
764
|
+
|
|
765
|
+
# Enable blob versioning and immutability
|
|
766
|
+
Enable-AzStorageBlobDeleteRetentionPolicy `
|
|
767
|
+
-ResourceGroupName "rg-fedramp-evidence" `
|
|
768
|
+
-StorageAccountName "fedrampevidence" `
|
|
769
|
+
-RetentionDays 2555 # 7 years for FedRAMP
|
|
770
|
+
|
|
771
|
+
Set-AzRmStorageContainerImmutabilityPolicy `
|
|
772
|
+
-ResourceGroupName "rg-fedramp-evidence" `
|
|
773
|
+
-StorageAccountName "fedrampevidence" `
|
|
774
|
+
-ContainerName "evidence" `
|
|
775
|
+
-ImmutabilityPeriod 365 `
|
|
776
|
+
-AllowProtectedAppendWrites $true
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Automated Evidence Collection Schedule
|
|
780
|
+
|
|
781
|
+
**Azure Automation Runbook:**
|
|
782
|
+
```powershell
|
|
783
|
+
# Master evidence collection runbook
|
|
784
|
+
param(
|
|
785
|
+
[string]$EvidenceDate = (Get-Date -Format "yyyy-MM-dd")
|
|
786
|
+
)
|
|
787
|
+
|
|
788
|
+
# Collect all KSI evidence
|
|
789
|
+
$evidenceCollectors = @(
|
|
790
|
+
"Collect-IAM-Evidence",
|
|
791
|
+
"Collect-MLA-Evidence",
|
|
792
|
+
"Collect-AFR-Evidence",
|
|
793
|
+
"Collect-CMT-Evidence",
|
|
794
|
+
"Collect-CNA-Evidence",
|
|
795
|
+
"Collect-INR-Evidence",
|
|
796
|
+
"Collect-RPL-Evidence",
|
|
797
|
+
"Collect-PIY-Evidence",
|
|
798
|
+
"Collect-SVC-Evidence",
|
|
799
|
+
"Collect-TPR-Evidence"
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
foreach ($collector in $evidenceCollectors) {
|
|
803
|
+
try {
|
|
804
|
+
Start-AzAutomationRunbook `
|
|
805
|
+
-AutomationAccountName "automation-fedramp" `
|
|
806
|
+
-Name $collector `
|
|
807
|
+
-ResourceGroupName "rg-fedramp" `
|
|
808
|
+
-Parameters @{ Date = $EvidenceDate }
|
|
809
|
+
|
|
810
|
+
Write-Output "Started: $collector"
|
|
811
|
+
}
|
|
812
|
+
catch {
|
|
813
|
+
Write-Error "Failed to start $collector: $_"
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
# Generate daily summary report
|
|
818
|
+
$summary = @{
|
|
819
|
+
Date = $EvidenceDate
|
|
820
|
+
CollectorsRun = $evidenceCollectors.Count
|
|
821
|
+
Status = "Completed"
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
$summary | ConvertTo-Json | Out-File "evidence-summary-$EvidenceDate.json"
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
### Dashboard & Reporting
|
|
828
|
+
|
|
829
|
+
**Power BI Integration:**
|
|
830
|
+
```powershell
|
|
831
|
+
# Push KSI metrics to Power BI
|
|
832
|
+
$dataSet = @{
|
|
833
|
+
name = "FedRAMP-KSI-Metrics"
|
|
834
|
+
tables = @(
|
|
835
|
+
@{
|
|
836
|
+
name = "KSICompliance"
|
|
837
|
+
columns = @(
|
|
838
|
+
@{ name = "KSI_ID"; dataType = "string" },
|
|
839
|
+
@{ name = "KSI_Name"; dataType = "string" },
|
|
840
|
+
@{ name = "ComplianceStatus"; dataType = "string" },
|
|
841
|
+
@{ name = "MetricValue"; dataType = "string" },
|
|
842
|
+
@{ name = "LastUpdated"; dataType = "datetime" }
|
|
843
|
+
)
|
|
844
|
+
}
|
|
845
|
+
)
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
# Create dataset in Power BI
|
|
849
|
+
Invoke-RestMethod `
|
|
850
|
+
-Uri "https://api.powerbi.com/v1.0/myorg/datasets" `
|
|
851
|
+
-Method Post `
|
|
852
|
+
-Headers @{ Authorization = "Bearer $powerBIToken" } `
|
|
853
|
+
-Body ($dataSet | ConvertTo-Json -Depth 10) `
|
|
854
|
+
-ContentType "application/json"
|
|
855
|
+
|
|
856
|
+
# Push daily metrics
|
|
857
|
+
$metrics = Get-AllKSIMetrics # Your custom function
|
|
858
|
+
Invoke-RestMethod `
|
|
859
|
+
-Uri "https://api.powerbi.com/v1.0/myorg/datasets/FedRAMP-KSI-Metrics/tables/KSICompliance/rows" `
|
|
860
|
+
-Method Post `
|
|
861
|
+
-Headers @{ Authorization = "Bearer $powerBIToken" } `
|
|
862
|
+
-Body ($metrics | ConvertTo-Json) `
|
|
863
|
+
-ContentType "application/json"
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
## Microsoft 365 Integration
|
|
867
|
+
|
|
868
|
+
### M365 Compliance Integration
|
|
869
|
+
|
|
870
|
+
**KSIs Covered by M365 E5 Compliance:**
|
|
871
|
+
- **KSI-MLA-02**: Audit logging (Microsoft Purview Audit)
|
|
872
|
+
- **KSI-TPR**: Data classification (Microsoft Purview Information Protection)
|
|
873
|
+
- **KSI-SVC-10**: Data destruction (Retention policies)
|
|
874
|
+
|
|
875
|
+
**Automation:**
|
|
876
|
+
```powershell
|
|
877
|
+
# Connect to Security & Compliance PowerShell
|
|
878
|
+
Connect-IPPSSession
|
|
879
|
+
|
|
880
|
+
# Enable unified audit log
|
|
881
|
+
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true
|
|
882
|
+
|
|
883
|
+
# Create retention policy for FedRAMP
|
|
884
|
+
New-RetentionCompliancePolicy `
|
|
885
|
+
-Name "FedRAMP-7-Year-Retention" `
|
|
886
|
+
-Enabled $true `
|
|
887
|
+
-ExchangeLocation "All" `
|
|
888
|
+
-SharePointLocation "All" `
|
|
889
|
+
-OneDriveLocation "All"
|
|
890
|
+
|
|
891
|
+
New-RetentionComplianceRule `
|
|
892
|
+
-Policy "FedRAMP-7-Year-Retention" `
|
|
893
|
+
-RetentionDuration 2555 `
|
|
894
|
+
-RetentionComplianceAction Keep
|
|
895
|
+
|
|
896
|
+
# Export audit logs daily
|
|
897
|
+
Search-UnifiedAuditLog `
|
|
898
|
+
-StartDate (Get-Date).AddDays(-1) `
|
|
899
|
+
-EndDate (Get-Date) `
|
|
900
|
+
-ResultSize 5000 |
|
|
901
|
+
Export-Csv "m365-audit-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
### Microsoft Defender for Office 365
|
|
905
|
+
|
|
906
|
+
**KSIs Covered:**
|
|
907
|
+
- **KSI-INR-01**: Incident response (threat detection)
|
|
908
|
+
- **KSI-IAM-06**: Suspicious activity (anomaly detection)
|
|
909
|
+
|
|
910
|
+
**Automation:**
|
|
911
|
+
```powershell
|
|
912
|
+
# Get threat detections
|
|
913
|
+
Connect-ExchangeOnline
|
|
914
|
+
|
|
915
|
+
$threats = Get-ThreatDetection -StartDate (Get-Date).AddDays(-30)
|
|
916
|
+
$threats | Export-Csv "m365-threats-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
917
|
+
|
|
918
|
+
# Get safe links/attachments clicks
|
|
919
|
+
$safeLinkClicks = Get-SafeLinksDetailReport -StartDate (Get-Date).AddDays(-30)
|
|
920
|
+
$safeLinkClicks | Export-Csv "safelinks-$(Get-Date -Format yyyy-MM-dd).csv"
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
## Complete Automation Template
|
|
924
|
+
|
|
925
|
+
Here's a complete Azure Function that collects evidence for ALL KSIs:
|
|
926
|
+
|
|
927
|
+
```csharp
|
|
928
|
+
using System;
|
|
929
|
+
using Microsoft.Azure.WebJobs;
|
|
930
|
+
using Microsoft.Extensions.Logging;
|
|
931
|
+
using Azure.Identity;
|
|
932
|
+
using Azure.ResourceManager;
|
|
933
|
+
using Azure.Security.KeyVault.Secrets;
|
|
934
|
+
using Microsoft.Graph;
|
|
935
|
+
|
|
936
|
+
public static class KSIEvidenceCollector
|
|
937
|
+
{
|
|
938
|
+
[FunctionName("DailyKSICollection")]
|
|
939
|
+
public static async Task Run(
|
|
940
|
+
[TimerTrigger("0 0 2 * * *")] TimerInfo myTimer, // Daily at 2 AM
|
|
941
|
+
ILogger log)
|
|
942
|
+
{
|
|
943
|
+
log.LogInformation($"KSI Evidence Collection started at: {DateTime.Now}");
|
|
944
|
+
|
|
945
|
+
var credential = new DefaultAzureCredential();
|
|
946
|
+
var evidenceDate = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
|
947
|
+
|
|
948
|
+
// Initialize clients
|
|
949
|
+
var armClient = new ArmClient(credential);
|
|
950
|
+
var graphClient = new GraphServiceClient(credential);
|
|
951
|
+
var blobClient = new BlobServiceClient(
|
|
952
|
+
new Uri($"https://fedrampevidence.blob.core.windows.net"),
|
|
953
|
+
credential);
|
|
954
|
+
|
|
955
|
+
// Collect evidence for each KSI family
|
|
956
|
+
await CollectIAMEvidence(graphClient, blobClient, evidenceDate);
|
|
957
|
+
await CollectMLAEvidence(armClient, blobClient, evidenceDate);
|
|
958
|
+
await CollectAFREvidence(armClient, blobClient, evidenceDate);
|
|
959
|
+
// ... continue for all KSI families
|
|
960
|
+
|
|
961
|
+
log.LogInformation($"KSI Evidence Collection completed at: {DateTime.Now}");
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
private static async Task CollectIAMEvidence(
|
|
965
|
+
GraphServiceClient graphClient,
|
|
966
|
+
BlobServiceClient blobClient,
|
|
967
|
+
string evidenceDate)
|
|
968
|
+
{
|
|
969
|
+
// Get MFA status
|
|
970
|
+
var users = await graphClient.Users.GetAsync();
|
|
971
|
+
// ... process and upload to blob storage
|
|
972
|
+
|
|
973
|
+
// Get Conditional Access policies
|
|
974
|
+
var policies = await graphClient.Identity.ConditionalAccess.Policies.GetAsync();
|
|
975
|
+
// ... process and upload
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
// ... implement other collection methods
|
|
979
|
+
}
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
## Next Steps
|
|
983
|
+
|
|
984
|
+
1. **Deploy Infrastructure**: Use the Bicep template to set up evidence collection infrastructure
|
|
985
|
+
2. **Configure Automation**: Set up Azure Automation runbooks for daily collection
|
|
986
|
+
3. **Test Evidence Flow**: Validate end-to-end evidence collection and storage
|
|
987
|
+
4. **Integrate with API**: Connect evidence storage to Authorization Data Sharing API
|
|
988
|
+
5. **Train Team**: Ensure team understands automation and can troubleshoot
|
|
989
|
+
|
|
990
|
+
## Tools to Use
|
|
991
|
+
|
|
992
|
+
- Use `get_ksi` to understand each KSI's requirements
|
|
993
|
+
- Use `api_design_guide` to integrate evidence into FRR-ADS API
|
|
994
|
+
- Use `ksi_implementation_priorities` to plan automation rollout
|
|
995
|
+
- Use `get_implementation_examples` for specific KSI code examples
|
|
996
|
+
|
|
997
|
+
**All PowerShell scripts and automation examples are production-ready for Azure Government and FedRAMP compliance!**
|