Skip to content

Commit c19b079

Browse files
authored
Merge pull request #437 from r3v5/absorb-spiffe-helper-config-into-global-kagenti-platform-config
Feature: absorb spiffe-helper config into global kagenti-platform-config
2 parents f822104 + 67b8a5e commit c19b079

18 files changed

Lines changed: 362 additions & 84 deletions

charts/kagenti-operator/values.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,21 @@ defaults:
284284
limits:
285285
cpu: 300m
286286
memory: 384Mi
287+
288+
# SPIFFE / spiffe-helper settings.
289+
# Keep helperConfig in sync with DefaultSpiffeHelperConfig in internal/webhook/config/defaults.go.
290+
spiffe:
291+
trustDomain: cluster.local
292+
socketPath: "unix:///spiffe-workload-api/spire-agent.sock"
293+
helperConfig: |
294+
agent_address = "/spiffe-workload-api/spire-agent.sock"
295+
cmd = ""
296+
cmd_args = ""
297+
svid_file_name = "/opt/svid.pem"
298+
svid_key_file_name = "/opt/svid_key.pem"
299+
svid_bundle_file_name = "/opt/svid_bundle.pem"
300+
cert_file_mode = 0644
301+
key_file_mode = 0640
302+
jwt_svids = [{jwt_audience="http://keycloak.localtest.me:8080/realms/kagenti", jwt_svid_file_name="/opt/jwt_svid.token"}]
303+
jwt_svid_file_mode = 0644
304+
include_federated_domains = true

kagenti-operator/cmd/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ func main() {
631631
EnableCardDiscovery: enableCardDiscovery,
632632
SpireTrustDomain: spireTrustDomain,
633633
GetFeatureGates: featureGateLoader.Get,
634+
GetPlatformConfig: configLoader.Get,
634635
}
635636
if enableCardDiscovery {
636637
artReconciler.AgentFetcher = agentFetcher

kagenti-operator/config/authbridge/spiffe-helper-config.yaml

Lines changed: 0 additions & 24 deletions
This file was deleted.

kagenti-operator/config/openshift/kustomization.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,3 @@ resources:
1212

1313
patches:
1414
- path: patches/authbridge-keycloak.yaml
15-
- path: patches/spiffe-helper-keycloak.yaml

kagenti-operator/config/openshift/patches/spiffe-helper-keycloak.yaml

Lines changed: 0 additions & 20 deletions
This file was deleted.

kagenti-operator/internal/controller/agentruntime_config.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ const (
4848
// ConfigMap are watched by AgentRuntimeReconciler so the resolved-config
4949
// hash picks them up and rolls affected workloads.
5050
AuthBridgeRuntimeConfigMapName = "authbridge-runtime-config"
51+
52+
// SpiffeHelperConfigMapName is the namespace-scoped ConfigMap holding
53+
// the spiffe-helper helper.conf. Derived from PlatformConfig by the
54+
// controller; included in the config hash for rolling updates.
55+
SpiffeHelperConfigMapName = "spiffe-helper-config"
5156
)
5257

5358
// ClusterDefaultsNamespace is the namespace where cluster-level ConfigMaps
@@ -84,6 +89,10 @@ type resolvedConfig struct {
8489
// we want any byte change to roll the workload. Empty string when
8590
// the ConfigMap doesn't exist in the namespace.
8691
AuthBridgeRuntime string `json:"authBridgeRuntime,omitempty"`
92+
93+
// SpiffeHelperConfig captures the spiffe-helper-config CM content so
94+
// changes to PlatformConfig's spiffe.helperConfig trigger rolling updates.
95+
SpiffeHelperConfig string `json:"spiffeHelperConfig,omitempty"`
8796
}
8897

8998
// ConfigResult holds the computed hash and any warnings from the config resolution.
@@ -130,10 +139,19 @@ func resolveConfig(ctx context.Context, c client.Reader, namespace string) (reso
130139
abRuntime = data["config.yaml"]
131140
}
132141

142+
// Layer 2c: spiffe-helper-config (helper.conf).
143+
// Derived from PlatformConfig by the controller; included in hash
144+
// so changes to spiffe.helperConfig trigger rolling updates.
145+
spiffeHelper := ""
146+
if data := readConfigMapData(ctx, c, namespace, SpiffeHelperConfigMapName); len(data) > 0 {
147+
spiffeHelper = data["helper.conf"]
148+
}
149+
133150
return resolvedConfig{
134-
FeatureGates: featureGates,
135-
Defaults: merged,
136-
AuthBridgeRuntime: abRuntime,
151+
FeatureGates: featureGates,
152+
Defaults: merged,
153+
AuthBridgeRuntime: abRuntime,
154+
SpiffeHelperConfig: spiffeHelper,
137155
}, warnings
138156
}
139157

