Index · Directives systemd 263~devel

Name

systemd-manifest — Generate and verify file manifests of directory trees

Synopsis

systemd-manifest [OPTIONS...] make [DIRECTORY [MANIFEST]]

systemd-manifest [OPTIONS...] verify [DIRECTORY [MANIFEST]]

Description

systemd-manifest generates file manifests of directory trees, and verifies directory trees against such manifests. Four manifest formats are supported:

list

A plain list of file names, one per line. Directories are suffixed with a slash.

Added in version 263.

sha256sums

The format generated by sha256sum(1), i.e. a hash and a file name per line. Only regular files are listed. This is the format systemd-sysupdate(8) consumes as SHA256SUMS file.

Added in version 263.

mtree

The BSD mtree format, listing inode type, access mode, ownership, size, hash, symlink target and device numbers of each file. This format is supported for generation only.

Added in version 263.

uapi16

A UAPI.16 file manifest, i.e. a JSON-SEQ stream with one object per file. This is the format systemd-sysupdate(8) consumes as Uapi16Manifest file, and the same format systemd-dissect(1) generates with --uapi16. This is the default.

Added in version 263.

Manifests are generated and verified in a streaming fashion, i.e. one file at a time, and never loaded into memory as a whole, so that very large trees can be processed.

Commands

make [DIRECTORY [MANIFEST]]

Generates a manifest of the specified directory tree, and writes it to the specified manifest file. If no directory is specified, the current working directory is used. If no manifest file is specified (or if "-" is specified), the manifest is written to standard output. The manifest file is replaced atomically, i.e. it is only put in place once it has been written completely.

Added in version 263.

verify [DIRECTORY [MANIFEST]]

Verifies the specified directory tree against the specified manifest file. If no directory is specified, the current working directory is used. If no manifest file is specified (or if "-" is specified), the manifest is read from standard input. If --format= is not specified, the format is derived from the file name of the manifest if possible, and otherwise defaults to uapi16.

Every entry of the manifest is checked against the tree: the file must exist, have the listed inode type and, as far as the manifest carries this information and the --field= setting asks for it, the listed size, hash, access mode, ownership, modification time, extended attributes, symlink target and device numbers. All mismatches are reported, and the command fails if there was at least one. The mtree format is not supported for verification.

Note that the check only goes one way: every file listed in the manifest must exist in the tree as described, but the tree may contain additional files that the manifest does not list. These are not reported, and do not cause verification to fail. Hence a successful verification shows that the tree contains everything the manifest describes, but not that it contains nothing else.

Added in version 263.

Options

The following options are understood:

--format=FORMAT

Selects the manifest format. Takes one of list, sha256sums, mtree, uapi16, see above. Defaults to uapi16 for make. For verify defaults to the format derived from the file name of the manifest, and uapi16 if that is not possible.

Added in version 263.

--field=FIELDS

Selects the per-file fields to include in the manifest when generating, and to check when verifying. Takes a comma separated list of the field names listed in the table below. The special values all, default and none may be used to select all, the default set or no fields. Items may be prefixed with "+" or "-" to add or remove fields from the current set instead of replacing it. The option may be specified multiple times. Note that the inode type is always included, if the format can express it. The list format carries no fields at all.

Table 1. Manifest fields

FieldIncluded by defaultFormatsDescription
modeyesmtree, uapi16Access mode bits
uidyesmtree, uapi16Owning numeric UID
gidyesmtree, uapi16Owning numeric GID
sizeyesmtree, uapi16Size of regular files
hashyesmtree, sha256sums, uapi16Digest of the contents of regular files
symlinkyesmtree, uapi16Symlink target
deviceyesmtree, uapi16Major/minor numbers of device nodes
hardlinkyesuapi16Hardlink relationships
mtimenomtree, uapi16Modification time
user-xattryesuapi16Extended attributes in the "user." namespace
user-namenomtree, uapi16Owning user name
group-namenomtree, uapi16Owning group name

The fields mtime, user-name and group-name are not included by default, and have to be enabled explicitly, for example with "--field=+user-name,+group-name". Modification times typically complicate reproducibility. User and group names are resolved via the user database of the host (i.e. via NSS, like tar(1) does), hence reflect the host's view, which is not necessarily the one of the tree or image the manifest describes. IDs that cannot be resolved to a name are counted as omitted metadata. When verifying, the names are compared with the ones the host resolves the IDs to.

If user-xattr is enabled (which it is by default), the extended attributes in the "user." namespace of all inodes except symlinks are recorded, including for inodes that have no such attributes, so that a verifier can tell missing attributes apart from unrecorded ones. On file systems that do not support extended attributes, inodes are considered to have none. Extended attributes in other namespaces (such as security labels) are never included.

The same default set of fields is used by systemd-dissect(1) and systemd-repart(8) when generating manifests.

Added in version 263.

--hash=ALGORITHM

Selects the hash algorithm to use for the hash field of the mtree format. Takes one of sha256 or sha512. With sha512 a "sha512sum=" keyword is listed instead of "sha256sum=". The other formats only support sha256. Defaults to sha256.

Added in version 263.

--graceful

