With the release of image scanning using Microsoft Defender for container registries, we received enormous interest in findings among wide audiences including traditional Microsoft Defender for Cloud admins along with repository owners and DevOps personnel.
One of the biggest challenges that was raised by these audiences was how to use the Defender for Container scanning capability in their integration and deployment processes to ensure only scanned and healthy images reach the production environments.
By embedding Microsoft Defender for container registries assessments into your CI/CD pipeline, you can address this need and have a more secure automation and deployment processes in enterprise environments.
This blog will take you through a few simple steps to take your CI/CD pipeline to the next security level.
How does Microsoft Defender’s container image scanning for vulnerabilities work?
When you enable Microsoft Defender for Cloud's optional Microsoft Defender for container registries advanced security plan, the images in your container registries are scanned for vulnerabilities.
There are multiple triggers for an image scan, such as On push, On import and Recently pulled.
Microsoft defender for container Registries pulls and scans the image in an isolated sandbox. It is then extracts, filters and classifies the findings, and presents them as actionable security recommendations.
Each finding Defender for container registries published for an image is represented as a Container Registry Vulnerability Sub Assessment.
Extract scan summary using API:
Scan summaries are available in Microsoft Defender for Cloud dashboards. You can also access them programmatically (through our API or PowerShell) using
With the scan summary ARG query published in Microsoft Defender for Cloud container image scan community GitHub, you can fetch results for all images by simply running it via ARG REST API, PowerShell module or Explorer.
securityresources
| where type == 'microsoft.security/assessments/subassessments'
| where id matches regex '(.+?)/providers/Microsoft.Security/assessments/dbd0cb49-b563-45e7-9724-889e799fa648/'
| parse id with registryResourceId '/providers/Microsoft.Security/assessments/' *
| parse registryResourceId with * "/providers/Microsoft.ContainerRegistry/registries/" registryName
| extend imageDigest = tostring(properties.additionalData.imageDigest)
| extend repository = tostring(properties.additionalData.repositoryName)
| extend scanFindingSeverity = tostring(properties.status.severity), scanStatus = tostring(properties.status.code)
| summarize scanFindingSeverityCount = count() by scanFindingSeverity, scanStatus, registryResourceId, registryName, repository, imageDigest
| summarize severitySummary = make_bag(pack(scanFindingSeverity, scanFindingSeverityCount)) by registryResourceId, registryName, repository, imageDigest, scanStatus
You can also filter results to get summary for a specific image or registry by adding
it to the bottom of the query, for example:
| where imageDigest == '<ImageDigest>' and repository == '<ImageRepository>'
and registryResourceId endswith '/<ImageRegistryName>'
Use scan summary as part of an image CI\CD pipeline:
In ASC container image scan GitHub community, you can also find the Image Scan Automation Enrichment Security Gate tool.
The security gate tool is used for enriching and acting upon image scan results as part of a CI\CD pipeline to follow a scan initiated by image push.
It is built by two parts:
- Scan automation gate PowerShell script:
An Azure CLI PowerShell script that fetches provided image scan result and assess them by configuration.
- Script run ends in one of the following modes:
- Success: scan results for image extracted successfully with no significant findings, image is healthy.
- Warning: scan results with some low & medium findings, but not enough to pass security gate findings severity thresholds (configurable).
- Failure: scan result with high severity finding or number of medium & low severity findings has passed threshold (configurable) or scan result not found after multiple retries (configurable).
- Customize security gate script vulnerability thresholds:
Security gate vulnerability severity thresholds can be customized by PS script’s optional parameters: `$mediumFindingsCountFailThreshold` , `$lowFindingsCountFailThreshold`, by default they are set to 5 and 15 respectively (script optional parameters).
In the case of a high severity vulnerability, security gate will always end up with a failure. -
.\ImageScanSummaryAssessmentGate.ps1 -registryName tomerregistry -repository build -tag latest
- This PS script can be included in any of your automation pipelines as a standalone gate to enrich scan results for image.
- Script run ends in one of the following modes:
- Azure DevOps pipeline template:
An Azure DevOps pipeline that: Builds image, Pushes it to Azure container registry, then Assesses scan results for image to decide whether to pass of fail pipeline.
- By copying security gate PS script presented above to pipeline’s path, following image’s Build and Push Docker task, pipeline can now run a custom Azure CLI PowerShell task with the PS script copied.
- Security Gate custom Task from Azure DevOps pipeline template:
# Run Image scan gate - which extracts image scan results and assess whether # to fail the pipeline based on severity threshold configuration. # Using the ImageScanSummaryAssessmentGate.ps1 script in same repo folder - job: ImageScanGate displayName: Image Scan security gate pool: vmImage: $(vmImageName) dependsOn: - BuildAndPush - WaitForScanResults steps: # Read more here: https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-cli?view=azure-devops) - task: AzureCLI@2 inputs: azureSubscription: '<Name of the Azure Resource Manager service connection>' scriptType: 'pscore' scriptLocation: 'scriptPath' # Security Gate powershell script in same folder scriptPath: '$(Build.SourcesDirectory)/ImageScanSummaryAssessmentGate.ps1' arguments: '-registryName $(containerRegistry) -repository $(imageRepository) -tag $(tag)'
- Image scan gate task runs following a short delay task (configurable) from image push task to make image scan results are published in ARG.
- Pipeline will complete successfully on image built, push, and security gate success result.
- Customize pipeline scan results extraction timeouts:
By default, pipeline waits 5 minutes following image push to run the scan gate task to make sure scan results are ready and published in ARG (can by customize in pipeline variable `$waitForScanResultsAfterPushInMinutes`).
- By copying security gate PS script presented above to pipeline’s path, following image’s Build and Push Docker task, pipeline can now run a custom Azure CLI PowerShell task with the PS script copied.
Push only scanned and healthy images to your production registry:
You can use the security gate task above as a conditional task to push image to your production registry.
- Push image to your staging registry first (make sure it is also on-boarded to Microsoft Defender for Cloud).
- Set Azure DevOps scan gate task to run on image in stagging registry.
- Set security gate task result as a dependency for Pushing the image to your production registry.
You are welcome to join Microsoft Defender for Cloud container image scan community on GitHub.
Contribute, share and suggest useful tools to automate or improve work with the Microsoft Defender for Cloud image scan service and results.
Tomer Weinberger, Microsoft Defender for Cloud.