Software Bill of Materials

The Software Bill of Materials (SBOM) is a west extension command that can be invoked by west ncs-sbom. It provides a list of used licenses for an application build or specific files.

Note

Generating a list of licenses from an application build is experimental. The accuracy of detection is constantly verified. Both implementation and usage may change in the future.

Overview

The process of using the ncs-sbom command involves the following steps:

  1. Create a list of input files based on provided command-line arguments, for example, all source files used for building a specific application. For details, see Specifying input.

  2. Detect the license applied to each file, for example, read SPDX identifier from SPDX-License-Identifier tag. For details, see Detectors.

  3. Create an output report containing all the files and license information related to them, for example, write a report file in HTML format. For details, see Specifying output.

Requirements

The ncs-sbom command requires installation of additional Python packages.

Use the following command to install the requirements.

Enter the following command in a command-line window in the ncs folder:

pip3 install -r nrf/scripts/requirements-west-ncs-sbom.txt

Note

The ncs-sbom command uses the Scancode-Toolkit that requires installation of additional dependencies on a Linux system. To install the required tools on Ubuntu, run:

sudo apt install python-dev bzip2 xz-utils zlib1g libxml2-dev libxslt1-dev libpopt0

For more details, see Scancode-Toolkit Installation.

Using the command

The following examples demonstrate the basic usage of the ncs-sbom command.

  • To see the help, run the following command:

    west ncs-sbom -h
    
  • To get an analysis of the built application and generate a report to the sbom_report.html file in the build directory, run:

     west ncs-sbom -d build-directory
  • To analyze the selected files and generate a report to an HTML file, run:

    west ncs-sbom --input-files file1 file2 --output-html file-name.html

Specifying input

You can specify all input options several times to provide more input for the report generation, for example, generate a report for two applications. You can also mix them, for example, to generate a report for the application and some directory.

  • To get an application SBOM from a build directory, use the following option:

    -d build_directory
    

    You have to first build the build_directory with the west build command using Ninja as the underlying build tool (default). The build must be successful. Any change in the application configuration may affect the results, so always rebuild it after reconfiguration and before calling the west ncs-sbom.

    You can skip this option if you are in the application directory and you have a default build directory there - the same way as in west build command.

    The Extracting a list of files from a build directory section describes in detail how to extract a list of files from a build directory.

    Note

    All files that are not dependencies of the zephyr/zephyr.elf target are not taken as an input. If you modify the .elf file after the linking, the modifications are not applied.

    The -d option is experimental.

  • Provide a list of input files directly on the command line:

    --input-files file1 file2 ...

    Each argument of this option can contain globs as defined by Python’s Path.glob with two additions:

    • Support for absolute paths.

    • Exclamation mark ! to exclude files.

    For example, if you want to include all .c files from the current directory and all subdirectories recursively:

    --input-files '**/*.c'
    

    Make sure to have correct quotes around globs, to not have the glob resolved by your shell, and go untouched to the command.

    You can prefix a pattern with the exclamation mark ! to exclude some files. Patterns are evaluated from left to right, so ! excludes files from patterns before it, but not after. For example, if you want to include all .c files from the current directory and all subdirectories recursively except all main.c files, run:

    --input-files '**/*.c' '!**/main.c'
    
  • Read a list of input files from a file:

    --input-list-file list_file

    It does the same as --input-files, but it reads files and patterns from a file (one file or pattern per line). Files and patterns contained in the list file are relative to the list file location (not the current directory). Comments starting with a # character are allowed.

Specifying output

You can specify the format of the report output using the output argument.

  • To generate a report in HTML format:

    --output-html file-name.html

    The HTML report overview section provides more details about the report.

    If you use the -d option, you do not need to specify any output argument. The sbom_report.html file is generated in your build directory (the first one if you specify more than one build directory).

  • To generate a cache database:

    --output-cache-database cache-database.json

    For details, see cache-database detector.

Detectors

The ncs-sbom command includes the following detectors:

  • spdx-tag - search for the SPDX-License-Identifier in the source code or the binary file.

    For guidelines, see SPDX identifier. Enabled by default.

  • full-text - compare the contents of the source file with a small database of reference texts.

    The database is part of the ncs-sbom command. Enabled by default.

  • scancode-toolkit - license detection by the Scancode-Toolkit. Enabled and optional by default.

    If the scancode command is not on your PATH, you can use the --scancode option to provide it, for example:

    --scancode ~/scancode-toolkit/scancode
    

    This detector is optional because it is significantly slower than the others.

  • external-file - search for license information in an external file. Enabled by default.

    The external file has the following properties:

    • It is located in the same directory as the file under detection or in one of its parent directories .

    • Its name contains LICENSE, LICENCE or COPYING (case insensitive).

    • It has an SPDX-License-Identifier tag.

    • It has one or several NCS-SBOM-Apply-To-File tags containing file paths or globs (as defined by the Python’s Path.glob). They are relative to the external file.

    If any of the NCS-SBOM-Apply-To-File tags matches the file under detection, the license from the SPDX tag is used, for example:

    /* The following lines will apply Nordic 5-Clause license to all ".a" files
     * and ".lib" files in the "lib" directory and all its subdirectories.
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     * NCS-SBOM-Apply-To-File: lib/**/*.a
     * NCS-SBOM-Apply-To-File: lib/**/*.lib
     */
    
  • cache-database - use license information detected and cached earlier in the cache database file. Disabled by default.

    Provide the cache database file using the following argument:

    --input-cache-database cache-database.json

    Each database entry has a path relative to the west workspace directory, a hash, and a list of detected licenses. If the file under detection has the same path and hash, the list of licenses from the database is used.

    Note

    To generate the database based on, for example the scancode-toolkit detector, run the following command:

    west ncs-sbom --input-files files ... --license-detectors scancode-toolkit --output-cache-database cache-database.json

If you prefer a non-default set of detectors, you can provide a list of comma-separated detectors with the --license-detectors option, for example:

--license-detectors spdx-tag,scancode-toolkit

Some of the detectors are optional, which means that they are not executed for a file that already has licenses detected by some other previously executed detector. Detectors are executed from left to right using a list provided by the --license-detectors.

--optional-license-detectors scancode-toolkit

Some detectors may run in parallel on all available CPU cores, which speeds up the detection time. Use the -n option to limit the number of parallel threads or processes.

HTML report overview

The HTML report has following structure:

  • Summary of the report, containing the following:

    • Notes at the beginning.

      General information on the report.

    • List of inputs.

      The file sources.

    • List of licenses.

      All licenses detected in the input files.

    • List of added license texts.

      If a license is not in the SPDX License List and it is in the internal database, the license text is added to the report.

    You can click links in the summary to get more details about specific items.

  • List of files without any license information or with license information that cannot be detected automatically.

    You have to investigate them manually to get the license information.

  • Details about each detected license:

    • License identifier.

    • Information if it is a standard SPDX license.

    • License name if available.

    • Link to license text or more details if available.

    • All files from the input covered by this license.

  • License texts added to this report.

Extracting a list of files from a build directory

The ncs-sbom extracts a list of files from a build directory. It queries ninja for the targets and dependencies.

The entry point is the zephyr/zephyr.elf target file. The script asks ninja for all input targets of the zephyr/zephyr.elf target. It also asks for all input targets of the previously extracted input targets, until it reaches all leaves in the dependency tree. The result is a list of all the leaves.

To change the target or specify multiple targets, you can add them after the build directory in the -d option, for example:

-d build_directory target1.elf target2.elf

There are two additional methods for improving the correctness of the above algorithm:

  • Each library is examined using the GNU ar tool.

    If the list of files returned by the GNU ar tool is covered by the list returned from the ninja, the list is assumed to be valid. Otherwise, the library is assumed to be a leaf, so it is shown in the report and its inputs are not analyzed further.

  • The ncs-sbom parses the .map file created during the zephyr/zephyr.elf linking.

    It provides a list of all object files and libraries linked to the zephyr/zephyr.elf file. The script ends with a fatal error if any file in the .map file is not visible by ninja.

    Exceptions are the runtime and standard libraries. You can specify the list of exceptions with the --allowed-in-map-file-only option. By default, it contains a few common names for the runtime and standard libraries.

    If the .map file and the associated .elf file have different names, you can provide the .map file after the : sign following the target, for example:

    -d build_directory target.elf:file.map