@@ -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
9397var 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+
766839func (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