This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

CI / CD Integration

Integrating Anchore Enterprise into your CI/CD pipeline enables fast shift-left feedback, allowing developers to identify and resolve security issues early in the software development lifecycle. This page provides best practices for tuning your CI/CD integration for performance and actionable feedback.

See the specific subpages for platform-specific guidance.

Requirements

The following a general requirements for CI/CD integration.

Accessibility

Anchore Enterprise should be deployed so that the API is accessible from your pipeline runner. Your Anchore Enterprise deployment must also be able to reach any relevant container registries from which to source images.

For access to the deployment, API keys are recommended.

Tooling Version Alignment

The primary interface for integrating Anchore Enterprise into CI/CD environments is AnchoreCTL, a CLI tool designed for scripted automation. To ensure compatibility and simplify runner configuration, AnchoreCTL should always be version-aligned with your Anchore Enterprise deployment.

A recommended practice is to fetch AnchoreCTL directly from your Anchore Enterprise installation during the CI job. This guarantees the client version matches the server.

For more details, see Deploying AnchoreCTL.

Modes of Analysis

Anchore support two primary modes of operation for image analysis in CI pipelines: Distributed Analysis or Centralised Analysis. Both modes work with any CI/CD system as long as the AnchoreCTL binary can be installed and run, or you can access the Enterprise APIs directly.

In distributed analysis, SBOM generation happens locally on the runner and is then sent to Anchore Enterprise for evaluation.

It is the recommended approach because it offers maximum flexibility in resourcing. You can improve SBOM generation speed by customising your anchoreCTL configuration and providing more CPU and fast I/O to your pipeline runners.

See Distributed Analysis for further information.

Centralized Analysis

In centralized analysis, the Anchore Enterprise deployment itself downloads and analyzes the image content. This is necessary if you require the malware scanning service to unpack and scan container layers.

See Centralized Analysis for further information.

Optimizing Performance

If you are using Distributed Analysis, you will want to ensure that your CI runners have fast CPU and I/O, to optimise the cataloging and SBOM generation process used by AnchoreCTL.

If your container images contain a large number of files and packages, you may be able to significantly reduce SBOM generation time by enabling parallelism. AnchoreCTL (v5.18+) can run catalogers in parallel rather than sequentially.

See Configuring AnchoreCTL for further information.

Use Policy Checks

Rather than just reviewing a raw list of vulnerabilities, which can be daunting and lack context, it is a best practice to use the Anchore Enforce policy engine to conduct compliance checks.

Policy-driven gating provides developers with precise, actionable feedback based on your own organizational policy or industry standards (e.g., NIST 800-53, CIS).

Use the following command to evaluate an image against your default policy and fail the CI job if it does not meet compliance requirements.

anchorectl image check <MY_IMAGE> --fail-based-on-results --detail

The --detail flag is essential for developers, as it provides the specific gate, trigger, and remediation recommendations needed to resolve policy violations.

One-Time Scan (Stateless Evaluation)

By default, adding an image to Anchore Enterprise for analysis means that the SBOM will be stored persistently in the deployment, until archived or deleted. This could mean your deployment stores more SBOMs than necessary; you may not care whether an SBOM for a CI build is persisted or not.

Anchore Enterprise has a featured called One Time Scan which can be used to deliver fast feedback in your pipeline jobs, namely vulnerability and policy analysis results, but doing so without persisting the SBOM in your Anchore Enterprise deployment. Use the anchorectl image one-time-scan command to conduct analysis in this mode. As with the anchorectl image check command, you can also pass a flag to fail the pipeline job if the policy analysis fails. For example:

anchorectl image one-time-scan ghcr.io/place/thing:v0.1.0 --from [docker, registry] --fail-on-policy-error

By default, this command will return a policy check. Using the -o json parameter, JSON results for policy check, vulnerability scan and the SBOM will be returned. These results can then be machine parsed by the CI/CD job to determine actions.

1 - GitLab

Requirements

  1. Anchore Enterprise is deployed in your environment, with the API accessible from your GitLab CI environment.
  2. Credentials for your GitLab Container Registry are added to Anchore Enterprise, under the Anchore account that you intend to use with GitLab CI. See Registries. For information on what registry/credentials must be added to allow Anchore Enterprise to access your GitLab Container Registry, see https://docs.gitlab.com/ee/user/packages/container_registry/.