kagenti-operator/internal/controller/agentruntime_config_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,32 @@ var _ = Describe("AgentRuntime Config", func() {
220220
r2, _ := ComputeConfigHash(ctx, k8sClient, namespace)
221221
Expect(r1.Hash).NotTo(Equal(r2.Hash))
222222
})
223+
224+
It("should change when spiffe-helper-config content changes", func() {
225+
const shHashNS = "sh-hash-ns"
226+
shNS := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: shHashNS}}
227+
_ = k8sClient.Create(ctx, shNS)
228+
229+
shCM := &corev1.ConfigMap{
230+
ObjectMeta: metav1.ObjectMeta{
231+
Name: "spiffe-helper-config",
232+
Namespace: shHashNS,
233+
},
234+
Data: map[string]string{
235+
"helper.conf": "agent_address = \"/old/socket\"",
236+
},
237+
}
238+
Expect(k8sClient.Create(ctx, shCM)).To(Succeed())
239+
defer func() { _ = k8sClient.Delete(ctx, shCM) }()
240+
241+
r1, _ := ComputeConfigHash(ctx, k8sClient, shHashNS)
242+
243+
shCM.Data["helper.conf"] = "agent_address = \"/new/socket\""
244+
Expect(k8sClient.Update(ctx, shCM)).To(Succeed())
245+
246+
r2, _ := ComputeConfigHash(ctx, k8sClient, shHashNS)
247+
Expect(r1.Hash).NotTo(Equal(r2.Hash))
248+
})
223249
})
224250

225251
Context("resolveConfig two-layer merge", func() {

kagenti-operator/internal/controller/agentruntime_controller.go

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ type AgentRuntimeReconciler struct {
113113
EnableCardDiscovery bool
114114
SpireTrustDomain string
115115
GetFeatureGates func() *webhookconfig.FeatureGates
116+
GetPlatformConfig func() *webhookconfig.PlatformConfig
116117
}
117118

118119
func (r *AgentRuntimeReconciler) getFeatureGates() *webhookconfig.FeatureGates {
@@ -122,6 +123,15 @@ func (r *AgentRuntimeReconciler) getFeatureGates() *webhookconfig.FeatureGates {
122123
return webhookconfig.DefaultFeatureGates()
123124
}
124125

126+
func (r *AgentRuntimeReconciler) getPlatformConfig() *webhookconfig.PlatformConfig {
127+
if r.GetPlatformConfig != nil {
128+
if cfg := r.GetPlatformConfig(); cfg != nil {
129+
return cfg
130+
}
131+
}
132+
return webhookconfig.CompiledDefaults()
133+
}
134+
125135
// +kubebuilder:rbac:groups=agent.kagenti.dev,resources=agentruntimes,verbs=get;list;watch;create;update;patch;delete
126136
// +kubebuilder:rbac:groups=agent.kagenti.dev,resources=agentruntimes/status,verbs=get;update;patch
127137
// +kubebuilder:rbac:groups=agent.kagenti.dev,resources=agentruntimes/finalizers,verbs=update
@@ -194,6 +204,19 @@ func (r *AgentRuntimeReconciler) Reconcile(ctx context.Context, req ctrl.Request
194204
}
195205
}
196206

207+
// 4.5b. Ensure spiffe-helper-config CM is derived from PlatformConfig.
208+
// Unlike template CMs above, this always overwrites to keep PlatformConfig
209+
// as the single source of truth.
210+
if err := r.ensureSpiffeHelperConfigMap(ctx, rt.Namespace); err != nil {
211+
logger.Error(err, "Failed to ensure spiffe-helper-config")
212+
if r.Recorder != nil {
213+
r.Recorder.Eventf(rt, nil, corev1.EventTypeWarning, "ConfigMapEnsureError",
214+
"EnsureSpiffeHelperConfig", err.Error())
215+
}
216+
r.updateErrorStatus(ctx, req.NamespacedName, ConditionTypeReady, "SpiffeHelperConfigError", err.Error())
217+
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
218+
}
219+
197220
// 4.6. Ensure namespace has Istio ambient mesh labels for ztunnel mTLS.
198221
istioLabeled, istioErr := r.ensureIstioMeshLabels(ctx, rt.Namespace)
199222
switch {
@@ -235,7 +258,7 @@ func (r *AgentRuntimeReconciler) Reconcile(ctx context.Context, req ctrl.Request
235258
}
236259

237260
// 5. Compute config hash from merged configuration (cluster → namespace)
238-
configResult, err := ComputeConfigHash(ctx, r.Client, rt.Namespace)
261+
configResult, err := ComputeConfigHash(ctx, r.uncachedReader(), rt.Namespace)
239262
if err != nil {
240263
logger.Error(err, "Failed to compute config hash")
241264
r.updateErrorStatus(ctx, req.NamespacedName, ConditionTypeReady, "ConfigHashError", err.Error())
@@ -1045,7 +1068,6 @@ func computeCardContentHash(cardData *agentv1alpha1.AgentCardData) string {
10451068
var templateConfigMapNames = []string{
10461069
"authbridge-config",
10471070
"authbridge-runtime-config",
1048-
"spiffe-helper-config",
10491071
}
10501072

10511073
// ensureNamespaceConfigMaps copies template ConfigMaps from kagenti-system to the
@@ -1097,6 +1119,65 @@ func (r *AgentRuntimeReconciler) ensureNamespaceConfigMaps(ctx context.Context,
10971119
return nil
10981120
}
10991121

1122+
// ensureSpiffeHelperConfigMap creates or updates the spiffe-helper-config ConfigMap
1123+
// in the target namespace using content from PlatformConfig. Unlike template CMs
1124+
// which are create-if-not-exists, this always overwrites because PlatformConfig is
1125+
// the single source of truth.
1126+
func (r *AgentRuntimeReconciler) ensureSpiffeHelperConfigMap(ctx context.Context, namespace string) error {
1127+
logger := log.FromContext(ctx)
1128+
cfg := r.getPlatformConfig()
1129+
1130+
desired := &corev1.ConfigMap{
1131+
ObjectMeta: metav1.ObjectMeta{
1132+
Name: SpiffeHelperConfigMapName,
1133+
Namespace: namespace,
1134+
Labels: map[string]string{
1135+
LabelManagedBy: LabelManagedByValue,
1136+
},
1137+
},
1138+
Data: map[string]string{
1139+
"helper.conf": cfg.Spiffe.HelperConfig,
1140+
},
1141+
}
1142+
1143+
existing := &corev1.ConfigMap{}
1144+
err := r.uncachedReader().Get(ctx, client.ObjectKey{Namespace: namespace, Name: SpiffeHelperConfigMapName}, existing)
1145+
if apierrors.IsNotFound(err) {
1146+
if err := r.Create(ctx, desired); err != nil {
1147+
if apierrors.IsAlreadyExists(err) {
1148+
return nil
1149+
}
1150+
return fmt.Errorf("failed to create spiffe-helper-config in %s: %w", namespace, err)
1151+
}
1152+
logger.Info("Created spiffe-helper-config from PlatformConfig", "namespace", namespace)
1153+
return nil
1154+
}
1155+
if err != nil {
1156+
return fmt.Errorf("failed to check spiffe-helper-config in %s: %w", namespace, err)
1157+
}
1158+
1159+
needsUpdate := existing.Data["helper.conf"] != cfg.Spiffe.HelperConfig
1160+
1161+
if existing.Labels == nil {
1162+
existing.Labels = make(map[string]string)
1163+
}
1164+
if existing.Labels[LabelManagedBy] != LabelManagedByValue {
1165+
existing.Labels[LabelManagedBy] = LabelManagedByValue
1166+
needsUpdate = true
1167+
}
1168+
1169+
if !needsUpdate {
1170+
return nil
1171+
}
1172+
1173+
existing.Data = desired.Data
1174+
if err := r.Update(ctx, existing); err != nil {
1175+
return fmt.Errorf("failed to update spiffe-helper-config in %s: %w", namespace, err)
1176+
}
1177+
logger.Info("Updated spiffe-helper-config from PlatformConfig", "namespace", namespace)
1178+
return nil
1179+
}
1180+
11001181
const (
11011182
sccClusterRoleName = "system:openshift:scc:kagenti-authbridge"
11021183
sccRoleBindingName = "agent-authbridge-scc"

0 commit comments

Comments
 (0)