HoustonPutman commented on a change in pull request #356:
URL: https://github.com/apache/solr-operator/pull/356#discussion_r739432363



##########
File path: controllers/solrcloud_controller_basic_auth_test.go
##########
@@ -144,6 +173,34 @@ var _ = FDescribe("SolrCloud controller - Basic Auth", 
func() {
                        expectStatefulSetBasicAuthConfig(ctx, solrCloud, false)
                })
        })
+
+       FContext("User Provided Credentials and security.json ConfigMap", 
func() {

Review comment:
       ```suggestion
        FContext("User Provided Credentials and security.json Secret", func() {
   ```

##########
File path: controllers/util/solr_security_util.go
##########
@@ -43,101 +44,134 @@ const (
        DefaultProbePath       = "/admin/info/system"
 )
 
+// Utility struct holding security related config and objects resolved at 
runtime needed during reconciliation,
+// such as the secret holding credentials the operator should use to make 
calls to secure Solr
 type SecurityConfig struct {
-       BasicAuthSecret *corev1.Secret
-       SecurityJson    string
+       SolrSecurity      *solr.SolrSecurityOptions
+       CredentialsSecret *corev1.Secret
+       SecurityJson      string
+       SecurityJsonSrc   *corev1.EnvVarSource
 }
 
 // Given a SolrCloud instance and an API service client, produce a 
SecurityConfig needed to enable Solr security
 func ReconcileSecurityConfig(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
-       reader := *client
+       sec := instance.Spec.SolrSecurity
+       if sec.AuthenticationType == solr.Basic {
+               return reconcileForBasicAuth(ctx, client, instance)
+       }
 
-       security := &SecurityConfig{}
-       basicAuthSecret := &corev1.Secret{}
+       // shouldn't ever get here since the YAML would be validated against 
the enum before this, but keeping it here for human readers to grok the overall 
flow
+       return nil, fmt.Errorf("%s not supported! Only 'Basic' authentication 
is supported by the Solr operator", sec.AuthenticationType)
+}
 
+// Reconcile the credentials and supporting config needed to make calls to 
Solr secured with basic auth
+// Also, bootstraps an initial security.json config if not supplied by the user
+// However, if users provide their own security.json, then they must also 
provide the basic auth secret containing
+// credentials the operator should use for making calls to Solr. In other 
words, we don't try to infuse a new user into
+// the user-provided security.json as that could get messy.
+func reconcileForBasicAuth(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
        // user has the option of providing a secret with credentials the 
operator should use to make requests to Solr
+       if instance.Spec.SolrSecurity.BasicAuthSecret != "" {
+               return reconcileForBasicAuthWithUserProvidedSecret(ctx, client, 
instance)
+       } else {
+               // user didn't provide a basicAuthSecret, so it's invalid for 
them to provide a security.json as the operator
+               // has no way of authenticating to Solr with a user provided 
security.json w/o also having the credentials in a secret
+               if instance.Spec.SolrSecurity.BootstrapSecurityJson != nil {
+                       return nil, fmt.Errorf("invalid basic auth config, you 
must also provide the 'basicAuthSecret' when providing your own 
'security.json'")
+               }
+               return reconcileForBasicAuthWithBootstrappedSecurityJson(ctx, 
client, instance)
+       }
+}
+
+// Create a "bootstrap" security.json with basic auth enabled with the 
"admin", "solr", and "k8s" users having random passwords
+func reconcileForBasicAuthWithBootstrappedSecurityJson(ctx context.Context, 
client *client.Client, instance *solr.SolrCloud) (*SecurityConfig, error) {
+       reader := *client
+
        sec := instance.Spec.SolrSecurity
+       security := &SecurityConfig{SolrSecurity: sec}
 
-       if sec.AuthenticationType != solr.Basic {
-               return nil, fmt.Errorf("%s not supported! Only 'Basic' 
authentication is supported by the Solr operator",
-                       instance.Spec.SolrSecurity.AuthenticationType)
-       }
+       // We're supplying a secret with random passwords and a default 
security.json
+       // since we randomly generate the passwords, we need to lookup the 
secret first and only create if not exist
+       basicAuthSecret := &corev1.Secret{}
+       err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
+       if err != nil && errors.IsNotFound(err) {
+               authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
 
-       // TODO: we shouldn't need to enforce this restriction?!?
-       //
-       // for now, we don't support 'solrSecurity.probesRequireAuth=true' and 
custom probe paths,
-       // so make the user fix that so there are no surprises later
-       if sec.ProbesRequireAuth && 
instance.Spec.CustomSolrKubeOptions.PodOptions != nil {
-               for _, path := range GetCustomProbePaths(instance) {
-                       if path != DefaultProbePath {
-                               return nil, fmt.Errorf(
-                                       "custom probe path %s not supported 
when 'solrSecurity.probesRequireAuth=true'; must use 
'solrSecurity.probesRequireAuth=false' when using custom probe endpoints", path)
-                       }
+               // take ownership of these secrets since we created them
+               if err := controllerutil.SetControllerReference(instance, 
authSecret, reader.Scheme()); err != nil {
+                       return nil, err
                }
-       }
-
-       if sec.BasicAuthSecret != "" {
-               // the user supplied their own basic auth secret, make sure it 
exists and has the expected keys
-               if err := reader.Get(ctx, types.NamespacedName{Name: 
sec.BasicAuthSecret, Namespace: instance.Namespace}, basicAuthSecret); err != 
nil {
+               if err := controllerutil.SetControllerReference(instance, 
bootstrapSecret, reader.Scheme()); err != nil {
                        return nil, err
                }
-
-               err := ValidateBasicAuthSecret(basicAuthSecret)
+               err = reader.Create(ctx, authSecret)
+               if err != nil {
+                       return nil, err
+               }
+               err = reader.Create(ctx, bootstrapSecret)
                if err != nil {
                        return nil, err
                }
 
-               // since the user supplied us with a basic auth secret, we're 
assuming they're also bootstrapping the security.json,
-               // so there is no bootstrap secret in this case
+               // supply the bootstrap security.json to the initContainer via 
a simple BASE64 encoding env var
+               security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
+               basicAuthSecret = authSecret
+       }
 
-       } else {
-               // We're supplying a secret with random passwords and a default 
security.json
-               // since we randomly generate the passwords, we need to lookup 
the secret first and only create if not exist
-               err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
-               if err != nil && errors.IsNotFound(err) {
-                       authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
-
-                       // take ownership of these secrets since we created them
-                       if err := 
controllerutil.SetControllerReference(instance, authSecret, reader.Scheme()); 
err != nil {
-                               return nil, err
-                       }
-                       if err := 
controllerutil.SetControllerReference(instance, bootstrapSecret, 
reader.Scheme()); err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, authSecret)
-                       if err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, bootstrapSecret)
-                       if err != nil {
-                               return nil, err
-                       }
+       if err != nil {
+               return nil, err
+       }
+       security.CredentialsSecret = basicAuthSecret
 
-                       // supply the bootstrap security.json to the 
initContainer via a simple BASE64 encoding env var
+       if security.SecurityJson == "" {
+               // the bootstrap secret already exists, so just stash the 
security.json needed for constructing initContainers
+               bootstrapSecret := &corev1.Secret{}
+               err = reader.Get(ctx, types.NamespacedName{Name: 
instance.SecurityBootstrapSecretName(), Namespace: instance.Namespace}, 
bootstrapSecret)
+               if err != nil {
+                       if !errors.IsNotFound(err) {
+                               return nil, err
+                       } // else perhaps the user deleted it after security 
was bootstrapped ... this is ok but may trigger a restart on the STS
+               } else {
+                       // stash this so we can configure the setup-zk 
initContainer to bootstrap the security.json in ZK
                        security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
-                       basicAuthSecret = authSecret
+                       security.SecurityJsonSrc = &corev1.EnvVarSource{

Review comment:
       Nice. love it.

##########
File path: controllers/util/solr_security_util.go
##########
@@ -431,3 +483,22 @@ func useSecureProbe(solrCloud *solr.SolrCloud, probe 
*corev1.Probe, mountPath st
                probe.TimeoutSeconds = 5
        }
 }
+
+// Called during reconcile to load the security.json from a user-supplied 
ConfigMap

Review comment:
       ```suggestion
   // Called during reconcile to load the security.json from a user-supplied 
Secret
   ```

##########
File path: controllers/util/solr_security_util.go
##########
@@ -43,101 +44,134 @@ const (
        DefaultProbePath       = "/admin/info/system"
 )
 
+// Utility struct holding security related config and objects resolved at 
runtime needed during reconciliation,
+// such as the secret holding credentials the operator should use to make 
calls to secure Solr
 type SecurityConfig struct {
-       BasicAuthSecret *corev1.Secret
-       SecurityJson    string
+       SolrSecurity      *solr.SolrSecurityOptions
+       CredentialsSecret *corev1.Secret
+       SecurityJson      string
+       SecurityJsonSrc   *corev1.EnvVarSource
 }
 
 // Given a SolrCloud instance and an API service client, produce a 
SecurityConfig needed to enable Solr security
 func ReconcileSecurityConfig(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
-       reader := *client
+       sec := instance.Spec.SolrSecurity
+       if sec.AuthenticationType == solr.Basic {
+               return reconcileForBasicAuth(ctx, client, instance)
+       }
 
-       security := &SecurityConfig{}
-       basicAuthSecret := &corev1.Secret{}
+       // shouldn't ever get here since the YAML would be validated against 
the enum before this, but keeping it here for human readers to grok the overall 
flow
+       return nil, fmt.Errorf("%s not supported! Only 'Basic' authentication 
is supported by the Solr operator", sec.AuthenticationType)
+}
 
+// Reconcile the credentials and supporting config needed to make calls to 
Solr secured with basic auth
+// Also, bootstraps an initial security.json config if not supplied by the user
+// However, if users provide their own security.json, then they must also 
provide the basic auth secret containing
+// credentials the operator should use for making calls to Solr. In other 
words, we don't try to infuse a new user into
+// the user-provided security.json as that could get messy.
+func reconcileForBasicAuth(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
        // user has the option of providing a secret with credentials the 
operator should use to make requests to Solr
+       if instance.Spec.SolrSecurity.BasicAuthSecret != "" {
+               return reconcileForBasicAuthWithUserProvidedSecret(ctx, client, 
instance)
+       } else {
+               // user didn't provide a basicAuthSecret, so it's invalid for 
them to provide a security.json as the operator
+               // has no way of authenticating to Solr with a user provided 
security.json w/o also having the credentials in a secret
+               if instance.Spec.SolrSecurity.BootstrapSecurityJson != nil {
+                       return nil, fmt.Errorf("invalid basic auth config, you 
must also provide the 'basicAuthSecret' when providing your own 
'security.json'")
+               }
+               return reconcileForBasicAuthWithBootstrappedSecurityJson(ctx, 
client, instance)
+       }
+}
+
+// Create a "bootstrap" security.json with basic auth enabled with the 
"admin", "solr", and "k8s" users having random passwords
+func reconcileForBasicAuthWithBootstrappedSecurityJson(ctx context.Context, 
client *client.Client, instance *solr.SolrCloud) (*SecurityConfig, error) {
+       reader := *client
+
        sec := instance.Spec.SolrSecurity
+       security := &SecurityConfig{SolrSecurity: sec}
 
-       if sec.AuthenticationType != solr.Basic {
-               return nil, fmt.Errorf("%s not supported! Only 'Basic' 
authentication is supported by the Solr operator",
-                       instance.Spec.SolrSecurity.AuthenticationType)
-       }
+       // We're supplying a secret with random passwords and a default 
security.json
+       // since we randomly generate the passwords, we need to lookup the 
secret first and only create if not exist
+       basicAuthSecret := &corev1.Secret{}
+       err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
+       if err != nil && errors.IsNotFound(err) {
+               authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
 
-       // TODO: we shouldn't need to enforce this restriction?!?
-       //
-       // for now, we don't support 'solrSecurity.probesRequireAuth=true' and 
custom probe paths,
-       // so make the user fix that so there are no surprises later
-       if sec.ProbesRequireAuth && 
instance.Spec.CustomSolrKubeOptions.PodOptions != nil {
-               for _, path := range GetCustomProbePaths(instance) {
-                       if path != DefaultProbePath {
-                               return nil, fmt.Errorf(
-                                       "custom probe path %s not supported 
when 'solrSecurity.probesRequireAuth=true'; must use 
'solrSecurity.probesRequireAuth=false' when using custom probe endpoints", path)
-                       }
+               // take ownership of these secrets since we created them
+               if err := controllerutil.SetControllerReference(instance, 
authSecret, reader.Scheme()); err != nil {
+                       return nil, err
                }
-       }
-
-       if sec.BasicAuthSecret != "" {
-               // the user supplied their own basic auth secret, make sure it 
exists and has the expected keys
-               if err := reader.Get(ctx, types.NamespacedName{Name: 
sec.BasicAuthSecret, Namespace: instance.Namespace}, basicAuthSecret); err != 
nil {
+               if err := controllerutil.SetControllerReference(instance, 
bootstrapSecret, reader.Scheme()); err != nil {
                        return nil, err
                }
-
-               err := ValidateBasicAuthSecret(basicAuthSecret)
+               err = reader.Create(ctx, authSecret)
+               if err != nil {
+                       return nil, err
+               }
+               err = reader.Create(ctx, bootstrapSecret)
                if err != nil {
                        return nil, err
                }
 
-               // since the user supplied us with a basic auth secret, we're 
assuming they're also bootstrapping the security.json,
-               // so there is no bootstrap secret in this case
+               // supply the bootstrap security.json to the initContainer via 
a simple BASE64 encoding env var
+               security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
+               basicAuthSecret = authSecret
+       }
 
-       } else {
-               // We're supplying a secret with random passwords and a default 
security.json
-               // since we randomly generate the passwords, we need to lookup 
the secret first and only create if not exist
-               err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
-               if err != nil && errors.IsNotFound(err) {
-                       authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
-
-                       // take ownership of these secrets since we created them
-                       if err := 
controllerutil.SetControllerReference(instance, authSecret, reader.Scheme()); 
err != nil {
-                               return nil, err
-                       }
-                       if err := 
controllerutil.SetControllerReference(instance, bootstrapSecret, 
reader.Scheme()); err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, authSecret)
-                       if err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, bootstrapSecret)
-                       if err != nil {
-                               return nil, err
-                       }
+       if err != nil {
+               return nil, err
+       }
+       security.CredentialsSecret = basicAuthSecret
 
-                       // supply the bootstrap security.json to the 
initContainer via a simple BASE64 encoding env var
+       if security.SecurityJson == "" {
+               // the bootstrap secret already exists, so just stash the 
security.json needed for constructing initContainers
+               bootstrapSecret := &corev1.Secret{}
+               err = reader.Get(ctx, types.NamespacedName{Name: 
instance.SecurityBootstrapSecretName(), Namespace: instance.Namespace}, 
bootstrapSecret)
+               if err != nil {
+                       if !errors.IsNotFound(err) {
+                               return nil, err
+                       } // else perhaps the user deleted it after security 
was bootstrapped ... this is ok but may trigger a restart on the STS
+               } else {
+                       // stash this so we can configure the setup-zk 
initContainer to bootstrap the security.json in ZK
                        security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
-                       basicAuthSecret = authSecret
+                       security.SecurityJsonSrc = &corev1.EnvVarSource{
+                               SecretKeyRef: &corev1.SecretKeySelector{
+                                       LocalObjectReference: 
corev1.LocalObjectReference{Name: bootstrapSecret.Name}, Key: SecurityJsonFile}}
                }
+       }
+
+       return security, nil
+}
+
+// Basic auth but the user provides a secret containing credentials the 
operator should use to make requests to a secure Solr
+func reconcileForBasicAuthWithUserProvidedSecret(ctx context.Context, client 
*client.Client, instance *solr.SolrCloud) (*SecurityConfig, error) {
+       reader := *client
+
+       sec := instance.Spec.SolrSecurity
+       security := &SecurityConfig{SolrSecurity: sec}
 
+       // the user supplied their own basic auth secret, make sure it exists 
and has the expected keys
+       basicAuthSecret := &corev1.Secret{}
+       if err := reader.Get(ctx, types.NamespacedName{Name: 
sec.BasicAuthSecret, Namespace: instance.Namespace}, basicAuthSecret); err != 
nil {
+               return nil, err
+       }
+
+       err := ValidateBasicAuthSecret(basicAuthSecret)
+       if err != nil {
+               return nil, err
+       }
+       security.CredentialsSecret = basicAuthSecret
+
+       // is there a user-provided security.json in a ConfigMap?

Review comment:
       ```suggestion
        // is there a user-provided security.json in a Secret?
   ```

##########
File path: controllers/util/solr_security_util.go
##########
@@ -43,101 +44,134 @@ const (
        DefaultProbePath       = "/admin/info/system"
 )
 
+// Utility struct holding security related config and objects resolved at 
runtime needed during reconciliation,
+// such as the secret holding credentials the operator should use to make 
calls to secure Solr
 type SecurityConfig struct {
-       BasicAuthSecret *corev1.Secret
-       SecurityJson    string
+       SolrSecurity      *solr.SolrSecurityOptions
+       CredentialsSecret *corev1.Secret
+       SecurityJson      string
+       SecurityJsonSrc   *corev1.EnvVarSource
 }
 
 // Given a SolrCloud instance and an API service client, produce a 
SecurityConfig needed to enable Solr security
 func ReconcileSecurityConfig(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
-       reader := *client
+       sec := instance.Spec.SolrSecurity
+       if sec.AuthenticationType == solr.Basic {
+               return reconcileForBasicAuth(ctx, client, instance)
+       }
 
-       security := &SecurityConfig{}
-       basicAuthSecret := &corev1.Secret{}
+       // shouldn't ever get here since the YAML would be validated against 
the enum before this, but keeping it here for human readers to grok the overall 
flow
+       return nil, fmt.Errorf("%s not supported! Only 'Basic' authentication 
is supported by the Solr operator", sec.AuthenticationType)
+}
 
+// Reconcile the credentials and supporting config needed to make calls to 
Solr secured with basic auth
+// Also, bootstraps an initial security.json config if not supplied by the user
+// However, if users provide their own security.json, then they must also 
provide the basic auth secret containing
+// credentials the operator should use for making calls to Solr. In other 
words, we don't try to infuse a new user into
+// the user-provided security.json as that could get messy.
+func reconcileForBasicAuth(ctx context.Context, client *client.Client, 
instance *solr.SolrCloud) (*SecurityConfig, error) {
        // user has the option of providing a secret with credentials the 
operator should use to make requests to Solr
+       if instance.Spec.SolrSecurity.BasicAuthSecret != "" {
+               return reconcileForBasicAuthWithUserProvidedSecret(ctx, client, 
instance)
+       } else {
+               // user didn't provide a basicAuthSecret, so it's invalid for 
them to provide a security.json as the operator
+               // has no way of authenticating to Solr with a user provided 
security.json w/o also having the credentials in a secret
+               if instance.Spec.SolrSecurity.BootstrapSecurityJson != nil {
+                       return nil, fmt.Errorf("invalid basic auth config, you 
must also provide the 'basicAuthSecret' when providing your own 
'security.json'")
+               }
+               return reconcileForBasicAuthWithBootstrappedSecurityJson(ctx, 
client, instance)
+       }
+}
+
+// Create a "bootstrap" security.json with basic auth enabled with the 
"admin", "solr", and "k8s" users having random passwords
+func reconcileForBasicAuthWithBootstrappedSecurityJson(ctx context.Context, 
client *client.Client, instance *solr.SolrCloud) (*SecurityConfig, error) {
+       reader := *client
+
        sec := instance.Spec.SolrSecurity
+       security := &SecurityConfig{SolrSecurity: sec}
 
-       if sec.AuthenticationType != solr.Basic {
-               return nil, fmt.Errorf("%s not supported! Only 'Basic' 
authentication is supported by the Solr operator",
-                       instance.Spec.SolrSecurity.AuthenticationType)
-       }
+       // We're supplying a secret with random passwords and a default 
security.json
+       // since we randomly generate the passwords, we need to lookup the 
secret first and only create if not exist
+       basicAuthSecret := &corev1.Secret{}
+       err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
+       if err != nil && errors.IsNotFound(err) {
+               authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
 
-       // TODO: we shouldn't need to enforce this restriction?!?
-       //
-       // for now, we don't support 'solrSecurity.probesRequireAuth=true' and 
custom probe paths,
-       // so make the user fix that so there are no surprises later
-       if sec.ProbesRequireAuth && 
instance.Spec.CustomSolrKubeOptions.PodOptions != nil {
-               for _, path := range GetCustomProbePaths(instance) {
-                       if path != DefaultProbePath {
-                               return nil, fmt.Errorf(
-                                       "custom probe path %s not supported 
when 'solrSecurity.probesRequireAuth=true'; must use 
'solrSecurity.probesRequireAuth=false' when using custom probe endpoints", path)
-                       }
+               // take ownership of these secrets since we created them
+               if err := controllerutil.SetControllerReference(instance, 
authSecret, reader.Scheme()); err != nil {
+                       return nil, err
                }
-       }
-
-       if sec.BasicAuthSecret != "" {
-               // the user supplied their own basic auth secret, make sure it 
exists and has the expected keys
-               if err := reader.Get(ctx, types.NamespacedName{Name: 
sec.BasicAuthSecret, Namespace: instance.Namespace}, basicAuthSecret); err != 
nil {
+               if err := controllerutil.SetControllerReference(instance, 
bootstrapSecret, reader.Scheme()); err != nil {
                        return nil, err
                }
-
-               err := ValidateBasicAuthSecret(basicAuthSecret)
+               err = reader.Create(ctx, authSecret)
+               if err != nil {
+                       return nil, err
+               }
+               err = reader.Create(ctx, bootstrapSecret)
                if err != nil {
                        return nil, err
                }
 
-               // since the user supplied us with a basic auth secret, we're 
assuming they're also bootstrapping the security.json,
-               // so there is no bootstrap secret in this case
+               // supply the bootstrap security.json to the initContainer via 
a simple BASE64 encoding env var
+               security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
+               basicAuthSecret = authSecret
+       }
 
-       } else {
-               // We're supplying a secret with random passwords and a default 
security.json
-               // since we randomly generate the passwords, we need to lookup 
the secret first and only create if not exist
-               err := reader.Get(ctx, types.NamespacedName{Name: 
instance.BasicAuthSecretName(), Namespace: instance.Namespace}, basicAuthSecret)
-               if err != nil && errors.IsNotFound(err) {
-                       authSecret, bootstrapSecret := 
generateBasicAuthSecretWithBootstrap(instance)
-
-                       // take ownership of these secrets since we created them
-                       if err := 
controllerutil.SetControllerReference(instance, authSecret, reader.Scheme()); 
err != nil {
-                               return nil, err
-                       }
-                       if err := 
controllerutil.SetControllerReference(instance, bootstrapSecret, 
reader.Scheme()); err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, authSecret)
-                       if err != nil {
-                               return nil, err
-                       }
-                       err = reader.Create(ctx, bootstrapSecret)
-                       if err != nil {
-                               return nil, err
-                       }
+       if err != nil {
+               return nil, err
+       }
+       security.CredentialsSecret = basicAuthSecret
 
-                       // supply the bootstrap security.json to the 
initContainer via a simple BASE64 encoding env var
+       if security.SecurityJson == "" {
+               // the bootstrap secret already exists, so just stash the 
security.json needed for constructing initContainers
+               bootstrapSecret := &corev1.Secret{}
+               err = reader.Get(ctx, types.NamespacedName{Name: 
instance.SecurityBootstrapSecretName(), Namespace: instance.Namespace}, 
bootstrapSecret)
+               if err != nil {
+                       if !errors.IsNotFound(err) {
+                               return nil, err
+                       } // else perhaps the user deleted it after security 
was bootstrapped ... this is ok but may trigger a restart on the STS
+               } else {
+                       // stash this so we can configure the setup-zk 
initContainer to bootstrap the security.json in ZK
                        security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
-                       basicAuthSecret = authSecret
+                       security.SecurityJsonSrc = &corev1.EnvVarSource{
+                               SecretKeyRef: &corev1.SecretKeySelector{
+                                       LocalObjectReference: 
corev1.LocalObjectReference{Name: bootstrapSecret.Name}, Key: SecurityJsonFile}}
                }
+       }
+
+       return security, nil
+}
+
+// Basic auth but the user provides a secret containing credentials the 
operator should use to make requests to a secure Solr
+func reconcileForBasicAuthWithUserProvidedSecret(ctx context.Context, client 
*client.Client, instance *solr.SolrCloud) (*SecurityConfig, error) {
+       reader := *client
+
+       sec := instance.Spec.SolrSecurity
+       security := &SecurityConfig{SolrSecurity: sec}
 
+       // the user supplied their own basic auth secret, make sure it exists 
and has the expected keys
+       basicAuthSecret := &corev1.Secret{}
+       if err := reader.Get(ctx, types.NamespacedName{Name: 
sec.BasicAuthSecret, Namespace: instance.Namespace}, basicAuthSecret); err != 
nil {
+               return nil, err
+       }
+
+       err := ValidateBasicAuthSecret(basicAuthSecret)
+       if err != nil {
+               return nil, err
+       }
+       security.CredentialsSecret = basicAuthSecret
+
+       // is there a user-provided security.json in a ConfigMap?
+       // in this config, we don't need to enforce the user providing a 
security.json as they can bootstrap the security.json however they want
+       if sec.BootstrapSecurityJson != nil {
+               securityJson, err := loadSecurityJsonFromSecret(ctx, client, 
sec.BootstrapSecurityJson, instance.Namespace)
                if err != nil {
                        return nil, err
                }
-
-               security.BasicAuthSecret = basicAuthSecret
-
-               if security.SecurityJson == "" {
-                       // the bootstrap secret already exists, so just stash 
the security.json needed for constructing initContainers
-                       bootstrapSecret := &corev1.Secret{}
-                       err = reader.Get(ctx, types.NamespacedName{Name: 
instance.SecurityBootstrapSecretName(), Namespace: instance.Namespace}, 
bootstrapSecret)
-                       if err != nil {
-                               if !errors.IsNotFound(err) {
-                                       return nil, err
-                               } // else perhaps the user deleted it after 
security was bootstrapped ... this is ok but may trigger a restart on the STS
-                       } else {
-                               // stash this so we can configure the setup-zk 
initContainer to bootstrap the security.json in ZK
-                               security.SecurityJson = 
string(bootstrapSecret.Data[SecurityJsonFile])
-                       }
-               }
-       }
+               security.SecurityJson = securityJson
+               security.SecurityJsonSrc = &corev1.EnvVarSource{SecretKeyRef: 
sec.BootstrapSecurityJson}
+       } // else no user-provided configMap, no sweat for us

Review comment:
       ```suggestion
        } // else no user-provided secret, no sweat for us
   ```




-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to