Skip to content

Commit f8c06b9

Browse files
authored
Merge pull request #461 from varshaprasad96/feat/mtls-ready-condition
Feat: add MTLSReady condition to AgentRuntime status
2 parents 630e855 + d3cb30e commit f8c06b9

2 files changed

Lines changed: 85 additions & 21 deletions

File tree

kagenti-operator/config/rbac/role.yaml

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@ rules:
4141
- ""
4242
resources:
4343
- serviceaccounts
44-
verbs:
45-
- create
46-
- get
47-
- list
48-
- update
49-
- watch
50-
- apiGroups:
51-
- ""
52-
resources:
5344
- services
5445
verbs:
5546
- create
@@ -168,17 +159,6 @@ rules:
168159
- get
169160
- list
170161
- watch
171-
- apiGroups:
172-
- k8s.keycloak.org
173-
resources:
174-
- keycloakrealmimports
175-
- keycloaks
176-
verbs:
177-
- create
178-
- get
179-
- list
180-
- patch
181-
- update
182162
- apiGroups:
183163
- datasciencecluster.opendatahub.io
184164
resources:
@@ -195,6 +175,17 @@ rules:
195175
- get
196176
- list
197177
- watch
178+
- apiGroups:
179+
- k8s.keycloak.org
180+
resources:
181+
- keycloakrealmimports
182+
- keycloaks
183+
verbs:
184+
- create
185+
- get
186+
- list
187+
- patch
188+
- update
198189
- apiGroups:
199190
- kuadrant.io
200191
resources:

kagenti-operator/internal/controller/agentruntime_controller.go

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ const (
8888

8989
// AnnotationRestartPendingValue is the value set on AnnotationRestartPending.
9090
AnnotationRestartPendingValue = "true"
91+
92+
// SPIRE volume names injected by the webhook when mTLS is enabled.
93+
VolumeSpireAgentSocket = "spire-agent-socket"
94+
VolumeSVIDOutput = "svid-output"
9195
)
9296

9397
var sandboxGVK = schema.GroupVersionKind{
@@ -212,7 +216,10 @@ func (r *AgentRuntimeReconciler) Reconcile(ctx context.Context, req ctrl.Request
212216
fmt.Sprintf("Namespace %s opted out of Istio mesh enrollment", rt.Namespace))
213217
}
214218

215-
// 4.7. Ensure SCC RoleBinding exists in the namespace.
219+
// 4.7. Evaluate MTLSReady condition based on resolved mTLSMode and SPIRE availability.
220+
r.evaluateMTLSReady(ctx, rt)
221+
222+
// 4.8. Ensure SCC RoleBinding exists in the namespace.
216223
// Creates a RoleBinding granting all ServiceAccounts in the namespace
217224
// access to the kagenti-authbridge SCC. No-op on non-OpenShift clusters.
218225
// On OpenShift, a transient failure is retried via requeue to prevent
@@ -763,6 +770,72 @@ func (r *AgentRuntimeReconciler) handleDeletion(ctx context.Context, rt *agentv1
763770
return ctrl.Result{}, nil
764771
}
765772

773+
// evaluateMTLSReady sets the MTLSReady condition based on the resolved
774+
// mTLSMode and whether SPIRE infrastructure is available on the workload.
775+
// This is informational — MTLSReady=False does NOT block Ready=True.
776+
func (r *AgentRuntimeReconciler) evaluateMTLSReady(ctx context.Context, rt *agentv1alpha1.AgentRuntime) {
777+
logger := log.FromContext(ctx)
778+
779+
mtlsMode := rt.Spec.MTLSMode
780+
if mtlsMode == "" {
781+
mtlsMode = "permissive"
782+
}
783+
784+
if mtlsMode == "disabled" {
785+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionTrue, "MTLSDisabled",
786+
"mTLS explicitly disabled on this AgentRuntime")
787+
return
788+
}
789+
790+
// Check if workload has SPIRE infrastructure by looking for
791+
// spire-agent-socket or svid-output volumes in the pod template.
792+
acc, ok := newRuntimePodTemplateAccessor(rt.Spec.TargetRef.Kind)
793+
if !ok {
794+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionFalse, "UnsupportedKind",
795+
fmt.Sprintf("Cannot check SPIRE availability for workload kind %s", rt.Spec.TargetRef.Kind))
796+
return
797+
}
798+
799+
key := types.NamespacedName{Name: rt.Spec.TargetRef.Name, Namespace: rt.Namespace}
800+
if err := r.Get(ctx, key, acc.obj); err != nil {
801+
logger.V(1).Info("Cannot read workload for SPIRE check", "error", err)
802+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionFalse, "WorkloadNotFound",
803+
fmt.Sprintf("Cannot verify SPIRE availability: %v", err))
804+
return
805+
}
806+
807+
podSpec := acc.getPodSpec(acc.obj)
808+
if podSpec == nil {
809+
// Sandbox workloads don't expose a typed PodSpec; assume SPIRE
810+
// is available since the webhook handles injection at pod CREATE.
811+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionTrue, "SPIREAssumed",
812+
"Sandbox workload; SPIRE availability assumed (webhook handles injection)")
813+
return
814+
}
815+
816+
spireDetected := false
817+
for _, v := range podSpec.Volumes {
818+
if v.Name == VolumeSpireAgentSocket || v.Name == VolumeSVIDOutput {
819+
spireDetected = true
820+
break
821+
}
822+
}
823+
824+
if spireDetected {
825+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionTrue, "SPIREAvailable",
826+
fmt.Sprintf("SPIRE volumes detected on workload %s; mTLS mode: %s", rt.Spec.TargetRef.Name, mtlsMode))
827+
} else {
828+
msg := "mTLS requires SPIRE; either deploy SPIRE or set mTLSMode: disabled"
829+
r.setCondition(rt, ConditionTypeMTLSReady, metav1.ConditionFalse, "SPIREUnavailable", msg)
830+
if r.Recorder != nil {
831+
r.Recorder.Eventf(rt, nil, corev1.EventTypeWarning, "SPIREUnavailable",
832+
"MTLSReadyCheck", msg)
833+
}
834+
logger.Info("SPIRE not detected for mTLS-enabled workload",
835+
"workload", rt.Spec.TargetRef.Name, "mtlsMode", mtlsMode)
836+
}
837+
}
838+
766839
func (r *AgentRuntimeReconciler) setCondition(rt *agentv1alpha1.AgentRuntime, condType string, status metav1.ConditionStatus, reason, message string) {
767840
meta.SetStatusCondition(&rt.Status.Conditions, metav1.Condition{
768841
Type: condType,

0 commit comments

Comments
 (0)