Basic Usage

This section covers the basics of using the BOMnipotent Client. It is relevant for both consumers and producers of supply chain security documents.

Feb 24, 2025

Subsections of Basic Usage

Installing the Client

To manually download BOMnipotent Client, go to https://www.bomnipotent.de/downloads/ , select your platform and version, and click on the download button.

To automate this process further, you can access the download link directly:

Invoke-WebRequest -Uri https://www.bomnipotent.de/downloads/raw/latest/windows/bomnipotent_client.exe -OutFile bomnipotent_client.exe
curl -O https://www.bomnipotent.de/downloads/raw/latest/macos/bomnipotent_client
chmod +x bomnipotent_client
wget https://www.bomnipotent.de/downloads/raw/latest/debian-glibc/bomnipotent_client;
chmod +x bomnipotent_client
wget https://www.bomnipotent.de/downloads/raw/latest/linux-musl/bomnipotent_client;
chmod +x bomnipotent_client

Replace “latest” with a specific version tag, e.g. “v1.0.0”, to download that version instead of the latest.

To access BOMnipotent Client from anywhere in your system, move it into a folder that is included in your PATH environment variable. This step is optional, though.

Mar 16, 2025

Account Creation

Most interactions with BOMnipotent require some permission. The sole exception is accessing data classified as TLP:WHITE / TLP:CLEAR.

Permissions are linked to user accounts. For more information on how permissions are granted, see the section about Access Management .

Creating a new Account

To create a new user account, run

Input (long variant)
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request user@example.com
Input (short variant)
bomnipotent_client -d bomnipotent_server_of_your_choice user request user@example.com
Output
[INFO] Generating new key pair
[INFO] Storing secret key to "/root/.config/bomnipotent/secret_key.pem" and public key to "/root/.config/bomnipotent/public_key.pem"
[INFO] User request submitted. A verification email has been sent to your inbox. The verification link expires after 1h.

If you call this for the first time, it will create a new key pair using the ED25519 Algorithm . A key pair consists of a public and a secret key. Both are stored in your local userfolder.

The secret key is more commonly called “private key”, but the author believes that “secret” is a more apt description and reduces the chance to confuse it with the public key.

The public key can, in principle, be shared with anyone. The “user request” call sends it to the BOMnipotent server. The secret key however should be treated like a password!

Subsequent calls to BOMnipotent Client will reuse an existing key pair.

Most BOMnipotent Server instances will require you to confirm that you have access to the provided email address. They will send you a verification link, which expires after some time.

After your request is made and your email verified, you need to wait for a user manager of the server to approve your account. Once that happened you can start making authenticated requests .

If you are said user manager and are looking for how approve users, consult the section about User Management .

Requesting a Robot Account

Not all accounts are necessarily associated with human users. BOMnipotent is built with pipeline integration in mind. To create an account to be used in a automation, add the ‘–robot’ option to the request:

Input (long variant)
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request example_robot --robot
Input (short variant)
bomnipotent_client -d bomnipotent_server_of_your_choice user request example_robot -r
Output
[INFO] Generating new key pair
[INFO] Storing secret key to "/root/.config/bomnipotent/secret_key.pem" and public key to "/root/.config/bomnipotent/public_key.pem"
[INFO] Request for robot user submitted. It now needs to be confirmed by a user manager.

This request will mark the account as a robot, and not send a verification mail.

Using stored Keys

If you have a key pair stored in the default user location (which depends on your platform), BOMnipotent Client will automatically read and use it.

If you would instead like to reuse an existing key stored at a different location, you can add the path as a positional argument:

Input (long variant)
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request other_user@example.com /home/some_public_key.pem
Input (short variant)
bomnipotent_client -d bomnipotent_server_of_your_choice user request other_user@example.com /home/some_public_key.pem
Output
[INFO] User request submitted. A verification email has been sent to your inbox. The verification link expires after 1h.

For this to work the key needs to have been generated using the ED25519 Algorithm , and it needs to be stored in PEM format. If you insist on managing keys yourself, or would like to see an example, then the easiest way to generate such a pair is to call openssl genpkey -algorithm ED25519 -out secret_key.pem to generate a secret key, and then openssl pkey -in secret_key.pem -pubout -out public_key.pem to generate the corresponding public key.

If you accidently specify the path to your secret key, BOMnipotent Client will throw an error before sending it to the server.

Jun 16, 2025

Authenticating

Authentication requires that you have requested a user account , and that it has been approved by a user manager.

Once your account (meaning your email and public key) is approved, you can provide your email to Bomnipotent Client to make a request that can be authenticated by the server:

