Compartir vía


Adición de datos de Defender for Cloud a Power BI

Al conectar los datos de Microsoft Defender for Cloud con Microsoft Power BI, puede supervisar y analizar fácilmente las métricas de seguridad. La integración le permite visualizar información de seguridad e identificar rápidamente posibles amenazas y vulnerabilidades. Este artículo le guía por los pasos necesarios para conectar los datos de Defender for Cloud a Power BI, lo que le ayuda a transformar la información de seguridad compleja en información clara y procesable.

Requisitos previos

Conexión de Power BI a Azure Resource Graph

Para poder conectar los datos de Defender for Cloud a Power BI, primero debe conectar Power BI a Azure Resource Graph.

  1. En el escritorio, abra Power BI Desktop.

  2. Seleccione Informe en blanco.

  3. Seleccione Obtener datos>Más.

    Captura de pantalla de la pantalla principal de Power BI Desktop que muestra dónde se encuentra el botón Obtener datos y la opción Más.

  4. Busque y seleccione Azure Resource Graph.

  5. Seleccione Conectar.

Consulta de datos de Defender for Cloud en Power BI

Una vez que Power BI Desktop esté conectado a Azure Resource Graph, puede usar Azure Resource Graph para consultar varios orígenes de datos de Defender for Cloud en Power BI.