1. Configure Variables

Ensure that the following variables are set in your GitLab repository (settings -> CI/CD -> Variables -> Expand -> Add variable) or GitLab Group:

ANCHORECTL_USERNAME
ANCHORECTL_PASSWORD (masked)
ANCHORECTL_URL

Note Gitlab has a minimum length of 8 for masked variables. Please ensure both your username and password meet this requirement.

Set Variables

2. Create config file

Create a new file in your repository. Name the file .gitlab-ci.yml.

Set Variables

3. Configure scanning mode

a) Distributed Mode

This is the most easily scalable method for scanning images. Distributed scanning uses the anchorectl utility to build the SBOM directly on the build runner and then pushes the SBOM to Anchore Enterprise through the API. To use this scanning method, paste the following workflow script into your new .gitlab-ci.yml file. After building the image from your Dockerfile and scanning it with anchorectl, this workflow will display vulnerabilities and policy results in the build log. After pasting, click “Commit changes” to save the new file.

### Anchore Distributed Scan
  # you will need three variables defined:
  # ANCHORECTL_USERNAME
  # ANCHORECTL_PASSWORD
  # ANCHORECTL_URL

image: docker:latest
services:
- docker:dind
stages:
- build
- anchore
variables:
  ### set this to true if you want the result of the policy check to determine whether the job succeeds or not
  ANCHORECTL_FAIL_BASED_ON_RESULTS: "false"
  ANCHORE_IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}

Build:
  stage: build
  script:
    ### build and push docker image
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    - docker build -t ${ANCHORE_IMAGE} .
    - docker push ${ANCHORE_IMAGE}

Anchore:
  stage: anchore
  before_script:
    ### install anchorectl binary
    - apk add --no-cache curl
    - 'curl "$ANCHORECTL_URL/v2/system/anchorectl?operating_system=linux&architecture=amd64" -H "accept: */*" | tar -zx anchorectl && mv -v anchorectl /usr/bin && chmod +x /usr/bin/anchorectl && /usr/bin/anchorectl version'
    - export PATH="${HOME}/.local/bin/:${PATH}"
  script:
    ### provide registry credentials for anchorectl
    - export ANCHORECTL_REGISTRY_AUTH_AUTHORITY=$CI_REGISTRY
    - export ANCHORECTL_REGISTRY_AUTH_USERNAME="$CI_REGISTRY_USER"
    - export ANCHORECTL_REGISTRY_AUTH_PASSWORD="$CI_REGISTRY_PASSWORD"
    ### scan image and push to anchore enterprise
    - anchorectl image add --no-auto-subscribe --wait --dockerfile ./Dockerfile --from registry ${ANCHORE_IMAGE}
    ### then get the results:
    - anchorectl image vulnerabilities ${ANCHORE_IMAGE}
    - anchorectl image check --detail ${ANCHORE_IMAGE}

b) Centralized Mode

This method uses the “analyzer” pods in the Anchore Enterprise deployment to build the SBOM. This can create queuing if there are not enough analyzer processes, and this method will require the operator to provide registry credentials in the Enterprise backend (if the images to be scanned are in private registries). This method may be preferred in cases where the Anchore Enterprise operator does not control the image build process (the analyzers can simply poll registries to look for new image builds as they are pushed), and this method also allows the operator to simply queue up the image for asynchronous scanning later if vulnerability and policy results are not required immediately. If the user wants malware scanning results from Anchore Enterprise’s clamav integration, the Centralized Scanning method is required. To use this scanning method, paste the following workflow script into your new .gitlab-ci.yml file. After building the image from your Dockerfile,, this workflow will tell Anchore Enterprise to scan the image, then it will display the vulnerability and policy results in the build log. After pasting, click “Commit changes” to save the new file.

### Anchore Centralized Scan
  # you will need three variables defined:
  # ANCHORECTL_USERNAME
  # ANCHORECTL_PASSWORD
  # ANCHORECTL_URL

image: docker:latest
services:
- docker:dind
stages:
- build
- anchore
variables:
  ANCHORECTL_FAIL_BASED_ON_RESULTS: "false"
  ANCHORE_IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}

Build:
  stage: build
  script:
    ### build and push docker image
    - echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin
    - docker build -t ${ANCHORE_IMAGE} .
    - docker push ${ANCHORE_IMAGE}