Input (long variant)
bomnipotent_client --domain=<server> --user=<your-email> <command>
Input (short variant)
bomnipotent_client -d <server> -u <your-email> <command>

BOMnipotent Client then automatically reads your secret key and uses it for authentication.

Your secret key is used to cryptographically sign the HTTP method, your email, a timestamp and the request body. This simultaneously protects your request against others impersonating you, malicious modifications and replay attacks. The secret key achieves all that without ever having to leave your local computer, the beauty of which is, sadly, beyond the scope of this documentation.

If you are not storing your keys in the default user location, you have to tell BOMnipotent Client the path to it via a command line option:

Input (long variant)
bomnipotent_client --domain=bomnipotent_server_of_your_choice --user=<your-email> --secret-key=<path/to/key> <command>
Input (short variant)
bomnipotent_client -d bomnipotent_server_of_your_choice -u <your-email> -s <path/to/key> <command>

To avoid providing three extra arguments to every single request, you can instead store this data in a User Session

Jun 16, 2025

User Session

Login

The BOMnipotent Client offers several global optional arguments. To avoid having to provide these time and time again, you can use the login command to store them in a user session. This will create a file in the local user folder which stores the provided parameters:

Input (long variant)
bomnipotent_client --domain=bomnipotent_server_of_your_choice --user=user@example.com --output-mode=normal --secret-key=/home/some_secret_key.pem session login
Input (short variant)
bomnipotent_client -d bomnipotent_server_of_your_choice -u user@example.com -o normal -s /home/some_secret_key.pem session login
Output
[INFO] Storing session data in /root/.config/bomnipotent/session.toml

Whenever you call the BOMnipotent Client from now on, it will use these parameters automatically.

Any relative filepaths you provide will be resolved to absolute paths before storing them. This way, the session data can be used from anywhere on your computer.

Overriding and Overwriting

If you are logged in and provide any of the global optional parameters to a BOMnipotent Client call, it will use these instead:

Input (long variant)
bomnipotent_client --domain=bomnipotent.wwh-soft.com health # Will contact the other server
Input (short variant)
bomnipotent_client -d bomnipotent.wwh-soft.com health # Will contact the other server
Output
[INFO] Service is healthy

To permanently change the data stored in the session, simply login again with the new parameters.

This can also be used to remove parameters, simply by not providing them:

Input (long variant)
bomnipotent_client --domain=some_other_bomnipotent_server --user=other_user@example.com session login # Will set secret-key and other non-specified options to none.
Input (short variant)
bomnipotent_client -d some_other_bomnipotent_server -u other_user@example.com session login # Will set secret-key and other non-specified options to none.
Output
[INFO] Storing session data in /root/.config/bomnipotent/session.toml

Status

To print the current parameters of your session, call “session status”. The output is in TOML format (which is also how it is stored on your filesystem):

Input
bomnipotent_client session status
Output
domain = "bomnipotent_server_of_your_choice"
user = "user@example.com"
output_mode = "Normal"
secret_key_path = "/home/some_secret_key.pem"

If you prefer JSON, merely append the “–json” option:

Input (long variant)
bomnipotent_client session status --json
Input (short variant)
bomnipotent_client session status -j
Output
{
  "domain": "bomnipotent_server_of_your_choice",
  "user": "user@example.com",
  "output_mode": "Normal",
  "secret_key_path": "/home/some_secret_key.pem"
}

If you are not logged in, you get an informational log and an empty TOML/JSON output:

Input
bomnipotent_client session status
Output
[INFO] No session data is currently stored
Input (long variant)
bomnipotent_client session status --json
Input (short variant)
bomnipotent_client session status -j
Output
[INFO] No session data is currently stored
{}

If you would like to use this command to programatically check if session data exists, you can for example use the “raw” output mode to avoid the info trace, and check if the return value is empty:

#!/bin/bash

output=$(bomnipotent_client --output-mode raw session status)
if [ -n "$output" ]; then
    echo "Found session data:"
    echo "$output"
else
    echo "Session not logged in."
fi
$output = bomnipotent_client --output-mode raw session status
if ($output) {
    Write-Output "Found session data:"
    Write-Output $output
} else {
    Write-Output "Session not logged in."
}

Logout

To remove all parameters, call logout:

Input
bomnipotent_client session logout

This will remove the session file.

Jun 21, 2025

Log Level

BOMnipotent Client offers several severity levels of logs:

  • error
  • warn
  • info (default)
  • debug
  • trace

