You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@solr.apache.org by GitBox <gi...@apache.org> on 2021/10/26 17:49:59 UTC

[GitHub] [solr-operator] thelabdude opened a new pull request #356: Support to bootstrap from a user-supplied security.json and minor refactorings to pass auth headers through a Context

thelabdude opened a new pull request #356:
URL: https://github.com/apache/solr-operator/pull/356


   Resolves #355 
   
   Removes the non-OIDC related security changes from #346 


-- 
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-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr-operator] thelabdude commented on a change in pull request #356: Support to bootstrap from a user-supplied security.json and minor refactorings to pass auth headers through a Context

Posted by GitBox <gi...@apache.org>.
thelabdude commented on a change in pull request #356:
URL: https://github.com/apache/solr-operator/pull/356#discussion_r739452396



##########
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:
       ugh, sorry @HoustonPutman ... moved a little too fast with that conversion! thanks for catching those I missed.




-- 
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-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr-operator] thelabdude merged pull request #356: Support to bootstrap from a user-supplied security.json and minor refactorings to pass auth headers through a Context

Posted by GitBox <gi...@apache.org>.
thelabdude merged pull request #356:
URL: https://github.com/apache/solr-operator/pull/356


   


-- 
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-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org


[GitHub] [solr-operator] HoustonPutman commented on a change in pull request #356: Support to bootstrap from a user-supplied security.json and minor refactorings to pass auth headers through a Context

Posted by GitBox <gi...@apache.org>.
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: issues-unsubscribe@solr.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscribe@solr.apache.org
For additional commands, e-mail: issues-help@solr.apache.org