appauth

package
v0.2.28 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 64 Imported by: 0

Documentation

Overview

Package appauth is the hub's login-time authorization endpoint for published applications.

The design deliberately keeps the hub OFF the per-request data path:

  • Public apps never contact the hub at all.
  • Private apps redirect an unauthenticated browser here exactly once. The hub reuses the shared portal browser session (or bounces through the normal /login flow), evaluates ONE SubjectAccessReview against the tenant workspace, and hands the app's access proxy a one-use code. The proxy exchanges the code server-to-server and then maintains its own bounded local session; the hub is not consulted again until that session expires.
  • Non-browser clients (CLIs, CI, agents) exchange their hub bearer AT THE HUB for a short-lived app access token bound to one instance (POST /auth/apps/token) and present that to the app. The proxy asks the hub once (POST /auth/apps/verify), then caches the verdict locally for at most the session TTL. A gate never sees a hub bearer (see apptoken.go and verify.go).

Access policy is plain kcp RBAC in the tenant workspace: visiting a private app requires `get` on the instance resource with subresource `access` (e.g. `applications/my-shop` + subresource `access`). Granting a member access is creating a ClusterRole/ClusterRoleBinding pair; revoking is deleting it. The hub carries no knowledge of any provider CRD schema — only resource coordinates supplied by the (controller-authored) proxy config, validated syntactically here.

Index

Constants

View Source
const (
	// AuthorizePath is the browser-facing entry point the access proxy
	// redirects to when a private app has no session.
	AuthorizePath = "/auth/apps/authorize"
	// ExchangePath is the server-to-server endpoint the access proxy calls to
	// turn a one-use code into a session grant.
	ExchangePath = "/auth/apps/exchange"
	// TokenPath is where a caller exchanges their hub bearer for an app
	// access token bound to one instance (see HandleMintToken).
	TokenPath = "/auth/apps/token"
	// VerifyPath is the server-to-server endpoint the access proxy calls to
	// authorize a request carrying an app access token (see HandleVerify).
	VerifyPath = "/auth/apps/verify"
	// IdentityAuthorizePath starts a Railgrid Auth browser sign-in for one
	// published app instance.
	IdentityAuthorizePath = "/auth/apps/identity/authorize"
	// IdentityExchangePath exchanges a one-use app sign-in code for a short-
	// lived Railgrid Auth assertion.
	IdentityExchangePath = "/auth/apps/identity/exchange"
	// IdentityJWKSPath publishes the signing key used by Railgrid Auth
	// assertions.
	IdentityJWKSPath = "/auth/apps/identity/jwks"
	// CallbackPath is the reserved path on the app host that authorize
	// redirects back to. It must stay in lockstep with the access proxy's
	// callback route (providers/infrastructure/accessproxy).
	CallbackPath = "/__railgrid/auth/callback"
	// IdentityCallbackPath is the callback path for Railgrid Auth. It is
	// intentionally distinct from the app access-proxy callback above.
	IdentityCallbackPath = "/__railgrid/auth/identity/callback"

	// AccessSubresource is the RBAC convention gating private apps: a visitor
	// needs `get` on `<resource>/<name>` with this subresource in the tenant
	// workspace. The subresource is never served; it exists only as an
	// authorization tuple.
	AccessSubresource = "access"
	// AccessVerb is the verb checked against the access subresource.
	AccessVerb = "get"

	// IdentityPurpose separates app identity codes from private-app access
	// codes in the shared, atomic CodeStore.
	IdentityPurpose = "app-identity"
)
View Source
const (
	// AppTokenPrefix marks an app access token. The access proxy mirrors it
	// (providers/infrastructure/accessproxy) and refuses to relay anything
	// else, so a raw hub token presented at a gate never leaves that gate.
	AppTokenPrefix = "fapp_"
)
View Source
const (
	// IdentityIssuerPath is the stable issuer URL suffix for Railgrid Auth.
	IdentityIssuerPath = "/auth/apps/identity"
)
View Source
const PreviewHandoffPath = "/auth/apps/preview-handoff"

PreviewHandoffPath exchanges a scoped workload credential for one-app browser access.

Variables

View Source
var ErrInstanceNotPublished = errors.New("instance has no published host")

ErrInstanceNotPublished is returned by an InstanceHostResolver when the referenced instance has no published host to pin the redirect against.

View Source
var ErrInvalidPreviewIdentity = errors.New("invalid preview identity")

ErrInvalidPreviewIdentity marks a caller credential that was absent, malformed, unauthenticated, or resolved to an identity outside the requested workspace service-account contract. Other resolver errors represent an identity-verification dependency failure and must not be charged as a bad credential.

Functions

func DeriveIdentitySubjectKey added in v0.2.21

func DeriveIdentitySubjectKey(sharedSecret []byte) ([]byte, error)

DeriveIdentitySubjectKey derives a test or externally managed stable app-subject key. Production uses the separately persisted pseudonym key in serviceaccounts.AppIdentityKeyRing.

func NewKCPPreviewIdentityResolver added in v0.2.14

func NewKCPPreviewIdentityResolver(config *rest.Config) func(*http.Request, InstanceRef) (browsersession.Identity, error)

NewKCPPreviewIdentityResolver authenticates in the requested workspace. A provider account from another cluster must never become a tenant-local SA merely because both accounts have the same username.

func NormalizeIdentityIssuer added in v0.2.21

func NormalizeIdentityIssuer(hubURL string) (string, error)

NormalizeIdentityIssuer converts a public hub origin into the canonical HTTPS issuer used by application assertions. It does not alter other hub URL consumers or allow identity assertions over HTTP.

func SetupAppAccessGrantMigrationWithManager added in v0.2.21

func SetupAppAccessGrantMigrationWithManager(sourceManager mcmanager.Manager, leaderCtx context.Context, kcpConfig *rest.Config, scheme *runtime.Scheme, handler *AppAccessGrantHandler) error

SetupAppAccessGrantMigrationWithManager registers the leader-scoped source controller that discovers platform and organization-owned Infrastructure exports from their CatalogEntries. sourceManager must watch the providers.railgrid.ai APIExport. The per-export Instance managers are derived only from verified provider workspaces and endpoint slices; their startup informer lists replay existing Instances after a leader restart.

leaderCtx owns every child manager. The shutdown runnable cancels and drains those managers before the source manager returns, so no migration writer outlives the hub's leader term.

Types

type AppAccessGrant added in v0.2.21

type AppAccessGrant struct {
	Name        string `json:"name"`
	UID         string `json:"uid,omitempty"`
	User        string `json:"user"`
	Publication string `json:"publication"`
	Revoked     bool   `json:"revoked"`
	Phase       string `json:"phase"`
	// MigrationPending is a read-only hint that the hub migration controller
	// has not yet upgraded this grant's RBAC metadata.
	MigrationPending bool `json:"migrationPending,omitempty"`
}

AppAccessGrant is the small, portal-facing view returned by the hub broker. It represents one named ClusterRoleBinding and carries no RBAC policy input.

type AppAccessGrantHandler added in v0.2.21

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

AppAccessGrantHandler owns the narrow RBAC broker used by App Studio.

func NewAppAccessGrantHandler added in v0.2.21

func NewAppAccessGrantHandler(cfg AppAccessGrantHandlerConfig) (*AppAccessGrantHandler, error)

NewAppAccessGrantHandler validates the broker dependencies.

func NewKCPAppAccessGrantHandler added in v0.2.21

func NewKCPAppAccessGrantHandler(kcpConfig *rest.Config, cfg AppAccessGrantHandlerConfig) (*AppAccessGrantHandler, error)

NewKCPAppAccessGrantHandler creates the per-tenant dynamic client factory from the hub's kcp admin configuration.

