webhooks

package
v0.8.5 Latest Latest
Warning

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

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type PodTenantQuotaValidator

type PodTenantQuotaValidator struct {
	Decoder                admission.Decoder
	Client                 client.Client
	MaxWorkspacesPerTenant int
	MaxCPUMillisPerTenant  int64
	MaxMemoryMiPerTenant   int64
}

PodTenantQuotaValidator enforces per-tenant resource quotas on workspace pods (Epic 51 S51.2). It prevents noisy-neighbor resource exhaustion in multi-tenant deployments by rejecting pod creation when the tenant's aggregate running resource usage would exceed configured limits.

The webhook is keyed on the llmsafespaces.dev/tenant pod label (set by the controller's pod builder per S51.3). Pods without this label are allowed unconditionally (filtered by objectSelector in the webhook config).

Quota limits are instance-level defaults from operator flags:

  • MaxWorkspacesPerTenant: maximum concurrent workspace pods per tenant
  • MaxCPUMillisPerTenant: maximum aggregate CPU requests per tenant
  • MaxMemoryMiPerTenant: maximum aggregate memory requests per tenant

Org-specific quota overrides (from org_policies) are a follow-up; billing tier → quota mapping is tracked under Epic 43.

Race window: the check-and-schedule gap between admission and pod scheduling is acceptable — workspace pods are long-lived; this guards against gross overage, not precise concurrency control.

func (*PodTenantQuotaValidator) Handle

Handle implements admission.Handler. It validates that creating this pod does not exceed the tenant's resource quota.

type RuntimeEnvironmentValidator

type RuntimeEnvironmentValidator struct {
	Decoder                admission.Decoder
	AllowedImageRegistries []string // mirrors WorkspaceValidator
}

RuntimeEnvironmentValidator validates RuntimeEnvironment resources.

F1.2.10 (Epic 17): pre-fix the validator only checked that Spec.Image was non-empty. A user with permission to create RuntimeEnvironment CRDs could supply `image: evil.example.com/malicious:latest` and any subsequent Workspace using that runtime would pull and run the attacker image. The validator now applies the same registry allow-list the workspace webhook uses (see workspace_webhook.go).

The Decoder MUST be set at construction time (controller-runtime v0.15+ removed the InjectDecoder DI callback). A nil Decoder causes Handle to panic with nil-pointer-deref on every admission request.

func (*RuntimeEnvironmentValidator) Handle

Handle validates the RuntimeEnvironment resource.

func (*RuntimeEnvironmentValidator) InjectDecoder

func (v *RuntimeEnvironmentValidator) InjectDecoder(d admission.Decoder) error

InjectDecoder retained for backwards compatibility (see RuntimeEnvironmentValidator).

type WorkspaceValidator

type WorkspaceValidator struct {
	Decoder                  admission.Decoder
	AllowedImageRegistries   []string
	AllowedStorageClassNames []string
	MaxStorageGi             int64
	MaxCPUMillicores         int64
	MaxMemoryMi              int64
}

WorkspaceValidator is a ValidatingAdmissionWebhook for Workspace resources.

It closes the following pentest findings (Epic 17):

  • F1.2.1 / RT-2.18 / RT-6.10 (Critical): Spec.Runtime arbitrary image pull. Without an allow-list, a user could create a Workspace with `runtime: "evil.example.com/malicious:latest"` and the controller would pull and run that image.
  • F1.2.2 (Critical): Status forge. On CREATE the kube-apiserver does NOT yet apply status-subresource semantics, so a malicious user can stamp `status.podIP` / `status.podName` / `status.endpoint` and the API proxy will route requests to the attacker-supplied pod-IP. Defense in depth: also reject status mutations on UPDATE through the spec endpoint (the kube-apiserver subresource split normally enforces this, but failure-modes during CRD upgrades have surfaced it as a real risk).
  • F1.2.9 (Medium): Spec.Storage.StorageClassName had no allow-list, letting users target hostPath / NFS / arbitrary CSIs.
  • RT-6.1 (High): Webhook accepted `runtime: "../../etc/passwd"` and `storage.size: "999999Gi"` (CRD pattern allowed any digit count).

The validator is configurable so the same chart works for every deployment topology — operators decide which registries and storage classes are safe in their environment.

Field reference (set by the controller manager at construction):

  • Decoder: required; nil decoder makes Handle deny with a clear error rather than panic on nil-pointer-deref.
  • AllowedImageRegistries: list of registry prefixes (e.g. "ghcr.io/lenaxia/", "registry.k8s.io/"). A Workspace whose Runtime contains "/" (i.e. is shaped like an explicit image reference) must match at least one prefix.
  • AllowedStorageClassNames: optional. If non-nil, the Spec.Storage. StorageClassName must be in this list (empty StorageClassName always passes — that means "use cluster default").
  • MaxStorageGi: maximum requested workspace storage in GiB. Any storage size above this is rejected. Set 0 to disable.
  • MaxCPUMillicores / MaxMemoryMi: maximum spec.resources.{cpu,memory} accepted at admission. Closes F1.2.3 secondary surface (a user can declare 999999999m CPU; the CRD pattern allows it; the pod stays Pending forever, wasting tenant quota — DoS at the API/etcd layer). Set 0 to disable each cap individually.

func (*WorkspaceValidator) Handle

Handle validates the Workspace resource. Errors are returned as admission.Denied with a human-readable message rather than as 5xx admission errors so kubectl shows the operator the precise reason.

func (*WorkspaceValidator) InjectDecoder

func (v *WorkspaceValidator) InjectDecoder(d admission.Decoder) error

InjectDecoder retained for backwards compatibility (see WorkspaceValidator).

Jump to

Keyboard shortcuts

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