They can be selected via:

Input (long variant)
bomnipotent_client --log-level=<LEVEL> <COMMAND>
Input (short variant)
bomnipotent_client -l <LEVEL> <COMMAND>

This defines the minimum severity level for a message to be logged: Choosing log level debug makes BOMnipotent print all messages of severity error, warn, info and debug, but not trace.

By default, BOMnipotent Client logs messages to stdout, regardless of severity level. You can instruct it to log to a file instead.

Info, Warn and Error

The default log-level is info. It prints some information, but does not overwhelm the user.

Input
bomnipotent_client health
Output
[INFO] Service is healthy
Input
bomnipotent_client bom list
Output
[INFO] 
╭────────────────────────┬─────────┬─────────────────────────┬───────────┬────────────╮
│ Product                │ Version │ Timestamp               │ TLP       │ Components │
├────────────────────────┼─────────┼─────────────────────────┼───────────┼────────────┤
│ Best Project           │ 3.1.4   │ 2025-01-01 10:11:12 UTC │ TLP:GREEN │ 75         │
│ Your Project           │ 1.0.0   │ 2025-01-01 10:11:12 UTC │ Default   │ 75         │
│ Your Project           │ 1.1.0   │ 2025-01-01 10:11:12 UTC │ Default   │ 75         │
│ Your Project Container │ 1.2.3   │ 2025-01-01 10:11:12 UTC │ TLP:WHITE │ 939        │
╰────────────────────────┴─────────┴─────────────────────────┴───────────┴────────────╯

Debug

The debug output mode prints some additional information which may be of interest when looking for the cause of an error in the input or setup:

Input (long variant)
bomnipotent_client --log-level=debug health
Input (short variant)
bomnipotent_client -l debug health
Output
[DEBUG] Looking for secret key
[DEBUG] The provided key is a path: /home/admin_secret_key.pem
[DEBUG] Reading secret key from provided path "/home/admin_secret_key.pem"
[DEBUG] Signing request.
[DEBUG] Assembled GET request to https://bomnipotent_server_of_your_choice/health.
[DEBUG] Call<Prepare>
[DEBUG] GET https://bomnipotent_server_of_your_choice/******
[DEBUG] Resolved: ArrayVec { len: 1, arr: [172.20.0.3:443] }
[DEBUG] Connected TcpStream to 172.20.0.3:443
[DEBUG] No cached session for DnsName("bomnipotent_server_of_your_choice")
[DEBUG] Not resuming any session
[DEBUG] Wrapped TLS
[DEBUG] Call<SendRequest>
[DEBUG] Request { method: GET, uri: https://bomnipotent_server_of_your_choice/******, version: HTTP/1.1, headers: {"accept": "*/*", "host": "bomnipotent_server_of_your_choice", "user-agent": "bomnipotent_client", "<NOTICE>": "5 HEADERS ARE REDACTED"} }
[DEBUG] Using ciphersuite TLS13_AES_256_GCM_SHA384
[DEBUG] Not resuming
[DEBUG] TLS1.3 encrypted extensions: [ServerNameAck]
[DEBUG] ALPN protocol is None
[DEBUG] add_parsable_certificates processed 143 valid and 0 invalid certs
[DEBUG] Loaded 143 CA certificates from the system
[DEBUG] Call<RecvResponse>
[DEBUG] Call<RecvBody>
[DEBUG] Response { status: 200, version: HTTP/1.1, headers: {"content-type": "text/plain; charset=utf-8", "content-length": "18", "date": "Wed, 01 Jan 2025 10:11:12 GMT", "<NOTICE>": "2 HEADERS ARE REDACTED"} }
[DEBUG] Call<Cleanup>
[DEBUG] Pool gone: PoolKey { scheme: "https", authority: bomnipotent_server_of_your_choice, proxy: None }
[INFO] Service is healthy

Trace

In output mode trace, BOMnipotent additionally prints the module where the log message originated. This is mainly interesting for finding the cause of an error in the program itself.

Input (long variant)
bomnipotent_client --log-level=trace health | grep "TRACE" | head -n 10
Input (short variant)
bomnipotent_client -l trace health | grep "TRACE" | head -n 10
Output
[bomnipotent_client] [TRACE] Running command Health with args Arguments {
[wwh_core_utils::http::request] [TRACE] Using platform's default root certificates.
[ureq::unversioned::resolver] [TRACE] Resolve: bomnipotent_server_of_your_choice:443
[ureq::unversioned::transport::tcp] [TRACE] Try connect TcpStream to 172.20.0.3:443
[ureq::tls::rustls] [TRACE] Try wrap in TLS
[rustls::client::hs] [TRACE] Sending ClientHello Message {
[ureq_proto::util] [TRACE] 4745 5420 2f68 6561 6c74 6820 4854 5450  GET./health.HTTP
[ureq_proto::util] [TRACE] 2f31 2e31 0d0a 6163 6365 7074 3a20 2a2f  /1.1..accept:.*/
[ureq_proto::util] [TRACE] 2a0d 0a68 6f73 743a 2062 6f6d 6e69 706f  *..host:.bomnipo
[ureq_proto::util] [TRACE] 7465 6e74 5f73 6572 7665 725f 6f66 5f79  tent_server_of_y
Jun 16, 2025

Log File

To store the log output of a call to BOMnipotent Client in a file instead of printing it to stdout, call

Input (long variant)
bomnipotent_client --log-file=/tmp/bomnipotent.log bom list
Input (short variant)
bomnipotent_client -f /tmp/bomnipotent.log bom list

The output is the same, except that the stdout output is coloured according to its severity level, while the file output is not.

If BOMnipotent Client is called repeatedly with the same log-file, it will overwrite the existing contents, if the existing file looks like a log-file.

A file looks like a log-file to BOMnipotent if it is either empty or contains at least one of the strings “[ERROR]”, “[WARN]”, “[INFO]”, “[DEBUG]” or “[TRACE]”.

If an existing file does not look like a log-file, BOMnipotent gets cautious and aborts:

Input (long variant)
bomnipotent_client --log-file=/home/george_r_r_martin_not_a.log bom list
Input (short variant)
bomnipotent_client -f /home/george_r_r_martin_not_a.log bom list
Output
Log-file "/home/george_r_r_martin_not_a.log" already exists and does not look like a log-file. Aborting before overwriting any data you do not want overwritten.

Because the commands “bom get” / “csaf get” as well as the “fetch” command are meant for machine-processing, they print their output to stdout even if a log-file is configured. This separation of outputs makes it possible to simultaneously process the data and store potential error messages.

Jun 16, 2025

Output Mode

Withouth any specifications of the output-mode, BOMnipotent Client prints its log messages either to stdout, or to a configured log-file . This is great if it used by humans, but not so useful for automation. This is why BOMnipotent Client offers the two additional output-modes “code” and “raw” . They modify which output is printed where.

Output Streams

In output-modes “code” or “raw”, only the HTTP code or the response body are printed to stdout. If you configure a log-file , any logs up to the specified log-level will be stored there.

If on the other hand you do not specify a log-file, BOMnipotent still wants you to know if something goes wrong. This is why, in this case, logs of severity “error” or “warn” are printed to stderr.

Modes

Code

The code output prints only the HTTP status code of the response to stdout.

Input (long variant)
bomnipotent_client --output-mode=code health
Input (short variant)
bomnipotent_client -o code health
Output
200

This can come in handy if you want to use BOMnipotent Client in a script:

#!/bin/bash
set -e # Return on error
# ...other code...
bomnipotent_client \
    --output-mode=code \
    --domain=$domain \
    --log-level=debug \
    --log-file="/tmp/loggy.log" \
    session login
code=$(bomnipotent_client health)
if (( code != 200 )); then
    echo "Server at $domain is not healthy!"
    cat /tmp/loggy.log
    exit 1;
fi

Note that there is no newline or carriage return character at the end of the output.

Attention: In code mode, BOMnipotent Client always exits with a terminal exit code of 0 (signaling success) if it can obtain any HTTP code. This way, the program is easier to use inside scripts that return on errors.

Raw

For calls to BOMnipotent Client that access some structured data, the raw output prints the response body, which is typically data in JSON format.

Input (long variant)
bomnipotent_client --output-mode=raw bom list
Input (short variant)
bomnipotent_client -o raw bom list
Output
[{"product":"Best Project","version":"3.1.4","timestamp":"2025-01-01T10:11:12Z","tlp":"TLP:GREEN","components":75},{"product":"Your Project","version":"1.0.0","timestamp":"2025-01-01T10:11:12Z","tlp":null,"components":75},{"product":"Your Project","version":"1.1.0","timestamp":"2025-01-01T10:11:12Z","tlp":null,"components":75},{"product":"Your Project Container","version":"1.2.3","timestamp":"2025-01-01T10:11:12Z","tlp":"TLP:WHITE","components":939}]

The output can then easily be parsed and processed by your program logic.

Note that there is no newline or carriage return character at the end of the output.