Anchore:
  stage: anchore
  before_script:
    ### install anchorectl binary
    - apk add --no-cache curl
    - 'curl "$ANCHORECTL_URL/v2/system/anchorectl?operating_system=linux&architecture=amd64" -H "accept: */*" | tar -zx anchorectl && mv -v anchorectl /usr/bin && chmod +x /usr/bin/anchorectl && /usr/bin/anchorectl version'
    - export PATH="${HOME}/.local/bin/:${PATH}"
  script:
    ### note that private registries will require registry credentials to be configured in your Anchore deployment
    ### queue image for scanning
    - anchorectl image add --no-auto-subscribe --wait --dockerfile ./Dockerfile ${ANCHORE_IMAGE} 
    ### then get the results:
    - anchorectl image vulnerabilities ${ANCHORE_IMAGE}
    - anchorectl image check --detail ${ANCHORE_IMAGE}

4. View pipeline

Gitlab will automatically start a pipeline. Navigate to “Build” -> “Pipelines” and then on your running pipeline.

Set Variables

5. View output

Once the build is complete, click on the “anchore” stage and view the output of the job. You will see the results of the vulnerability match and policy evaluation in the output.

2 - Azure Pipelines

Anchore Enterprise can be integrated into Azure DevOps pipelines to generate and analyze SBOMs, perform vulnerability scanning, and enforce policy evaluation as a pipeline gate. This page covers two integration approaches: distributed analysis and centralized analysis.


Prerequisites

The following are required for both integration approaches:

  • A running Anchore Enterprise instance. See Deployment for setup instructions.
  • An Azure DevOps pipeline.
  • An Azure Key Vault variable group named anchoreCredentials containing your Anchore Enterprise credentials. The following variables are required:
VariableDescription
anchore_urlThe URL of your Anchore Enterprise instance
anchore_endpointThe hostname of your Anchore Enterprise instance (used to download AnchoreCTL)
anchore_userYour Anchore username, or _api_key if using an API key
anchore_passYour Anchore password or API key value

Note: API keys are the recommended authentication method for CI/CD pipelines. They can be rotated and revoked independently of user accounts. See API Keys for setup instructions.


Distributed Analysis

In distributed analysis, AnchoreCTL generates the SBOM locally on the pipeline agent and uploads it to Anchore Enterprise for vulnerability matching and policy evaluation. The image is not required to be in a remote registry before scanning.

This is the recommended approach for most pipelines. It requires less infrastructure than centralized analysis and avoids the need for a staging registry.

Note: Distributed analysis does not support malware scanning. If your workflow requires malware scanning via ClamAV, use Centralized Analysis instead.

How It Works

The anchorectl image add command accepts a --from flag that specifies the source from which AnchoreCTL should generate the SBOM:

  • --from docker:<image> — generates the SBOM from a locally available Docker image on the pipeline agent.
  • --from registry — pulls the image from a remote registry for local analysis. Use this when the image has already been pushed to a registry in a prior pipeline step, as it captures the registry-assigned digest, which remains consistent as the image moves through environments.

The first positional argument to image add is the tag Anchore Enterprise uses to identify the image in its database. This does not need to be a pullable registry path.

Distributed Pipeline

trigger:
- master

resources:
- repo: self

variables:
- name: imageRef
  value: 'production/simpleserver:$(Build.BuildId)'
- group: anchoreCredentials

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - task: Docker@2
      displayName: Build image
      inputs:
        command: build
        repository: simpleserver
        dockerfile: Dockerfile
        tags: |
          $(Build.BuildId)

- stage: Security
  displayName: Security scan stage
  dependsOn: Build
  jobs:
  - job: Security
    displayName: Security
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: curl -X GET "https://$(anchore_endpoint)/v2/system/anchorectl?operating_system=linux&architecture=amd64" -H "accept: */*" | tar -zx anchorectl
      displayName: Install AnchoreCTL

    - script: |
        export PATH=$PATH:$HOME/.local/bin
        export ANCHORECTL_URL=$(anchore_url)
        export ANCHORECTL_USERNAME=$(anchore_user)
        export ANCHORECTL_PASSWORD=$(anchore_pass)
        # To authenticate with an API key instead:
        # export ANCHORECTL_USERNAME=_api_key
        # export ANCHORECTL_PASSWORD=$(api_token)
        ./anchorectl image add $(imageRef) --from docker:simpleserver:$(Build.BuildId) --dockerfile Dockerfile --wait
        ./anchorectl image vulnerabilities $(imageRef)
        ./anchorectl image check $(imageRef) --fail-based-on-results
      displayName: Anchore Security Scan

- stage: Production
  displayName: Production stage
  dependsOn: Security
  # Push the image to your production registry and deploy

Centralized Analysis

In centralized analysis, the image is pushed to a staging registry and Anchore Enterprise pulls and analyzes it directly using the analyzer service. The SBOM is stored in Anchore Enterprise and available for post-scan reporting, compliance auditing, and policy justification.

This approach is required when malware scanning is enabled. See Malware Scanning for configuration details. Note that enabling malware scanning increases overall scan time.

Providing the Dockerfile via --dockerfile also enables Dockerfile-specific policy checks, such as validating the effective user ID or flagging exposed ports.

Additional Prerequisites

The following are required in addition to the common prerequisites:

  • A staging registry. Images are pushed here before scanning and promoted to production only after passing policy evaluation. The example below provisions an Azure Container Registry using Terraform:

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    resource "azurerm_resource_group" "blog" {
      name     = "blog"
      location = "West US"
    }
    
    resource "azurerm_container_registry" "blog" {
      name                = "staging"
      resource_group_name = azurerm_resource_group.blog.name
      location            = azurerm_resource_group.blog.location
      sku                 = "Standard"
      admin_enabled       = true
    }
    

    Note: admin_enabled = true enables the ACR built-in admin account, which uses a single shared credential and cannot be scoped or audited per consumer. For production use, set admin_enabled = false and grant access using a service principal or managed identity with the AcrPull and AcrPush roles as appropriate. See Azure Container Registry authentication options for details.

  • An Azure DevOps service connection. Required for the pipeline to push images to the staging registry. Configure a Docker Registry service connection targeting your Azure Container Registry. See Azure DevOps service connections for instructions.

  • Registry credentials in Anchore Enterprise. Anchore Enterprise must be able to pull images from the staging registry. See Registry Configuration for instructions.

Centralized Pipeline

trigger:
- master

resources:
- repo: self

variables:
- name: stagedImage
  value: 'staging/simpleserver:$(Build.BuildId)'
- name: productionImage
  value: 'production/simpleserver:$(Build.BuildId)'
- group: anchoreCredentials

stages:
- stage: Build
  displayName: Build and push to staging
  # Build and push the image to the staging registry

- stage: Security
  displayName: Security scan stage
  dependsOn: Build
  jobs:
  - job: Security
    displayName: Security
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: curl -X GET "https://$(anchore_endpoint)/v2/system/anchorectl?operating_system=linux&architecture=amd64" -H "accept: */*" | tar -zx anchorectl
      displayName: Install AnchoreCTL

    - script: |
        export PATH=$PATH:$HOME/.local/bin
        export ANCHORECTL_URL=$(anchore_url)
        export ANCHORECTL_USERNAME=$(anchore_user)
        export ANCHORECTL_PASSWORD=$(anchore_pass)
        ./anchorectl image add $(stagedImage) --dockerfile Dockerfile --wait
        ./anchorectl image vulnerabilities $(stagedImage)
        ./anchorectl image check $(stagedImage) --fail-based-on-results
      displayName: Anchore Security Scan

- stage: Production
  displayName: Production stage
  dependsOn: Security
  # Push the image to your production registry and deploy

Failing a Pipeline on Policy Evaluation

The --fail-based-on-results flag (shorthand: -f) on anchorectl image check causes AnchoreCTL to return a non-zero exit code when the policy evaluation result is stop. This fails the pipeline stage and prevents the image from being promoted.

anchorectl image check <image> --fail-based-on-results

Example output for a failed evaluation:

 ✔ Evaluated against policy                  [failed]
Tag: docker.io/anchore/test_images:convertigo-7.9.2
Digest: sha256:b649023ebd9751db65d2f9934e3cfeeee54a010d4ba90ebaab736100a1c34d7d
Policy ID: anchore_secure_default
Last Evaluation: 2026-02-20T17:19:26Z
Evaluation: fail
Final Action: stop
Reason: policy_evaluation
error: 1 error occurred:
        * failed policies:

One-Time Analysis

Anchore Enterprise supports one-time analysis, which performs vulnerability scanning and policy evaluation without storing the SBOM. This is useful for quick feedback during development before pushing to a registry.

For details, see the CI/CD one-time scan documentation or contact the customer success team via the Support Portal.


Next Steps

3 - GitHub

Image Scanning can be easily integrated into your GitHub Actions pipeline using anchorectl.

1. Configure Variables

Ensure that the following variables/secrets are set in your GitHub repository (repository settings -> secrets and variables -> actions):

  • Variable ANCHORECTL_URL
  • Variable ANCHORECTL_USERNAME
  • Secret ANCHORECTL_PASSWORD

These are necessary for the integration to access your Anchore Enterprise deployment. The ANCHORECTL_PASSWORD value should be created as a repository secret to prevent exposure of the value in job logs, while ANCHORECTL_URL and ANCHORECTL_USERNAME can be created as repository variables.

Set Variables

2. Configure Permissions

(“Settings” -> “Actions” -> “General” -> “Workflow permissions”) select “Read and write permissions” and click “Save”.

Set Variables

3. Create config file

In your repository, create a new file ( “Add file” -> “Create new file”) and name it .github/workflows/anchorectl.yaml.

Set Variables

4. Set scanning mode

a) Distributed Mode

This is the most easily scalable method for scanning images. Distributed scanning uses the anchorectl utility to build the SBOM directly on the build runner and then pushes the SBOM to Anchore Enterprise through the API. To use this scanning method, paste the following workflow script into your new anchorectl.yaml file. After building the image from your Dockerfile and scanning it with anchorectl, this workflow will display vulnerabilities and policy results in the build log.

name: Anchore Enterprise Distributed Scan

on:
  workflow_dispatch:
    inputs:
      mode:
        description: 'On-Demand Build'  
        
env:
  ANCHORECTL_URL: ${{ vars.ANCHORECTL_URL }}
  ANCHORECTL_USERNAME: ${{ vars.ANCHORECTL_USERNAME }}
  ANCHORECTL_PASSWORD: ${{ secrets.ANCHORECTL_PASSWORD }}
  ## set ANCHORECTL_FAIL_BASED_ON_RESULTS to true if you want to break the pipeline based on the evaluation
  ANCHORECTL_FAIL_BASED_ON_RESULTS: false
  REGISTRY: ghcr.io
     
jobs:
  Build:
    runs-on: ubuntu-latest
    steps:
    
    - name: "Set IMAGE environmental variables"
      run: |
        echo "IMAGE=${REGISTRY}/${GITHUB_REPOSITORY}:${GITHUB_REF_NAME}" >> $GITHUB_ENV
        
    - name: Checkout Code
      uses: actions/checkout@v3
      
    - name: Log in to the Container registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}      
      
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2


    - name: build local container
      uses: docker/build-push-action@v3
      with:
        tags: ${{ env.IMAGE }}
        push: true
        load: false


  Anchore:
    runs-on: ubuntu-latest
    needs: Build
    steps:
    
    - name: "Set IMAGE environmental variables"
      run: |
        echo "IMAGE=${REGISTRY}/${GITHUB_REPOSITORY}:${GITHUB_REF_NAME}" >> $GITHUB_ENV
        
    - name: Checkout Code
      ### only need to do this if you want to pass the dockerfile to Anchore during scanning
      uses: actions/checkout@v3
        
    - name: Install Latest anchorectl Binary
      run: |
        mkdir -p $HOME/.local/bin
        curl -sSfL "${ANCHORECTL_URL}/v2/system/anchorectl?operating_system=linux&architecture=amd64" \
            -H "accept: /" | tar -zx -C $HOME/.local/bin anchorectl
        echo "$HOME/.local/bin" >> $GITHUB_PATH
            
    - name: Generate SBOM and Push to Anchore
      run: |        
        anchorectl image add --no-auto-subscribe --wait --from registry --dockerfile Dockerfile ${IMAGE}
        
    - name: Pull Vulnerability List
      run: |
        anchorectl image vulnerabilities ${IMAGE} 
        
    - name: Pull Policy Evaluation
      run: |
        # set "ANCHORECTL_FAIL_BASED_ON_RESULTS=true" (see above in the "env:" section) to break the pipeline here if the 
        # policy evaluation returns FAIL or add -f, --fail-based-on-results to this command for the same result
        #
        anchorectl image check --detail ${IMAGE}

b) Centralized Mode

This method uses the “analyzer” pods in the Anchore Enterprise deployment to build the SBOM. This can create queuing if there are not enough analyzer processes, and this method may require the operator to provide registry credentials in the Enterprise backend (if the images to be scanned are in private registries). This method may be preferred in cases where the Anchore Enterprise operator does not control the image build process (the analyzers can simply poll registries to look for new image builds as they are pushed), and this method also allows the operator to simply queue up the image for asynchronous scanning later if vulnerability and policy results are not required immediately. If the user wants malware scanning results from Anchore Enterprise’s clamav integration, the Centralized Scanning method is required. To use this scanning method, paste the following workflow script into your new anchorectl.yaml file. After building the image from your Dockerfile,, this workflow will tell Anchore Enterprise to scan the image, then it will display the vulnerability and policy results in the build log.

name: Anchore Enterprise Centralized Scan

on:
  workflow_dispatch:
    inputs:
      mode:
        description: 'On-Demand Build'  

env:
  ANCHORECTL_URL: ${{ vars.ANCHORECTL_URL }}
  ANCHORECTL_USERNAME: ${{ vars.ANCHORECTL_USERNAME }}
  ANCHORECTL_PASSWORD: ${{ secrets.ANCHORECTL_PASSWORD }}
  ## set ANCHORECTL_FAIL_BASED_ON_RESULTS to true if you want to break the pipeline based on the evaluation
  ANCHORECTL_FAIL_BASED_ON_RESULTS: false
  REGISTRY: ghcr.io

jobs:

  Build:
    runs-on: ubuntu-latest
    steps:
    
    - name: "Set IMAGE environmental variables"
      run: |
        echo "IMAGE=${REGISTRY}/${GITHUB_REPOSITORY}:${GITHUB_REF_NAME}" >> $GITHUB_ENV
        
    - name: Checkout Code
      uses: actions/checkout@v3
      
    - name: Log in to the Container registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}      
      
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2


    - name: build local container
      uses: docker/build-push-action@v3
      with:
        tags: ${{ env.IMAGE }}
        push: true
        load: false

  Anchore:
    runs-on: ubuntu-latest
    needs: Build

    steps:
    
    - name: "Set IMAGE environmental variables"
      run: |
        echo "IMAGE=${REGISTRY}/${GITHUB_REPOSITORY}:${GITHUB_REF_NAME}" >> $GITHUB_ENV
        
    - name: Checkout Code
      uses: actions/checkout@v3
        
    - name: Install Latest anchorectl Binary
      run: |
        mkdir -p $HOME/.local/bin
        curl -sSfL "${ANCHORECTL_URL}/v2/system/anchorectl?operating_system=linux&architecture=amd64" \
            -H "accept: /" | tar -zx -C $HOME/.local/bin anchorectl
        echo "$HOME/.local/bin" >> $GITHUB_PATH
    
    - name: Queue Image for Scanning by Anchore Enterprise
      run: |        
       anchorectl image add --no-auto-subscribe --wait --dockerfile ./Dockerfile ${IMAGE} 
                
    - name: Pull Vulnerability List
      run: |
        anchorectl image vulnerabilities ${IMAGE} 
        
    - name: Pull Policy Evaluation
      run: |
        # set "ANCHORECTL_FAIL_BASED_ON_RESULTS=true" (see above in the "env:" section) to break the pipeline here if the 
        # policy evaluation returns FAIL or add -f, --fail-based-on-results to this command for the same result
        #
        anchorectl image check --detail ${IMAGE}

5. Run Workflow

Go to “Actions” -> “Anchore Enterprise with anchorectl” and hit “Run workflow”.

Set Variables

6. View Results

When the workflow completes, view the results by clicking on the workflow name (“Anchore Enterprise with anchorectl”), then on the job (“Anchore”), then expand the “Pull Vulnerability List” and/or “Pull Policy Evaluation” steps to see the details.

Set Variables

7. Notifications

You can also integrate your Anchore deployment with the GitHub API so that Anchore notifications are sent to GitHub Notifications as new issues in a repository.

