Skip to content

bfreis/rules_bsx

Repository files navigation

rules_bsx

CI

Bazel rules for building Binary Self-eXtracting archives (BSX) with integrity verification and cryptographic signing.

A BSX file is a single executable shell script containing an embedded gzipped tarball. When run, it verifies the payload checksum, extracts the contents to a temporary directory, and executes an embedded script. No external tools beyond a POSIX shell, tar, and base64 are required to run the output.

Setup

Add to your MODULE.bazel:

bazel_dep(name = "rules_bsx", version = "0.1.0")

Rules

bsx

Creates a self-extracting archive.

load("@rules_bsx//:bsx.bzl", "bsx")

bsx(
    name = "deploy",
    data = {
        ":config": "config.yaml",
        ":binary": "bin/server",
    },
    main = "deploy.sh",
)
Attribute Type Description
cmd string Inline shell command to execute after extraction. Mutually exclusive with main.
main label Script file to execute after extraction. Mutually exclusive with cmd.
data label_keyed_string_dict Files to include in the archive. Keys are labels, values are destination paths within the archive.
tarballs label_list Pre-built tarballs (.tar, .tar.gz, .tgz) to merge into the archive. Later entries override earlier ones.

Exactly one of cmd or main must be provided. The script runs with the extraction directory as its working directory and receives any command-line arguments passed to the BSX file.

bsx_sign

Creates a detached cryptographic signature for a BSX file. The signature covers the entire file (preamble + payload), so any modification is detected.

load("@rules_bsx//:bsx.bzl", "bsx_sign")

bsx_sign(
    name = "deploy_signed",
    bsx = ":deploy",
    signing_key_cmd = "op read 'op://Vault/deploy-key/private_key'",
)
Attribute Type Description
bsx label The BSX target to sign. Required.
signing_key_cmd string Shell command that outputs the signing private key (PEM) to stdout. Runs at bazel run time, so interactive key retrieval (e.g., 1Password, YubiKey) works. Required.
output_name string Filename for the signed output. Defaults to the BSX target's filename.

Run with bazel run to produce the signed binary and its .sig file:

$ bazel run :deploy_signed
Signed: /path/to/deploy
Signature: /path/to/deploy.sig
Key type: Private-Key: (2048 bit, 2 primes)

Verify with:
  openssl pkeyutl -verify -pubin -inkey <pubkey.pem> -rawin -digest sha256 -in deploy -sigfile deploy.sig

Signing happens at bazel run time (not build time) so that interactive key retrieval works. The key type is auto-detected — RSA and ECDSA use -digest sha256, while algorithms with built-in hashing (ML-DSA, Ed25519, Ed448) omit it.

OpenSSL requirement: bsx_sign invokes openssl from your host PATH (not inside the Bazel sandbox). RSA and ECDSA signing work with any OpenSSL or LibreSSL version. ML-DSA and Ed25519 require OpenSSL 3.5+ (they use pkeyutl -rawin, which is not supported by LibreSSL or older OpenSSL). On macOS, the system /usr/bin/openssl is LibreSSL — install OpenSSL via Homebrew and ensure it is on your PATH for ML-DSA/Ed25519 support.

Integrity verification

Every BSX file embeds a SHA-256 checksum of the payload. Before extraction, the checksum is verified — if it doesn't match, the file exits with an error. This catches accidental corruption (truncated downloads, bad sectors, etc).

This is not a security measure against tampering. An attacker who can modify the payload can also modify the embedded checksum. For tamper resistance, use bsx_sign with a detached signature verified externally against a trusted public key.

Environment variables

Variable Description
BSX_EXTRACT_DIR If set, extract to this directory instead of a temporary one. The directory is not cleaned up on exit.

License

Apache License 2.0. See LICENSE.

About

Bazel rules for building self-extracting binaries (BSX) with integrity verification and cryptographic signing

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors