Skip to content

fix(operator): move defaults to admission webhook#194

Merged
Agent-Hellboy merged 5 commits into
mainfrom
operator/admission_defaults_validation
Jun 12, 2026
Merged

fix(operator): move defaults to admission webhook#194
Agent-Hellboy merged 5 commits into
mainfrom
operator/admission_defaults_validation

Conversation

@Agent-Hellboy

@Agent-Hellboy Agent-Hellboy commented May 15, 2026

Copy link
Copy Markdown
Owner

Rebuilt on current main after the setup package refactor.

  • applies MCPServer defaults through the mutating admission webhook
  • passes operator-scoped ingress and analytics defaults into webhook registration
  • keeps in-memory reconcile defaulting for legacy objects without persisting spec changes
  • retains reconcile-time validation on the defaulted copy
  • deploys webhook TLS, service, and CA-injected configurations from internal/cli/setup/platform/
  • preserves empty MCPAccessGrant subjects as wildcard grants, matching the governance runtime contract and fixing the prior Kind E2E failure
  • allows expired MCPAgentSession objects to remain valid persisted state
  • uses repo-root asset resolution, a 10-year CA with a 1-year serving certificate, and MCP Runtime-qualified webhook configuration names

Validation:

  • race-enabled tests for API types, operator, setup platform, manifest mutator, and operator command
  • bash test/e2e/scenarios_test.sh
  • full envtest integration suite with Kubernetes 1.36 assets
  • generated DeepCopy, CRD, RBAC, webhook, and package-reference drift checks
  • pre-commit: gitleaks, gofmt, staticcheck, vet, unit tests, integration tests, generated drift

Fixes #18.

@Agent-Hellboy Agent-Hellboy marked this pull request as ready for review May 15, 2026 19:19

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request transitions the application and persistence of default values from the operator's reconciliation loop to Kubernetes admission webhooks. It introduces a mechanism to pass environment-specific defaults to the webhooks via a new options structure and updates the reconciler to use in-memory defaulting for legacy objects. Additionally, the CLI setup process is enhanced to manage webhook TLS certificates and manifest injection. Review feedback identifies a missing yaml import in the setup package, suggests extending the CA certificate's lifespan for better rotation practices, and recommends using reliable path resolution for reading configuration files.

Comment thread internal/cli/setup/platform.go Outdated

func injectOperatorWebhookCABundle(webhookYAML, caBundlePEM []byte) ([]byte, error) {
caBundle := base64.StdEncoding.EncodeToString(caBundlePEM)
decoder := yaml.NewDecoder(bytes.NewReader(webhookYAML))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The yaml package is used here (via yaml.NewDecoder), but it is not included in the file's import block. This will cause a compilation error. Please add "gopkg.in/yaml.v3" to the imports.

Comment thread internal/cli/setup/platform.go Outdated
Comment on lines +1781 to +1791
caTemplate := x509.Certificate{
SerialNumber: caSerialNumber,
Subject: pkix.Name{
CommonName: operatorWebhookServiceName + "-ca",
},
NotBefore: now.Add(-1 * time.Hour),
NotAfter: now.AddDate(1, 0, 0),
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
IsCA: true,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The CA certificate and the serving certificate are configured with the same expiration date (1 year from now). It is a best practice for a Certificate Authority to have a longer lifetime than the certificates it signs to ensure continuity during rotation. Consider increasing the NotAfter duration for the caTemplate.

References
  1. Certificates signed by a CA should generally have a shorter lifespan than the CA itself to avoid simultaneous expiration issues.

Comment thread internal/cli/setup/platform.go Outdated
Comment on lines +1826 to +1834
serviceYAML, err := os.ReadFile("config/webhook/service.yaml")
if err != nil {
return fmt.Errorf("read operator webhook service manifest: %w", err)
}
if err := kube.ApplyManifestContent(kubectl.CommandArgs, string(serviceYAML)); err != nil {
return err
}

webhookYAML, err := os.ReadFile("config/webhook/manifests.yaml")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These os.ReadFile calls use relative paths (config/webhook/...). While consistent with some other parts of this file, this makes the setup command fragile if executed from a directory other than the repository root. Consider using assetpath.ResolveRepoAssetPath to resolve these paths reliably.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 907caeb45e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if requeue {
return ctrl.Result{}, nil
}
mcpServer = r.defaultedMCPServerForReconcile(mcpServer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reinstate reconcile-time validation fallback

The reconcile loop now defaults the object and proceeds without any MCPServer spec validation, but webhook registration is still conditional on MCP_ENABLE_WEBHOOKS (cmd/operator/main.go). In installs where that env var is unset/false (for example config/default style deployments or older operator pods), malformed CRs such as OAuth without required issuer fields or invalid rollout values bypass admission and reach reconciliation, causing late runtime/deployment failures instead of deterministic API rejection. Please keep controller-side validation as a fallback (or hard-require webhooks at startup) so non-webhook environments don’t silently accept invalid specs.

Useful? React with 👍 / 👎.

@Agent-Hellboy Agent-Hellboy force-pushed the operator/admission_defaults_validation branch from abc9f39 to 2cd2617 Compare June 11, 2026 10:35
Agent-Hellboy and others added 3 commits June 11, 2026 16:11
Make ensureOperatorWebhookTLSSecret idempotent: store ca.crt in the
webhook Secret, read it back on both the kubectl and client-go deploy
paths, and keep the existing CA + serving certificate when the chain
still verifies for the webhook service DNS name and stays valid beyond
a 30-day renewal window. Rotation now only happens on first install,
near expiry, or when the Secret is missing/malformed, so setup re-runs
no longer roll the operator and open a fail-closed admission window.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Persist CA key for serving cert renewal, set mutating webhook failurePolicy
to Ignore, warn on wildcard grants, wait for rollout before caBundle patch,
and add doctor expiry warning within the renewal window.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Agent-Hellboy

Copy link
Copy Markdown
Owner Author

Pushed review fixes (also on `fix/pr-194-review`):

  • Persist `ca.key` for CA-stable serving cert renewal + doctor expiry warning
  • Mutating webhook `failurePolicy: Ignore`
  • Admission warning on empty-subject wildcard grants
  • Wait for operator rollout before patching webhook `caBundle`
  • Kustomization footgun comment for standalone `kubectl apply -k config/webhook`

Co-authored-by: Cursor <cursoragent@cursor.com>
@Agent-Hellboy Agent-Hellboy merged commit 8c5a600 into main Jun 12, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

use Admission webhook to apply default and validate things inside operator

1 participant