Las consultas proporcionadas en esta página son ejemplos que proporcionan resultados. Azure Resource Graph le permite consultar una amplia gama de datos que puede crear y personalizar para devolver resultados que se adapten a sus requisitos específicos.

  1. Copie y pegue una de las consultas proporcionadas en el editor de consultas de Power BI Desktop.

    Esta consulta recupera las recomendaciones de seguridad por riesgo de MDC, lo que le permite analizar evaluaciones e identificar áreas que necesitan atención.

    securityresources 
            | where type =~ "microsoft.security/assessments"
            | extend assessmentType = iff(type == "microsoft.security/assessments", tostring(properties.metadata.assessmentType), dynamic(null))
            | where (type == "microsoft.security/assessments" and (assessmentType in~ ("BuiltIn", "CustomerManaged")))
            | extend assessmentTypeSkimmed = iff(type == "microsoft.security/assessments", case(
                        tostring(properties.metadata.assessmentType) == "BuiltIn", "BuiltIn",
                        tostring(properties.metadata.assessmentType) == "BuiltInPolicy", "BuiltIn",
                        tostring(properties.metadata.assessmentType) == "CustomPolicy", "Custom",
                        tostring(properties.metadata.assessmentType) == "CustomerManaged", "Custom",
                        tostring(properties.metadata.assessmentType) == "ManualCustomPolicy", "Custom",
                        tostring(properties.metadata.assessmentType) == "ManualBuiltInPolicy", "BuiltIn",
                        dynamic(null)
                    ), dynamic(null))
            | extend assessmentId = tolower(id)
            | extend assessmentKey = iff(type == "microsoft.security/assessments", name, dynamic(null))
            | extend source = iff(type == "microsoft.security/assessments", trim(' ', tolower(tostring(properties.resourceDetails.Source))), dynamic(null))
            | extend statusCode = iff(type == "microsoft.security/assessments", tostring(properties.status.code), dynamic(null))
            | extend resourceId = iff(type == "microsoft.security/assessments", trim(" ", tolower(tostring(case(source =~ "azure", properties.resourceDetails.Id,
                (type == "microsoft.security/assessments" and (source =~ "aws" and isnotempty(tostring(properties.resourceDetails.ConnectorId)))), properties.resourceDetails.Id,
                (type == "microsoft.security/assessments" and (source =~ "gcp" and isnotempty(tostring(properties.resourceDetails.ConnectorId)))), properties.resourceDetails.Id,
                source =~ "aws", properties.resourceDetails.AzureResourceId,
                source =~ "gcp", properties.resourceDetails.AzureResourceId,
                extract("^(?i)(.+)/providers/Microsoft.Security/assessments/.+$",1,id)
                )))), dynamic(null))
            | extend resourceName = iff(type == "microsoft.security/assessments", tostring(coalesce(properties.resourceDetails.ResourceName, properties.additionalData.CloudNativeResourceName, properties.additionalData.ResourceName, properties.additionalData.resourceName, split(resourceId, '/')[-1], extract(@"(.+)/(.+)", 2, resourceId))), dynamic(null))
            | extend resourceType = iff(type == "microsoft.security/assessments", tolower(properties.resourceDetails.ResourceType), dynamic(null))
            | extend riskLevelText = iff(type == "microsoft.security/assessments", tostring(properties.risk.level), dynamic(null))
            | extend riskLevel = iff(type == "microsoft.security/assessments", case(riskLevelText =~ "Critical", 4,
                      riskLevelText =~ "High", 3,
                      riskLevelText =~ "Medium", 2,
                      riskLevelText =~ "Low", 1,
                      0), dynamic(null))
            | extend riskFactors = iff(type == "microsoft.security/assessments", iff(isnull(properties.risk.riskFactors), dynamic([]), properties.risk.riskFactors), dynamic(null))
            | extend attackPaths = array_length(iff(type == "microsoft.security/assessments", iff(isnull(properties.risk.attackPathsReferences), dynamic([]), properties.risk.attackPathsReferences), dynamic(null)))           
            | extend displayName = iff(type == "microsoft.security/assessments", tostring(properties.displayName), dynamic(null))
            | extend statusCause = iff(type == "microsoft.security/assessments", tostring(properties.status.cause), dynamic(null))
            | extend isExempt = iff(type == "microsoft.security/assessments", iff(statusCause == "Exempt", tobool(1), tobool(0)), dynamic(null))
            | extend statusChangeDate = tostring(iff(type == "microsoft.security/assessments", todatetime(properties.status.statusChangeDate), dynamic(null)))
            | project assessmentId,
                        statusChangeDate,
                        isExempt,
                        riskLevel,
                        riskFactors,
                        attackPaths,
                        statusCode,
                        displayName,
                        resourceId,               
                        assessmentKey,
                        resourceType,
                        resourceName,
                        assessmentTypeSkimmed               
                | join kind=leftouter (
                    securityresources
                    | where type == 'microsoft.security/assessments/governanceassignments'
                    | extend assignedResourceId = tolower(iff(type == "microsoft.security/assessments/governanceassignments", tostring(properties.assignedResourceId), dynamic(null)))
                    | extend dueDate = iff(type == "microsoft.security/assessments/governanceassignments", todatetime(properties.remediationDueDate), dynamic(null))
                    | extend owner = iff(type == "microsoft.security/assessments/governanceassignments", iff(isempty(tostring(properties.owner)), "unspecified", tostring(properties.owner)), dynamic(null))
                    | extend governanceStatus = iff(type == "microsoft.security/assessments/governanceassignments", case(
                                isnull(todatetime(properties.remediationDueDate)), "NoDueDate",
                                todatetime(properties.remediationDueDate) >= bin(now(), 1d), "OnTime",
                                "Overdue"
                            ), dynamic(null))
                    | project assignedResourceId, dueDate, owner, governanceStatus
                ) on $left.assessmentId == $right.assignedResourceId
                | extend completionStatusNumber = case(governanceStatus == "Overdue", 5,
                                                           governanceStatus == "OnTime", 4,
                                                           statusCode == "Unhealthy", 3, 
                                                           isExempt, 7,
                                                           1)
                    | extend completionStatus = case(completionStatusNumber == 5, "Overdue",
                                                     completionStatusNumber == 4, "OnTime",
                                                     completionStatusNumber == 3, "Unassigned",
                                                     completionStatusNumber == 7, "Exempted",
                                                     "Completed")
                | where completionStatus in~ ("OnTime","Overdue","Unassigned")
                | project-away assignedResourceId, governanceStatus, isExempt
                           | order by riskLevel desc, attackPaths desc, displayName
    
  2. Seleccione Aceptar.

    Captura de pantalla que muestra dónde escribir la consulta de Azure Resource Graph y dónde se encuentra el botón Aceptar.

    Nota:

    De forma predeterminada, en Resource Graph hay un límite en el número de registros que se pueden devolver en una consulta, y son 1000 registros. Este control protege tanto al usuario como al servicio de consultas no intencionadas que darían lugar a grandes conjuntos de datos. Si desea que los resultados de la consulta no se trunquen con el límite de 1000 registros, establezca el valor de "Opción avanzada: $resultTruncated (opcional)" en FALSE.

    Captura de pantalla que muestra dónde se encuentran las opciones avanzadas y cómo establecerlas en false.

  3. Seleccione Cargar.

Con Azure Resource Graph, tiene la flexibilidad de recuperar y analizar los datos disponibles en el entorno de Defender for Cloud, lo que garantiza información completa y adaptada. Una vez agregados los datos a Power BI, puede crear visualizaciones y paneles para supervisar y administrar la posición de seguridad de forma eficaz.

Paso siguiente