func (*AppAccessGrantHandler) Handle added in v0.2.21

Handle performs one fixed list/create/revoke/reset operation after checking the exact action proof, Project ownership and human SARs.

func (*AppAccessGrantHandler) Register added in v0.2.21

func (h *AppAccessGrantHandler) Register(router *mux.Router)

Register mounts the sole POST endpoint on the hub-access and tenant-scoped router.

type AppAccessGrantHandlerConfig added in v0.2.21

type AppAccessGrantHandlerConfig struct {
	Clients          AppAccessWorkspaceClientFactory
	SARClient        SARFactory
	IdentityApp      IdentityAppResolver
	WorkspaceCluster IdentityWorkspaceCluster
	AccountLookup    IdentityAccountLookup
	Memberships      tenant.MembershipLookup
}

AppAccessGrantHandlerConfig assembles the hub-owned app-access broker. The handler accepts only the fixed Infrastructure Instance tuple and writes source-specific UID-fenced primary grants.

type AppAccessWorkspaceClientFactory added in v0.2.21

type AppAccessWorkspaceClientFactory func(clusterID string) (dynamic.Interface, error)

AppAccessWorkspaceClientFactory resolves the tenant logical cluster named by the authenticated hub context.

type CodeRecord

type CodeRecord struct {
	Purpose        string
	Ref            InstanceRef
	RedirectHost   string
	RedirectOrigin string
	AppID          string
	Environment    string
	InstanceUID    string
	CodeChallenge  string
	Identity       browsersession.Identity
	ExpiresAt      time.Time
}

CodeRecord is what authorize binds a code to and exchange verifies against. It carries identity metadata only — never a credential.

type CodeStore

type CodeStore interface {
	Put(ctx context.Context, code string, record CodeRecord) error
	// Peek reads a record without consuming it. Implementations return an error
	// when the backing store is unavailable, false when the code is absent or
	// expired, and the record otherwise.
	Peek(ctx context.Context, code string) (CodeRecord, bool, error)
	Take(ctx context.Context, code string) (CodeRecord, bool)
}

CodeStore persists one-use authorization codes between the browser's authorize hop and the access proxy's server-to-server exchange.

Take MUST be atomic across every hub replica: a code that two callers can redeem is a replayable app sign-in.

type Config

type Config struct {
	// PreviewIdentity verifies a workspace service account for a scoped preview.
	// It should return ErrInvalidPreviewIdentity only for caller credential or
	// identity rejection; other errors are treated as transient dependencies.
	PreviewIdentity func(*http.Request, InstanceRef) (browsersession.Identity, error)
	// Sessions is the shared hub browser-session store (portal SSO).
	Sessions *browsersession.Store
	// PreviewSessions stores short-lived one-app browser sessions separately
	// from portal sessions. A separate backend is required for mixed-version
	// hubs because older replicas ignore unknown scoped identity fields.
	PreviewSessions *browsersession.Store
	// SARClient resolves per-workspace SubjectAccessReview clients.
	SARClient SARFactory
	// InstanceHost resolves the published host of the instance a sign-in is
	// for. Redirects are only issued to exactly that host.
	InstanceHost InstanceHostResolver
	// IdentityApp resolves the generic Railgrid Auth descriptor for an
	// instance. Nil leaves the identity flow unregistered.
	IdentityApp IdentityAppResolver
	// IdentityAccountLookup revalidates the platform User record captured by
	// the browser session before issuing or exchanging a Railgrid Auth code.
	// It is required whenever the identity flow is configured.
	IdentityAccountLookup IdentityAccountLookup
	// IdentityWorkspaceMember is required for non-production app sign-ins;
	// production sign-ins are governed by the instance access SAR.
	IdentityWorkspaceMember IdentityWorkspaceMember
	// Codes persists the one-use authorization codes. It defaults to a
	// bounded process-local map, which is only correct for a single hub
	// replica: authorize and exchange are separate requests and a scaled hub
	// serves them from different pods. Supply a shared store (see
	// pkg/hub/sharedstore) whenever the hub runs more than one replica.
	Codes CodeStore
	// PreviewCodes stores scoped handoff and final app-authorization codes in
	// an isolated collection. Ordinary Codes must never be used as a fallback.
	PreviewCodes CodeStore
	// LoginPath is the hub-relative path of the interactive login page an
	// unauthenticated browser is sent to. Defaults to "/ui/login" (the
	// portal SPA is mounted under /ui/).
	LoginPath string
	// BearerIdentity authenticates the Authorization bearer on a request and
	// resolves it to the platform identity. It MUST be the same validator the
	// hub uses to mint browser sessions from a bearer (KCPProxy.BrowserIdentity),
	// so the token endpoint admits exactly the identities the browser flow
	// admits. Nil leaves the token endpoint unregistered.
	BearerIdentity func(*http.Request) (browsersession.Identity, error)
	// TokenKey returns the hub secret (>= 32 bytes, identical on every
	// replica) that app access tokens are HKDF-derived from. Nil leaves both
	// the token and verify endpoints unregistered.
	TokenKey func(context.Context) ([]byte, error)
	// IdentityUnavailable is the sentinel BearerIdentity wraps when the
	// credential was accepted but the identity could not be resolved (a
	// transient hub-side failure). Such errors answer 503 and are not counted
	// as failed verifications. Nil treats every BearerIdentity error as an
	// invalid credential.
	IdentityUnavailable error
	// IdentityIssuer is the absolute issuer URL for Railgrid Auth assertions.
	// NormalizeIdentityIssuer derives it from the public HTTPS hub origin.
	IdentityIssuer string
	// IdentityKeys returns a coherent signing, subject and public-key snapshot.
	// Production uses this instead of the individual callbacks below, so a
	// rotation cannot split a single response across two Secret versions.
	IdentityKeys func(context.Context) (IdentityKeySnapshot, error)
	// IdentitySigningKey returns the current Ed25519 private signing key.
	// The matching public key is exposed by IdentityJWKSPath.
	IdentitySigningKey func(context.Context) (ed25519.PrivateKey, error)
	// IdentityPublicKeys returns the current public key and any still-valid
	// previous public keys. Keeping previous keys available for one assertion
	// lifetime lets app sessions survive an explicit signing-key rotation.
	IdentityPublicKeys func(context.Context) ([]ed25519.PublicKey, error)
	// IdentitySubjectKey returns a purpose-separated secret used to derive
	// stable, opaque app subjects. Keep this key stable across signing-key
	// rotations.
	IdentitySubjectKey func(context.Context) ([]byte, error)
	// ClientIP keys the failed-verification limiter. It should see through
	// the hub's trusted reverse proxies (proxy.ClientIP). Nil uses the
	// connection peer address.
	ClientIP func(*http.Request) string
	// Now and Random are test seams.
	Now    func() time.Time
	Random io.Reader
}

Config assembles a Handler.

type ExchangeResponse

type ExchangeResponse struct {
	Allowed           bool   `json:"allowed"`
	UserID            string `json:"userId"`
	Email             string `json:"email,omitempty"`
	Name              string `json:"name,omitempty"`
	SessionTTLSeconds int64  `json:"sessionTtlSeconds"`
}

ExchangeResponse is returned to the proxy on a successful exchange. It contains identity metadata only — never a credential of any kind.

type Handler

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

Handler serves the authorize, exchange and verify endpoints.

func New

func New(cfg Config) (*Handler, error)

New validates cfg and returns a Handler.

func (*Handler) HandleAuthorize

func (h *Handler) HandleAuthorize(w http.ResponseWriter, r *http.Request)

HandleAuthorize is the browser entry point.

