feat(rbac): wire hardened admission webhook for rbac-controller 0.2.0-pr9690.1 #49

Open
Daniel.Sy wants to merge 2 commits from ipceicis-9690-rbac-admission-deploy into main
Owner

Summary

Wires the hardened RBAC admission controller (0.2.0-pr9690.1) into the deployment stack. Promotes the controller from prototype (0.0.1) to the final artifact from commit fd17b13, adding the admission webhook, permission ceiling enforcement, and the updated KCP APIExport schema.

⚠️ Not merge-ready — local OrbStack E2E: PASS. Shared dev cluster: not tested (deny-all ceiling active). Dev cluster runtime validation required before merge.


Dependencies

Dependency Status Notes
PR #11 — rbac-controller-kcp KCP workspace bootstrap Required first APIExport + APIResourceSchemas must exist before the controller polls its EndpointSlice
cert-manager CRDs Required first The chart uses cert-manager Certificate + Issuer for webhook TLS; cert-manager CRDs must be installed in the cluster
PR #32 — tenant-controller Recommended / functional APIBinding clusterroles pre-acceptance; functional dependency before tenant bindings are accepted
PR #47 — identity/OIDC changes No relation This PR is independent; it does not touch OIDC, Zitadel, or projected auth. The ipceicis-9690-rbac-admission-deploy bookmark is separate from PR #47's bookmark.

Artifact Versions

Artifact Version Source commit OCI digest
Image edp.buildth.ing/devfw-cicd/rbac-controller:0.2.0-pr9690.1 fd17b13 sha256:227c7137c04f435f1d4bd92fd77f6091bb9b8aff8cbac8169349b2f8166ec057
Chart rbac-controller 0.2.0-pr9690.1 OCI: edp.buildth.ing/devfw-cicd/charts/rbac-controller sha256:68c2720bf1b8ee9f0afb0a989fb6f40ea166c3ce4e87975179655dfd49cdd439
Chart rbac-controller-kcp 0.2.0-pr9690.1 OCI: edp.buildth.ing/devfw-cicd/charts/rbac-controller-kcp sha256:43dacd087d85d2367d4723de2c082bbae9971df893f21021540b20b0454fb813
KCP schema prefix scel50items001 bumped from s17f7e0b431fc (MaxItems CEL cost-budget fix)

Admission Webhook Configuration

The controller runs an in-process HTTPS admission webhook server. The service URL and cert SANs were derived from helm template output — not assumed.

Helm fullname derivation:

  • Release name: rbac-controller-dev (from ApplicationSet name: 'rbac-controller-{{name}}' with name=dev)
  • Chart name: rbac-controller
  • Since release name contains chart name → fullname = rbac-controller-dev
  • Service name: rbac-controller-dev-webhook

Verified cert SANs (from helm template on 0.2.0-pr9690.1):

rbac-controller-dev-webhook
rbac-controller-dev-webhook.edge-connect-system
rbac-controller-dev-webhook.edge-connect-system.svc
rbac-controller-dev-webhook.edge-connect-system.svc.cluster.local  ✓ matches serviceURL

webhook.serviceURL: https://rbac-controller-dev-webhook.edge-connect-system.svc.cluster.local:443
webhook.platformUsername: rbac-controller — the KCP X.509 mTLS CN of the controller cert. Bypasses only the edge-connect-rt-* reserved-name-prefix guard; all hard denials and ceiling rules still apply.


Dynamic CA / VWC (No caBundle in Git)

The controller bootstrap reconciler manages the ValidatingWebhookConfiguration in the KCP provider workspace (root:controllers:rbac) and dynamically syncs the cert-manager CA into the VWC caBundle. No static caBundle is committed to Git.

The manage-vwc ClusterRole + ClusterRoleBinding are now included in rbac-controller-kcp:0.2.0-pr9690.1 — no new consumer permissionClaim for validatingwebhookconfigurations is needed.


Permission Ceiling Postures

Local (E2E ceiling)

Read-only allowlist covering existing E2E RoleTemplate examples/tests. Only get/list/watch verbs; no write or delete verbs granted to tenants.

ceiling:
  rules:
    - apiGroup: ""
      resource: secrets
      verbs: [get, list, watch]
    - apiGroup: apps
      resource: deployments
      verbs: [get, list, watch]
    - apiGroup: ""
      resource: pods
      verbs: [get, list, watch]
    - apiGroup: ""
      resource: pods/log
      verbs: [get, list]