To configure and enable this please review the GitHub Notifications documentation.

4 - Jenkins

Configure variables

Before getting started, you need to configure your Jenkins instance with the required credentials. Make sure the following values are added under Dashboard → Manage Jenkins → Credentials as credentials of type Secret text:

ANCHORECTL_USERNAME 
ANCHORECTL_PASSWORD
ANCHORECTL_URL

These are necessary for the integration to access your Anchore Enterprise deployment. The ANCHORECTL_PASSWORD value should be created as a repository secret to prevent exposure of the value in job logs, while ANCHORECTL_URL and ANCHORECTL_USERNAME can be created as repository variables.

Configure scanning mode

Below are examples of the two types of image scans. For a detailed explanation of their differences, refer to the documentation

a) Distributed

This is the most easily scalable method for scanning images. Distributed scanning uses the anchorectl utility to build the SBOM directly on the build runner and then pushes the SBOM to Anchore Enterprise through the API. The example below demonstrates how to automate distributed analysis within a pipeline.

pipeline {
        
    // Define parameters for user input
    parameters {
        string(name: 'REGISTRY', defaultValue: 'docker.io', description: 'The container registry to use.', trim: true)
        string(name: 'REPOSITORY', defaultValue: 'library/nginx', description: 'The image repository path.', trim: true)
        string(name: 'TAG', defaultValue: 'latest', description: 'The image tag to analyze.', trim: true)
        choice(name: 'ANCHORECTL_QUIET', choices: ['true', 'false'], description: 'Suppress anchorectl informational messages.')
        choice(name: 'ANCHORECTL_FORMAT', choices: ['json', 'csv'], description: 'The output format for anchorectl (e.g., json, csv).')
        choice(name: 'ANCHORECTL_FAIL_BASED_ON_RESULTS', choices: ['true', 'false'], description: 'How to handle fail signals (e.g., policy check outcomes)')
    }

    stages {
        stage('Anchore Image Scan') {
            environment {
              // This is the AnchoreCTL service endpoint (fetched securely from Jenkins credentials)
                ANCHORECTL_URL = credentials('ANCHORECTL_URL')
              // Define the Anchore account username
                ANCHORECTL_USERNAME = credentials('ANCHORECTL_USERNAME')

              // Define the Anchore account password
                ANCHORECTL_PASSWORD = credentials('ANCHORECTL_PASSWORD')

              // Whether to fail the pipeline based on AnchoreCTL scan results (controlled by Jenkins parameter)
                ANCHORECTL_FAIL_BASED_ON_RESULTS = "${params.ANCHORECTL_FAIL_BASED_ON_RESULTS}"

              // You can also choose to Suppress unnecessary output logs
                ANCHORECTL_QUIET = "${params.ANCHORECTL_QUIET}"

              // Define the Output format for AnchoreCTL results
                ANCHORECTL_FORMAT = "${params.ANCHORECTL_FORMAT}"
            }
            steps {
                script {
                    echo 'Starting image analysis pipeline.'
                    
                    // Download and configure the Anchore CLI
                    sh '''
                        mkdir -p $HOME/.local/bin
                        curl -sSfL "${ANCHORECTL_URL}v2/system/anchorectl?operating_system=linux&architecture=amd64" \\
                            -H "accept: /" | tar -zx -C $HOME/.local/bin anchorectl
                        export PATH="$HOME/.local/bin:$PATH"
                    '''

                    // Add the image to Anchore and wait for analysis to complete
                    sh "anchorectl image add --wait --from registry ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG}"

                    // Retrieve and archive vulnerability report
                    sh "anchorectl image vulnerabilities ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG} | tee vulnerabilities.${ANCHORECTL_FORMAT}"
                    archiveArtifacts artifacts: "vulnerabilities.${env.ANCHORECTL_FORMAT}"
                    
                    // Run and archive the policy check
                    sh """#!/bin/bash
                        set -o pipefail
                        anchorectl image check --detail ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG} | tee policy-check.${ANCHORECTL_FORMAT}
                    """
                    archiveArtifacts artifacts: "policy-check.${env.ANCHORECTL_FORMAT}"

                    // Post-build action to handle policy failure, if configured
                    if (env.ANCHORECTL_FAIL_BASED_ON_RESULTS == 'true') {
                        def policyCheckResult = sh(script: "grep -q 'Policy Evaluation: PASS' policy-check.${ANCHORECTL_FORMAT}", returnStatus: true)
                        if (policyCheckResult != 0) {
                            error('Policy check failed based on results.')
                        }
                    }
                }
            }
        }
    }
}

