mirror of
https://github.com/hanzoai/k8s.git
synced 2026-10-02 15:40:05 +00:00
The tree was staged but never committed — this is the repo's first commit, so it carries both the existing content and the zip v1.18.8 -> v1.20.0 migration. Migration: Prepare() is replaced by Build() error, and both test harnesses assert the verdict rather than discarding it. main.go:59's Use call needed no change — the three middleware constructors already return zip.Handler, which satisfies the closed Component interface. The committed projections (k8s.plugin.json, openapi.json, ops/zipdoc_gen.go) are regenerated: v1.20.0 splits an op's prose into summary (first line) + description and zipdoc now emits per-field docs, so all three artifacts move with the bump. Co-authored-by: Hanzo Dev <[email protected]>
58 lines
2.3 KiB
Go
58 lines
2.3 KiB
Go
package registry
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/zap-proto/zip"
|
|
|
|
"github.com/hanzoai/k8s/plane"
|
|
)
|
|
|
|
// Sealed is the production [Store]: the KMS peer, reached over the call plane.
|
|
//
|
|
// Every credential this app holds lives there and nowhere else. There is no
|
|
// kubeconfig on disk, no credential in an environment variable, and no path by
|
|
// which one is printed — the material is fetched at the moment of use, held for
|
|
// the length of one client construction, and never returned to a caller.
|
|
//
|
|
// The call carries the CALLER, so KMS applies its own tenant rule to the ref: a
|
|
// ref under "orgs/<org>/" is served only to a call acting for that org. That is a
|
|
// second refusal, in a second process, of the thing this package already refuses —
|
|
// and the reason the ref shape is derived rather than stored.
|
|
type Sealed struct{}
|
|
|
|
// Get reads one sealed value. An absent ref is (nil, nil): a registry with no
|
|
// index yet is an org with no clusters, which is not an error. An unreachable KMS
|
|
// IS an error, because answering "no clusters" during a KMS outage would make a
|
|
// tenant's whole fleet look deregistered.
|
|
func (Sealed) Get(ctx context.Context, ref string) ([]byte, error) {
|
|
out, err := zip.Ask[plane.SecretIn, plane.Secret](ctx, plane.KMS, plane.KMSGet, &plane.SecretIn{Ref: ref})
|
|
if err != nil {
|
|
if absent(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return out.Value, nil
|
|
}
|
|
|
|
// Put writes one sealed value. A nil value is a legitimate write: it destroys the
|
|
// material at that ref, which is how a deregistration disposes of a credential
|
|
// without this app needing a delete verb KMS does not offer.
|
|
func (Sealed) Put(ctx context.Context, ref string, value []byte) error {
|
|
_, err := zip.Ask[plane.SecretIn, plane.Secret](ctx, plane.KMS, plane.KMSPut, &plane.SecretIn{Ref: ref, Value: value})
|
|
return err
|
|
}
|
|
|
|
// absent reports whether an error means "there is nothing at that ref" rather
|
|
// than "the store did not answer". Only a 404 counts: every other status —
|
|
// including a 403, which means the ref belongs to another tenant — must surface,
|
|
// because treating a refusal as an empty registry is how a tenancy failure turns
|
|
// into a silently empty board.
|
|
func absent(err error) bool {
|
|
var he *zip.HTTPError
|
|
return errors.As(err, &he) && he.Status == http.StatusNotFound
|
|
}
|