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.
This section covers the basics of using the BOMnipotent Client. It is relevant for both consumers and producers of supply chain security documents.
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.
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 .
To create a new user account, run
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request user@example.com
bomnipotent_client -d bomnipotent_server_of_your_choice user request user@example.com
[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 .
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:
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request example_robot --robot
bomnipotent_client -d bomnipotent_server_of_your_choice user request example_robot -r
[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.
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:
bomnipotent_client --domain=bomnipotent_server_of_your_choice user request other_user@example.com /home/some_public_key.pem
bomnipotent_client -d bomnipotent_server_of_your_choice user request other_user@example.com /home/some_public_key.pem
[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 thenopenssl 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.
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:
bomnipotent_client --domain=<server> --user=<your-email> <command>
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:
bomnipotent_client --domain=bomnipotent_server_of_your_choice --user=<your-email> --secret-key=<path/to/key> <command>
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
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:
bomnipotent_client --domain=bomnipotent_server_of_your_choice --user=user@example.com --output-mode=normal --secret-key=/home/some_secret_key.pem session login
bomnipotent_client -d bomnipotent_server_of_your_choice -u user@example.com -o normal -s /home/some_secret_key.pem session login
[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.
If you are logged in and provide any of the global optional parameters to a BOMnipotent Client call, it will use these instead:
bomnipotent_client --domain=bomnipotent.wwh-soft.com health # Will contact the other server
bomnipotent_client -d bomnipotent.wwh-soft.com health # Will contact the other server
[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:
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.
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.
[INFO] Storing session data in /root/.config/bomnipotent/session.toml
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):
bomnipotent_client session status
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:
bomnipotent_client session status --json
bomnipotent_client session status -j
{
"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:
bomnipotent_client session status
[INFO] No session data is currently stored
bomnipotent_client session status --json
bomnipotent_client session status -j
[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."
}
To remove all parameters, call logout:
bomnipotent_client session logout
This will remove the session file.
BOMnipotent Client offers several severity levels of logs:
They can be selected via:
bomnipotent_client --log-level=<LEVEL> <COMMAND>
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.
The default log-level is info. It prints some information, but does not overwhelm the user.
bomnipotent_client health
[INFO] Service is healthy
bomnipotent_client bom list
[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 │
╰────────────────────────┴─────────┴─────────────────────────┴───────────┴────────────╯
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:
bomnipotent_client --log-level=debug health
bomnipotent_client -l debug health
[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
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.
bomnipotent_client --log-level=trace health | grep "TRACE" | head -n 10
bomnipotent_client -l trace health | grep "TRACE" | head -n 10
[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
To store the log output of a call to BOMnipotent Client in a file instead of printing it to stdout, call
bomnipotent_client --log-file=/tmp/bomnipotent.log bom list
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:
bomnipotent_client --log-file=/home/george_r_r_martin_not_a.log bom list
bomnipotent_client -f /home/george_r_r_martin_not_a.log bom list
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.
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.
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.
The code output prints only the HTTP status code of the response to stdout.
bomnipotent_client --output-mode=code health
bomnipotent_client -o code health
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.
For calls to BOMnipotent Client that access some structured data, the raw output prints the response body, which is typically data in JSON format.
bomnipotent_client --output-mode=raw bom list
bomnipotent_client -o raw bom list
[{"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.