Documentation
¶
Overview ¶
Package api reaches the extension servers an operator runs: gRPC services implementing one of the contracts published under api/, currently api.kms.v1.EncryptionService.
Extension servers exist so an operator can plug in a backend the proxy has no built-in support for, such as an on-prem HSM or an internal key service.
Module dials every server named in the configuration and publishes the results as Connections, keyed by server name. Callers build their own clients over those connections rather than receiving finished ones, because the two do not correspond one-to-one: KMS is the client for the encryption service, and one is built per key, several of which may live on one server.
Dialing happens when the connections are first demanded rather than on the first call over them, so a bad address, certificate, or credential is caught during construction. The connections outlive this package and are closed with the application, not by any client built over them.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Module = fx.Options( fx.Provide(func(p APIParams) (Connections, error) { if err := p.Config.ExtensionServers.Validate(); err != nil { return nil, fmt.Errorf("invalid extension server configuration: %w", err) } out := make(Connections, len(p.Config.ExtensionServers)) conns := make([]*connect.Conn, 0, len(p.Config.ExtensionServers)) for i := range p.Config.ExtensionServers { es := &p.Config.ExtensionServers[i] conn, err := extensionConn(p.Pool, es) if err != nil { return nil, err } out[es.Name] = conn conns = append(conns, conn) } p.Lifecycle.Append(fx.StartHook(func(ctx context.Context) error { if err := connect.WaitReady(ctx, conns...); err != nil { return fmt.Errorf("extension server connection not ready: %w", err) } return nil })) return out, nil }), )
Module provides the pooled connection for every configured extension server, built when the provider runs rather than on first use, so a bad dial target surfaces at construction instead of on the first encryption call, and opened on start so an unreachable server (or one whose certificate this proxy will not accept) fails startup. Per-call credentials are still only exercised by a real request.
Functions ¶
This section is empty.
Types ¶
type APIParams ¶
APIParams collects the fx-provided dependencies needed to reach the configured extension servers. Pool is shared with the proxy's upstream connections; connect.Module owns it and closes every pooled connection on shutdown, which is why KMS.Close is a no-op.
type Connections ¶
type Connections map[string]grpc.ClientConnInterface
Connections maps an extension server name to a connection to that server. It carries no lifecycle: closing a connection is the owner's responsibility, not the caller's.
Callers get connections rather than finished clients because the two do not correspond one-to-one: several keys may live on one extension server, so a caller builds one KMS per key over the shared connection.
type KMS ¶
type KMS struct {
// contains filtered or unexported fields
}
KMS wraps and unwraps data encryption keys on an extension server implementing api.kms.v1.EncryptionService. Only key material crosses the wire; payload plaintext never reaches the server.
The id names the key this client addresses. It is recorded in every DEK the key wraps and is what selects the key again when unwrapping, so it must stay stable for as long as any sealed payload references it.
func NewKMS ¶
func NewKMS(id string, cc grpc.ClientConnInterface) *KMS
NewKMS returns a KMS addressing the key named by id over cc. Several keys may live on one extension server and share a connection, so cc is not owned here.
func (*KMS) Close ¶
Close is a no-op. The gRPC connection passed to NewKMS is owned by the caller that dialed it, which remains responsible for closing it; a KEKRegistry closing this KEK must not tear down a connection it does not own.