Documentation
¶
Overview ¶
Package registrytokenwire — composition-root adapters binding the registry `/iam/token` shim use-case to iam infrastructure:
HydraExchangeAdapter — brokers the client_credentials + private_key_jwt exchange with Hydra's public token endpoint, mapping issuer-unavailability to the use-case's fail-closed sentinel. Пользуется им АНОНИМНЫЙ поток на контуре, ещё не переведённом на нашу чеканку.
SAClientLookupAdapter — обратный резолв ключа служебной учётки по client_id. Живёт ТОЛЬКО ради окна перехода #1143: полоса предъявленного удостоверения принимает базовый токен доступа, а ключевой материал — лишь пока оператор держит окно открытым. Предикат снятия — снятие ручки `api-server.registry-token.key-material-window-until`.
These are thin adapters over already-tested primitives; they carry no policy.
provider_hop.go — выбор полосы обмена для контура выдачи докер-токена и отставленная дорога к прежнему издателю (задача #1119, Ф4б эпика #896).
───────────────────────────────────────────────────────────────────────────── ПРЕДМЕТ
Контур выдачи докер-токена переводится на СВОЮ чеканку подключением подписанта (`BuildConfig.Signer`). Обе точки входа контура — выдача по предъявленным учётным данным и анонимное чтение — при подключённом подписанте возвращаются ДО обращения к обменнику: утверждение для прежнего издателя не строится, обмен не производится, адрес его токен-эндпоинта не читается ни одним путём.
Сборка при этом строила клиента к прежнему издателю БЕЗУСЛОВНО и отказывала в старте на негодном якоре — то есть требовала пригодной дороги к тому, с кем на этой посадке не разговаривают.
ПОЧЕМУ ЭТО ХУЖЕ ЛИШНЕГО КОДА. Требование без предмета неотличимо от действующего. Оператор, читающий отказ, идёт чинить адрес и якорь, по которым процесс не пойдёт ни разу; а посадка, у которой прежнего издателя нет вовсе, не поднимается по причине, к её работе отношения не имеющей.
───────────────────────────────────────────────────────────────────────────── ГРАНИЦА НАЗВАНА: ТРЕБОВАНИЕ СНИМАЕТСЯ ТОЛЬКО У ПЕРЕВЕДЁННОГО КОНТУРА
Пока подписант не подключён, прежний издатель — ЕДИНСТВЕННЫЙ производитель токена на этом контуре, и пригодность дороги к нему обязана проверяться при старте ровно как прежде: якорь, который нельзя прочитать, — отказ, а не тихий откат к системным корням. Снять требование со всех значило бы обменять видимый отказ в старте на непроверенную дорогу, о которой никто не узнает.
───────────────────────────────────────────────────────────────────────────── ЧЕГО ЗДЕСЬ НЕТ: СНЯТИЯ САМОЙ ПОЛОСЫ ОБМЕНА
Ветка обмена в use-case остаётся: у неё есть предмет — посадка без своей чеканки. Снимается она вместе с последним профилем, который её объявляет, и это отдельная работа со своим предикатом.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Build ¶
Build assembles the registry `/iam/token` shim from a pgx pool: the authority on the presented BASIC ACCESS TOKEN (the only credential kind this lane accepts, задача #1143), plus the ES256 client_assertion signer and the Hydra token exchanger the ANONYMOUS flow still needs on a contour not yet moved to our own minting. The caller mounts the returned mux on an EXTERNAL-reachable HTTP listener.
Composition root only — this is the single wire-up call for serve.go. Unlike the deprecated RS256 signer, the shim needs NO JWKS encryption key: it does not mint tokens (Hydra does) and does not decrypt any at-rest signing key. The data-plane's verification keys are Hydra's, served via the separate cluster-internal jwks-proxy mirror (internal/handler/jwksproxyhttp) — not by this `/iam/token` shim.
Types ¶
type BuildConfig ¶
type BuildConfig struct {
// Logger — журнал причин отказа выдачи. Наружу тело фиксировано; без этого
// поля причина не уходила никуда, и разные по природе отказы выглядели
// одинаково. nil допустим — тогда журналирования нет.
Logger *slog.Logger
// Realm — the WWW-Authenticate realm URL advertised to docker clients
// (e.g. https://api.kacho.local/iam/token). Must match the data-plane's
// advertised Bearer realm.
Realm string
// Service — the default registry service name (→ requested token audience +
// WWW-Authenticate service, e.g. registry.kacho.local).
Service string
// HydraTokenURL — the Hydra public token endpoint the shim POSTs the exchange
// to (cluster-internal in production, e.g.
// http://kacho-umbrella-hydra-public.<ns>.svc:4444/oauth2/token).
HydraTokenURL string
// AssertionAudience — the `aud` of the client_assertion: the Hydra token
// endpoint URL Hydra recognises (its external issuer's token endpoint).
AssertionAudience string
// Scope — optional scope requested from Hydra.
Scope string
// AnonymousClientID / AnonymousKeyID / AnonymousPrivateKeyPEM — the configured
// public-principal identity the shim authenticates as for anonymous pull (RG-1
// D-7). The data-plane resolves this client_id's token to the FGA wildcard
// `user:*`. Empty (the default) leaves anonymous pull DISABLED — no-Basic-creds
// then fails closed to a 401 challenge (secure-by-default; anon is opt-in).
// HydraTokenCAFile — the anchor the hop to the provider's token endpoint is
// verified against, when the profile pins one. Empty ⇒ the default transport,
// which is what a plaintext in-cluster address needs; the production boot guard
// is what forbids claiming https without an anchor.
HydraTokenCAFile string
AnonymousClientID string
AnonymousKeyID string
AnonymousPrivateKeyPEM string
// Signer — НАШ подписант. nil означает «контур ещё на прежнем издателе»:
// законное состояние до перевода, а не полусобранная зависимость.
Signer *tokensigner.Signer
// TokenTTL — срок выпускаемого токена контура. Слагаемое арифметики
// отсрочки снятия ключа, поэтому объявлено числом, а не выведено.
TokenTTL time.Duration
// KeyMaterialWindowUntil — ОКНО ПЕРЕХОДА ЛОМАЮЩЕГО ИЗМЕНЕНИЯ #1143:
// мгновение, до которого полоса ПРОДОЛЖАЕТ принимать ключевой материал в
// поле пароля наряду с базовым токеном доступа. Нулевое — окна нет
// (умолчание, fail-closed).
//
// Приезжает РАЗОБРАННЫМ из настройки: разбор живёт у стража старта, а не
// здесь, иначе неразборчивое значение доживало бы до первого входа клиента.
// Разбор нормы, цена обоих умолчаний и предикат снятия —
// registry_token/key_material_window.go.
KeyMaterialWindowUntil time.Time
// CredentialKindObserver — счётчик исходов полос по виду предъявленного
// удостоверения. nil → счёта нет; решения полосы это не меняет.
//
// Единственное НАБЛЮДАЕМОЕ различие между закрытым и открытым окном: наружу
// оба отвечают одинаково (различимость снаружи была бы оракулом посадки).
// Без него оператор не знает ни скольких ломает закрытое окно, ни когда
// открытое можно закрыть.
CredentialKindObserver registrytokenuc.CredentialKindObserver
}
BuildConfig — the composition inputs for the registry `/iam/token` shim.
type HydraExchangeAdapter ¶
type HydraExchangeAdapter struct {
// contains filtered or unexported fields
}
HydraExchangeAdapter — the TokenExchanger backed by Hydra's public token endpoint. Issuer unavailability is surfaced as the use-case's fail-closed sentinel; a Hydra rejection is returned as-is (the use-case collapses it to a 401 challenge).
func NewHydraExchange ¶
func NewHydraExchange(c hydraClientCredentials) *HydraExchangeAdapter
NewHydraExchange — builder.
func (*HydraExchangeAdapter) Exchange ¶
func (a *HydraExchangeAdapter) Exchange(ctx context.Context, in registrytokenuc.ExchangeInput) (registrytokenuc.ExchangeOutput, error)
Exchange brokers the client_credentials + private_key_jwt exchange.
type LocalMintAdapter ¶
type LocalMintAdapter struct {
// contains filtered or unexported fields
}
LocalMintAdapter — НАШ подписант с точки зрения контура выдачи докер-токена.
Тонкий переходник без политики: срок берётся настройкой контура, субъект и адресат приходят от use-case, а всё, что делает токен токеном — обязательные `kid`, срок, тип, издатель, — проставляет подписант.
func NewLocalMinter ¶
func NewLocalMinter(s *tokensigner.Signer, ttl time.Duration) *LocalMintAdapter
NewLocalMinter — построитель.
func (*LocalMintAdapter) MintToken ¶
func (a *LocalMintAdapter) MintToken(ctx context.Context, in registrytokenuc.MintInput) (registrytokenuc.MintOutput, error)
MintToken выпускает токен контура.
type SAClientLookupAdapter ¶
type SAClientLookupAdapter struct {
// contains filtered or unexported fields
}
SAClientLookupAdapter — resolves the registered SA-key for a Hydra client_id.
func NewSAClientLookup ¶
func NewSAClientLookup(repo saClientByIDReader) *SAClientLookupAdapter
NewSAClientLookup — builder.
func (*SAClientLookupAdapter) KeyByClientID ¶
func (a *SAClientLookupAdapter) KeyByClientID(ctx context.Context, clientID string) (registrytokenuc.RegisteredKey, error)
KeyByClientID returns the registered key material for a Hydra client_id, together with whether the owning ServiceAccount may authenticate.
The owner's state is resolved here, on the lookup, because the validator decides on it: a lookup that returned only key material would hand back a zero value for the state, and every docker login in the platform would be refused by a check that never saw a row.