Skip to content

Azure DevOps


Enabling Boost advisor


The Boost advisor let you address your findings backlog easier and faster. With it AppSec team can initiate a finding remediation from the Boost finding view.

The following describes how to set it up on Azure DevOps.

  1. Go to the boost repository.
  2. Commit a pipeline definition file named boost-advisor.yml, by default at the root of the boost repository.

    Boost Security runs the pipeline named boostsecurityio.boost-advisor. When no pipeline has that name, Boost Security creates it from the boost-advisor.yml file at the root of the boost repository, so you don't need to register the pipeline manually.

    Keeping the file elsewhere in the repository

    To store the pipeline definition at another path of the boost repository, register the pipeline yourself:

    1. Go to Pipelines → New pipeline → Azure Repos Git, select the boost repository, choose Existing Azure Pipelines YAML file, and pick your file.
    2. In the Run dropdown, click Save instead of running the pipeline.
    3. From the pipeline's ⋮ menu, click Rename/move and name it exactly boostsecurityio.boost-advisor. Boost Security runs only the pipeline with that name.
    4. Open Pipelines → Library → boostsecurityio → Pipeline permissions and add the boostsecurityio.boost-advisor pipeline, so its runs are not held waiting for permission to use the variable group.

    The pipeline expects a variable group named boostsecurityio (declared in the YAML at variables.group). Create it under Pipelines → Library → + Variable group.

    File contents:

    trigger: none
    
    parameters:
      - name: payload
        type: string
        default: ""
    
    variables:
      - group: boostsecurityio
    
    pool:
      vmImage: ubuntu-latest
    
    steps:
      - script: |
          set -euo pipefail
          curl -sSL https://assets.build.boostsecurity.io/boost-advisor/get-boost-advisor | sh
        displayName: Download boost-advisor
      - script: |
          set -euo pipefail
          # A variable missing from the group is passed as its unexpanded macro text.
          defined() { [ -n "$1" ] && [[ "$1" != '$('* ]]; }
          if defined "$BOOST_SCM_TOKEN"; then
            echo "Authenticating to Azure DevOps with the BOOST_SCM_TOKEN personal access token"
          elif defined "$AZURE_TENANT_ID" && defined "$AZURE_CLIENT_ID" && defined "$AZURE_CLIENT_SECRET"; then
            echo "Authenticating to Azure DevOps with the service principal"
            ACCESS_TOKEN=$(curl -sS --fail-with-body -X POST "https://login.microsoftonline.com/$AZURE_TENANT_ID/oauth2/v2.0/token" \
              -H "Content-Type: application/x-www-form-urlencoded" \
              -d "grant_type=client_credentials" \
              -d "client_id=$AZURE_CLIENT_ID" \
              --data-urlencode "client_secret=$AZURE_CLIENT_SECRET" \
              -d "scope=499b84ac-1321-427f-aa17-267ca6975798/.default" | jq -er .access_token)
            echo "##vso[task.setvariable variable=BOOST_SCM_TOKEN;issecret=true]$ACCESS_TOKEN"
          else
            echo "##vso[task.logissue type=error]Define BOOST_SCM_TOKEN, or AZURE_TENANT_ID, AZURE_CLIENT_ID and AZURE_CLIENT_SECRET, in the boostsecurityio variable group."
            exit 1
          fi
        displayName: Resolve Azure DevOps credentials
        env:
          BOOST_SCM_TOKEN: $(BOOST_SCM_TOKEN)
          AZURE_TENANT_ID: $(AZURE_TENANT_ID)
          AZURE_CLIENT_ID: $(AZURE_CLIENT_ID)
          AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
      - script: |
          export BOOST_SCM_TOKEN=$(BOOST_SCM_TOKEN)
          export BOOST_API_KEY=$(BOOST_API_TOKEN)
          export BOOST_LLM_MODEL=$(BOOST_LLM_MODEL)
          export BOOST_LLM_KEY=$(BOOST_LLM_KEY)
          echo "$PAYLOAD" | /tmp/boost-advisor/latest -
        displayName: Run boost-advisor
        env:
          PAYLOAD: ${{ parameters.payload }}
    
  3. Create the Personal Access Token

    By default, the Boost advisor authenticates to Azure DevOps with a Personal Access Token (PAT). To authenticate with a Microsoft Entra ID service principal instead, see Authenticating with a service principal.

    1. Sign in to Azure DevOps as a user with at least Basic access to the project (and admin rights on the repository, so PR creation is permitted).

    2. Click your profile icon (top right) → Personal access tokens → + New Token. Direct link: https://dev.azure.com/{organization}/_usersSettings/tokens

    3. Set:

      • Name: boost-advisor
      • Organization: the target organization
      • Expiration: per customer policy (max 1 year)
      • Scopes: click Custom defined and grant:
        • Code → Read & write (clone and push)
        • Code → Status (optional, to set commit statuses)
        • Pull Request Threads → Read & write (post review comments, optional)
    4. Click Create and copy the token (shown only once).

      ADO PATs respect the user's permissions. Make sure the user owning the PAT is a member of the Contributors group of the target repository, otherwise pushes and PRs will fail with a 403.

  4. Add the secrets to the variable group

    Open Pipelines → Library → boostsecurityio and add these variables. Click the lock icon to mark each as secret.

    Variable Name Value
    BOOST_SCM_TOKEN Personal access token created in the previous step
    BOOST_LLM_MODEL LLM model identifier
    BOOST_LLM_KEY LLM provider API key

    Note

    BOOST_API_TOKEN is provisioned automatically by ZTP and does not need to be added manually.


