Add a signing backend¶
The standard gtb binary ships with two backends: aws-kms and
local (PEM file on disk). If you need to sign against something
else — GCP KMS, Azure Key Vault, HashiCorp Vault Transit, a YubiKey —
you implement a signing.Backend, register it from your own main
package, and gtb keys mint --backend <name> / gtb sign --backend
<name> picks it up.
Canonical guide lives in the signing module
The backend registry was extracted from go-tool-base into the
standalone signing module (gitlab.com/phpboyscout/go/signing,
v0.1.0). The canonical, in-depth "Implement a custom backend"
how-to — plus the trust model, threat model, and per-backend
guides — now lives in the
signing module documentation,
with the API on
pkg.go.dev/gitlab.com/phpboyscout/go/signing.
This page keeps the gtb-side essentials: the contract, how to register, and how to activate a backend in a gtb-derived binary.
The Backend contract¶
The contract is CLI-agnostic — two methods, both backed by stdlib
seams (crypto.Signer, context.Context):
// gitlab.com/phpboyscout/go/signing
type Backend interface {
Name() string
NewSigner(ctx context.Context, keyID string) (crypto.Signer, error)
}
Name()— the identifier the user types after--backend. Lowercase, kebab-case, must be unique across the process. Duplicate registration panics atinit()time (fail-fast).NewSigner(ctx, keyID)— given the user's--key-id, return acrypto.SignerwhosePublic()is an*rsa.PublicKeyand whoseSign()makes the remote signing call.Public()must return RSA in v0.1 — Ed25519 minting goes throughgtb keys generate, not through the backend registry.
RegisterFlags is not part of the Backend contract. A backend
that needs CLI flags (e.g. aws-kms's --kms-region) implements an
optional interface that the CLI front-end type-asserts for; a backend
with no flags simply omits it and stays free of any CLI dependency. See
the signing module's how-to for that optional interface's exact shape.
Register from init()¶
// yourtool/signing/gcp/gcp.go
package gcp
import (
"context"
"crypto"
"gitlab.com/phpboyscout/go/signing"
)
type backend struct{ /* optional flag-bound state */ }
func (b *backend) Name() string { return "gcp-kms" }
func (b *backend) NewSigner(ctx context.Context, keyID string) (crypto.Signer, error) {
// resolve the key, construct the SDK client, return a crypto.Signer
}
func init() {
signing.Register(&backend{})
}
The implementation pattern matches the two reference backends:
gitlab.com/phpboyscout/go/signing-aws-kms(packageawskms) — a separate module wrapping AWS KMS, and the example of a backend that contributes a CLI flag (--kms-region) via the optional interface.gitlab.com/phpboyscout/go/signing/local— the on-disk PEM backend, the example of a flag-less backend.
Activate it in your binary¶
Backends register by side effect, so a blank import is all it takes:
// cmd/your-cli/main.go
import (
"gitlab.com/phpboyscout/go-tool-base/internal/cmd/root"
// Activate the backends you want. Standard gtb ships aws-kms +
// local; your tool can ship anything.
_ "gitlab.com/yourorg/yourtool/signing/gcp"
)
That's it. your-cli keys mint --backend gcp-kms --key-id <id> ...
now works, and omitting a backend's import drops it (and its SDK) from
the linked binary entirely.
See also¶
- signing module documentation — the canonical "Implement a custom backend" guide, trust model, and per-backend reference.
gtb keys mint— the user-facing surface your backend plugs into.signingcomponent — the registry overview as consumed by gtb.gitlab.com/phpboyscout/go/signing-aws-kmsandgitlab.com/phpboyscout/go/signing/local— production example backends.