thelabdude commented on a change in pull request #312: URL: https://github.com/apache/solr-operator/pull/312#discussion_r699689067
########## File path: controllers/solrcloud_controller.go ########## @@ -960,80 +950,160 @@ func (r *SolrCloudReconciler) indexAndWatchForTLSSecret(mgr ctrl.Manager, ctrlBu return ctrlBuilder.Watches( &source.Kind{Type: &corev1.Secret{}}, - &handler.EnqueueRequestsFromMapFunc{ - ToRequests: handler.ToRequestsFunc(func(a handler.MapObject) []reconcile.Request { - foundClouds := &solr.SolrCloudList{} - listOps := &client.ListOptions{ - FieldSelector: fields.OneTermEqualSelector(".spec.solrTLS.pkcs12Secret", a.Meta.GetName()), - Namespace: a.Meta.GetNamespace(), - } - err := r.List(context.TODO(), foundClouds, listOps) - if err != nil { - return []reconcile.Request{} - } + r.findSolrCloudByFieldValueFunc(field), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{})), nil +} - requests := make([]reconcile.Request, len(foundClouds.Items)) - for i, item := range foundClouds.Items { - requests[i] = reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: item.GetName(), - Namespace: item.GetNamespace(), - }, - } - } - return requests - }), - }, +func (r *SolrCloudReconciler) indexAndWatchForClientTLSSecret(mgr ctrl.Manager, ctrlBuilder *builder.Builder) (*builder.Builder, error) { + field := ".spec.solrClientTLS.pkcs12Secret" + if err := mgr.GetFieldIndexer().IndexField(context.TODO(), &solr.SolrCloud{}, field, func(rawObj runtime.Object) []string { + // grab the SolrCloud object, extract the used configMap... + solrCloud := rawObj.(*solr.SolrCloud) + if solrCloud.Spec.SolrClientTLS == nil || solrCloud.Spec.SolrClientTLS.PKCS12Secret == nil { + return nil + } + // ...and if so, return it + return []string{solrCloud.Spec.SolrClientTLS.PKCS12Secret.Name} + }); err != nil { + return ctrlBuilder, err + } + + return ctrlBuilder.Watches( + &source.Kind{Type: &corev1.Secret{}}, + r.findSolrCloudByFieldValueFunc(field), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{})), nil } +func (r *SolrCloudReconciler) findSolrCloudByFieldValueFunc(field string) *handler.EnqueueRequestsFromMapFunc { + return &handler.EnqueueRequestsFromMapFunc{ + ToRequests: handler.ToRequestsFunc(func(a handler.MapObject) []reconcile.Request { + foundClouds := &solr.SolrCloudList{} + listOps := &client.ListOptions{ + FieldSelector: fields.OneTermEqualSelector(field, a.Meta.GetName()), + Namespace: a.Meta.GetNamespace(), + } + err := r.List(context.TODO(), foundClouds, listOps) + if err != nil { + return []reconcile.Request{} + } + + requests := make([]reconcile.Request, len(foundClouds.Items)) + for i, item := range foundClouds.Items { + requests[i] = reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: item.GetName(), + Namespace: item.GetNamespace(), + }, + } + } + return requests + }), + } +} + // Ensure the TLS config is ready, such as verifying the TLS secret exists, to enable TLS on SolrCloud pods -func (r *SolrCloudReconciler) reconcileTLSConfig(instance *solr.SolrCloud) (*util.TLSConfig, error) { - tls := &util.TLSConfig{} - tls.InitContainerImage = instance.Spec.BusyBoxImage - tls.Options = instance.Spec.SolrTLS +func (r *SolrCloudReconciler) reconcileTLSConfig(instance *solr.SolrCloud) (*util.TLSCerts, error) { + tls := util.TLSCertsForSolrCloud(instance) // Has the user configured a secret containing the TLS cert files that we need to mount into the Solr pods? - if instance.Spec.SolrTLS.PKCS12Secret != nil { + serverCert := tls.ServerConfig.Options + if serverCert.PKCS12Secret != nil { // Ensure one or the other have been configured, but not both - if instance.Spec.SolrTLS.MountedServerTLSDir != nil { - return nil, fmt.Errorf("invalid TLS config, either supply `solrTLS.pkcs12Secret` or `solrTLS.mountedServerTLSDir` but not both") + if serverCert.MountedTLSDir != nil { + return nil, fmt.Errorf("invalid TLS config, either supply `solrTLS.pkcs12Secret` or `solrTLS.mountedTLSDir` but not both") } - foundTLSSecret, err := r.verifyTLSSecretConfig(instance.Spec.SolrTLS.PKCS12Secret.Name, instance.Namespace, instance.Spec.SolrTLS.KeyStorePasswordSecret) + foundTLSSecret, err := r.verifyTLSSecretConfig(serverCert.PKCS12Secret.Name, instance.Namespace, serverCert.KeyStorePasswordSecret) if err != nil { return nil, err } else { - // We have a watch on secrets, so will get notified when the secret changes (such as after cert renewal) - // capture the hash of the secret and stash in an annotation so that pods get restarted if the cert changes - if instance.Spec.SolrTLS.RestartOnTLSSecretUpdate { - if tlsCertBytes, ok := foundTLSSecret.Data[util.TLSCertKey]; ok { - tls.CertMd5 = fmt.Sprintf("%x", md5.Sum(tlsCertBytes)) - } else { - return nil, fmt.Errorf("%s key not found in TLS secret %s, cannot watch for updates to"+ - " the cert without this data but 'solrTLS.restartOnTLSSecretUpdate' is enabled", - util.TLSCertKey, foundTLSSecret.Name) + if serverCert.RestartOnTLSSecretUpdate { + tls.ServerConfig.CertMd5, err = r.computeCertMd5(foundTLSSecret) + if err != nil { + return nil, err } + tls.ServerConfig.CertMd5Annotation = util.SolrTlsCertMd5Annotation } - if _, ok := foundTLSSecret.Data[instance.Spec.SolrTLS.PKCS12Secret.Key]; !ok { + if _, ok := foundTLSSecret.Data[serverCert.PKCS12Secret.Key]; !ok { // the keystore.p12 key is not in the TLS secret, indicating we need to create it using an initContainer - tls.NeedsPkcs12InitContainer = true + tls.ServerConfig.NeedsPkcs12InitContainer = true } } - if instance.Spec.SolrTLS.TrustStoreSecret != nil { + if serverCert.TrustStoreSecret != nil { // verify the TrustStore secret is configured correctly - passwordSecret := instance.Spec.SolrTLS.TrustStorePasswordSecret - if passwordSecret == nil { - passwordSecret = instance.Spec.SolrTLS.KeyStorePasswordSecret + err = r.verifyTruststoreConfig(serverCert, instance.Namespace) + if err != nil { + return nil, err + } + } else { + // does the supplied keystore secret also contain the truststore? + if _, ok := foundTLSSecret.Data[util.DefaultPkcs12TruststoreFile]; ok { + // there's a truststore in the supplied TLS secret + serverCert.TrustStoreSecret = &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: foundTLSSecret.Name}, + Key: util.DefaultPkcs12TruststoreFile, + } + serverCert.TrustStorePasswordSecret = serverCert.KeyStorePasswordSecret } - _, err := r.verifyTLSSecretConfig(instance.Spec.SolrTLS.TrustStoreSecret.Name, instance.Namespace, passwordSecret) + } + + // is there a client TLS config too? + if tls.ClientConfig != nil { + if tls.ClientConfig.Options.PKCS12Secret == nil { + // cannot mix options with the client cert, if the server cert comes from a secret, so too must the client, not a mountedTLSDir + return nil, fmt.Errorf("invalid TLS config, the 'solrClientTLS.pkcs12Secret' option is required when using a secret for server cert") + } + + clientOpts := tls.ClientConfig.Options + // shouldn't configure a client cert if it's the same as the server cert + if clientOpts.PKCS12Secret == tls.ServerConfig.Options.PKCS12Secret { + return nil, fmt.Errorf("invalid TLS config, the 'solrClientTLS.pkcs12Secret' option should not be the same as the 'solrTLS.pkcs12Secret'") Review comment: Probably not an issue for Solr but seemed like that would be a mis-configuration / accident by the user since it wouldn't be sensible to use the same cert for the client & server (you don't need a separate client in that case) so I felt raising an error would help draw attention to a mistake. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org For additional commands, e-mail: issues-h...@solr.apache.org