feat(clusters): setup workload identity confguration for oidc clusters - #2192
Conversation
cd2432a to
d2bebb1
Compare
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed correctness issues (e2e ClusterRoleBinding update without resourceVersion, and missing/empty CA key can produce a “ready” Flux access ConfigMap with empty CA data).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds support for Flux HelmReleases to reach OIDC-onboarded remote clusters via Flux’s ObjectLevelWorkloadIdentity by switching from a rotating kubeconfig Secret reference to a rendered per-cluster access ConfigMap (while leaving kubeconfig-onboarded clusters unchanged).
Changes:
- Render a Flux access ConfigMap for OIDC clusters during cluster reconciliation (and surface readiness via a new Cluster condition).
- Update Plugin → HelmRelease reconciliation to use
kubeConfig.configMapRefwhen the access ConfigMap exists, otherwise fall back to the kubeconfig Secret. - Add unit/e2e coverage and enable the Flux helm-controller feature gate in the sample Flux install.
File summaries
| File | Description |
|---|---|
| internal/flux/helm_release_builder.go | Adds builder support for kubeConfig.configMapRef. |
| internal/flux/helm_release_builder_test.go | Unit tests for new ConfigMap kubeconfig reference builder method. |
| internal/controller/plugin/plugin_controller_flux.go | Chooses ConfigMap vs Secret cluster access mode when building HelmRelease spec. |
| internal/controller/plugin/flux_kubeconfig.go | Determines whether OIDC cluster access ConfigMap should be used (with fallback). |
| internal/controller/plugin/flux_kubeconfig_test.go | Unit tests for access-mode detection logic. |
| internal/controller/cluster/phases/phases.go | Inserts new Flux access rendering phase for OIDC clusters. |
| internal/controller/cluster/phases/ensure_flux_access.go | Renders the Flux access ConfigMap for OIDC clusters and sets Cluster condition. |
| internal/controller/cluster/phases/ensure_flux_access_test.go | Unit tests for ConfigMap rendering and phase ordering/conditions. |
| internal/controller/cluster/cluster_controller.go | Adds RBAC for ConfigMaps and watches owned ConfigMaps. |
| e2e/shared/cluster.go | Adds shared helper to set up OIDC ClusterRoleBinding for e2e. |
| e2e/plugin/scenarios/flux_object_level_workload_identity.go | New e2e scenario covering OIDC onboarding → ConfigMap rendering → HelmRelease via configMapRef. |
| e2e/plugin/e2e_test.go | Runs the new plugin e2e scenario and offboards the extra OIDC cluster. |
| e2e/cluster/expect/expect.go | Removes duplicated OIDC role binding helper (moved to shared). |
| e2e/cluster/e2e_test.go | Switches cluster e2e tests to use the shared OIDC role binding helper. |
| config/samples/flux/kustomization.yaml | Enables ObjectLevelWorkloadIdentity feature gate for helm-controller in sample Flux install. |
| charts/manager/templates/rbac/manager-role.yaml | Extends manager RBAC to create/update/patch ConfigMaps. |
| api/v1alpha1/plugin_types.go | Adds a new condition reason for “access mode undetermined”. |
| api/v1alpha1/cluster_types.go | Adds FluxAccessReady condition type for OIDC access ConfigMap readiness. |
Review details
- Files reviewed: 18/18 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
d2bebb1 to
e0c505f
Compare
13abfdf to
d8d82f3
Compare
639bc7b to
950fe0b
Compare
There was a problem hiding this comment.
🟡 Changes recommended
The new ReconcileObject finalizer logic mishandles ctrl.Result{Requeue:true} and the feature-flag “hot reload” handlers currently don’t reconcile resources (and silently drop errors), which can break expected behavior when toggling the gate.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Files not reviewed (5)
- pkg/mocks/mock_Client.go: Generated file
- pkg/mocks/mock_FinalizerNamer.go: Generated file
- pkg/mocks/mock_ObjectReconciler.go: Generated file
- pkg/mocks/mock_Reconciler.go: Generated file
- pkg/mocks/mock_Storage.go: Generated file
- Files reviewed: 26/31 changed files
- Comments generated: 5
- Review effort level: Lite
|
needs - #2203 |
Add an ensureFluxAccess phase rendering a ConfigMap with provider, address, audiences, serviceAccountName and ca.crt, and the configmaps RBAC marker for the cluster controller. On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
Move ensureFluxAccess to the end of the OIDC phase chain so a ConfigMap write failure no longer breaks out before the phases that renew the kubeconfig Secret token, add a FluxAccessReady condition, and take the ConfigMap keys from the upstream Flux constants. On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
Set a controller owner reference, enqueue the cluster when the ConfigMap changes, and take the service account name from the cluster instead of the secret. On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
Add the workloadIdentity feature key and IsWorkloadIdentityEnabled accessor, the global.workloadIdentity.enabled chart value and helper, and drop the unused FluxAccessReady condition. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Split the bootstrap controller into idempotent phases and, under workload identity, write the Flux remote ConfigMap instead of a static kubeconfig. Enable the ObjectLevelWorkloadIdentity feature gate on the Flux controllers. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Add NewRestClientGetterForWI which mints a ServiceAccount token and builds the rest config from the OIDC secret, and move remote client construction into the cluster phases to select the WI or kubeconfig path per secret. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Label the feature-flags ConfigMap and watch it in the cluster and bootstrap controllers, updating the workload identity gate live via an atomic bool. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Flip the feature flag live and verify the Flux config map is written with no static kubeconfig. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Delete the KubeConfig secret instead of the Cluster so the bootstrap controller does not recreate the Cluster from the still-present secret during AfterAll. Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
this is handled in createOrUpdateCluster Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
after suite handles it and the finalizer check is asserted in pkg/lifecycle/reconcile_test Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
Signed-off-by: abhijith-darshan <abhijith.ravindra@sap.com>
e6d971c to
eab1e74
Compare
On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
0a2239d to
9a6d1b6
Compare
…e changes On-behalf-of: @SAP <mikolaj.kucinski@sap.com> Signed-off-by: Mikolaj Kucinski <osidu12@gmail.com>
bcb1383 to
4c008ce
Compare
Description
Flux reaches a Plugin's target cluster through the kubeconfig Secret that onboarding writes, and for OIDC onboarded clusters that Secret holds a token that has to be rotated. Flux can mint the token itself with
ObjectLevelWorkloadIdentity, via a ConfigMap describing the cluster instead of a kubeconfig.A
workloadIdentityfeature toggle is added. When enabled the bootstrap controller now renders that ConfigMap for every OIDC onboarded cluster, with the API server address, the CA and the service account Flux should impersonate.bootstrap controller implements generic object reconciler without status patches.
A new RestClientGetter method for WorkloadIdentity is added in clientutil -
NewRestClientGetterForWIcluster controller uses the new RestClientGetter method if
workloadIdentityis enabledoff-boarding is strictly cluster secret drop and not anymore by
Clusterresource deletionWhat type of PR is this? (check all applicable)
Related Tickets & Documents
Added tests?
Added to documentation?
Checklist