Skip to content

About

bao-wrapper is a CI-agnostic process wrapper for OpenBao

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

bao-wrapper

bao-wrapper is a CI-agnostic process wrapper for OpenBao / HashiCorp Vault.
It fetches secrets at runtime, injects them into the child process's environment (or as temporary files), and masks registered values in captured stdout and stderr — all without touching the CI runner's own environment.

Table of Contents

Key features

Feature Details
Zero external dependencies Uses only the Go standard library (net/http, encoding/json, …)
Authentication Direct token, JWT/OIDC, or AppRole, with ownership-aware token cleanup
Streaming log masking Replaces registered plaintext values of at least four bytes with [MASKED], including matches split across writes
env and file injection Secrets are exposed as env vars or temp files (0600 on Unix; inherited ACLs on Windows); sensitive config vars are stripped from the child process
Template engine Go text/template rendering with in-template {{ secret "..." }} lookups and selective masking
Automatic retry Secret reads and revocation: up to 3 retries on network errors or HTTP 502/503/504, with exponential backoff and jitter; logins are not retried
Direct execution Launches the supplied command without implicit shell expansion
Cross-platform Linux, macOS (amd64/arm64), Windows (amd64)

Installation

This README describes the current source. Published releases may differ; build from source if a documented feature is not yet released. The README examples are updated automatically but may lag behind new releases. See GitHub Releases for the latest version.

Download from GitHub Releases

# Linux amd64; pin the release version and its verified checksum.
BAO_WRAPPER_VERSION=v0.7.0
BAO_WRAPPER_SHA256='a5501404e717b4fd39b5597c5f390019c6656543112f5079c2fbac0368fbff17'
curl -fsSLO "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/bao-wrapper-linux-amd64" &&
printf '%s  %s\n' "$BAO_WRAPPER_SHA256" bao-wrapper-linux-amd64 | sha256sum --check --strict &&
install -m 0755 bao-wrapper-linux-amd64 bao-wrapper

Available release assets:

Platform File
Linux amd64 bao-wrapper-linux-amd64
Linux arm64 bao-wrapper-linux-arm64
macOS amd64 bao-wrapper-darwin-amd64
macOS arm64 (M-series) bao-wrapper-darwin-arm64
Windows amd64 bao-wrapper-windows-amd64.exe

The current release workflow publishes an SPDX 2.3 JSON SBOM for each binary as <binary-name>.spdx.json, including bao-wrapper-windows-amd64.exe.spdx.json for Windows. Syft generates each SBOM from the compiled binary, recording its Go modules and standard library version. The pinned SBOM action also pins its default Syft version; Renovate updates the action.

SHA256SUMS covers both binaries and SBOMs. GitHub build-provenance attestations cover the manifest, binaries and SBOM files; a separate SBOM attestation binds each SBOM to its binary's digest. Publication requires successful tests, SBOM generation and attestations. Older releases may not include these assets.

Verify release provenance

For releases containing SHA256SUMS, download the manifest and selected binary from an explicit version, authenticate both with the GitHub CLI, and only then install the binary:

BAO_WRAPPER_VERSION=v0.7.0
BAO_WRAPPER_SHA256='a5501404e717b4fd39b5597c5f390019c6656543112f5079c2fbac0368fbff17'
curl -fsSLO "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/SHA256SUMS" &&
curl -fsSLO "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/bao-wrapper-linux-amd64" &&

gh attestation verify SHA256SUMS --repo philhartung/bao-wrapper &&
gh attestation verify bao-wrapper-linux-amd64 --repo philhartung/bao-wrapper &&
sha256sum --check --ignore-missing --strict SHA256SUMS &&
printf '%s  %s\n' "$BAO_WRAPPER_SHA256" bao-wrapper-linux-amd64 | sha256sum --check --strict &&
install -m 0755 bao-wrapper-linux-amd64 bao-wrapper

The attestation verifies the artifact's signed provenance; SHA256SUMS makes the release's complete digest set easy to inspect and use in systems that require a pinned checksum.

To download and verify the selected binary's SBOM, using the same release version:

curl -fsSLO "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/bao-wrapper-linux-amd64.spdx.json" &&
gh attestation verify bao-wrapper-linux-amd64.spdx.json --repo philhartung/bao-wrapper &&
sha256sum --check --ignore-missing --strict SHA256SUMS &&
gh attestation verify bao-wrapper-linux-amd64 --repo philhartung/bao-wrapper \
  --predicate-type https://spdx.dev/Document/v2.3

Build from source

git clone https://github.com/philhartung/bao-wrapper.git
cd bao-wrapper
CGO_ENABLED=0 go build -o bao-wrapper .

Quick Start

  1. Download the binary (see Installation).
  2. Set your Vault address and authentication variables.
  3. Prefix every secret you need with SECRET_ (or a custom prefix via --secret-prefix) and describe where to fetch it.
  4. Wrap your command with bao-wrapper run --:
export BAO_ADDR="https://vault.example.com"
export BAO_JWT_ROLE="my-role"
export BAO_JWT_TOKEN="<jwt>"          # or use AppRole / GitHub Actions OIDC
export SECRET_DB_PASS="kv://password@kv/myapp/db"

bao-wrapper run -- ./my-app

The child process receives DB_PASS=<actual value>. Exact plaintext matches of registered values at least four bytes long are masked in captured stdout and stderr. See Security notes for the limits of masking and cleanup.


Usage

bao-wrapper run [options] -- <command> [args...]

Options

Flag Default Description
--auth-path <path> jwt for JWT; approle for AppRole Authentication mount used by the selected login method. Accepts a mount name such as gitlab or an auth-relative path such as auth/gitlab; /login is appended automatically. Can also be set via BAO_AUTH_PATH (fallback: VAULT_AUTH_PATH); the CLI flag takes priority.
--revoke-token <policy> auto Token cleanup policy: auto revokes login-issued tokens and preserves supplied tokens; always revokes either; never preserves either. Also accepts --revoke-token=<policy>. Overrides BAO_REVOKE_TOKEN.
--secret-prefix <prefix> SECRET_ Prefix used to identify secret environment variables. Variables whose name starts with this prefix are parsed as secret references; the prefix is stripped before injecting the value into the child process. Can also be set via the BAO_SECRET_PREFIX environment variable; the CLI flag takes priority.

Environment variables

Variable Fallback Required Description
BAO_ADDR VAULT_ADDR yes OpenBao/Vault server URL (e.g. https://openbao.example.com)
BAO_NAMESPACE VAULT_NAMESPACE no Namespace
BAO_TOKEN VAULT_TOKEN no Direct client token; takes priority over all login methods. Use when a token is already available (e.g. local dev, pre-issued tokens). This token is borrowed and preserved by default, including after failures and signals. Use --revoke-token=always to opt into revoking a disposable token.
BAO_AUTH_PATH VAULT_AUTH_PATH no Authentication mount used for JWT or AppRole login. Accepts gitlab and auth/gitlab forms. Defaults to jwt for JWT and approle for AppRole; overridden by --auth-path.
BAO_JWT_ROLE VAULT_JWT_ROLE no JWT auth role (used when BAO_TOKEN is not set; skips JWT login when omitted)
BAO_JWT_TOKEN VAULT_JWT_TOKEN no JWT token for authentication (auto-detected from GitHub Actions OIDC when unset)
BAO_APP_ID VAULT_APP_ID no AppRole role ID (used when BAO_TOKEN and BAO_JWT_ROLE are not set)
BAO_APP_SECRET VAULT_APP_SECRET no AppRole secret ID (used together with BAO_APP_ID)
BAO_CACERT VAULT_CACERT no Path to a PEM-encoded CA certificate file (for self-signed or corporate CA)
BAO_MAX_RESPONSE_BYTES VAULT_MAX_RESPONSE_BYTES no Maximum OpenBao/Vault response body size in bytes (default: 33554432 / 32 MiB)
BAO_OIDC_MAX_RESPONSE_BYTES VAULT_OIDC_MAX_RESPONSE_BYTES no Maximum GitHub Actions OIDC response body size in bytes (default: 65536 / 64 KiB)
BAO_REVOKE_TOKEN – no Token cleanup policy: auto (default), always, or never; overridden by --revoke-token.
BAO_SECRET_PREFIX – no Prefix for secret variables (default: SECRET_); overridden by --secret-prefix

Nonempty BAO_* values take priority over their VAULT_* fallbacks. Authentication selects the first applicable method: direct token → JWT role (with an explicit JWT or GitHub OIDC) → AppRole credentials. A selected method does not fall back to another method if credentials are missing or login fails. BAO_AUTH_PATH is ignored for direct tokens.

Token ownership follows the selected authentication method: tokens supplied through BAO_TOKEN or VAULT_TOKEN are borrowed; client tokens issued by JWT/OIDC or AppRole login are owned. Under the default auto policy, only owned tokens are revoked. This changes the previous behavior that revoked supplied tokens. To retain that behavior for disposable tokens:

bao-wrapper run --revoke-token=always -- make test

Policy precedence is CLI → nonempty BAO_REVOKE_TOKEN → auto. Values must be exactly auto, always, or never; invalid values fail before authentication. There is no VAULT_REVOKE_TOKEN fallback. With never, even login-issued tokens remain valid until expiry or external revocation.

OpenBao/Vault and GitHub OIDC requests have a 10-second HTTP client timeout and do not follow redirects. Secret reads and token revocation retry network errors and HTTP 502/503/504 up to three times, subject to request deadlines; login and OIDC requests are not automatically retried.

Secret variables

Define secrets with the configured prefix (default SECRET_) using this format:

<PREFIX><NAME>=<engine>://[[field][:type]@]path

An explicit supported engine scheme is required. Prefixed variables without one are skipped during secret discovery and stripped from the child environment. The field and type are optional. Query parameters are not supported. file delivery uses an isolated temporary directory; the destination cannot be configured.

Component Default Description
engine (required) Secret engine type. Only kv, legacy, and template are supported. kv uses the KV v2 API path; legacy uses the KV v1 API path; template renders a Go template stored in KV.
field (empty) Key in the secret data; empty = full JSON. Requires @ separator.
type env env = env var, file = temp file path. Specified as field:type before @.
path (required) Full path to the secret, including the mount point (e.g. kv/test, kvv1/my/secret)
Engine API path used Description
kv GET /v1/<mount>/data/<secret_path> (KV v2) KV v2 secrets. The path includes the mount point; /data/ is inserted automatically. Example: path kv/test → /v1/kv/data/test
legacy GET /v1/<path> (KV v1) KV v1 path style. The path is used as-is after validation. Example: path kvv1/test → /v1/kvv1/test
template (fetches template from KV v2, then renders) Fetches a Go text/template from a KV v2 path, renders it with {{ secret "..." }} support (see Template engine)

Path restrictions: Secret paths must be canonical and relative, without traversal or redundant separators. legacy also rejects OpenBao's reserved auth/, sys/, identity/, and cubbyhole/ prefixes because these are system endpoints, not KV v1 mounts. This restriction also applies to legacy:// references used inside templates.

The child process receives the bare name without the prefix.

Examples

# Full format: engine, field, type, and path (path includes mount point)
SECRET_DB_PASS=kv://password:env@kv/myapp/db

# Write TLS cert to a temp file; TLS_CERT contains the file path
SECRET_TLS_CERT=kv://cert:file@kv/myapp/tls

# Path only (no field or type — reads full JSON from kv)
SECRET_KEY=kv://kv/myapp/db

# Render a config from a KV-stored template into a temporary file;
# APP_CFG contains its path
SECRET_APP_CFG=template://tpl:file@kv/myapp/config

# Legacy KV v1 engine
SECRET_TOKEN=legacy://token:env@kvv1/my/path

Template engine

The template engine fetches a Go text/template from an OpenBao/Vault KV secret, renders it, and returns the result. This is useful for generating configuration files that embed multiple secrets.

Declaration syntax

Use the template engine in the SECRET_* variable:

# Render template stored at KV path "kv/myapp/config", field "tpl",
# write the result to a temporary file, and expose its path as APP_CFG
SECRET_APP_CFG=template://tpl:file@kv/myapp/config

# Render template and inject as an env var
SECRET_APP_CFG=template://tpl@kv/myapp/config

In-template lookups

Inside the template, use {{ secret "url" }} to reference individual secrets. The in-template URL uses a reduced syntax compared to the main SECRET_* declaration:

{{ secret "[engine://][field@]path" }}

The engine defaults to kv when omitted. The field is optional; omitting it returns the full JSON data.

Restrictions for in-template URLs:

  • Only kv and legacy engines are allowed (no template recursion).
  • Type selectors (:env, :file) are not allowed.
  • Query parameters (?key=value) are not allowed.

Template example

Suppose the KV path kv/myapp/config field tpl contains this Go template:

[database]
host = db.example.com
password = {{ secret "kv://password@kv/myapp/db" }}

[api]
token = {{ secret "kv://token@kv/myapp/api" }}

With the declaration:

SECRET_APP_CFG=template://tpl:file@kv/myapp/config

The wrapper fetches and renders the template, writes it to a temporary file, and exposes the path as APP_CFG. Cleanup attempts to remove the file after use; see Security notes.

Selective masking

Only values fetched through {{ secret "..." }} are registered for template masking. The template source and complete rendered output are not registered. Literal credentials in a template and transformed values therefore have no automatic masking guarantee. The usual minimum length of four bytes applies.


Examples

GitLab CI Pipeline

This example uses a JWT auth method mounted at auth/gitlab and requires a release supporting BAO_AUTH_PATH. It assumes your project provides an npm build script and installs its dependencies before the build.

# .gitlab-ci.yml
stages:
  - build

build:
  stage: build
  image: node:24-bookworm@sha256:3d27e5c11e5786e309ec3e03f93ae536eb36e6e5eb3714d5eb3300a36157add0
  id_tokens:
    BAO_JWT_TOKEN:
      aud: https://vault.example.com
  variables:
    BAO_ADDR: "https://vault.example.com"
    BAO_NAMESPACE: "mynamespace"
    BAO_AUTH_PATH: "gitlab" # JWT method mounted at auth/gitlab
    BAO_JWT_ROLE: "gitlab-ci"
    # Inject the NPM token as an env var
    SECRET_NPM_TOKEN: "kv://npmToken:env@kv/frontend/ci"
    # Render a Docker config into a temporary file; DOCKER_CFG contains its path
    SECRET_DOCKER_CFG: "template://tpl:file@kv/ci/docker-config"
  before_script:
    - |
      BAO_WRAPPER_VERSION=v0.7.0
      BAO_WRAPPER_SHA256='a5501404e717b4fd39b5597c5f390019c6656543112f5079c2fbac0368fbff17'
      curl -fsSL \
        "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/bao-wrapper-linux-amd64" \
        -o bao-wrapper-linux-amd64 &&
      printf '%s  %s\n' "$BAO_WRAPPER_SHA256" bao-wrapper-linux-amd64 | sha256sum --check --strict &&
      install -m 0755 bao-wrapper-linux-amd64 /usr/local/bin/bao-wrapper || exit 1
  script:
    - bao-wrapper run -- npm run build

The build receives NPM_TOKEN and the temporary config path in DOCKER_CFG. The token and secrets fetched inside the template are registered for log masking.


GitHub Actions Pipeline

With id-token: write permission and BAO_JWT_ROLE set, the wrapper can request a JWT using GitHub's ACTIONS_ID_TOKEN_REQUEST_* variables. Configure the Vault role to accept GitHub's issuer, audience, and repository claims. This example assumes your project provides an npm build script and installs its dependencies before the build.

# .github/workflows/build.yml
name: Build

on: [push]

permissions:
  id-token: write   # required for OIDC token generation
  contents: read

jobs:
  build:
    runs-on: ubuntu-26.04
    env:
      BAO_ADDR: "https://vault.example.com"
      BAO_NAMESPACE: "mynamespace"
      BAO_JWT_ROLE: "github-actions"
      # Inject the NPM token as an env var
      SECRET_NPM_TOKEN: "kv://npmToken:env@kv/frontend/ci"
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

      - name: Install bao-wrapper
        run: |
          BAO_WRAPPER_VERSION=v0.7.0
          BAO_WRAPPER_SHA256='a5501404e717b4fd39b5597c5f390019c6656543112f5079c2fbac0368fbff17'
          curl -fsSL \
            "https://github.com/philhartung/bao-wrapper/releases/download/${BAO_WRAPPER_VERSION}/bao-wrapper-linux-amd64" \
            -o bao-wrapper-linux-amd64 &&
          printf '%s  %s\n' "$BAO_WRAPPER_SHA256" bao-wrapper-linux-amd64 | sha256sum --check --strict &&
          sudo install -m 0755 bao-wrapper-linux-amd64 /usr/local/bin/bao-wrapper || exit 1

      - name: Build
        run: bao-wrapper run -- npm run build

Note: BAO_JWT_TOKEN is intentionally omitted. bao-wrapper detects the GitHub Actions OIDC environment and requests the JWT automatically. Explicitly setting BAO_JWT_TOKEN (or its fallback VAULT_JWT_TOKEN) always takes precedence over auto-detection.


AppRole Authentication

For non-interactive environments where JWT/OIDC is not available, you can use AppRole authentication by providing a RoleID and SecretID.

export BAO_ADDR="https://vault.example.com"
export BAO_APP_ID="my-role-id"
export BAO_APP_SECRET="my-secret-id"
# export BAO_AUTH_PATH="ci-approle" # if AppRole is mounted at auth/ci-approle

# Inject secrets from KV
export SECRET_API_KEY="kv://apiKey@kv/services/api"

bao-wrapper run -- ./start-service.sh

bao-wrapper logs in with AppRole, fetches the secrets, runs the command, and attempts to revoke the client token during cleanup under the default auto policy.


Architecture

Package Responsibility
main CLI options, authentication selection, secret resolution, token lifecycle
parser Secret declarations and template lookup syntax
api OpenBao/Vault HTTP requests, path validation, retries, token revocation
template Go template rendering and collection of inner secrets for masking
runner Child environment, temporary files, process execution, signals, cleanup
masker Streaming plaintext replacement in stdout and stderr

Security notes

  • Transport: Use an HTTPS BAO_ADDR outside local testing; plain HTTP is accepted. HTTPS certificate verification is enabled, with optional custom roots via BAO_CACERT. GitHub OIDC requires HTTPS and uses system trust; its request URL comes from the CI environment and has no hostname allowlist.
  • Child environment: Inherited variables starting with BAO_, VAULT_, ACTIONS_ID_TOKEN_REQUEST_, or the configured secret prefix are removed case-insensitively before resolved secrets are added. Other environment variables are inherited.
  • Masking: Only exact matches of registered values at least four bytes long are masked in captured stdout and stderr. Full-JSON reads register the JSON string, not its individual fields; templates register only inner lookups. Encoding, escaping, splitting a value between streams, or writing elsewhere can bypass masking. Run trusted child code: masking is not a security boundary. Output may be buffered by up to the longest registered value minus one byte to handle matches split across writes.
  • Temporary files: File secrets use an isolated temporary directory (0700) and exclusive file creation (0600) on Unix. Windows uses inherited ACLs, so protect the account and temporary directory. Cleanup attempts removal on child exit and on SIGINT/SIGTERM, retrying removal after exit if necessary.
  • Token cleanup: When the revocation policy selects a token for cleanup, cleanup attempts POST /v1/auth/token/revoke-self, including after failures before child startup. By default, JWT/OIDC and AppRole client tokens are revoked; supplied BAO_TOKEN and VAULT_TOKEN credentials are preserved. SIGINT/SIGTERM starts cleanup while the child is running. Revocation can fail, and forced termination such as SIGKILL prevents cleanup. Use short TTLs for login-issued tokens and disposable tokens selected for revocation; a lost login response can also leave an issued token unavailable for revocation. Tokens are not renewed.
  • Signals and exit status: The wrapper attempts to forward SIGINT/SIGTERM to its direct child. Process-tree termination and shutdown deadlines are the CI or container runtime's responsibility; Unix-style signal forwarding is not supported on Windows. Normal child exit codes are preserved, but a cleanup failure turns a successful exit into failure; signal termination is reported as exit code 1.
  • Output draining: After the direct child exits, the wrapper allows up to one second for inherited stdout/stderr pipes to close before starting cleanup. At the deadline it closes the capture pipes, potentially truncating descendant output. A drain timeout after a successful child exit reports an error and exit code 1; nonzero child exit codes are preserved. SIGINT/SIGTERM still starts cleanup immediately. Descendants are not terminated by this deadline.

Development

Prerequisites

Running tests

To run the unit tests:

go test ./...

To run tests with coverage:

go test -cover ./...

Running integration tests

The integration suite runs the compiled wrapper and a Go child helper against a native OpenBao process on Linux, macOS, and Windows. Install the OpenBao version pinned in integration/openbao.json on PATH, or set BAO_TEST_BINARY to the full path to bao (bao.exe on Windows). The suite never downloads dependencies itself and fails clearly if OpenBao is missing. Ordinary go test ./... does not require OpenBao.

go test -tags=integration -count=1 -timeout=8m -v ./integration

Local development only requires an installed OpenBao executable; no installer script or PowerShell is required to run the tests.

CI uses a small PowerShell installer, available on all three hosted runner platforms. It first verifies the SHA-256 of OpenBao's checksums.txt against integration/openbao.json, then verifies the native archive against that trusted checksum list before extracting it. One committed digest therefore pins the archives for every platform. The release tag and digest are updated together by Renovate; neither is fetched as an unpinned value during CI.

Each suite builds its own executables, selects a loopback port, and creates isolated storage. A static test-only auto-unseal key and shared declarative self-initialization mount KV v1/v2, seed secrets, and create read-only AppRoles in root and test namespaces; no root token or manual bootstrap is needed. Server and child processes have bounded lifetimes, temporary resources are cleaned up, and server logs are printed on failures. Independent invocations can run concurrently.

The scenarios cover authentication, namespace selection through BAO_NAMESPACE and VAULT_NAMESPACE (including BAO precedence), KV engines, environment and file delivery, template masking, credential stripping, argument/stdin forwarding, Unicode and space-containing paths, failure handling, cleanup, and token revocation. Unix also checks file/directory permissions and SIGINT/SIGTERM forwarding; Windows checks file access and cleanup under inherited ACLs. CI runs the suite on all three operating systems for PRs, main pushes, and release tags, and requires the whole matrix before publishing a release. JWT and TLS integration fixtures are not yet included; transport faults remain covered by mock-server tests.

Docker Compose remains available as an optional manual fixture using the same initialization declarations:

docker compose up --detach --wait openbao
# When finished:
docker compose down --volumes --remove-orphans

Set OPENBAO_PORT to change the Compose fixture's default port 8200. It does not affect the native suite, which always starts its own server. Remove the Compose volume before restarting if you need to reapply initialization changes. All fixture credentials and seal keys are public test values and must never be used in a persistent or production environment.

Building for all platforms

The project uses GitHub Actions to build binaries for multiple platforms. You can build them locally using:

# Linux
GOOS=linux GOARCH=amd64 go build -o bao-wrapper-linux-amd64 .
GOOS=linux GOARCH=arm64 go build -o bao-wrapper-linux-arm64 .

# macOS
GOOS=darwin GOARCH=amd64 go build -o bao-wrapper-darwin-amd64 .
GOOS=darwin GOARCH=arm64 go build -o bao-wrapper-darwin-arm64 .

# Windows
GOOS=windows GOARCH=amd64 go build -o bao-wrapper-windows-amd64.exe .

Reproducing a release build

The current release workflow pins the same Go version as go.mod, disables CGO and automatic VCS stamping, removes local paths, and embeds the version from git describe --tags --always and full source commit. To reproduce one asset, start from a clean checkout of its tag and use the same target and flags:

BAO_WRAPPER_VERSION=v0.7.0
BAO_WRAPPER_SHA256='a5501404e717b4fd39b5597c5f390019c6656543112f5079c2fbac0368fbff17'
git clone https://github.com/philhartung/bao-wrapper.git
cd bao-wrapper
git checkout --detach "$BAO_WRAPPER_VERSION"
COMMIT=$(git rev-parse HEAD)
test "$(git describe --tags --exact-match)" = "$BAO_WRAPPER_VERSION"

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
  go build -trimpath -buildvcs=false -mod=readonly \
  -ldflags="-s -w -X main.version=${BAO_WRAPPER_VERSION} -X main.commit=${COMMIT}" \
  -o bao-wrapper-linux-amd64 .
printf '%s  %s\n' "$BAO_WRAPPER_SHA256" bao-wrapper-linux-amd64 | sha256sum --check --strict

Compare the result with the attested SHA256SUMS entry. Reproduction requires the exact Go toolchain version and target architecture used by the workflow.

About

bao-wrapper is a CI-agnostic process wrapper for OpenBao

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages