registrytokenwire

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 13, 2026 License: AGPL-3.0 Imports: 14 Imported by: 0

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

func Build(pool *pgxpool.Pool, cfg BuildConfig) (*http.ServeMux, error)

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

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

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL