server

package
v1.4.1 Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

approval_authorizer.go — the Protocol-side resolve authorizer.

Pre-111f the admin/console:fleet scope check lived INSIDE `internal/tools/approval` as a hard `internal/protocol/auth` import the one standing violation of the direction rule (runtime packages import protocol TYPES only, never protocol auth / methods / transports). The check moves here, one-way: the server package (the Runtime's network surface) adapts the Protocol's verified scope claims onto the approval package's injected `ResolveAuthorizer` seam. The approval package no longer knows the Protocol's auth vocabulary exists.

dev-only bootstrap endpoint.

BootstrapHandler is mounted at POST /v1/dev/bootstrap.json on harbor dev and harbor console only. It mints a fresh dev token and returns the full connection envelope so the Console Settings page can offer a one-click "Attach to local Runtime" button.

The endpoint is loopback-gated: only localhost peers receive a 200. Non-loopback peers get 403 regardless of headers. The gate reads r.RemoteAddr directly — no header-based spoofing vector exists.

The endpoint is never registered by harbor serve.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SearchAdminScopeFromAuth added in v1.3.0

func SearchAdminScopeFromAuth(ctx context.Context) bool

SearchAdminScopeFromAuth is the production `search.ScopeChecker` — it consults the auth-attached scope set on ctx via `protocolauth.HasScope`.

The function is exported so the wiring (and tests that want the real shape) can inject it directly without re-implementing the closed-scope-set predicate.

pins the closed two-scope set `{admin, console:fleet}` — BOTH are cross-tenant fan-in entitlements. The §17.5 checkpoint (a checkpoint fix) corrected this predicate to honour `console:fleet` too: a Console fleet operator carrying only `console:fleet` is entitled to a cross-tenant search, exactly as it is entitled to a cross-tenant `events.subscribe`.

Types

type BootstrapHandler

type BootstrapHandler struct {
	// contains filtered or unexported fields
}

BootstrapHandler serves POST /v1/dev/bootstrap.json.

func NewBootstrapHandler

func NewBootstrapHandler(
	signer BootstrapSigner,
	id identity.Identity,
	scopes []string,
	baseURL string,
	logger *slog.Logger,
) *BootstrapHandler

NewBootstrapHandler returns a handler wired for the dev identity triple and scope set. baseURL is the absolute URL the bootstrapping Console should target (populated from the actual listener address).

func (*BootstrapHandler) ServeHTTP

func (h *BootstrapHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type BootstrapRequest added in v1.4.0

type BootstrapRequest struct {
	// Tenant / User / Session override the minted token's identity
	// triple. All three must be non-empty to take effect; a partial
	// triple is rejected (identity is mandatory — CLAUDE.md §6). When
	// all three are empty, the handler's default identity is used.
	Tenant  string `json:"tenant"`
	User    string `json:"user"`
	Session string `json:"session"`
	// Scopes overrides the minted token's verified scope set. A nil
	// pointer (the field absent from the JSON) keeps the handler's
	// default scopes; a non-nil pointer — INCLUDING an explicit empty
	// array — replaces them, so `"scopes": []` mints a token with NO
	// scopes (the non-admin case). Each entry SHOULD be a canonical
	// auth.Scope string; unknown scopes are dropped from the verified
	// set at validation time (auth.WithScopes), never elevated.
	Scopes *[]string `json:"scopes"`
}

BootstrapRequest is the OPTIONAL request body the bootstrap endpoint accepts. An empty body (the common `-d '{}'` case) mints the handler's default admin dev token, preserving the one-click Console-attach flow. A body that names a full identity triple and/or a scope set mints a token for THAT principal instead — the dev-only path that makes a lesser-privileged (non-admin) token obtainable so the non-admin authorization contract is exercisable end-to-end (and the live negative-escalation smoke can run).

The override is gated by the same loopback boundary as the default mint: only a localhost peer ever reaches the signer, so a caller that can request a token for an arbitrary principal already controls the loopback dev surface. This is dev-only convenience — production (`harbor serve`) never mounts this endpoint.

type BootstrapResponse

type BootstrapResponse struct {
	BaseURL         string            `json:"base_url"`
	Token           string            `json:"token"`
	Identity        bootstrapIdentity `json:"identity"`
	Scopes          []string          `json:"scopes"`
	ProtocolVersion string            `json:"protocol_version"`
}

BootstrapResponse is the JSON envelope returned by the bootstrap endpoint. It carries every field the Console's attachConnection helper needs for a one-click attach.

type BootstrapSigner

type BootstrapSigner interface {
	SignDevToken(now time.Time, tenant, user, session string, scopes []string) (string, error)
}

BootstrapSigner is the minimal token-signing surface the bootstrap handler needs. The harbor dev cmd's devSigner satisfies it.

type ProtocolScopeAuthorizer added in v1.3.0

type ProtocolScopeAuthorizer struct {
	// Next is the fallback authorizer consulted when ctx carries no
	// qualifying Protocol scope. Nil = no fallback (strict).
	Next approval.ResolveAuthorizer
}

ProtocolScopeAuthorizer is the wire-side approval.ResolveAuthorizer: a resolving ctx that carries the verified `admin` OR `console:fleet` Protocol scope claim (JWT validation → edge) is authorized — exactly the acceptance the pre-111f in-gate check enforced, so wire behaviour is unchanged. Everything else delegates to Next (production wires `approval.NewIdentityAuthorizer()`), which is how the in-process steering bridge resolves without the deleted protocol-scope self-elevation.

A nil Next is the strict wire-only posture: protocol scopes or nothing — fail closed with a wrapped approval.ErrResolveForbidden, byte-for-byte the pre-seam gate semantics.

Stateless; safe for concurrent use.

func NewProtocolScopeAuthorizer added in v1.3.0

func NewProtocolScopeAuthorizer(next approval.ResolveAuthorizer) ProtocolScopeAuthorizer

NewProtocolScopeAuthorizer constructs the wire-side authorizer with next as the non-Protocol fallback. Production gate assembly (`cmd/harbor`, `harbortest/devstack`) passes `approval.NewIdentityAuthorizer()` so both resolution paths work: Protocol-scoped callers keep today's admin/console:fleet acceptance; the runtime steering bridge resolves via the originating identity.

func (ProtocolScopeAuthorizer) AuthorizeResolve added in v1.3.0

func (a ProtocolScopeAuthorizer) AuthorizeResolve(ctx context.Context, pending approval.PendingInfo) error

AuthorizeResolve implements approval.ResolveAuthorizer.

Jump to

Keyboard shortcuts

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