Documentation
¶
Overview ¶
Package admin implements the platform-admin surface mounted at /api/admin/* and surfaced in the portal's gated /bonkers area. It lets a platform admin see all users / organizations / providers / root identities. It is read-only: provider provisioning (workspace + ServiceAccount + kubeconfig) is driven declaratively by the Provider CR reconciler (pkg/hub/providers/provider_controller.go), not by an admin HTTP action.
Index ¶
- Variables
- func Middleware(resolver UserResolver, checker AdminChecker) func(http.Handler) http.Handler
- func UserFromContext(ctx context.Context) string
- type AdminChecker
- type AdminCheckerFunc
- type Handler
- func (h *Handler) GracePeriod() time.Duration
- func (h *Handler) Register(r *mux.Router)
- func (h *Handler) WithArchivedPlanLookup(archived func(ctx context.Context, name string) (bool, error)) *Handler
- func (h *Handler) WithDefaultPlanValidation(validate func(ctx context.Context) error) *Handler
- func (h *Handler) WithPlanAssignment(assign func(ctx context.Context, org, plan string) error) *Handler
- func (h *Handler) WithPlanLookup(exists func(ctx context.Context, name string) (bool, error)) *Handler
- func (h *Handler) WithPlanReset(reset func(ctx context.Context, org string) error) *Handler
- func (h *Handler) WithSoftDeleteGracePeriod(d time.Duration) *Handler
- type KubeconfigServerMode
- type OnboardedWorkspace
- type OrgWorkspace
- type Service
- func (s *Service) AvailableKubeconfigServerModes() []KubeconfigServerMode
- func (s *Service) CreateProvider(ctx context.Context, name, displayName string) error
- func (s *Service) DeleteProvider(ctx context.Context, name string) error
- func (s *Service) GetProviderKubeconfig(ctx context.Context, name string, mode KubeconfigServerMode) ([]byte, error)
- func (s *Service) ListOnboardedWorkspaces(ctx context.Context) ([]OnboardedWorkspace, error)
- func (s *Service) ListOrgWorkspaces(ctx context.Context, orgUUID string) ([]OrgWorkspace, error)
- func (s *Service) RotateProviderCredential(ctx context.Context, name string, mode KubeconfigServerMode) ([]byte, *providers.RotatedCredential, error)
- func (s *Service) UndeleteOrgWorkspace(ctx context.Context, orgUUID, wsUUID string, gracePeriod time.Duration) error
- type UserResolver
- type UserResolverFunc
- type WorkspaceProviderReference
Constants ¶
This section is empty.
Variables ¶
var ErrGracePeriodExpired = errors.New("soft-delete grace period has expired")
ErrGracePeriodExpired is returned by UndeleteOrgWorkspace when the workspace's soft-delete window has elapsed: the reconciler owns it now and a restore would race the cascade.
ErrServerModeUnavailable is returned when a caller asks for a server mode this deployment has no URL for — chiefly ServerModeInternal on a hub started without --hub-internal-url.
Functions ¶
func Middleware ¶
func Middleware(resolver UserResolver, checker AdminChecker) func(http.Handler) http.Handler
Middleware gates a subrouter so only platform admins reach it: 401 when no identity resolves, 403 when the caller is authenticated but not an admin.
func UserFromContext ¶ added in v0.2.27
UserFromContext returns the admin identity Middleware stamped on the request, or "" outside a gated request. Handlers mounted behind the middleware use it to attribute their writes in logs.
Types ¶
type AdminChecker ¶
AdminChecker decides whether a resolved caller is a platform admin. The hub supplies an implementation that matches the User CR's name / email / rbacIdentity against the --admin-users allowlist.
type AdminCheckerFunc ¶
AdminCheckerFunc adapts a function to AdminChecker.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves the /api/admin/* endpoints.
func NewHandler ¶
func NewHandler(svc *Service, userClient *railgridclient.Client, registry *providers.Registry) *Handler
NewHandler builds an admin Handler.
func (*Handler) GracePeriod ¶ added in v0.2.31
GracePeriod returns the configured recovery window, falling back to softdelete.DefaultGracePeriod.
func (*Handler) Register ¶
Register mounts the admin routes on r (already gated by the admin Middleware).
func (*Handler) WithArchivedPlanLookup ¶ added in v0.2.42
func (h *Handler) WithArchivedPlanLookup(archived func(ctx context.Context, name string) (bool, error)) *Handler
WithArchivedPlanLookup enables idempotent retries for assignments already recorded on an organization when their plan was archived in the meantime.
func (*Handler) WithDefaultPlanValidation ¶ added in v0.2.42
WithDefaultPlanValidation checks the configured default before the plan route clears Organization.spec.plan. ResetPlan repeats this check before it writes the Entitlement, so a plan archived between the two reads is not newly assigned.
func (*Handler) WithPlanAssignment ¶ added in v0.2.42
func (h *Handler) WithPlanAssignment(assign func(ctx context.Context, org, plan string) error) *Handler
WithPlanAssignment makes a nonempty organization assignment also update its Entitlement immediately. Retrying the same assignment retries this write.
func (*Handler) WithPlanLookup ¶ added in v0.2.32
func (h *Handler) WithPlanLookup(exists func(ctx context.Context, name string) (bool, error)) *Handler
WithPlanLookup enables PUT /organizations/{name}/plan with the given assignable-plan check (metering.PlanExists in production).
func (*Handler) WithPlanReset ¶ added in v0.2.34
WithPlanReset makes PUT /organizations/{name}/plan with an empty plan also reset the organization's Entitlement to the default plan (metering.ResetPlan in production), so the route returns an organization to the default plan whoever put it on its current one.
func (*Handler) WithSoftDeleteGracePeriod ¶ added in v0.2.31
WithSoftDeleteGracePeriod sets the recovery window the undelete routes enforce and the listing reports. Wire it to the value the softdelete reconciler runs with; non-positive keeps softdelete.DefaultGracePeriod.
type KubeconfigServerMode ¶
type KubeconfigServerMode string
KubeconfigServerMode selects which hub address is baked into a downloaded provider kubeconfig. The minted Secret carries exactly one server URL (the hub's --hub-internal-url when set, else --hub-external-url), but the same Secret feeds two different consumers: a provider installed by Helm into this cluster, which should stay on the in-cluster Service, and a provider run outside the cluster (another cluster, a laptop during development), which can only reach the public hostname. Whoever downloads the kubeconfig knows which one they are, so the choice is made per download rather than per deployment.
const ( // ServerModeAsMinted leaves the server URL exactly as the Provider // controller wrote it. The default, so existing callers are unaffected. ServerModeAsMinted KubeconfigServerMode = "" // ServerModeExternal rewrites the server to the hub's external URL — for // providers running outside this cluster. ServerModeExternal KubeconfigServerMode = "external" // ServerModeInternal rewrites the server to the hub-internal URL (the // in-cluster Service) — for providers installed into this cluster. Keeps // provider→hub traffic off the public path. ServerModeInternal KubeconfigServerMode = "internal" )
func ParseKubeconfigServerMode ¶
func ParseKubeconfigServerMode(v string) (KubeconfigServerMode, error)
ParseKubeconfigServerMode maps the `server` query parameter to a mode. An empty value means "as minted". Unknown values are rejected rather than silently falling back, so a typo can't hand out the wrong address.
type OnboardedWorkspace ¶
OnboardedWorkspace mirrors providers.OnboardedWorkspace for the admin API.
type OrgWorkspace ¶
type OrgWorkspace struct {
UUID string `json:"uuid"`
DisplayName string `json:"displayName"`
ClusterName string `json:"clusterName"`
Providers []string `json:"providers"`
ProviderReferences []WorkspaceProviderReference `json:"providerReferences"`
DeletionRequestedAt *time.Time `json:"deletionRequestedAt,omitempty"`
// DeletionForced is set when the deletion was requested without the
// recovery window: the cascade runs on the reconciler's next sweep and
// a restore is refused.
DeletionForced bool `json:"deletionForced,omitempty"`
}
OrgWorkspace is a child Workspace of an organization together with the provider names enabled in it (derived from the workspace's provider APIBindings).
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service performs read-only admin queries against kcp.
func NewService ¶
func NewService(kcpConfig *rest.Config, hubExternalURL, hubInternalURL string, provOpts ...providers.ProvisionerOption) *Service
NewService returns an admin Service. hubExternalURL and hubInternalURL are the hub's --hub-external-url and --hub-internal-url; they let the kubeconfig download offer either address regardless of which one the Provider reconciler baked into the Secret. hubInternalURL may be empty, in which case only the external mode is offered.
func (*Service) AvailableKubeconfigServerModes ¶
func (s *Service) AvailableKubeconfigServerModes() []KubeconfigServerMode
AvailableKubeconfigServerModes reports which modes this hub can actually serve, so the portal can offer only the ones that will work. External is present whenever --hub-external-url is set (always, in practice); internal only when --hub-internal-url is.
func (*Service) CreateProvider ¶
CreateProvider create-or-updates a Provider object in root:railgrid:system:providers. name drives the provisioned sub-workspace (root:railgrid:providers:<name>); displayName is informational. Idempotent.
func (*Service) DeleteProvider ¶
DeleteProvider removes a Provider object from root:railgrid:system:providers. The reconciler's finalizer then tears down the sub-workspace. Idempotent.
func (*Service) GetProviderKubeconfig ¶
func (s *Service) GetProviderKubeconfig(ctx context.Context, name string, mode KubeconfigServerMode) ([]byte, error)
GetProviderKubeconfig returns the minted kubeconfig the Provider controller wrote into a Secret in root:railgrid:system:providers. It reads the Provider's status.secretRef to locate the Secret (falling back to the "<name>-kubeconfig" / "default" / "kubeconfig" conventions). Returns a nil slice + nil error when the Provider exists but hasn't been provisioned yet (no Secret), so callers can surface "not ready".
mode re-points the server URL on the way out; the stored Secret is never modified. ServerModeAsMinted returns the bytes untouched.
func (*Service) ListOnboardedWorkspaces ¶
func (s *Service) ListOnboardedWorkspaces(ctx context.Context) ([]OnboardedWorkspace, error)
ListOnboardedWorkspaces returns the provider sub-workspaces created by onboarding, so the admin UI can show providers that have been onboarded but whose Helm chart (and CatalogEntry) is not yet installed.
func (*Service) ListOrgWorkspaces ¶
ListOrgWorkspaces returns every child Workspace under the org at root:railgrid:tenants:{orgUUID}, enriched with display name, cluster name, soft-delete timestamp and the set of enabled provider names. Reads run with kcp-admin credentials, so the admin surface sees all workspaces regardless of per-user RBAC. Per-workspace lookups are best-effort: a workspace that hasn't reached Ready (no cluster) or whose provider listing fails still appears with whatever fields resolved.
func (*Service) RotateProviderCredential ¶
func (s *Service) RotateProviderCredential(ctx context.Context, name string, mode KubeconfigServerMode) ([]byte, *providers.RotatedCredential, error)
RotateProviderCredential issues a NEW workspace credential for a platform provider's ServiceAccount, rewrites the kubeconfig Secret the Provider controller keeps in root:railgrid:system:providers, and returns the fresh kubeconfig in the same shape the download endpoint serves.
The Secret is rewritten rather than left alone because that Secret is where in-cluster consumers read the credential from: a rotation the Secret did not see would hand the operator a kubeconfig while every automated reader kept the retired one, and the retired one is on a deletion clock.
mode re-points the server URL on the way out, exactly as GetProviderKubeconfig does; the stored Secret always keeps the address the hub minted.
func (*Service) UndeleteOrgWorkspace ¶ added in v0.2.31
func (s *Service) UndeleteOrgWorkspace(ctx context.Context, orgUUID, wsUUID string, gracePeriod time.Duration) error
UndeleteOrgWorkspace clears the soft-delete annotation on the child Workspace at root:railgrid:tenants:{orgUUID}:{wsUUID} while it is still inside gracePeriod. Nil when the workspace was never soft-deleted (the caller's intent already holds); ErrGracePeriodExpired once the window has elapsed; kcp.ErrWorkspaceDeletionForced when the deletion was requested without a window, which is never restorable.
The bootstrapper's clear is a single conditional update that hands kcp conflicts back, so this mirrors the tenant REST handler: re-read after a conflict, retry only while the same deletion stamp is still present, and stop if a newer delete won the race and owns the recovery clock now.
type UserResolver ¶
UserResolver maps an inbound request to the caller's User CR name, or returns an error if no identity can be resolved. Mirrors tenant.UserResolver so the hub can reuse the same OIDC IdentifyUser plumbing.
type UserResolverFunc ¶
UserResolverFunc adapts a function to UserResolver.
func (UserResolverFunc) ResolveUser ¶
func (f UserResolverFunc) ResolveUser(r *http.Request) (string, error)
ResolveUser implements UserResolver.
type WorkspaceProviderReference ¶ added in v0.2.42
type WorkspaceProviderReference struct {
Name string `json:"name"`
ExportPath string `json:"exportPath"`
Scope string `json:"scope"`
Terminating bool `json:"terminating,omitempty"`
DeletionBlocked string `json:"deletionBlocked,omitempty"`
}
WorkspaceProviderReference preserves the identity and state of a workspace binding. Names alone cannot distinguish platform and organization-owned providers.