Documentation
¶
Overview ¶
Package hub implements the railgrid hub server.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrAnonymousProviderCaller = errors.New("anonymous caller")
ErrAnonymousProviderCaller is returned by the tenant resolver when the caller carries no bearer token. The backend proxy treats this as a non-error "forward without identity headers" so unauthenticated probes (health checks, smoke tests) work without provider auth.
Functions ¶
func NewScheme ¶
NewScheme builds a runtime.Scheme containing all types needed by the multicluster manager: core k8s types, railgrid CRDs, tenancy CRDs, and the kcp SDK types required by multicluster-provider internals.
func WithPortalSecurityHeaders ¶
WithPortalSecurityHeaders wraps a portal handler to set the portal's Content-Security-Policy and related headers.
Provider micro-frontends are not iframes. The portal loads each provider's /ui/providers/{name}/main.js (hub-proxied, so same-origin) as a classic script and mounts the custom element it registers directly in the portal document. A provider bundle therefore executes as fully trusted code in the host document; `script-src 'self'` admits it because it is same-origin, and the portal pins it with the Subresource Integrity hash the hub computed at registration (CatalogEntry status.ui.mainJSIntegrity). There is no 'unsafe-inline' for scripts: the portal ships no inline script (the theme pre-paint bootstrap is a static file), so an injected inline handler or <script> is refused by the browser.
frame-src still lists 'self' plus optional platform-owned sources (App Studio preview hosts): those are the portal's own iframes, not provider bundles.
Applied to both the embedded portal SPA and the --portal-dev-url proxy so the dev experience matches production.
Types ¶
type Options ¶
type Options struct {
DataDir string
ListenAddr string
Kubeconfig string
ExternalKCPKubeconfig string
IDPIssuerURL string
// IDPBrowserAuthURL optionally overrides only the OIDC authorization
// endpoint placed in browser redirects. Discovery, token exchange, JWKS,
// and issuer validation continue to use IDPIssuerURL.
IDPBrowserAuthURL string
IDPClientID string
// DisableTokenLogin removes the interactive static-token login: the
// /auth/token-login endpoint is not registered and /healthz advertises
// tokenLogin=false so the portal hides its token form. Static bearer
// tokens keep authenticating API/MCP/CLI calls — only the browser login
// path is disabled. Use with OIDC so humans sign in with a username and
// password at the IdP.
DisableTokenLogin bool
// PublishedAppsDomain is deprecated and ignored. The published-app
// authorize/exchange endpoints are always mounted, and sign-in redirects
// are pinned per request to the host stamped on the instance being
// authorized — so apps under BYO provider zones and customer-owned
// domains need no hub-side domain configuration. The flag is kept only
// so existing deployments that pass it keep starting.
PublishedAppsDomain string
// IDPCAFile is a path to a PEM-encoded CA bundle used to verify the IdP's
// TLS certificate. Required when IDPIssuerURL is https and uses a cert
// not signed by a system trust anchor (e.g. the dev Dex deployment).
IDPCAFile string
ServingCertFile string
ServingKeyFile string
HubExternalURL string
// HubInternalURL, when set, is the address in-cluster components use to
// reach this hub instead of HubExternalURL. It is baked into minted provider
// kubeconfigs and offered as the "internal" option by the admin kubeconfig
// download.
//
// Without it, a provider pod's calls to the hub resolve the public hostname,
// leave the cluster, and re-enter through whatever fronts it (CDN, tunnel,
// load balancer) — for a provider running beside the hub that is a pointless
// round trip that also makes the whole platform look like one noisy client
// IP to the edge.
//
// Typically the hub's in-cluster Service
// (https://<release>-railgrid-hub.<namespace>.svc.cluster.local:9443). Also
// useful when provider pods reach the hub at a different address than
// browsers do — e.g. a kind pod dialing https://host.docker.internal:9443
// while browsers use https://localhost:9443. Leave empty when providers run
// outside the cluster.
HubInternalURL string
DevMode bool
StaticAuthTokens []string
// TrustedProxyCIDRs lists the address ranges of the reverse proxies that
// front this hub (ingress controller, load balancer, CDN egress). The
// pre-authentication rate limiters (token-login, /auth/refresh, the
// published-app code exchange, the aggregate MCP bearer check) key their
// buckets on the client address, and a proxy's X-Forwarded-For is only
// believed when the connection peer is inside one of these ranges — see
// proxy.ClientIP for the exact rule.
//
// Empty (the default) means proxy headers are ignored and every request is
// keyed on its connection peer. A hub deployed behind a proxy without this
// set therefore sees all of its clients as the proxy's own address and
// throttles them as one; that is the safe failure, so set it. Never widen
// it to ranges clients can connect from: any peer inside it can pick its
// own bucket by sending X-Forwarded-For.
TrustedProxyCIDRs []string
// ProviderDelegatedTokens selects which providers receive a short-lived,
// workspace-scoped ServiceAccount token in place of the caller's own hub
// bearer on the backend proxy (/services/providers/{name}/*). Org-owned
// providers always receive the delegated token regardless of this
// setting; it governs platform providers only:
//
// off — platform providers receive the caller's bearer as-is
// (the historical behaviour).
// platform — platform providers receive the delegated token, except
// the names in ProviderDelegatedTokensExclude.
// all — every platform provider receives the delegated token;
// the exclusion list is ignored.
//
// Default "off" for this release. The next release defaults to
// "platform"; deployments should run "platform" ahead of that to
// confirm their providers need nothing beyond /clusters/{id} access.
ProviderDelegatedTokens string
// ProviderDelegatedTokensExclude names platform providers that keep
// receiving the caller's bearer under ProviderDelegatedTokens=platform.
// Defaults to providers.DefaultDelegationExclude.
ProviderDelegatedTokensExclude []string
// ProviderHubAccessPlatformDefault lets a platform provider use the hub
// capabilities it declares (CatalogEntry.spec.hubAccess) in a workspace
// where no tenant decision was recorded yet. Platform providers are
// operator-installed and, under ProviderDelegatedTokens=off, hold the
// caller's own bearer anyway; this keeps them working across the upgrade
// to the hub-access contract. An explicit decision (Enable with or
// without accepting) always wins, and org-owned providers always need
// one. Set false to require acceptance for every provider.
ProviderHubAccessPlatformDefault bool
// AdminUsers is the allowlist of platform-admin identities permitted to
// reach the /api/admin/* surface and the portal's /bonkers area. Each entry
// matches a User CR by name, email, or rbacIdentity (case-insensitive).
// Empty disables the admin surface entirely.
AdminUsers []string
// Providers is the list of first-party builtin providers to materialize
// into root:railgrid:providers at bootstrap. The flag accepts a comma-
// separated list or repeats; see cmd/railgrid-hub/main.go for the default.
// Empty/nil enables every known builtin (kcp.BuiltinProviderNames()).
// Dependencies between builtins are validated at hub startup — see
// pkg/hub/kcp.builtinEntries[].Requires.
Providers []string
// ProviderHeartbeatAuth is what the hub does with a provider heartbeat
// whose bearer token does not verify as that provider's own service
// account: "warn" logs and records the beat, "enforce" rejects it. The
// default is "warn" for this release so providers installed from charts
// that predate the authenticated heartbeat keep reporting alive while
// they are rolled forward; the next release flips the default to
// "enforce". See providers.HeartbeatAuthMode.
ProviderHeartbeatAuth string
// ProviderWorkspaceClusterAdmin selects the role the provider ServiceAccount
// is bound to inside its own provider workspace: true (the default this
// release) keeps cluster-admin, false binds the generated, narrower
// railgrid:provider ClusterRole.
//
// The default is the wide one for one release so an operator can stage the
// change — flip it, watch their providers, flip back if one of them needed
// a right the narrow role does not grant (the infrastructure provider, which
// serves its own CRDs from this workspace, is the known case). The NEXT
// release defaults this to false. Flipping either way replaces the existing
// binding: RoleRef is immutable, so the hub deletes and recreates it.
ProviderWorkspaceClusterAdmin bool
// PortalDevURL, when set, reverse-proxies /ui/* to this URL (typically
// a Vite dev server, e.g. http://localhost:3000). Takes precedence over the
// embedded portal dist (if built with -tags portal_embed).
PortalDevURL string
// PortalFrameSources are additional CSP frame-src source expressions allowed
// by the portal. Keep this narrow; provider UIs are still same-origin through
// the hub, while platform-owned preview hosts can be added explicitly.
PortalFrameSources []string
// Embedded kcp options
EmbeddedKCP bool // Enable embedded kcp server
KCPRootDir string // Root directory for kcp data (default: <DataDir>/kcp)
KCPSecurePort int // Secure port for kcp API server (default: 6443)
KCPBindAddress string // Bind address for kcp API server (default: "127.0.0.1")
KCPBatteriesInclude string // Comma-separated list of batteries to include (default: "admin,user")
KCPTLSCertFile string // TLS certificate file for kcp API server
KCPTLSKeyFile string // TLS key file for kcp API server
// KCPShardExternalURL is the URL kcp publishes into APIExportEndpointSlice
// and CachedResourceEndpointSlice statuses for outside consumers to dial.
// Empty defaults to kcp's auto-detected external address, which for an
// embedded kcp bound to 127.0.0.1 is "https://127.0.0.1:6443" — fine for
// host-side clients, broken for clients running in a kind pod (they
// resolve 127.0.0.1 to the pod itself). Override with e.g.
// "https://host.docker.internal:6443" for kind-based dev setups.
KCPShardExternalURL string
// KCPShardVirtualWorkspaceURL must be set alongside KCPShardExternalURL.
// The two URLs cover different slots in Shard.spec — externalURL feeds
// generic outside-clients discovery, virtualWorkspaceURL is what
// APIExportEndpointSlice / CachedResourceEndpointSlice publish in their
// status.endpoints[]. For a single-shard embedded dev setup both want
// the same value.
KCPShardVirtualWorkspaceURL string
}
Options holds configuration for the hub server.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package admin implements the platform-admin surface mounted at /api/admin/* and surfaced in the portal's gated /bonkers area.
|
Package admin implements the platform-admin surface mounted at /api/admin/* and surfaced in the portal's gated /bonkers area. |
|
Package appauth is the hub's login-time authorization endpoint for published applications.
|
Package appauth is the hub's login-time authorization endpoint for published applications. |
|
Package bootstrap embeds bootstrap resources for hub initialization.
|
Package bootstrap embeds bootstrap resources for hub initialization. |
|
controllers
|
|
|
mcpserver
Package mcpserver reconciles MCPServer objects.
|
Package mcpserver reconciles MCPServer objects. |
|
membershipindex
Package membershipindex implements the UMI invariant reconciler: a controller that watches UserMembershipIndex CRs in root:railgrid:users and repairs rows that strand a user.
|
Package membershipindex implements the UMI invariant reconciler: a controller that watches UserMembershipIndex CRs in root:railgrid:users and repairs rows that strand a user. |
|
organization
Package organization implements the bootstrap controller that gives every User a personal Organization on creation (per docs/organizations.md §Personal Org).
|
Package organization implements the bootstrap controller that gives every User a personal Organization on creation (per docs/organizations.md §Personal Org). |
|
softdelete
Package softdelete implements roadmap step 8: the soft-delete reconciler that honours the 30-day grace window from docs/organizations.md decisions O-8 (User delete) and O-13 (Org + Workspace delete).
|
Package softdelete implements roadmap step 8: the soft-delete reconciler that honours the 30-day grace window from docs/organizations.md decisions O-8 (User delete) and O-13 (Org + Workspace delete). |
|
Package hubaccess implements the hub-access half of the provider contract: the hub REST capabilities a provider may exercise with the delegated user token the hub hands it in place of the caller's bearer.
|
Package hubaccess implements the hub-access half of the provider contract: the hub REST capabilities a provider may exercise with the delegated user token the hub hands it in place of the caller's bearer. |
|
Package kcp bootstraps kcp API resources.
|
Package kcp bootstraps kcp API resources. |
|
Package leaderelection gates the hub's singleton controllers so a hub scaled to multiple replicas still reconciles each object exactly once.
|
Package leaderelection gates the hub's singleton controllers so a hub scaled to multiple replicas still reconciles each object exactly once. |
|
Package mcpaggregate serves the hub's always-on aggregate MCP endpoint.
|
Package mcpaggregate serves the hub's always-on aggregate MCP endpoint. |
|
Package providers backs the hub's pluggable-provider extension surface: an in-memory routing table, reverse proxies for /ui/providers/{name}/* and /services/providers/{name}/*, and the controller that keeps the table in sync with ProviderCatalogEntry resources.
|
Package providers backs the hub's pluggable-provider extension surface: an in-memory routing table, reverse proxies for /ui/providers/{name}/* and /services/providers/{name}/*, and the controller that keeps the table in sync with ProviderCatalogEntry resources. |
|
Package quota implements the quota checks pinned by decisions O-5 (Org quota = soft cap, admin-overridable per User; default 10) and O-6 (Workspace quota = soft cap, admin-overridable per Org; default 50) in docs/organizations.md.
|
Package quota implements the quota checks pinned by decisions O-5 (Org quota = soft cap, admin-overridable per User; default 10) and O-6 (Workspace quota = soft cap, admin-overridable per Org; default 50) in docs/organizations.md. |
|
Package restapi implements roadmap step 10: the hub-mediated REST surface for Org / Workspace / Membership / User CRUD per docs/organizations.md decision O-10 ("Org workspaces are hub-mediated only"), plus the undelete actions wired to PR #212's soft-delete reconciler, the self-leave / role PATCH from O-12, and the ?cascade=true shortcut from O-9.
|
Package restapi implements roadmap step 10: the hub-mediated REST surface for Org / Workspace / Membership / User CRUD per docs/organizations.md decision O-10 ("Org workspaces are hub-mediated only"), plus the undelete actions wired to PR #212's soft-delete reconciler, the self-leave / role PATCH from O-12, and the ?cascade=true shortcut from O-9. |
|
Package serviceaccounts implements roadmap step 9 (O-14): bot identity for child Workspaces via native kube `core/v1.ServiceAccount`s marked with railgrid annotations.
|
Package serviceaccounts implements roadmap step 9 (O-14): bot identity for child Workspaces via native kube `core/v1.ServiceAccount`s marked with railgrid annotations. |
|
Package sharedstore is the hub's cross-replica key/value store for short-lived login state: browser sessions and published-app authorization codes.
|
Package sharedstore is the hub's cross-replica key/value store for short-lived login state: browser sessions and published-app authorization codes. |
|
Package tenant implements the hub-side tenant middleware described in docs/organizations.md §Switch the active context.
|
Package tenant implements the hub-side tenant middleware described in docs/organizations.md §Switch the active context. |
|
Package workloadidentity owns the production provider-action workload capability exchange.
|
Package workloadidentity owns the production provider-action workload capability exchange. |