GET /auth/apps/authorize?cluster=&group=&resource=&name=&redirect_uri=&state=

func (*Handler) HandleExchange

func (h *Handler) HandleExchange(w http.ResponseWriter, r *http.Request)

HandleExchange consumes a one-use code.

POST /auth/apps/exchange  {"code":..., "host":..., "cluster":..., ...}

func (*Handler) HandleIdentityAuthorize added in v0.2.21

func (h *Handler) HandleIdentityAuthorize(w http.ResponseWriter, r *http.Request)

func (*Handler) HandleIdentityExchange added in v0.2.21

func (h *Handler) HandleIdentityExchange(w http.ResponseWriter, r *http.Request)

func (*Handler) HandleIdentityJWKS added in v0.2.21

func (h *Handler) HandleIdentityJWKS(w http.ResponseWriter, r *http.Request)

func (*Handler) HandleMintToken

func (h *Handler) HandleMintToken(w http.ResponseWriter, r *http.Request)

HandleMintToken exchanges the caller's hub bearer for an app access token.

POST /auth/apps/token
Authorization: Bearer <hub token>
{"cluster":..., "group":..., "resource":..., "name":..., "ttlSeconds":600}

The caller is authenticated with the same validator that mints browser sessions from a bearer (Config.BearerIdentity) and must pass the same SubjectAccessReview as a browser sign-in. Answers 200 MintResponse, 400 malformed, 401 not a hub user credential, 403 no access grant, 404 instance not published, 429 source over its failure budget, 503 dependency outage.

func (*Handler) HandlePreviewHandoff added in v0.2.14

func (h *Handler) HandlePreviewHandoff(w http.ResponseWriter, r *http.Request)

HandlePreviewHandoff issues a short-lived, one-app browser capability. It never creates a portal session or accepts an asserted end-user identity. Existing name-scoped instances/proxy rights authorize the same app here.

func (*Handler) HandleVerify

func (h *Handler) HandleVerify(w http.ResponseWriter, r *http.Request)

HandleVerify authorizes a non-browser request at a private app's gate.

POST /auth/apps/verify
Authorization: Bearer <app access token>
{"cluster":..., "group":..., "resource":..., "name":...}

Only app access tokens minted by HandleMintToken are accepted — never a hub bearer, which a gate must not be trusted with. The token must be bound to exactly the instance the gate names and unexpired, and the SubjectAccessReview is re-run so a revoked grant stops working within the gate's cache window. Answers 200 VerifyResponse, 400 malformed, 401 not a valid token for this instance, 403 no access grant, 429 source over its failure budget, 503 dependency outage.

Like HandleExchange this endpoint does not authenticate the calling gate — gates hold no credentials by design. It is safe to expose because the request is self-authenticating: nothing is disclosed unless the caller holds a valid app token, and then only the token's own user ID and its yes/no.

func (*Handler) RegisterRoutes

func (h *Handler) RegisterRoutes(router *mux.Router, limit func(http.HandlerFunc) http.HandlerFunc)

RegisterRoutes mounts the endpoints. limit wraps each handler with the hub's auth rate limiter; pass nil to mount unwrapped (tests).

type IdentityAccount added in v0.2.21

type IdentityAccount struct {
	User         string
	Email        string
	RBACIdentity string
	Deleted      bool
}

IdentityAccount is the minimal existing platform-user data needed to write a workspace-local app-access binding. Email and the User CR itself never leave the resolver.

type IdentityAccountLookup added in v0.2.21

type IdentityAccountLookup func(context.Context, string) (IdentityAccount, error)

IdentityAccountLookup performs a direct lookup by stable User CR name. It must not list users, create users, or resolve arbitrary identifiers.

type IdentityApp added in v0.2.21

type IdentityApp struct {
	InstanceUID     string
	AppID           string
	Environment     string
	PublishedOrigin string
	Enabled         bool
}

IdentityApp describes the generic instance metadata needed for Railgrid Auth. It deliberately contains no provider-specific API types.

type IdentityAppResolver added in v0.2.21

type IdentityAppResolver func(ctx context.Context, ref InstanceRef) (IdentityApp, error)

IdentityAppResolver reads the identity-auth descriptor and published origin for an instance. Implementations should return ErrInstanceNotPublished for absent instances and fail closed for malformed or unavailable metadata.

func NewKCPIdentityAppResolver added in v0.2.21

func NewKCPIdentityAppResolver(kcpConfig *rest.Config) (IdentityAppResolver, error)

NewKCPIdentityAppResolver returns a generic descriptor resolver for Railgrid Auth. It reads only unstructured instance metadata, so appauth does not depend on the Infrastructure or App Studio API packages.

The app audience is derived from a live App Studio Project and its matching spec environment binding. The Instance's mutable Railgrid Auth values must match that descriptor, and its UID and published origin are checked again when the one-use code is exchanged.

type IdentityExchangeResponse added in v0.2.21

type IdentityExchangeResponse struct {
	Assertion string              `json:"assertion"`
	ExpiresIn int64               `json:"expiresIn"`
	User      IdentityUserProfile `json:"user"`
}

IdentityExchangeResponse contains the signed assertion and the small display profile needed to establish an app-local session. No hub bearer, provider credential, RBAC identity, or platform User ID leaves the hub.

type IdentityKeySnapshot added in v0.2.21

type IdentityKeySnapshot struct {
	SigningKey ed25519.PrivateKey
	SubjectKey []byte
	PublicKeys []ed25519.PublicKey
}

IdentityKeySnapshot contains keys from one persisted key-ring version. PublicKeys starts with the public key matching SigningKey.

type IdentityUserLookupConfig added in v0.2.21

type IdentityUserLookupConfig struct {
	SARClient        SARFactory
	IdentityApp      IdentityAppResolver
	WorkspaceCluster IdentityWorkspaceCluster
	AccountLookup    IdentityAccountLookup
}

IdentityUserLookupConfig assembles the narrow app-grant account resolver.

type IdentityUserLookupHandler added in v0.2.21

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

IdentityUserLookupHandler returns an existing account's workspace RBAC identity only after an App Studio authentication-grant proof, an accepted hub-access capability, and a human SAR update on the exact enabled app instance.

func NewIdentityUserLookupHandler added in v0.2.21

func NewIdentityUserLookupHandler(cfg IdentityUserLookupConfig) (*IdentityUserLookupHandler, error)

NewIdentityUserLookupHandler validates the dependencies for this one route. The route is mounted separately under the hub-access and tenant middlewares, so callers must register it only on that protected router.

func (*IdentityUserLookupHandler) Handle added in v0.2.21

Handle resolves one existing User CR for an enabled production app. The action proof binds {user,appId}; this request adds the exact Infrastructure Instance coordinates that must pass a human update SAR.

func (*IdentityUserLookupHandler) Register added in v0.2.21

func (h *IdentityUserLookupHandler) Register(router *mux.Router)

Register mounts the account resolver on a /api/orgs subrouter that has both hubaccess.Gate and tenant.Middleware installed.

type IdentityUserProfile added in v0.2.21

type IdentityUserProfile struct {
	Name string `json:"name,omitempty"`
}

IdentityUserProfile is the signed-in user's app-facing display profile.

type IdentityWorkspaceCluster added in v0.2.21

type IdentityWorkspaceCluster func(context.Context, string, string) (string, error)

IdentityWorkspaceCluster resolves an org/workspace UUID pair to its kcp logical-cluster ID after the caller has been admitted by tenant middleware.

type IdentityWorkspaceMember added in v0.2.21

type IdentityWorkspaceMember func(ctx context.Context, identity browsersession.Identity, ref InstanceRef) (bool, error)