b ) Centralized

Centralized Scanning uses analyzer pods in Anchore Enterprise to generate the SBOM. This method is ideal when the operator does not control the image build process, supports asynchronous scanning, and is required for malware detection through ClamAV. After your container image is built, you can trigger a scan by adding the provided stage to your pipeline, which will instruct Anchore Enterprise to analyze the image and display vulnerability and policy results in the build log. Below is an example of how to achieve centralized scanning in your pipeline

pipeline {
    
    // Define parameters for user input
    parameters {
        string(name: 'REGISTRY', defaultValue: 'docker.io', description: 'The container registry to use.', trim: true)
        string(name: 'REPOSITORY', defaultValue: 'library/nginx', description: 'The image repository path.', trim: true)
        string(name: 'TAG', defaultValue: 'latest', description: 'The image tag to analyze.', trim: true)
        choice(name: 'ANCHORECTL_QUIET', choices: ['true', 'false'], description: 'Suppress anchorectl informational messages.')
        choice(name: 'ANCHORECTL_FORMAT', choices: ['json', 'csv'], description: 'The output format for anchorectl (e.g., json, csv).')
        choice(name: 'ANCHORECTL_FAIL_BASED_ON_RESULTS', choices: ['true', 'false'], description: 'How to handle fail signals (e.g., policy check outcomes)')
    }

    stages {
        stage('Anchore Image Scan') {
            environment {
                // This is the AnchoreCTL service endpoint (fetched securely from Jenkins credentials)
                ANCHORECTL_URL = credentials('ANCHORECTL_URL')
              // Define the Anchore account username
                ANCHORECTL_USERNAME = credentials('ANCHORECTL_USERNAME')

              // Define the Anchore account password
                ANCHORECTL_PASSWORD = credentials('ANCHORECTL_PASSWORD')

              // Whether to fail the pipeline based on AnchoreCTL scan results (controlled by Jenkins parameter)
                ANCHORECTL_FAIL_BASED_ON_RESULTS = "${params.ANCHORECTL_FAIL_BASED_ON_RESULTS}"

              // You can also choose to Suppress unnecessary output logs
                ANCHORECTL_QUIET = "${params.ANCHORECTL_QUIET}"

              // Define the Output format for AnchoreCTL results
                ANCHORECTL_FORMAT = "${params.ANCHORECTL_FORMAT}"
            }
            steps {
                script {
                    echo "Starting image analysis for: ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG}"

                    // Download and configure the Anchore CLI
                    sh '''
                        mkdir -p $HOME/.local/bin
                        curl -sSfL "${ANCHORECTL_URL}v2/system/anchorectl?operating_system=linux&architecture=amd64" \\
                            -H "accept: /" | tar -zx -C $HOME/.local/bin anchorectl
                        export PATH="$HOME/.local/bin:$PATH"
                    '''

                    // Add the image to Anchore and wait for analysis to complete
                    sh "anchorectl image add --wait ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG}"

                    // Retrieve and archive vulnerability report
                    sh "anchorectl image vulnerabilities ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG} | tee vulnerabilities.${ANCHORECTL_FORMAT}"
                    archiveArtifacts artifacts: "vulnerabilities.${env.ANCHORECTL_FORMAT}"

                    // Run and archive the policy check
                    sh """#!/bin/bash
                        set -o pipefail
                        anchorectl image check --detail ${params.REGISTRY}/${params.REPOSITORY}:${params.TAG} | tee policy-check.${ANCHORECTL_FORMAT}
                    """
                    archiveArtifacts artifacts: "policy-check.${env.ANCHORECTL_FORMAT}"

                    // Post-build action to handle policy failure, if configured
                    if (env.ANCHORECTL_FAIL_BASED_ON_RESULTS == 'true') {
                        def policyCheckResult = sh(script: "grep -q 'Policy Evaluation: PASS' policy-check.${ANCHORECTL_FORMAT}", returnStatus: true)
                        if (policyCheckResult != 0) {
                            error('Policy check failed based on results.')
                        }
                    }
                }
            }
        }
    }
}