Salt Command-Line Reference
Salt Authentication
Before using salt make sure you have a valid Xygeni account as well as a Xygeni token. Please see Generate Xygeni Token for further info.
Once you have a valid Xygeni Token, provide the token as an env variable named XYGENI_TOKEN
. Salt will read and use it to authenticate against the Xygeni platform.
Salt Command-Line Reference
Salt provides a command-line interface (Salt CLI) with commands for creating the attestation document from the inputs, interacting with the attestations registry, and verifying an attestation with respect to the referenced software product.
salt CMD
, with CMD = attestation | keygen | registry | contract | verify
.
The main commands are:
salt keygen
: Generate key pairs for signingsalt attestation init|add|run|status|commit|reset
: Incremental attestation buildsalt attestation provenance
: Provenance for pipeline, in a single shotsalt registry search | get | put
: Operations with Attestation Registrysalt verify
: Verify contract / attestation for SW artifactsalt contract create | from-build | upload | download
: Contract handling
Software attestations are typically created in the same pipeline that builds and/or deploys the software. One or more steps can run Salt CLI commands to either build the attestation either in one shot (salt attestation provenance
) or incrementally at different steps along the pipeline (salt attestation init|add|run|commit
).
The attestation is always a JSON file following a standard format, that could be distributed along with the software products, or registered in a specific Attestation Registry.
The -h | --help could be used with any command / subcommand:
$ salt -h
oooo .
`888 .o8
.oooo.o .oooo. 888 .o888oo
d88( "8 `P )88b 888 888
`"Y88b. .oP"888 888 888
o. )88b d8( 888 888 888 .
8""888P' `Y888""8o o888o "888"
Software Attestations Layer for Trust, by Xygeni Security.
Usage:
salt [-hqvV] [--config=<config>] [@<filename>...] [COMMAND]
Parameters:
[@<filename>...] One or more argument files containing options.
-v, --verbose Verbose output?
-q, --quiet Quiet mode: do not generate output at console
--config=<config> config file (default $HOME/.salt/salt.yaml or
$SALT_HOME/conf/salt.yaml)
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
Commands:
attestation, at
Create software attestation: incrementally using init / add / run
/ commit|reset, or SLSA build provenance in a single shot.
keygen, kg Generate and save signing keys to disk. These keys may be used
later in attestation commands.
registry, reg Operations on Attestations Registry (store, retrieve, search)
verify, v, check download and verify an attestation for an artifact
generate-completion Generate bash/zsh completion script for salt.
Key Generation
Keys need to be generated before generating attestations (unless you use the keyless mode with --keyless
). You may use your own tooling like openssl
$ salt --no-banner keygen -h
Usage:
salt keygen [-hV] [-b=<bits>] [--config=<config>] [-d=<path>] [-f=NAME] [-t=<type>]
[@<filename>...]
Generate and save signing keys to disk.
These keys may be used later in attestation commands.
Parameters:
[@<filename>...] One or more argument files containing options.
-f, --file-prefix=NAME Name for generated .key / .pub files (default: salt).
-t, --type=<type> key type, one of rsa, ed25519, ecdsa (default: rsa).
-b, --bits=<bits> key size, in bits.
RSA defaults to 3072. Use values between 2048 and 4096.
ECDSA curve will be P-192 up to P-521 depending on bits
(defaults to 384).
Not applicable to Ed25519.
-d, --basedir=<path> directory for key files.
Default is the current working dir.
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
--config=<config> config file (default $HOME/.salt/salt.yaml or
$SALT_HOME/conf/salt.yaml)
Examples:
# generate key-pair and write to salt.key and salt.pub files
salt keygen
# generate key-pair and write to my-signer.key and my-signer.pub files
salt keygen --file-prefix my-signer
NOTE:
The command interactively prompts for a password.
You may use SALT_PRIVATE_KEY_PASSWORD environment variable to provide one.
Example: To generate an Ed25519 keypair and store in my_key.pub (public key) and my_key.key (private key), use the following:
$ salt -nb kg -t ed25519 -f my_key
# with long options:
# salt --no-banner keygen --type ed25519 --file my_key
Enter password for private key:
Repeat password:
2023-11-29 05:15:15 INFO Salt - Generating ed25519 key-pair...
2023-11-29 05:15:15 INFO Salt - Private key stored in my_key.key
2023-11-29 05:15:15 INFO Salt - Public key stored in my_key.pub
The command generates the keypair of the requested type and stores its parts in two files. Please note that, unless the password should be written from the console unless it is passed in the SALT_PRIVATE_KEY_PASSWORD
env var.
For generating on-the-fly, single-use keys, and if you have an OIDC provider available, it could be more convenient to use keyless signing.
Create attestations
Creating and verifying software attestations is the core of the SALT framework. Attestations in SALT follow the in-toto Attestations Framework. See Attestation Format for more details.
The command salt attestation
is used for creating software attestations:
$ salt attestation --help
Usage: salt attestation [-hV] [--never-fail] [--config=<config>] -p=<pipeline>
[@<filename>...] CMD
Create software attestation: incrementally using init / add / run / commit|reset, or SLSA
build provenance in a single shot.
[@<filename>...] One or more argument files containing options.
-p, --pipeline=<pipeline>
name of the pipeline/workflow being run.
--never-fail Always return 0, even with errors, to keep the pipeline
running. Default: false
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
--config=<config> config file (default $HOME/.salt/salt.yaml or
$SALT_HOME/conf/salt.yaml)
Commands:
init start attestation drafting process
run run a command and add attestation for the command execution
add add element (material, subject, product or statement) to draft
attestation
status show the current draft attestation
commit complete and store the attestation in draft
reset reset attestation in draft
provenance, slsa generate and sign SLSA provenance
There are two modes: incremental (init …​ commit) and one-shot (provenance).
Notes:
(1) The working directory used for resolving file / directory paths is the -d | --basedir
option, or the current working directory when not given.
(2) Key material is typically encoded in PEM format, and can be passed as an environment variable, local file path, or the PEM value itself. You may also use prefix-based syntax like env:YOUR_VARNAME_HERE
or file:YOUR_PATH_HERE
. File paths are resolved against the current working directory.
Please note that using env:VAR_NAME
could be more convenient than passing $VAR_NAME
substitution to the command option directly, as the value will not be shown in logfiles.
Generate Provenance
For generating attestation during the build of software in a single shot, you may use the attestation provenance
command (alias: attestation slsa
). SLSA Provenance is a common attestation format.
Usage:
salt attestation provenance [-hV] [--config=<config>] [-d=<basedir>] -p=<pipeline>
([-n=<name>] (-v=<value> | -f=<file> | -i=<image> |
--digest=<digest>))... [[-k=<key>] [-pk=<publicKey>]
[-cert=<certificate>] [-kpass=<keyPassword>]
[--pki-format=pkiFormat] [--keyless]] [[-o=<output>]
[--output-unsigned=<outputStatement>] [--pretty-print]
[--project=<project>] [--[no-]upload] [--[no-]result-upload]]
[@<filename>...]
generate and sign SLSA provenance
Parameters:
[@<filename>...] One or more argument files containing options.
-d, --basedir=<basedir> base directory where source files are located
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
-p, --pipeline=<pipeline> name of the pipeline/workflow being run.
--config=<config> config file (default $HOME/.salt/salt.yaml or
$SALT_HOME/conf/salt.yaml)
Subject content, choose one:
-v, --value=<value> value (string) to add to attestation
-f, --file=<file> file to add to attestation
-i, --image=<image> published container image, [REG/]NAME[:TAG]
Example: index.docker.io/my_org/my_image:latest or
my_org/my_image
--digest=<digest> digest, prefixed by the digest function
Example: sha256:d82938...8e62
Signer configuration:
-k, --key=<key> reference (path, env-var name) to the private key for
signing the attestation.
Alternatively uses SALT_PRIVATE_KEY env-var when provided.
-pk, --public-key=<publicKey>
reference (path, env-var name or value) to the public key
for signing the attestation.
Alternatively uses SALT_PUBLIC_KEY env-var when provided.
-cert, --certificate=<certificate>
optional reference (path, env-var name or value) to the
signer's certificate.
Alternatively uses SALT_CERTIFICATE env-var when provided.
-kpass, --key-password=<keyPassword>
reference (path or env-var name) to the private key password
Alternatively uses SALT_PRIVATE_KEY_PASSWORD env-var when
provided.
If '-', the password will be prompted (DO NOT USE in CI/CD)
--pki-format=pkiFormat format for signature and private key: One of pgp, x509,
minisign, ssh, pkcs7, tuf (default null)
--keyless Sign using an ephemeral keypair and a short-lived
certificate with OIDC identity.
Uses OIDC identity token to obtain a 10' public-key
certificate from Fulcio CA.
Attestation options:
-o, --output=<output> file for the signed attestation. Use '-' for stdout.
--output-unsigned=<outputStatement>
file for the unsigned attestation. Use '-' for stdout.
--pretty-print pretty-print the attestation. Default: false.
--project=<project> The software name (project), default: git repository.
--[no-]upload Do not upload the attestation, useful for testing or using
your own storage.
--[no-]result-upload Do not upload the result of the attestation forging to
Xygeni.
Subjects to add:
-n, --name=<name> name for the subject (if under contract, use the contract's
field name)
Example: Generate SLSA provenance for a container image.
With REPO_DIR = path to the software repository, and OUT_DIR = directory where the output files will be written.
$ salt -nb attestation provenance --basedir $REPO_DIR --pipeline my_pipeline \
--name sources --file src \
--name my_tool_cli --file build/my_cli \
--image myorg/myimage:latest \
--keyless --certificate=$OUT_DIR/ephemeral_cert.crt \
-o $OUT_DIR/provenance.signed.json --output-unsigned=$OUT_DIR/provenance.json \
--pretty-print
Generating ephemeral ecdsa keypair of 256 bits
Authenticating using OIDC provider https://oauth2.sigstore.dev/auth
Opening in an existing browser session.
Retrieving ephemeral certificate chain from fulcio
Ephemeral fulcio certificate:
-----BEGIN CERTIFICATE-----
MIIC0TCCAligAwIBAgIUJcAbnJyHfrPM7CHQvXZjuEOoyKwwCgYIKoZIzj0EAwMw
...
2nhi3BU=
-----END CERTIFICATE-----
IntotoEnvelope written to provenance.signed.json
Statement https://slsa.dev/provenance/v1 written to provenance.json
Ephemeral certificate saved in file ephemeral_cert.crt
Chain (length 2) for ephemeral certificate saved in file ephemeral_cert.crt.chain
Created entry in the attestations registry with id: 8a...c5b0
Entry may be downloaded from: https://salt.xygeni.io/download/8a...c5b0
The above command will:
compute the gitoid:sha256 digest on the
$REPO_DIR/src
directory as a subject named 'sources', the sha256 digest on the$REPO_DIR/build/my_cli
executable (one product of the build), and the docker sha256 digest on the container image (as a second product).use keyless signing to generate and certify on-the-fly keys,
produce a signed SLSA v1 Provenance in
$OUT_DIR/provenance.signed.json
and the unsigned in-toto Statement (easier to see the attestation contents) into$OUT_DIR/provenance.json
.upload the signed attestation to the configured attestations registry, and the result from the build and attestation drafting to Xygeni platform.
Generate Custom Attestation
As an alternative to the attestation provenance
command, you may incrementally generate a fully customized attestation using the attestation init | add | run | commit/reset
subcommands. If you need to create a customized attestation.
You may consider different attestation formats, for different use cases:
"Know your container" - Feed into automated policy engines, like Google Cloud’s Binary Authorization.
Add statements about the current security position of the software: Typically, the statement reads like "I hereby certify that, to the best of my knowledge, the software does not have any critical security flaw…​"
The idea is to integrate the usual software product security reports like static analysis' detected flaws, software composition and vulnerabilities in components, results from dynamic vulnerability scans. Formats like SCAI or the Vulnerabilities Predicate allow for this.
Attestation drafting
Attestation could be built incrementally, using multiple steps kept in a context, and a final step that signs the attestation and publishes it. This incremental process is called attestation drafting. The drafting process follows the commands in the developer’s possibly favorite tool, git
: init / add / commit. An attestation run
subcommand is added to capture the execution of a build command.
Example of attestation drafting: Assume that PIPELINE is the reference to the running pipeline where the commands are inserted, and that REPO_DIR points to the software repo directory.
# Initialize attestation
salt -nb attestation init -p $PIPELINE -d $REPO_DIR \
--attestor git --attestor environment
# Add material (src directory) and products
# (command-line executable tool built, and OCI image)
salt -nb attestation add -p $PIPELINE -d $REPO_DIR \
--type material --file src
--type product --file path/to/cli_tool \
--type product --image myorg/my_image:my_tag
# Add an attestation predicate,
# for example issues from your favorite Xygeni scan
# in the in-toto Vulnerabilities predicate format:
salt -nb attestatation add -p $PIPELINE -d $REPO_DIR \
-n xygeni-scan -t predicate -f path/to/xygeni_scan.json \
--predicate-type https://in-toto.io/attestation/vulns
# Capture a build step to be included in the attestation
# In the example the current Go package is built and installed:
salt -nb attestation run -p $PIPELINE -d $REPO_DIR \
--step compile -- \
go install
# ... more attestation add commands may follow ...
salt -nb attestation commit -p $PIPELINE -d $REPO_DIR \
-k env:MY_KEY -kpass env:MY_KEY_PASS -pk env:MY_PUB \
-o attestation.json --output-unsigned
attestation init
creates the initial draft with initial information (like system environment and git data) extracted by one or more predefined 'attestors'. Available attestors are currentlygit
andenvironment
. Materials (inputs) may also be added as files or directories.attestation add
adds elements (material, subject, product or statement) to the current draft attestation. Typically, a digest (SHA-256) is computed on the element. Container images may be added.The image digest is the 'official' from the manifest, as extracted from
docker manifest inspect IMAGE -v
orgcrane digest IMAGE
attestation run
runs a command and adds an attestation predicate for the command execution. Cryptographic digests for input artifacts (materials) will be computed before running the command, and for output artifacts (by-products) at the end of the command. This could be used to link the inputs and outputs of the step with other steps in the pipeline. The predicate has a type URI ofxygeni.io/attestations/command-run/v1
, and includes the following information:
{
"name" : "pipeline@compile",
"cmd" : [ "go", "install" ],
"exitcode" : 0,
"startTime" : "2023-07-29T21:03:59.519225Z",
"endTime" : "2023-07-29T21:05:01.244904Z",
"stdout": "base64-encoded, truncated standard output",
"stderr": "base64-encoded, truncated standard error",
"materials": {
"source_code": {
"name": "source_code",
"uri": "./src",
"digest": { "gitoid:sha256": "938cd...34af" }
},
...
},
"products": { ... }
}
attestation commit
builds the final attestation as in-toto Statement, serializes it as JSON, signs it with the passed key material, creates an in-toto Envelope with the statement as payload, the signature and the reference for the signing key, and publishes it in the attestation registryThe final statement is composed using the added predicates, input artifacts ('materials'), run command predicates, init attestors, and output artifacts ('products'), and then signed using the key materials passed as options.
As multiple predicates are typically added, a special collection predicate (with type URI
xygeni.io/attestations/collection-predicates/v1
) is used to compound multiple predicates in the single predicate that goes as the predicate for the in-toto statement to be signed.
For full command syntax, use the --help | -h option on the attestation subcommand:
salt attestation init -h
salt attestation add -h
salt attestation run -h
salt attestation commit -h
Attestation Status
You may use the attestation status
subcommand in the drafting process to show the current context for the drafted attestation. Example:
$ salt -nb attestation status -p pipe01 --full
Pipeline 'pipe01' has potential attestations.
Has 1 materials and 1 products
Material #1: path/to/cli={
"name" : "path/to/cli",
"digest" : {
"gitoid:sha256" : "426271ff2486829a7b7774309c490fe7ebb51fd207b711a067de3f9397a18fbf"
}
}
Product #1: myorg/myimage:latest={
"name" : "myorg/myimage:latest",
"uri" : "myorg/myimage:latest",
"digest" : {
"sha256" : "0c8a2fb6a0b3c8db482e841ddb5be69ff48d418ca7e585065e49d14ac6df3a0f"
}
}
Has 3 pending attestations:
Attestation #1: predicate with type URI 'xygeni.io/attestations/git/v1'
{
"gitInfo" : {
"commitHash" : {
"sha1" : "a984aa1e224b0e399dceda0f17b782e10abb9499"
},
"author" : "John Doe",
"authorEmail" : "[email protected]",
"commitDate" : "2023-07-28T10:29:51+01:00",
"commitMessage" : "[Bug] Fix the thing",
"signature" : {
"status" : "good",
"signer" : "John Doe <[email protected]>",
"signerKey" : "758e48...95328",
"signerPrimaryKey" : "8690454...0152b"
},
"treeHash" : "2bc830...62de9",
"parentHashes" : [ "e236e...4cc092" ],
"refs" : [ "refs/heads/feature/myfeat" ]
},
"timestamp" : "2023-07-29T07:56:20.325872Z"
}
...
Attestation Reset
If the attestation drafting process should be aborted, due to an failure ini the build, the attestation reset command should be invoked for cleaning up the attestation context:
salt -nb attestation reset -p $PIPELINE \
--cause failure --reason "Image deployment failed"
Run salt attestation reset -h
for full command reference.
Verify Attestation
Attestation verification can be performed by the user of the software the attestation refers to. The verification process:
(1) Computes the digests of the subjects that are passed to the command, following the same syntax as with the attestation add | provenance
commands. Emits a verification failure if any digest does not match with the digests present in the attestation. This could help with detecting post-build tampering.
(2) Verifies the signature of the attestation payload (statement included in the attestation envelope) with the public key or certificate passed.
(3) If a certificate is available, verify the certificate and certificate chain. For ephemeral certificates used with --keyless, it checks that the certificate was valid at the moment when the attestation was signed, and checks that certificate issuance was registered in the transparency log at the given timestamp.
The attestation verify
performs this validation:
$ salt -nb verify \
--image=myorg/myimage:my_tag \
--attestation=attestation.json \
--public-key=ephemeral_cert.crt
Verifying in-toto envelope with type = https://in-toto.io/Statement/v1
Attestations passed OK
When there is a failure in validation, the result shows what failed:
$ salt -nb verify \
--image=myorg/myimage:my_tag \
--attestation=attestation.json \
--public-key=ephemeral_cert.crt
WARN Salt - Attestations do not pass: {
"subjects" : [ {
"name" : "xygeni/xygeni_scanner:latest",
"digest" : {
"sha256" : "0c8a2...f3a0f"
}
} ],
"errors" : [ {
"state" : "signature_failed",
"reason" : "Invalid signature for key e083...32a7f",
"publicKeyId" : "e083a...2a7f"
} ],
"contract" : "",
"pass" : false,
"unverifiedSubjects" : [ ]
}
Use salt verify -h
to display the full syntax of the command.
Registry Operations
Attestation generation and verification may connect with the Attestations Registry to fetch the attestation. The registry
command allows you to upload, search for, and download attestations.
Attestation entries in the registry have a digest (64 hexadecimal digits) for downloading.
Search typically uses the digest value of a subject in the attestation to list the attestations that refer to it (there could be multiple).
salt -nb registry search --digest $IMAGE_SHA
29 attestations found containing digest sha256:0c8a...df3a0f:
---
Attestation #1: 3a7062b...d6a3
Download URL: https://salt.xygeni.io/download/3a7062b...d6a3
Payload type: application/vnd.in-toto+json
Signature #1: MEUCI...+tE=
Public Key ID #1: d0a3e...b63
---
Attestation #2: 5f6b....3c89
...
Use salt reg -h
for the full syntax of the commands.
$ salt reg -h
Usage: salt registry [-hV] [--never-fail] [--config=<config>] [--format=<format>]
[@<filename>...] CMD
Operations on Attestations Registry (store, retrieve, search)
[@<filename>...] One or more argument files containing options.
--format=<format> Output format, one of json, text (default: text)
--never-fail Always return 0, even with errors, to keep the pipeline running.
Default: false
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
--config=<config> config file (default $HOME/.salt/salt.yaml or
$SALT_HOME/conf/salt.yaml)
Commands:
store, put, upload store an attestation in the registry
retrieve, get, download get an attestation from registry
search, find, query search for attestations in the registry
Last updated