IdentityWorkspaceMember reports whether the signed-in account is a member of the workspace that owns ref. Development app environments require this additional check so a stale explicit app grant cannot make a preview available to an outside account.

func NewKCPIdentityWorkspaceMemberResolver added in v0.2.21

func NewKCPIdentityWorkspaceMemberResolver(kcpConfig *rest.Config, memberships tenant.MembershipLookup) (IdentityWorkspaceMember, error)

NewKCPIdentityWorkspaceMemberResolver builds the development-environment membership check. It resolves the tenant path from the workspace's logical cluster and checks the hub's UserMembershipIndex, including the existing rule that an organization admin is an implicit workspace admin.

type InstanceHostResolver

type InstanceHostResolver func(ctx context.Context, ref InstanceRef) (string, error)

InstanceHostResolver reports the public host a published instance is served on — the FQDN the provider deployment stamped onto the instance itself. Redirects are pinned to exactly this host, which is what lets published apps live under ANY zone (platform, BYO edge, or a customer-owned domain) without the hub keeping a domain registry: the instance is the single source of truth for where its traffic terminates.

ErrInstanceNotPublished means the instance exists but exposes no host (or does not exist); anything else is an infrastructure failure and fails the authorize closed with a retryable error page.

func NewKCPInstanceHostResolver

func NewKCPInstanceHostResolver(kcpConfig *rest.Config) (InstanceHostResolver, error)

NewKCPInstanceHostResolver returns an InstanceHostResolver that reads the referenced instance in its tenant workspace through the hub's admin kcp config and reports the host the provider stamped onto it.

The host is taken from spec.values.expose.fqdn — the field the instance controller stamps on every exposed instance, i.e. on exactly the set of instances whose access gate can ever start this flow — falling back to status.host for resources that mirror it there instead. A missing object and a missing host are deliberately the same ErrInstanceNotPublished: authorize has already SAR-checked the caller against these coordinates, and collapsing the two keeps the error page from confirming which one it was.

The instance's group version is discovered per call (one GET of /apis/<group> before the instance read). Sign-ins are per-user-per-app-session rare and already cost a SubjectAccessReview, so two extra reads beat carrying a discovery cache that can go stale across provider upgrades.

type InstanceRef

type InstanceRef struct {
	Cluster  string // logical cluster ID of the tenant workspace
	Group    string // API group of the instance CRD
	Resource string // REST plural of the instance CRD
	Name     string // instance name
}

InstanceRef are the resource coordinates of a published template instance. They are authorization inputs only; the hub never reads the object.

type MintRequest

type MintRequest struct {
	Cluster    string `json:"cluster"`
	Group      string `json:"group"`
	Resource   string `json:"resource"`
	Name       string `json:"name"`
	TTLSeconds int64  `json:"ttlSeconds,omitempty"`
}

MintRequest is the body of POST /auth/apps/token: the published instance to mint an app access token for, in the same coordinates the access gate uses (they appear in the query of the gate's sign-in redirect and in its 401 body). TTLSeconds is optional: 0 means the default (600), otherwise 60..900.

type MintResponse

type MintResponse struct {
	Token     string    `json:"token"`
	ExpiresAt time.Time `json:"expiresAt"`
	Host      string    `json:"host"`
}

MintResponse is the body of a successful mint. Token is sent to the app as `Authorization: Bearer <token>`; Host is the instance's published host.

type SARFactory

type SARFactory func(clusterID string) (authorizationv1client.SubjectAccessReviewInterface, error)

SARFactory returns a SubjectAccessReview client scoped to one logical cluster. The hub wires this from its kcp admin config; tests use fakes.

type VerifyResponse

type VerifyResponse struct {
	Allowed           bool   `json:"allowed"`
	UserID            string `json:"userId"`
	SessionTTLSeconds int64  `json:"sessionTtlSeconds"`
}

VerifyResponse is returned to the gate on an allowed verify.

Jump to

Keyboard shortcuts

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