@@ -142,6 +142,14 @@ func add(mgr manager.Manager, c ctrlruntime.Controller) error {
142142 return fmt .Errorf ("logcollector-controller failed to watch ConfigMap %s: %v" , rlogcollector .FluentBitFilterConfigMapName , err )
143143 }
144144
145+ // Watch the user-supplied CA ConfigMaps so creating or rotating a syslog or
146+ // Splunk CA takes effect without waiting for an unrelated reconcile.
147+ for _ , caConfigMap := range []string {rlogcollector .SyslogCAConfigMapName , rlogcollector .SplunkCAConfigMapName } {
148+ if err = utils .AddConfigMapWatch (c , caConfigMap , common .OperatorNamespace (), & handler.EnqueueRequestForObject {}); err != nil {
149+ return fmt .Errorf ("logcollector-controller failed to watch ConfigMap %s: %v" , caConfigMap , err )
150+ }
151+ }
152+
145153 // Watch the rendered configuration ConfigMaps so tampering with them
146154 // triggers a reconcile that restores the rendered content.
147155 for _ , configMapName := range []string {
@@ -465,11 +473,11 @@ func (r *ReconcileLogCollector) Reconcile(ctx context.Context, request reconcile
465473 }
466474
467475 // Fluent Bit needs to mount system certificates in the case where Splunk, Syslog or AWS are used.
468- trustedBundle , err := certificateManager . CreateTrustedBundleWithSystemRootCertificates ( prometheusCertificate , linseedCertificate )
469- if err != nil {
470- r . status . SetDegraded ( operatorv1 . ResourceCreateError , "Unable to create tigera-ca- bundle configmap" , err , reqLogger )
471- return reconcile. Result {}, err
472- }
476+ // The bundle carries fluent-bit's own name: calico-system's shared tigera-ca-bundle is rendered by
477+ // the core Installation controller with a different certificate set, and the component handler
478+ // replaces ConfigMap data wholesale — an unnamed bundle here would fight it, and additions like
479+ // the syslog user CA would be lost to whichever controller wrote last.
480+ trustedBundle := certificatemanagement . CreateNamedTrustedBundle ( render . FluentBitNodeName , certificateManager . KeyPair (), true , prometheusCertificate , linseedCertificate )
473481
474482 certificateManager .AddToStatusManager (r .status , render .LogCollectorNamespace )
475483
@@ -524,7 +532,7 @@ func (r *ReconcileLogCollector) Reconcile(ctx context.Context, request reconcile
524532 var useSyslogCertificate bool
525533 if instance .Spec .AdditionalStores != nil {
526534 if instance .Spec .AdditionalStores .Syslog != nil && instance .Spec .AdditionalStores .Syslog .Encryption == operatorv1 .EncryptionTLS {
527- syslogCert , err := getSysLogCertificate (r .client )
535+ syslogCert , err := getUserCACertificate (r .client , rlogcollector . SyslogCAConfigMapName )
528536 if err != nil {
529537 r .status .SetDegraded (operatorv1 .ResourceReadError , "Error loading Syslog certificate" , err , reqLogger )
530538 return reconcile.Result {}, err
@@ -534,6 +542,22 @@ func (r *ReconcileLogCollector) Reconcile(ctx context.Context, request reconcile
534542 trustedBundle .AddCertificates (syslogCert )
535543 }
536544 }
545+ // The Splunk output verifies https HEC endpoints against the trusted
546+ // bundle, so a user CA for a self-hosted Splunk rides the same way as
547+ // the syslog one. Plain-http endpoints do no verification, so like
548+ // syslog's TLS gate the CA is only loaded for https.
549+ if splunk := instance .Spec .AdditionalStores .Splunk ; splunk != nil {
550+ if proto , _ , _ , err := url .ParseEndpoint (splunk .Endpoint ); err == nil && proto == "https" {
551+ splunkCert , err := getUserCACertificate (r .client , rlogcollector .SplunkCAConfigMapName )
552+ if err != nil {
553+ r .status .SetDegraded (operatorv1 .ResourceReadError , "Error loading Splunk certificate" , err , reqLogger )
554+ return reconcile.Result {}, err
555+ }
556+ if splunkCert != nil {
557+ trustedBundle .AddCertificates (splunkCert )
558+ }
559+ }
560+ }
537561 }
538562
539563 if instance .Spec .AdditionalStores != nil {
@@ -872,24 +896,25 @@ func getEksCloudwatchLogConfig(client client.Client, interval int32, region, gro
872896 }, nil
873897}
874898
875- func getSysLogCertificate (client client.Client ) (certificatemanagement.CertificateInterface , error ) {
899+ // getUserCACertificate reads an optional user-supplied CA from the named
900+ // ConfigMap in the operator namespace (key tls.crt), for stores whose TLS
901+ // endpoint is not signed by a publicly trusted CA.
902+ func getUserCACertificate (client client.Client , name string ) (certificatemanagement.CertificateInterface , error ) {
876903 cm := & corev1.ConfigMap {}
877904 cmNamespacedName := types.NamespacedName {
878- Name : rlogcollector . SyslogCAConfigMapName ,
905+ Name : name ,
879906 Namespace : common .OperatorNamespace (),
880907 }
881908 if err := client .Get (context .Background (), cmNamespacedName , cm ); err != nil {
882909 if errors .IsNotFound (err ) {
883- log .Info (fmt .Sprintf ("ConfigMap %q is not found, assuming syslog 's certificate is signed by publicly trusted CA" , rlogcollector . SyslogCAConfigMapName ))
910+ log .Info (fmt .Sprintf ("ConfigMap %q is not found, assuming the endpoint 's certificate is signed by publicly trusted CA" , name ))
884911 return nil , nil
885912 }
886- return nil , fmt .Errorf ("failed to read ConfigMap %q: %s" , rlogcollector . SyslogCAConfigMapName , err )
913+ return nil , fmt .Errorf ("failed to read ConfigMap %q: %s" , name , err )
887914 }
888915 if len (cm .Data [corev1 .TLSCertKey ]) == 0 {
889- log .Info (fmt .Sprintf ("ConfigMap %q does not have a field named %q, assuming syslog 's certificate is signed by publicly trusted CA" , rlogcollector . SyslogCAConfigMapName , corev1 .TLSCertKey ))
916+ log .Info (fmt .Sprintf ("ConfigMap %q does not have a field named %q, assuming the endpoint 's certificate is signed by publicly trusted CA" , name , corev1 .TLSCertKey ))
890917 return nil , nil
891918 }
892- syslogCert := certificatemanagement .NewCertificate (rlogcollector .SyslogCAConfigMapName , common .OperatorNamespace (), []byte (cm .Data [corev1 .TLSCertKey ]), nil )
893-
894- return syslogCert , nil
919+ return certificatemanagement .NewCertificate (name , common .OperatorNamespace (), []byte (cm .Data [corev1 .TLSCertKey ]), nil ), nil
895920}
0 commit comments