in internal/scanners/defender.go [63:134]
func (s *DefenderScanner) GetRecommendations(ctx context.Context, scan bool, cred azcore.TokenCredential, subscriptions map[string]string, filters *models.Filters) []models.DefenderRecommendation {
models.LogResourceTypeScan("Defender Recommendations")
resources := []models.DefenderRecommendation{}
if scan {
graphClient := graph.NewGraphQuery(cred)
query := `
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 SubscriptionId=subscriptionId, SubscriptionName, ResourceGroupName, ResourceType,
ResourceName, Category, RecommendationSeverity, RecommendationName, ActionDescription,
RemediationDescription, AzPortalLink, ResourceId
`
log.Debug().Msg(query)
subs := make([]*string, 0, len(subscriptions))
for s := range subscriptions {
subs = append(subs, &s)
}
result := graphClient.Query(ctx, query, subs)
resources = []models.DefenderRecommendation{}
if result.Data != nil {
for _, row := range result.Data {
m := row.(map[string]interface{})
if filters.Azqr.IsServiceExcluded(to.String(m["ResourceId"])) {
continue
}
resources = append(resources, models.DefenderRecommendation{
SubscriptionId: to.String(m["SubscriptionId"]),
SubscriptionName: to.String(m["SubscriptionName"]),
ResourceGroupName: to.String(m["ResourceGroupName"]),
ResourceType: to.String(m["ResourceType"]),
ResourceName: to.String(m["ResourceName"]),
Category: to.String(m["Category"]),
RecommendationSeverity: to.String(m["RecommendationSeverity"]),
RecommendationName: to.String(m["RecommendationName"]),
ActionDescription: to.String(m["ActionDescription"]),
RemediationDescription: to.String(m["RemediationDescription"]),
AzPortalLink: fmt.Sprintf("https://%s", to.String(m["AzPortalLink"])),
ResourceId: to.String(m["ResourceId"]),
})
}
}
}
return resources
}