When generating a manifest with make, do not fail if some inodes had to be skipped or some of their metadata had to be omitted, because they could not be read (for example due to missing privileges) or are not representable in the selected format. Instead, log a warning and return success. The top-level inode must be covered by the manifest in any case, but its metadata may be incomplete.

Added in version 263.

--private-key=PATH/URI, --private-key-source=TYPE[:NAME], --certificate=PATH, --certificate-source=TYPE[:NAME]

Set the private key and certificate to use for signing. When generating a uapi16 manifest with make, the manifest is signed if (and only if) --private-key= is specified, in which case --certificate= must be specified too. A signature object is then appended to the manifest, carrying a detached PKCS#7 (CMS) signature in DER format. The signature covers the exact bytes of the manifest preceding the signature object (without any color sequences that might be inserted when writing to a terminal). RSA, ECDSA and Ed25519 keys are supported. For RSA and ECDSA keys the signature is made directly over the digest of the manifest, for Ed25519 keys it is made over a set of signed attributes carrying the SHA-512 digest of the manifest, as required by RFC 8419. Signing requires OpenSSL.

When verifying, only --certificate= is used: if specified, the manifest must carry a signature that verifies against this certificate, instead of one of the certificates found in the VOA hierarchy, see --verify-signature= below. The --certificate= option takes a path to a PEM encoded X.509 certificate or a URI that's passed to the OpenSSL provider configured with --certificate-source=. The --certificate-source= option takes one of "file" or "provider", with the latter being followed by a specific provider identifier, separated with a colon, e.g. "provider:pkcs11". The --private-key= option can take a path or a URI that will be passed to the OpenSSL engine or provider, as specified by --private-key-source= as a "type:name" tuple, such as "engine:pkcs11".

Added in version 263.

--verify-signature=BOOL

Controls whether to verify the signature of uapi16 manifests when verifying a directory tree. Takes a boolean, defaults to true. If enabled, the manifest must carry a PKCS#7 signature made with the private key of the certificate specified with --certificate=, or, if that option is not used, of one of the X.509 certificates found in the File Hierarchy for the Verification of OS Artifacts (VOA), otherwise verification fails. In the latter case, certificates are read from OS/manifest/CONTEXT/x509/NAME-certificate.pem below the VOA load paths /etc/voa/, /run/voa/, /usr/local/share/voa/ and /usr/share/voa/, where OS is derived from os-release(5) and CONTEXT is configured with --voa-context=. Only artifact verifiers are supported, i.e. the certificates are trusted as they are, and are not checked against trust anchors. Verification fails if no certificates are found. If disabled, signature objects in the manifest are ignored. The list and sha256sums formats carry no signatures, hence for these this option has no effect, except that explicitly enabling it results in an error. Requires OpenSSL.

Added in version 263.

--voa-context=CONTEXT

Selects the VOA context to look up certificates in, if signatures are verified without --certificate=, see above. Defaults to "default". Use --voa-context=sysupdate to verify manifests against the same certificates systemd-sysupdate(8) uses for verifying Uapi16Manifest files it downloads.

Added in version 263.

--json=MODE

Shows output formatted as JSON. Expects one of "short" (for the shortest possible output without any redundant whitespace or line breaks), "pretty" (for a pretty version of the same, with indentation and line breaks) or "off" (to turn off JSON output, the default).

--no-pager

Do not pipe output into a pager.

-h, --help

Print a short help text and exit.

--version

Print a short version string and exit.

Exit status

On success, 0 is returned, a non-zero failure code otherwise. In particular, verify returns non-zero if the directory tree does not match the manifest, and make returns non-zero if an inode had to be skipped or some of its requested metadata had to be omitted, because it could not be read (for example due to missing privileges) or is not representable in the selected format, unless --graceful is specified. In the latter cases the manifest is still generated, but is not written to the output file if one is specified. Inodes other than regular files skipped in sha256sums format are not considered a failure, since this format does not list them by design.

Examples

Example 1. Generate an unsigned UAPI.16 manifest of a directory tree and verify it

$ systemd-manifest make /srv/tree > Uapi16Manifest
$ systemd-manifest verify --verify-signature=no /srv/tree Uapi16Manifest

Example 2. Generate a SHA256SUMS file of the current directory, without ownership or mode information

$ systemd-manifest make --format=sha256sums > SHA256SUMS
$ sha256sum -c SHA256SUMS

Example 3. Only verify file contents, ignoring ownership and access modes

$ systemd-manifest verify --verify-signature=no --field=size,hash /srv/tree Uapi16Manifest

Example 4. Generate a signed manifest, and verify it against the certificate

$ systemd-manifest make --private-key=foo-private-key.pem --certificate=foo-certificate.pem /srv/tree > Uapi16Manifest
$ systemd-manifest verify --certificate=foo-certificate.pem /srv/tree Uapi16Manifest

Example 5. Verify a manifest against the certificates systemd-sysupdate trusts

# cp foo-certificate.pem /etc/voa/$(. /etc/os-release; echo $ID)/manifest/sysupdate/x509/
$ systemd-manifest verify --voa-context=sysupdate /srv/tree Uapi16Manifest

See Also

systemd(1), systemd-dissect(1), systemd-sysupdate(8), sha256sum(1)