iTranslated by AI
Getting Started with SBOM Management using Azure DevOps and ServiceNow
Target Audience
- People who want to gain a clearer understanding of SBOM
- People who manage software using Azure DevOps
- People who want to try managing SBOM with ServiceNow
Motivation
I recently found myself working on a public sector project for the first time in a while. While reviewing the revised contents of the "Common Standards Group for Cybersecurity Measures for Government Agencies and Related Organizations," I noticed a mention regarding SBOM.

Actions following the revision of the Common Standards Group for Cybersecurity Measures for Government Agencies and Related Organizations [1]
While the term SBOM was familiar to me, I hadn't quite internalized what it entails or for what purpose it should be managed. This led me to want to learn about and implement it.
About SBOM
First, let's deepen our understanding of SBOM by looking at excerpts from the "Guide for SBOM Introduction and Operation [2]" published by the IPA.
Although I will only introduce excerpts here, the guide is very well-summarized and informative, so I encourage you to read the whole thing.
What is SBOM?
Literally translated, SBOM (Software Bill of Materials) is a "software parts list."
It manages the components and other elements that make up the software as a parts list.
SBOM refers to a software parts list that includes the names, version information, dependencies, and developer information of the components that make up the software, as shown in Figure 2.1.1. The information can also include data on OSS and proprietary software, and it is provided in a machine-readable format.
Benefits of Implementing SBOM
There are two main benefits to implementing SBOM:
1. Improvement in vulnerability management capabilities
2. Improvement in license management capabilities
First, let's talk about vulnerability management.
In traditional management, which components were included in which applications was not always visualized.
In such cases, the initial response when a zero-day vulnerability like Log4j is discovered is delayed.
By implementing SBOM, the visibility and searchability of components included in software improve, enabling a faster initial response when a vulnerability is found.
Next is license management.
Here, I will explain with a focus on OSS license types.
OSS has various license types such as GPL, MPL, and BSD, and there may be restrictions on duplication or code disclosure depending on the type.
By properly understanding which type each software component belongs to, you can prevent license violations.
Creating and Managing SBOM
The actual substance of an SBOM is a file in formats such as JSON or XML.
SBOM formats are standardized, with SPDX, CycloneDX, and SWID tags being recommended as representative formats.

Sample CycloneDX format file
There are various tools, both free and paid, for generating these SBOM files.
The introduction guide mentions that it is important to select tools according to your requirements.
While there are management benefits to having the SBOM file alone, usability is further enhanced when a GUI is available.
Some creation tools have a built-in GUI, while others are tools designed to import and visualize files. (In the implementation phase described later, I used a ServiceNow developer instance as a visualization tool.)
Implementation
Now that the theoretical learning is over, let's get hands-on.
I want to start small, so I've chosen a configuration that costs as little as possible. I selected Trivy [3] for creating SBOM files and ServiceNow's SBOM Management feature [4] as the visualization tool.
Here is the screen after actually importing into ServiceNow.
You can see the components included in the software, their versions, included CVEs, and the number of BOM entities containing the same component.

ServiceNow Implementation
Since I am not very familiar with ServiceNow and struggled due to limited public information, I will write it down step-by-step for future reference.
Installing Applications
First, install the necessary applications in the Application Manager.
I installed the following three:
- SBOM Core
- Data Model for SBOM
- SBOM Response
Open the Application Manager and install the corresponding software.




A popup notified me when the installation was complete.

Install SBOM Core and SBOM Response in the same way.
SBOM Response took some time because it has many related components.
Check the activity log of the Application Manager to confirm that the installation is complete.

Creating a User
Create a user to execute the API.
Create a new user on the Users screen.


First, create the user with only the username entered,

Then set the password for the created user.



This API execution requires the "sn_sbom_core.sbom_ingest" role, so assign it.


Creating an Authentication Scope
Create an authentication scope to assign to the application registry.




Creating an Application Registry
Finally, create an application registry for OAuth access token issuance.


Since it is for OAuth, select "Create an OAuth API endpoint for external clients."


This completes the settings on the ServiceNow side.
Preparation on the Azure DevOps Side
Azure Repos
In this instance, we will create an SBOM for the Python application created in a separate article [5].
Since we are reusing the Azure Repos from that time, details are omitted.
Azure Pipelines
Next, we will build a pipeline to create the SBOM and push it to ServiceNow.
First, configure the secrets.
In this case, for the API execution user:
The yaml is explained in the comments.
variables:
pythonVersion: '3.11'
# Set the application name to be displayed in ServiceNow
projectname: python
# URL of the ServiceNow instance
INSTANCE_URL: 'https://xxxxxxxxx.service-now.com'
# API endpoint for SBOM upload
UPLOAD_ENDPOINT: '/api/sbom/core/upload'
# Username created for API execution
USER_NAME: 'sbom_uploader'
# Client ID of the application registry
CLIENT_ID: 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'
resources:
repositories:
- repository: "functions"
name: "functions"
ref: "main"
type: git
stages:
- stage: Build
displayName: 'Build stage'
jobs:
- job: Build
displayName: 'Build Python Functions'
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: functions
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
addToPath: true
displayName: 'Use Python $(pythonVersion)'
- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
workingDirectory: '$(Build.SourcesDirectory)'
displayName: 'Install dependencies'
# Install Trivy
- script: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.47.0
displayName: 'Install Trivy'
# Generate SBOM
- script: |
trivy fs --format cyclonedx --output $(Build.ArtifactStagingDirectory)/functions_sbom.json $(Build.SourcesDirectory)
jq '.metadata.component.name = "$(projectName)"' $(Build.ArtifactStagingDirectory)/functions_sbom.json > $(Build.ArtifactStagingDirectory)/temp.json
mv $(Build.ArtifactStagingDirectory)/temp.json $(Build.ArtifactStagingDirectory)/functions_sbom.json
displayName: 'Generate SBOM with Trivy'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'SBOM'
publishLocation: 'Container'
displayName: 'Publish SBOM'
# Get ServiceNow access token
- script: |
TOKEN_RESPONSE=$(curl -s -X POST \
"$(INSTANCE_URL)/oauth_token.do" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=password" \
--data-urlencode 'username=$(USER_NAME)' \
--data-urlencode 'password=$(PASSWORD)' \
--data-urlencode 'client_id=$(CLIENT_ID)' \
--data-urlencode 'client_secret=$(CLIENT_SECRET)')
ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
echo "##vso[task.setvariable variable=ACCESS_TOKEN]$ACCESS_TOKEN"
displayName: 'Get Access Token'
# Upload SBOM
# https://www.servicenow.com/docs/ja-JP/bundle/xanadu-security-management/page/product/secops-integration-vr/sbom/concept/vr-sbom-preparing-upload.html
- script: |
response_body=$(mktemp)
status_code=$(
curl -v -X POST \
"$(INSTANCE_URL)$(UPLOAD_ENDPOINT)?requestedBy=devops&buildId=$(Build.BuildId)&lifecycleStage=pre_production" \
-H "Authorization: Bearer $(ACCESS_TOKEN)" \
-H 'Content-Type: application/json' \
--data-binary "@$(Build.ArtifactStagingDirectory)/functions_sbom.json" \
-w '%{http_code}' \
-s \
-o "$response_body"
)
# Verify response
if [ "$status_code" -eq 200 ]; then
echo "SBOM file upload successful."
else
error_message=$(cat "$response_body" | jq -r '.result.message // "Unknown error"')
echo "Failed. Status Code: $status_code"
echo "Error Message: $error_message"
rm "$response_body"
exit 1
fi
displayName: 'Upload SBOM'
Summary
I have explained the overview of SBOM and the process up to its visualization using Azure DevOps and ServiceNow.

Discussion