-
Notifications
You must be signed in to change notification settings - Fork 89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Defender Recommendations #325
Comments
Hey @PixelRobots can you run the following ARG query and let us know if it's close to what you are looking for? SecurityResources
| where type == 'microsoft.security/assessments'
| extend resourceId=id,
recommendationId=name,
resourceType=type,
recommendationName=properties.displayName,
source=properties.resourceDetails.Source,
recommendationState=properties.status.code,
description=properties.metadata.description,
assessmentType=properties.metadata.assessmentType,
remediationDescription=properties.metadata.remediationDescription,
policyDefinitionId=properties.metadata.policyDefinitionId,
implementationEffort=properties.metadata.implementationEffort,
recommendationSeverity=properties.metadata.severity,
category=properties.metadata.categories,
userImpact=properties.metadata.userImpact,
threats=properties.metadata.threats,
portalLink=properties.links.azurePortal |
This is what i am using now to create a csv. I only want the unhealty recommendations you see. and more important information then everything else: # Fetch the current tenant ID
$tenantId = (az account show --query tenantId -o tsv)
# Initialize variables
$MDC_Recommendations = @()
$pageSize = 1000
$iteration = 0
$skipCount = 0
# Define the Resource Graph query in a readable multiline format
$queryLines = @(
"SecurityResources",
"| where type == 'microsoft.security/assessments'",
"| where properties.status.code == 'Unhealthy'",
"| mvexpand Category = properties.metadata.categories",
"| extend",
" AssessmentId = id,",
" AssessmentKey = name,",
" ResourceId = properties.resourceDetails.Id,",
" ResourceIdsplit = split(properties.resourceDetails.Id, '/'),",
" RecommendationName = properties.displayName,",
" RecommendationState = properties.status.code,",
" ActionDescription = properties.metadata.description,",
" RemediationDescription = properties.metadata.remediationDescription,",
" RecommendationSeverity = properties.metadata.severity,",
" PolicyDefinitionId = properties.metadata.policyDefinitionId,",
" AssessmentType = properties.metadata.assessmentType,",
" Threats = properties.metadata.threats,",
" UserImpact = properties.metadata.userImpact,",
" AzPortalLink = tostring(properties.links.azurePortal)",
"| extend",
" ResourceSubId = tostring(ResourceIdsplit[2]),",
" ResourceGroupName = tostring(ResourceIdsplit[4]),",
" ResourceType = tostring(ResourceIdsplit[6]),",
" ResourceName = tostring(ResourceIdsplit[8])",
"| join kind=leftouter (resourcecontainers",
" | where type == 'microsoft.resources/subscriptions'",
" | project SubscriptionName = name, subscriptionId) on subscriptionId",
"| project SubscriptionName, ResourceGroupName, ResourceName, Category, RecommendationSeverity, RecommendationName, ActionDescription, RemediationDescription, AzPortalLink"
)
# Convert the query into a single line
$query = $queryLines -join " "
# Pagination logic
do {
$iteration += 1
Write-Verbose "Iteration #$iteration" -Verbose
# Fetch a page of results
$pageResultsJson = az graph query -q $query --first $pageSize --skip $skipCount --output json
$pageResults = $pageResultsJson | ConvertFrom-Json
# Extract data field and add to recommendations
if ($pageResults.data) {
$MDC_Recommendations += $pageResults.data
}
# Update skip count
$skipCount += $pageResults.data.Count
} while ($pageResults.data.Count -eq $pageSize)
# Update AzPortalLink to include the tenantId in the URL
$MDC_Recommendations = $MDC_Recommendations | ForEach-Object {
if ($_.AzPortalLink -match "portal.azure.com") {
$_.AzPortalLink = $_.AzPortalLink -replace "portal.azure.com", "https://portal.azure.com/$tenantId"
}
$_
}
# Reorder and select columns explicitly
$OrderedRecommendations = $MDC_Recommendations | Select-Object `
SubscriptionName, `
ResourceGroupName, `
ResourceName, `
Category, `
RecommendationSeverity, `
RecommendationName, `
ActionDescription, `
RemediationDescription, `
AzPortalLink
# Output summary
Write-Output "Total recommendations fetched: $($OrderedRecommendations.Count)"
# Export results to a CSV
$CsvPath = "UnhealthyRecommendations.csv"
$OrderedRecommendations | Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8
Write-Output "Recommendations exported to $CsvPath."
. ./$CsvPath |
@PixelRobots my friend can you try the binaries from here: https://github.com/Azure/azqr/actions/runs/12928181677 and let me know if this works for you? |
That works well. The only thing I would say is the azure portal link needs a bit of manipulation to add the https:// and the tenant ID in if possible. (The reason for the tenant id is when you have multiple tenants it makes it easier to connect to the right one). Also, when running the scan, the subscription id is not shown when doing the recommendation part as in the image below: Thanks for this |
The scan runs in batch for "all" subscriptions and that's why logs show one line as for Costs, Defender Status and more. Let me add the |
Thanks. I can always add the tenant id my side if needed. |
Describe the feature
It would be good to get defender recommendations with a link to the azure portal.
The text was updated successfully, but these errors were encountered: