Azure DevOps Pipelines

Integrating Security Scanning into Azure Pipelines

Enhance your software development lifecycle by incorporating security scanning directly into your Azure DevOps pipelines. This tutorial will guide you through setting up automated security checks for your code, dependencies, and containers.

Why Integrate Security Scanning?

Proactive security is crucial in modern software development. By automating security scanning, you can:

  • Identify vulnerabilities early in the development cycle.
  • Reduce the cost and effort of fixing security flaws.
  • Ensure compliance with security standards and regulations.
  • Build trust and confidence in your software.

Types of Security Scans

Several types of security scanning can be integrated:

  • Static Application Security Testing (SAST): Analyzes source code for security vulnerabilities without executing the code.
  • Software Composition Analysis (SCA): Identifies open-source components with known vulnerabilities and license issues.
  • Dynamic Application Security Testing (DAST): Tests running applications for vulnerabilities by simulating attacks.
  • Container Image Scanning: Scans container images for known vulnerabilities in the operating system and application packages.

Setting up SAST and SCA with Azure Pipelines

Azure DevOps integrates seamlessly with various security scanning tools. We'll use a common open-source tool as an example.

Example: Using Trivy for Container Image Scanning

Trivy is a popular, easy-to-use vulnerability scanner for container images and filesystems.

Prerequisite: You have a containerized application and an Azure DevOps pipeline set up to build and push your Docker image.

Step 1: Add a Scan Stage to your Pipeline

You can add a new stage to your existing `azure-pipelines.yml` file.


stages:
- stage: Build
  displayName: Build and Push Docker Image
  jobs:
  - job: Build
    displayName: Build Docker Image
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: 'buildAndPush'
        repository: 'my-app-repo'
        dockerfile: '$(Build.SourcesDirectory)/Dockerfile'
        containerRegistry: ''
        tags: |
          $(Build.BuildId)
          latest

- stage: SecurityScan
  displayName: Security Scan
  jobs:
  - job: ScanImage
    displayName: Scan Docker Image
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        docker pull $(ACR_NAME).azurecr.io/my-app-repo:$(Build.BuildId)
        trivy image $(ACR_NAME).azurecr.io/my-app-repo:$(Build.BuildId) --severity HIGH,CRITICAL --exit-code 1
      displayName: 'Run Trivy Scan'
      env:
        ACR_NAME: ''
                

Explanation:

  • We added a new stage named SecurityScan.
  • In the ScanImage job, we first pull the Docker image that was built and pushed in the previous stage.
  • The trivy image command scans the pulled image for vulnerabilities.
  • --severity HIGH,CRITICAL filters the results to only report high and critical severity vulnerabilities.
  • --exit-code 1 ensures the pipeline will fail if any high or critical vulnerabilities are found, enforcing security gates.
  • You'll need to replace <your-azure-container-registry-service-connection> and <your-acr-name> with your actual Azure Container Registry details. Set ACR_NAME as a pipeline variable.

Step 2: Configure Pipeline Variables

Ensure you have the necessary variables defined in your Azure DevOps pipeline settings, such as your Azure Container Registry name.

Step 3: Integrate SAST Tools

For SAST, you can use tools like SonarQube, Checkmarx, or open-source options like Semgrep. Many of these have dedicated Azure DevOps tasks available in the Marketplace.

Here's a conceptual example using a generic SAST task:


- stage: SecurityScan
  displayName: Security Scan
  jobs:
  - job: ScanCode
    displayName: Static Code Analysis
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: YourSASTToolTask@1 # Replace with actual task name
      inputs:
        scanDirectory: '$(Build.SourcesDirectory)'
        thresholds: 'BLOCKER=0,CRITICAL=0' # Example thresholds
        connectionDetails: ''
                

Best Practices

  • Scan Early and Often: Integrate scans into every commit or pull request.
  • Fail the Build: Configure scans to fail the pipeline if critical vulnerabilities are found.
  • Review Findings: Regularly review scan reports and prioritize remediation.
  • Manage Dependencies: Keep your dependencies updated and use SCA tools to track them.
  • Scan Artifacts: Beyond code, scan build artifacts, containers, and infrastructure as code.

Further Reading