Dev (deny-all)

ceiling.rules: [] — intentionally empty. The chart omits the --ceiling-config flag and the ConfigMap/volume entirely when rules is empty. The controller starts with Ceiling=nil → fail-closed: no tenant RoleTemplate creates or updates are accepted until an approved persona ceiling is explicitly configured. Verified via helm template (no ceiling resources rendered).


KCP APIExport Changes

Both local and dev KCP values updated:

  • schemaNamePrefix: s17f7e0b431fcscel50items001 (schema now has MaxItems bounds on PolicyRule arrays; required to avoid CEL cost-budget rejection in KCP)
  • Added clusterroles permissionClaim (required by the RoleTemplate controller in 0.2.0; previously missing)
  • manage-vwc ClusterRoleBinding for rbac-controller user is chart-managed (0.2.0+)

Files Changed

File Change
argocd/edge-connect-rbac-controller.yaml Both chart targetRevisions bumped 0.0.10.2.0-pr9690.1
rbac-controller-values-local.yaml image tag, webhook URL/platformUsername, local read-only ceiling
rbac-controller-values-dev.yaml image tag, webhook URL/platformUsername, deny-all ceiling
rbac-controller-kcp-values-local.yaml schema prefix, add clusterroles claim, manage-vwc note
rbac-controller-kcp-values-dev.yaml schema prefix, add clusterroles claim, manage-vwc note

Pre-merge Checklist

  • helm lint — both charts, both envs: 0 failures
  • helm template — webhook URL, cert SANs, image tag, args verified (0.2.0-pr9690.1)
  • dev: no ceiling ConfigMap/volume/arg rendered (fail-closed confirmed)
  • local: ceiling ConfigMap mounted with correct read-only rules
  • KCP: scel50items001 schema, clusterroles+clusterrolebindings+events claims
  • manage-vwc RBAC in KCP chart — no Git caBundle
  • Local OrbStack E2E — PASS
  • Runtime E2E on shared dev cluster (pending — deny-all ceiling; do not merge before this)

Refs: IPCEICIS-9690

## Summary Wires the hardened RBAC admission controller (0.2.0-pr9690.1) into the deployment stack. Promotes the controller from prototype (`0.0.1`) to the final artifact from commit `fd17b13`, adding the admission webhook, permission ceiling enforcement, and the updated KCP APIExport schema. > ⚠️ **Not merge-ready** — local OrbStack E2E: ✅ PASS. Shared dev cluster: not tested (deny-all ceiling active). Dev cluster runtime validation required before merge. --- ## Dependencies | Dependency | Status | Notes | |---|---|---| | **PR #11** — rbac-controller-kcp KCP workspace bootstrap | Required first | APIExport + APIResourceSchemas must exist before the controller polls its EndpointSlice | | **cert-manager CRDs** | Required first | The chart uses cert-manager `Certificate` + `Issuer` for webhook TLS; cert-manager CRDs must be installed in the cluster | | **PR #32** — tenant-controller | Recommended / functional | `APIBinding` clusterroles pre-acceptance; functional dependency before tenant bindings are accepted | | **PR #47** — identity/OIDC changes | **No relation** | This PR is independent; it does not touch OIDC, Zitadel, or projected auth. The `ipceicis-9690-rbac-admission-deploy` bookmark is separate from PR #47's bookmark. | --- ## Artifact Versions | Artifact | Version | Source commit | OCI digest | |---|---|---|---| | Image | `edp.buildth.ing/devfw-cicd/rbac-controller:0.2.0-pr9690.1` | `fd17b13` | `sha256:227c7137c04f435f1d4bd92fd77f6091bb9b8aff8cbac8169349b2f8166ec057` | | Chart `rbac-controller` | `0.2.0-pr9690.1` | OCI: `edp.buildth.ing/devfw-cicd/charts/rbac-controller` | `sha256:68c2720bf1b8ee9f0afb0a989fb6f40ea166c3ce4e87975179655dfd49cdd439` | | Chart `rbac-controller-kcp` | `0.2.0-pr9690.1` | OCI: `edp.buildth.ing/devfw-cicd/charts/rbac-controller-kcp` | `sha256:43dacd087d85d2367d4723de2c082bbae9971df893f21021540b20b0454fb813` | | KCP schema prefix | `scel50items001` | bumped from `s17f7e0b431fc` (MaxItems CEL cost-budget fix) | — | --- ## Admission Webhook Configuration The controller runs an in-process HTTPS admission webhook server. The service URL and cert SANs were derived from `helm template` output — not assumed. **Helm fullname derivation:** - Release name: `rbac-controller-dev` (from ApplicationSet `name: 'rbac-controller-{{name}}'` with `name=dev`) - Chart name: `rbac-controller` - Since release name _contains_ chart name → `fullname = rbac-controller-dev` - Service name: `rbac-controller-dev-webhook` **Verified cert SANs** (from `helm template` on `0.2.0-pr9690.1`): ```text rbac-controller-dev-webhook rbac-controller-dev-webhook.edge-connect-system rbac-controller-dev-webhook.edge-connect-system.svc rbac-controller-dev-webhook.edge-connect-system.svc.cluster.local ✓ matches serviceURL ``` **`webhook.serviceURL`**: `https://rbac-controller-dev-webhook.edge-connect-system.svc.cluster.local:443` **`webhook.platformUsername`**: `rbac-controller` — the KCP X.509 mTLS CN of the controller cert. Bypasses only the `edge-connect-rt-*` reserved-name-prefix guard; all hard denials and ceiling rules still apply. --- ## Dynamic CA / VWC (No caBundle in Git) The controller bootstrap reconciler manages the `ValidatingWebhookConfiguration` in the KCP provider workspace (`root:controllers:rbac`) and dynamically syncs the cert-manager CA into the VWC `caBundle`. **No static `caBundle` is committed to Git.** The `manage-vwc` ClusterRole + ClusterRoleBinding are now included in `rbac-controller-kcp:0.2.0-pr9690.1` — no new consumer `permissionClaim` for `validatingwebhookconfigurations` is needed. --- ## Permission Ceiling Postures ### Local (E2E ceiling) Read-only allowlist covering existing E2E RoleTemplate examples/tests. Only `get/list/watch` verbs; no write or delete verbs granted to tenants. ```yaml ceiling: rules: - apiGroup: "" resource: secrets verbs: [get, list, watch] - apiGroup: apps resource: deployments verbs: [get, list, watch] - apiGroup: "" resource: pods verbs: [get, list, watch] - apiGroup: "" resource: pods/log verbs: [get, list] ``` ### Dev (deny-all) `ceiling.rules: []` — intentionally empty. The chart omits the `--ceiling-config` flag and the ConfigMap/volume entirely when `rules` is empty. The controller starts with `Ceiling=nil` → fail-closed: **no tenant RoleTemplate creates or updates are accepted until an approved persona ceiling is explicitly configured.** Verified via `helm template` (no ceiling resources rendered). --- ## KCP APIExport Changes Both `local` and `dev` KCP values updated: - `schemaNamePrefix`: `s17f7e0b431fc` → `scel50items001` (schema now has `MaxItems` bounds on `PolicyRule` arrays; required to avoid CEL cost-budget rejection in KCP) - Added `clusterroles` permissionClaim (required by the RoleTemplate controller in 0.2.0; previously missing) - `manage-vwc` ClusterRoleBinding for `rbac-controller` user is chart-managed (0.2.0+) --- ## Files Changed | File | Change | |---|---| | `argocd/edge-connect-rbac-controller.yaml` | Both chart `targetRevision`s bumped `0.0.1` → `0.2.0-pr9690.1` | | `rbac-controller-values-local.yaml` | image tag, webhook URL/platformUsername, local read-only ceiling | | `rbac-controller-values-dev.yaml` | image tag, webhook URL/platformUsername, deny-all ceiling | | `rbac-controller-kcp-values-local.yaml` | schema prefix, add clusterroles claim, manage-vwc note | | `rbac-controller-kcp-values-dev.yaml` | schema prefix, add clusterroles claim, manage-vwc note | --- ## Pre-merge Checklist - [x] `helm lint` — both charts, both envs: 0 failures - [x] `helm template` — webhook URL, cert SANs, image tag, args verified (0.2.0-pr9690.1) - [x] dev: no ceiling ConfigMap/volume/arg rendered (fail-closed confirmed) - [x] local: ceiling ConfigMap mounted with correct read-only rules - [x] KCP: `scel50items001` schema, `clusterroles`+`clusterrolebindings`+`events` claims - [x] `manage-vwc` RBAC in KCP chart — no Git `caBundle` - [x] Local OrbStack E2E — PASS - [ ] Runtime E2E on shared dev cluster (pending — deny-all ceiling; do not merge before this) Refs: IPCEICIS-9690
Promote rbac-controller-manager from prototype to hardened admission
deployment. Upgrades both Helm charts to 0.2.0-pr9690, wires the
admission webhook, and sets environment-appropriate ceiling postures.

Changes:
- argocd/edge-connect-rbac-controller.yaml: bump both chart
  targetRevisions 0.0.1 → 0.2.0-pr9690
- rbac-controller-values-{local,dev}.yaml:
  - image.tag 0.0.1 / 0.1.0-pr9690 → 0.2.0-pr9690
  - webhook.serviceURL: https://rbac-controller-dev-webhook.edge-connect-system.svc.cluster.local:443
    (verified: fullname=rbac-controller-dev, cert SANs match)
  - webhook.platformUsername: rbac-controller (KCP mTLS CN, prefix guard)
  - local: read-only ceiling (secrets/deployments/pods/pods/log get/list/watch)
  - dev: ceiling.rules=[] → deny-all; ConfigMap/volume/arg omitted by chart
- rbac-controller-kcp-values-{local,dev}.yaml:
  - schemaNamePrefix s17f7e0b431fc → scel50items001 (MaxItems CEL fix)
  - add clusterroles permissionClaim (RoleTemplate controller requires it)
  - manage-vwc ClusterRole+Binding now included in chart (no Git caBundle)

Dependency: controller CA bootstrap (manage-vwc RBAC) is in 0.2.0
chart; no additional consumer permissionClaim for VWC required.
Dynamic CA sync into root:controllers:rbac VWC is controller-managed.

Not merge-ready: runtime E2E validation on dev cluster pending.

Refs: IPCEICIS-9690
Bump image tag and both chart targetRevisions from 0.2.0-pr9690 to
0.2.0-pr9690.1, sourced from rbac-controller-manager PR #11 head fd17b13.

- argocd/edge-connect-rbac-controller.yaml: rbac-controller-kcp +
  rbac-controller chart targetRevisions 0.2.0-pr9690 → 0.2.0-pr9690.1
- rbac-controller-values-local.yaml: image.tag → 0.2.0-pr9690.1
- rbac-controller-values-dev.yaml:    image.tag → 0.2.0-pr9690.1

OCI digests (verified):
  image:               sha256:227c7137c04f435f1d4bd92fd77f6091bb9b8aff8cbac8169349b2f8166ec057
  chart rbac-controller:     sha256:68c2720bf1b8ee9f0afb0a989fb6f40ea166c3ce4e87975179655dfd49cdd439
  chart rbac-controller-kcp: sha256:43dacd087d85d2367d4723de2c082bbae9971df893f21021540b20b0454fb813

helm lint: 0 failures (both charts, both envs)
helm template: image tag, webhook URL, ceiling postures verified

Ref: IPCEICIS-9690
Daniel.Sy changed title from feat(rbac): wire hardened admission webhook for rbac-controller 0.2.0-pr9690 to feat(rbac): wire hardened admission webhook for rbac-controller 0.2.0-pr9690.1 2026-07-27 12:12:28 +00:00
This pull request has changes conflicting with the target branch.
  • argocd/edge-connect-rbac-controller.yaml
  • rbac-controller-values-dev.yaml
  • rbac-controller-values-local.yaml
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin ipceicis-9690-rbac-admission-deploy:ipceicis-9690-rbac-admission-deploy
git switch ipceicis-9690-rbac-admission-deploy

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff ipceicis-9690-rbac-admission-deploy
git switch ipceicis-9690-rbac-admission-deploy
git rebase main
git switch main
git merge --ff-only ipceicis-9690-rbac-admission-deploy
git switch ipceicis-9690-rbac-admission-deploy
git rebase main
git switch main
git merge --no-ff ipceicis-9690-rbac-admission-deploy
git switch main
git merge --squash ipceicis-9690-rbac-admission-deploy
git switch main
git merge --ff-only ipceicis-9690-rbac-admission-deploy
git switch main
git merge ipceicis-9690-rbac-admission-deploy
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
DevFW-CICD/poc-core-deploy!49
No description provided.