diff --git a/providers/azure/resources/azure.lr b/providers/azure/resources/azure.lr index 4f7faaa988..1e7e7f1e42 100644 --- a/providers/azure/resources/azure.lr +++ b/providers/azure/resources/azure.lr @@ -1719,6 +1719,20 @@ private azure.subscription.cloudDefenderService @defaults("defenderForServers.en defenderForContainers() dict // List of configured security contacts securityContacts() []azure.subscription.cloudDefenderService.securityContact + // List of recommendations + defenderRecommendations() []azure.subscription.cloudDefenderService.recommendation +} + +// Microsoft Defender for Cloud recommendation +private azure.subscription.cloudDefenderService.recommendation @defaults("title affectedResource status properties") { + // Recommendation title + title string + // Affected resource + affectedResource string + // Recommendation status + status string + // Properties of the recommendation + properties dict } // Microsoft Defender for Cloud security contact diff --git a/providers/azure/resources/azure.lr.manifest.yaml b/providers/azure/resources/azure.lr.manifest.yaml index 524b191475..1230dbb1cf 100644 --- a/providers/azure/resources/azure.lr.manifest.yaml +++ b/providers/azure/resources/azure.lr.manifest.yaml @@ -386,6 +386,8 @@ resources: min_mondoo_version: 9.0.0 defenderForStorageAccounts: min_mondoo_version: 9.0.0 + defenderRecommendations: + min_mondoo_version: 9.0.0 monitoringAgentAutoProvision: {} securityContacts: {} subscriptionId: {} @@ -397,6 +399,17 @@ resources: refs: - title: Microsoft Defender for Cloud Apps overview url: https://learn.microsoft.com/en-us/defender-cloud-apps/what-is-defender-for-cloud-apps + azure.subscription.cloudDefenderService.recommendation: + fields: + affectedResource: {} + properties: {} + status: {} + title: {} + is_private: true + min_mondoo_version: 9.0.0 + platform: + name: + - azure azure.subscription.cloudDefenderService.securityContact: fields: alertNotifications: {} diff --git a/providers/azure/resources/cloud_defender.go b/providers/azure/resources/cloud_defender.go index 5d50c1dafc..e4a5bee113 100644 --- a/providers/azure/resources/cloud_defender.go +++ b/providers/azure/resources/cloud_defender.go @@ -657,3 +657,56 @@ type ServerVulnerabilityAssessmentsSettings struct { type ServerVulnerabilityAssessmentsSettingsList struct { Settings []ServerVulnerabilityAssessmentsSettings `json:"value"` } + +func (r *mqlAzureSubscriptionCloudDefenderServiceRecommendation) id() (string, error) { + return r.Title.Data, nil +} + +func (a *mqlAzureSubscriptionCloudDefenderService) defenderRecommendations() ([]interface{}, error) { + conn := a.MqlRuntime.Connection.(*connection.AzureConnection) + ctx := context.Background() + token := conn.Token() + subId := a.SubscriptionId.Data + + clientFactory, err := armsecurity.NewClientFactory(subId, token, nil) + if err != nil { + return nil, err + } + + assessmentsClient := clientFactory.NewAssessmentsClient() + pager := assessmentsClient.NewListPager(fmt.Sprintf("subscriptions/%s", subId), &security.AssessmentsClientListOptions{}) + res := []interface{}{} + + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + return nil, err + } + + for _, assessment := range page.Value { + if assessment.Properties == nil { + continue + } + + properties, err := convert.JsonToDict(assessment.Properties) + if err != nil { + return nil, err + } + + recommendationData := map[string]*llx.RawData{ + "title": llx.StringData(*assessment.Properties.DisplayName), + "affectedResource": llx.StringData(*assessment.ID), + "properties": llx.DictData(properties), + "status": llx.StringData(string(*assessment.Properties.Status.Code)), + } + + mqlRecommendation, err := CreateResource(a.MqlRuntime, "azure.subscription.cloudDefenderService.recommendation", recommendationData) + if err != nil { + return nil, err + } + res = append(res, mqlRecommendation) + } + } + + return res, nil +}