Authenticating with a service principal


Instead of a personal access token, the Boost advisor can authenticate to Azure DevOps with a Microsoft Entra ID service principal. A service principal isn't tied to a user account, and a single one can be added to every Azure DevOps organization connected to the Microsoft Entra ID tenant where it is registered. On each run, the pipeline exchanges the service principal's secret for an Azure DevOps access token.

The advisor can use the service principal of your Boost Security ADO Account Integration, or a service principal dedicated to the advisor. Whichever you use, it must have the Basic access level and be a member of the Project Contributors group of the projects hosting the repositories the advisor remediates, otherwise pushes and PRs will fail with a 403.

This option applies when your ADO Account Integration uses the App Registration method. With the Microsoft Entra ID method, the BoostSecurity.io application belongs to Boost Security and you don't hold its secret, so create a dedicated service principal instead.

  1. In the Azure portal, go to Microsoft Entra ID → App registrations and open the app registration of the integration, created during the Entra ID Configuration.
  2. On the app's Overview page, copy the Application (client) ID and the Directory (tenant) ID.
  3. Go to Certificates & secrets → + New client secret, and copy the secret Value (shown only once). A secret of its own lets you rotate the advisor's secret without touching the integration. When the secret expires, the advisor pipeline fails until you update AZURE_CLIENT_SECRET in the variable group.
  4. Check that the service principal is a member of the Project Contributors group of every project hosting repositories the advisor remediates. The Azure DevOps Configuration of the integration adds it with Basic access to the Project Contributors group, and recommends all projects.
  1. In the Azure portal, go to Microsoft Entra ID → App registrations → + New registration, name it boost-advisor, keep Accounts in this organizational directory only, and click Register.
  2. On the app's Overview page, copy the Application (client) ID and the Directory (tenant) ID.
  3. Go to Certificates & secrets → + New client secret, set an expiration per your policy, and copy the secret Value (shown only once). When the secret expires, the advisor pipeline fails until you update AZURE_CLIENT_SECRET in the variable group.
  4. In each Azure DevOps organization hosting repositories the advisor remediates, go to Organization settings → Users → Add users as a Project Collection Administrator. Search for boost-advisor, give it the Basic access level, and add it to the Project Contributors group of the target projects.

The integration's own service principal must remain a member of the Project Contributors group as well: the dedicated service principal adds to it and does not replace it.

Then open Pipelines → Library → boostsecurityio and add these variables, in place of BOOST_SCM_TOKEN. Click the lock icon to mark each as secret. BOOST_LLM_MODEL and BOOST_LLM_KEY from step 4 above are still required.

