Skip to content

Backends are the consumer's responsibility

The sign and keys mint commands need a signing backend — AWS KMS, an on-disk PEM key, or something else. This module ships none of them. This page explains why, and how the commands find the backends the host compiled in.

This module imports no concrete backend

signing-cli never imports signing-aws-kms, signing/local, or any other backend package. Instead it talks to the go/signing registry:

  • signing.Names() — the names of every backend registered in this binary.
  • signing.Get(name) — resolve one to a signing.Backend.

Both sign and keys mint build their --backend help text from signing.Names() and resolve the chosen backend with signing.Get(). Whatever backends the host binary registered are exactly the backends the commands offer — no more, no fewer.

Activation by blank import

Backends register themselves from init(). A host turns one on by blank-importing its package in main, the same side-effect pattern as net/http/pprof, the image/* decoders, and database drivers:

import (
    _ "gitlab.com/phpboyscout/go/signing-aws-kms" // registers "aws-kms"
    _ "gitlab.com/phpboyscout/go/signing/local"   // registers "local"
)

With those two imports present, sign --backend aws-kms … and sign --backend local … both work, and --help lists both names. Drop the KMS import and rebuild, and aws-kms simply disappears from the command — no code change in signing-cli or in the command wiring.

Why push backends out to the host

The same dependency-inversion logic that keeps go/signing light applies here:

  • The AWS SDK is enormous. A tool that only ever signs with the local PEM backend should not link it. Because the SDK is imported only by signing-aws-kms, and that package is imported only when the host blank-imports it, linker dead-code elimination keeps the SDK out of any binary that does not opt in.
  • Regulated / FIPS-only builds can drop a backend cleanly. go-tool-base isolates its backend imports in a single file (cmd/gtb/signing.go); a downstream that must exclude the AWS SDK omits that one blank import and rebuilds. Its companion cmd/gtb-no-aws-smoke binary exists precisely to prove the AWS SDK is not pulled in transitively by anything inside signing-cli.
  • The command surface stays universal. Because the commands discover backends at runtime, one build of signing-cli serves every host regardless of which backends that host chose.

Per-backend flags

Some backends need their own flags — aws-kms, for example, adds --kms-region. The signing.Backend contract is CLI-agnostic, so a backend that needs flags implements an optional interface:

interface{ RegisterFlags(*pflag.FlagSet) }

When NewCmdSign and NewCmdKeysMint build their command, they iterate the registered backends and type-assert for that interface, letting each backend declare its flags onto the command's flag set. So --kms-region appears in sign --help only when a KMS-capable backend is compiled in. The front-end type-asserts for this; the library never does — keeping go/signing free of any flag machinery.

keys generate and keys wkd take no backend: generate produces a fresh keypair entirely in-process, and wkd only reads already-minted public keys. Only sign and keys mint consult the backend registry.

See also