Previously in the Part 1 Blog, I showed you how to use Anchore to perform a stateful scan in Azure DevOps using Anchore Engine or Anchore Enterprise. This method works great, but what if you don’t have a running instance of Anchore? What if you just want to run a scan, gather the results, and then move on? Anchore (being the versatile tool it is) has that capability too!

Azure Starter Pipeline

Remember our simple Azure DevOps pipeline from my previous post:

trigger:
- master
 
resources:
- repo: self
 
stages:
- stage: Build
  displayName: Build and push stage
  jobs: 
  - job: Build
    displayName: Build
    pool:
      vmImage: ‘ubuntu-latest’
    steps:
    - task: Docker@2
      displayName: Build and push an image to container registry
      inputs:
        command: buildAndPush
        repository: jpetersenames/simpleserver
        dockerfile: Dockerfile
        containerRegistry: production
        tags: |
          $(Build.BuildId)

All this pipeline does is build an image and push it to our production registry every time code is pushed to our repository. We want to add security to our pipeline using Anchore, but we don’t have the resources to run a staging registry as well as an instance of Anchore. Perhaps you just want to try out Anchore in your pipeline to see how the compliance scanning works. This is where the inline scan offered by Anchore comes in. You can read more about the tool in the Anchore documentation, but I want to show you how you can seamlessly integrate Anchore into your pipeline with almost no dependencies.

Take a look at the pipeline below. You can see that we no longer need a staging registry. Instead, we just build a local image using BuildKit so we have all the nice features; suggested but not required for Anchore. Once we have our local image, we can grab the inline scan script that is publicly available through Anchore. Using the inline scan script and container, we can perform a compliance scan on a locally built image without any outside dependencies. Pretty cool!

trigger:
- master

resources:
- repo: self

variables:
- name: localImage
  value: 'local/simpleserver:$(Build.BuildId)'
- name: productionImage
  value: 'production/simpleserver:$(Build.BuildId)'

stages:
- stage: Build
  displayName: Build and push stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        DOCKER_BUILDKIT=1 docker build -t $(localImage) -f Dockerfile .
      displayName: Build the local image

    - script: |
        curl -s https://ci-tools.anchore.io/inline_scan-latest | bash -s -- \
          scan -b .anchore/policy.json -d Dockerfile -f -r $(localImage)
      displayName: Anchore Security Scan

    - script: |
        docker tag $(localImage) $(productionImage)
      displayName: Tag the image as production

    - task: Docker@2
      displayName: Push the image to the production registry
      inputs:
        command: push
        repository: jpetersenames/simpleserver
        dockerfile: Dockerfile
        containerRegistry: production
        tags: |
          $(Build.BuildId)

You can see that this pipeline is shorter than our previous pipeline that used anchore-cli and an instance of Anchore. The scan is the exact same as using any other instance of Anchore and it will provide the same results. Inline scan can also be loaded with any policy bundle you want to audit your image as I have done here using the -b option. You can also provide the -f option which will fail the pipeline when the policy scan returns a ‘fail’ result. This will provide output similar to what you see below where you are provided with the ‘fail’ result as well as which gates in the policy bundle were violated.

Security Fail Notice and Violated Policy Gates
You can also see at the top of the output in the terminal that some reports were generated. These are JSON files that contain the contents Anchore found inside the image as well as a list of the vulnerabilities that were detected.

Overall Anchore’s inline scan functionality is a powerful way to integrate security into your Azure DevOps pipeline. It allows you to run a full Anchore compliance scan with no dependencies. This is great for environments that are air-gapped or if it doesn’t make sense to keep a staging registry or a running Anchore instance.