Variable Name Value
AZURE_TENANT_ID Directory (tenant) ID of the service principal
AZURE_CLIENT_ID Application (client) ID of the service principal
AZURE_CLIENT_SECRET Client secret value of the service principal

Note

The pipeline uses BOOST_SCM_TOKEN whenever it is defined in the variable group. To switch from a personal access token to the service principal, delete the BOOST_SCM_TOKEN variable.


Manual security scans


Scanning steps can be added to your Azure DevOps pipelines by installing the Boost Security extension.

To do so:

  1. Navigate to the Marketplace App.
  2. Click Get it free.
  3. Select your organization and click Install.

Additionally, it would help if you made the Boost API Token available in your Variables. If you do not already have an API token created, you may create one on the dashboard Settings Page.

Once everything is ready, a scanning step can be added, for example:

  - stage: Run Security Scanners
    variables:
      - group: boostsecurity
      - name: boostApiToken
        value: $[variables.BOOST_API_TOKEN]
    jobs:
      - job:
        steps:
          - task: BoostSecurityScan@1
            inputs:
              apiToken: $(boostApiToken)
              registryModule: boostsecurityio/semgrep

BoostSecurityScan is the Boost Security pipeline task enabling running scanners and uploading results to the Boost Security service.

The input apiToken configures the API key for authenticating the scanner.

The keyword registry_module specifies the scanner module to use. The example above configures the Semgrep scanner with the id boostsecurityio/semgrep.


Azure DevOps for Source Scanning


This configuration is appropriate for scanner modules for SAST scanning or SBOM inventory from source code.

Note: Even if the pipeline is configured to run the SBOM scanner on pull requests, the SBOM scanner does not collect components inventory on pull requests.

  - stage: Run Security Scanners
    variables:
      - group: boostsecurity
      - name: boostApiToken
        value: $[variables.BOOST_API_TOKEN]
      - name: isMainBranch
        value: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
    jobs:
      - job:
        steps:
          - task: BoostSecurityScan@1
            inputs:
              apiToken: $(boostApiToken)
              registryModule: boostsecurityio/semgrep
          - task: BoostSecurityScan@1
            condition: eq(variables.isMainBranch, 'true')
            inputs:
              apiToken: $(boostApiToken)
              registryModule: boostsecurityio/trivy-sbom

Azure DevOps for scanning generated artifacts


This configuration is appropriate for scanner modules that scan artifacts generated from the build process. For example, scanner modules that generate SBOM from container images or scan for vulnerabilities need to generate the container image first.

Add the Boost Security scanner module-related stanza to your build pipeline, for example:

  - stage: Build Step
    variables:
      - group: boostsecurity
      - name: boostApiToken
        value: $[variables.BOOST_API_TOKEN]
    jobs:
      - job:
        steps:
          - task: Bash@3
            displayName: Build Image
            inputs:
              targetType: "inline"
              script: |
                docker build . -t acme-analytics
          - task: BoostSecurityScan@1
            env:
              BOOST_IMAGE_NAME: acme-analytics  # set image name to scan
            inputs:
              apiToken: $(boostApiToken)
              registryModule: boostsecurityio/trivy-image

In the example above, the container image name set in the environment variable BOOST_IMAGE_NAME is static. If your image name needs to be created dynamically, a step can be inserted prior to the scan step, to set the environment variable. i.e., replace.

  steps:
    - task: Bash@3
      displayName: Build Image
      inputs:
        targetType: "inline"
        script: |
          docker build . -t acme-analytics
    - task: BoostSecurityScan@1
      env:
        BOOST_IMAGE_NAME: acme-analytics  # set image name to scan
      inputs:
        apiToken: $(boostApiToken)
        registryModule: boostsecurityio/trivy-image
with
  steps:
    - task: Bash@3
      displayName: Build Image
      inputs:
        targetType: "inline"
        script: |
          docker build . -t acme-analytics
          echo "##vso[task.setvariable variable=BOOST_IMAGE_NAME]my_image_name_and_tag"
    - task: BoostSecurityScan@1
      inputs:
        apiToken: $(boostApiToken)
        registryModule: boostsecurityio/trivy-image

Note

The task.setvariable step sets the environment variable, and the key env is removed from step BoostSecurityScan.