Query Details

Azure Dev Ops Code Recommendations

Query

# Azure DevOps Security - Code Scanning Recommendations

## Query Information

### Description

Use the below queries to list all Azure DevOps *Code* and *Infrastructure as code* recommendations.

![](../AzureDevOps/devOps_assessments.png)

### References

- [Agentless code scanning in Microsoft Defender for Cloud](https://learn.microsoft.com/en-us/azure/defender-for-cloud/agentless-code-scanning)
- [Scan your connected GitHub repository or Azure DevOps project](https://learn.microsoft.com/en-us/azure/defender-for-cloud/iac-vulnerabilities)
- [Security recommendations for DevOps resources](https://learn.microsoft.com/en-us/azure/defender-for-cloud/recommendations-reference-devops)

### Tools

- [Bandit](https://github.com/PyCQA/bandit)
- [Checkov](https://github.com/bridgecrewio/checkov)
- [ESLint](https://github.com/eslint/eslint)
- [Template Analyzer](https://github.com/Azure/template-analyzer)
- [Terrascan](https://github.com/accurics/terrascan)

## Queries

### Azure Resource Graph Explorer

```kql
securityresources 
        | where type == "microsoft.security/assessments/subassessments"
        | where tostring(properties.id) != ""
        | extend category=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.category), dynamic(null)))
        | where category ==  "Code" or category == 'Infrastructure as Code'         
        | extend severity=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.severity), dynamic(null)))
        | extend severitySort = iff(severity == "Critical", 4, iff (severity == "High", 3, iff(severity == "Medium", 2, iff(severity == "Low", 1, 0))))
        | extend subAssessmentName=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.displayName), dynamic(null))),
            description=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.description), dynamic(null))),
            status=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.code), dynamic(null))),
            statusDescription=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.description), dynamic(null))),
            resourceDetails=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.resourceDetails), dynamic(null))),
            timeGenerated=(iff(type == "microsoft.security/assessments/subassessments", todatetime(properties.timeGenerated), dynamic(null))),
            additionalData=(iff(type == "microsoft.security/assessments/subassessments", (properties.additionalData),dynamic(null))),
            ToolName=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.ToolName), dynamic(null))),
            RuleId=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RuleId), dynamic(null))),
            RuleDescription=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RuleDescription), dynamic(null))),
            RepositoryUri=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RepositoryUri), dynamic(null))),
            File=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.File), dynamic(null))),
            Line=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.Line), dynamic(null)))
      | project timeGenerated, severitySort, category, resourceDetails, subAssessmentName, description, severity, status, additionalData,  statusDescription, ToolName, RuleId, RuleDescription,RepositoryUri, File,Line
        
```

### Defender XDR Advanced Hunting

```kql
arg("").securityresources 
        | where type == "microsoft.security/assessments/subassessments"
        | where tostring(properties.id) != ""
        | extend category=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.category), dynamic(null)))
        | where category ==  "Code" or category == 'Infrastructure as Code'         
        | extend severity=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.severity), dynamic(null)))
        | extend severitySort = iff(severity == "Critical", 4, iff (severity == "High", 3, iff(severity == "Medium", 2, iff(severity == "Low", 1, 0))))
        | extend subAssessmentName=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.displayName), dynamic(null))),
            description=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.description), dynamic(null))),
            status=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.code), dynamic(null))),
            statusDescription=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.status.description), dynamic(null))),
            resourceDetails=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.resourceDetails), dynamic(null))),
            timeGenerated=(iff(type == "microsoft.security/assessments/subassessments", todatetime(properties.timeGenerated), dynamic(null))),
            additionalData=(iff(type == "microsoft.security/assessments/subassessments", (properties.additionalData),dynamic(null))),
            ToolName=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.ToolName), dynamic(null))),
            RuleId=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RuleId), dynamic(null))),
            RuleDescription=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RuleDescription), dynamic(null))),
            RepositoryUri=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.RepositoryUri), dynamic(null))),
            File=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.File), dynamic(null))),
            Line=(iff(type == "microsoft.security/assessments/subassessments", tostring(properties.additionalData.data.Line), dynamic(null)))
      | project timeGenerated, severitySort, category, resourceDetails, subAssessmentName, description, severity, status, additionalData,  statusDescription, ToolName, RuleId, RuleDescription,RepositoryUri, File,Line
```

Explanation

This query is designed to extract and list security recommendations related to code and infrastructure as code from Azure DevOps. It does this by querying the security resources in Azure, specifically looking at sub-assessments related to security. Here's a simplified breakdown of what the query does:

  1. Data Source: It pulls data from Azure's security resources, focusing on sub-assessments.

  2. Filter Criteria:

    • It filters the data to only include entries where there is a valid ID.
    • It further narrows down the results to those categorized as "Code" or "Infrastructure as Code".
  3. Data Extraction:

    • It extracts various details from each relevant sub-assessment, such as:
      • Severity: How critical the issue is, with a numerical sort value assigned for easier sorting (Critical = 4, High = 3, Medium = 2, Low = 1).
      • Sub-assessment Name: The name of the specific security check.
      • Description: A description of the issue.
      • Status: The current status of the issue (e.g., active, resolved).
      • Additional Data: Includes tool name, rule ID, rule description, repository URI, file, and line number where the issue was found.
  4. Output:

    • The query projects (or selects) specific fields to display, such as the time the issue was generated, severity, category, and various details about the issue and its context.

This query can be run in two environments: Azure Resource Graph Explorer and Defender XDR Advanced Hunting, providing a comprehensive view of security recommendations for code and infrastructure as code in Azure DevOps projects.

Details

Alex Verboon profile picture

Alex Verboon

Released: December 9, 2024

Tables

securityresources

Keywords

SecurityResourcesCodeInfrastructureAssessmentsPropertiesCategorySeverityDescriptionStatusToolNameRuleIdRepositoryUriFileLine

Operators

securityresourceswheretostringextendiffdynamicortodatetimeprojectarg

Actions