thelabdude commented on a change in pull request #221:
URL: 
https://github.com/apache/lucene-solr-operator/pull/221#discussion_r577999978



##########
File path: controllers/util/solr_util.go
##########
@@ -1158,3 +1195,170 @@ func createZkConnectionEnvVars(solrCloud 
*solr.SolrCloud, solrCloudStatus *solr.
 
        return envVars, solrOpt, len(zkChroot) > 1
 }
+
+func setupVolumeMountForUserProvidedConfigMapEntry(configMapInfo 
map[string]string, fileKey string, solrVolumes []corev1.Volume, envVar string) 
(*corev1.VolumeMount, *corev1.EnvVar, *corev1.Volume) {
+       volName := strings.ReplaceAll(fileKey, ".", "-")
+       mountPath := fmt.Sprintf("/var/solr/%s", configMapInfo[fileKey])
+       appendedToExisting := false
+       if configMapInfo[fileKey] == configMapInfo[SolrXmlFile] {
+               // the user provided a custom log4j2.xml and solr.xml, append 
to the volume for solr.xml created above
+               for _, vol := range solrVolumes {
+                       if vol.Name == "solr-xml" {
+                               vol.ConfigMap.Items = 
append(vol.ConfigMap.Items, corev1.KeyToPath{Key: fileKey, Path: fileKey})
+                               appendedToExisting = true
+                               volName = vol.Name
+                               break
+                       }
+               }
+       }
+
+       var vol *corev1.Volume = nil
+       if !appendedToExisting {
+               defaultMode := int32(420)
+               vol = &corev1.Volume{
+                       Name: volName,
+                       VolumeSource: corev1.VolumeSource{
+                               ConfigMap: &corev1.ConfigMapVolumeSource{
+                                       LocalObjectReference: 
corev1.LocalObjectReference{Name: configMapInfo[fileKey]},
+                                       Items:                
[]corev1.KeyToPath{{Key: fileKey, Path: fileKey}},
+                                       DefaultMode:          &defaultMode,
+                               },
+                       },
+               }
+       }
+       pathToFile := fmt.Sprintf("%s/%s", mountPath, fileKey)
+
+       return &corev1.VolumeMount{Name: volName, MountPath: mountPath}, 
&corev1.EnvVar{Name: envVar, Value: pathToFile}, vol
+}
+
+func GenerateSecurityJsonConfigMap(solrCloud *solr.SolrCloud, basicAuthSecret 
*corev1.Secret) *corev1.ConfigMap {
+       labels := solrCloud.SharedLabelsWith(solrCloud.GetLabels())
+       var annotations map[string]string
+
+       customOptions := solrCloud.Spec.CustomSolrKubeOptions.ConfigMapOptions
+       if nil != customOptions {
+               labels = MergeLabelsOrAnnotations(labels, customOptions.Labels)
+               annotations = MergeLabelsOrAnnotations(annotations, 
customOptions.Annotations)
+       }
+
+       username := solrCloud.BasicAuthUsername()
+
+       blockUnknown := true
+       anonymousPaths := ""
+       if solrCloud.Spec.SolrSecurity.InitAnonymousEndpoints != nil && 
len(solrCloud.Spec.SolrSecurity.InitAnonymousEndpoints) > 0 {
+               blockUnknown = false // to allow anonymous access to query 
endpoints
+
+               for i, path := range 
solrCloud.Spec.SolrSecurity.InitAnonymousEndpoints {
+                       fromPath := strings.ReplaceAll(strings.ReplaceAll(path, 
"/", "_"), "*", "_")
+                       name := fmt.Sprintf("anonymous%d%s", i, fromPath)
+                       anonymousPaths += fmt.Sprintf(", { \"name\": \"%s\", 
\"path\": \"%s\", \"collection\": \"*\", \"role\": null }", name, path)
+               }
+       }
+
+       // create a security.json with the same passwords from our secret
+       // hashed with random salt, just as Solr's hashing works
+       adminPasswordHash := solrPasswordHash(basicAuthSecret.Data["admin"])
+       operPasswordHash := solrPasswordHash(basicAuthSecret.Data[username])
+       solrPasswordHash := solrPasswordHash(basicAuthSecret.Data["solr"])
+
+       configMap := &corev1.ConfigMap{
+               ObjectMeta: metav1.ObjectMeta{
+                       Name:        solrCloud.SecurityJsonConfigMapName(),
+                       Namespace:   solrCloud.GetNamespace(),
+                       Labels:      labels,
+                       Annotations: annotations,
+               },
+               Data: map[string]string{
+                       SecurityJsonFile: fmt.Sprintf(`{
+      "authentication":{
+        "blockUnknown": %t,
+        "class":"solr.BasicAuthPlugin",
+        "credentials": {
+          "admin": "%s",
+          "%s": "%s",
+          "solr": "%s"
+        },
+        "realm":"Solr Basic Auth",
+        "forwardCredentials": false
+      },
+      "authorization": {
+        "class": "solr.RuleBasedAuthorizationPlugin",
+        "user-role": {
+          "admin": ["admin", "probe"],
+          "%s": ["probe"],
+          "solr": ["users", "probe"]
+        },
+        "permissions": [
+          { "name": "k8s-probes", "role":"probe", "collection": null, 
"path":"/admin/info/system" },
+          { "name": "k8s-status", "role":"probe", "collection": null, 
"path":"/admin/collections" },
+          { "name": "all", "role":["admin","users"] },
+          { "name": "read", "role":["admin","users"] },
+          { "name": "update", "role":["admin"] },
+          { "name": "security-read", "role": "admin"},
+          { "name": "security-edit", "role": "admin"}%s
+        ]
+      }
+    }`, blockUnknown, adminPasswordHash, username, operPasswordHash, 
solrPasswordHash, username, anonymousPaths),
+               },
+       }
+       return configMap
+}
+
+func GenerateBasicAuthSecret(solrCloud *solr.SolrCloud) *corev1.Secret {
+       labels := solrCloud.SharedLabelsWith(solrCloud.GetLabels())
+       var annotations map[string]string
+
+       username := solrCloud.BasicAuthUsername()
+
+       // setup a secret with random passwords
+       adminPassword := randomPassword()
+       operPassword := randomPassword()
+       solrPassword := randomPassword()
+       return &corev1.Secret{
+               ObjectMeta: metav1.ObjectMeta{
+                       Name:        solrCloud.BasicAuthSecretName(),
+                       Namespace:   solrCloud.GetNamespace(),
+                       Labels:      labels,
+                       Annotations: annotations,
+               },
+               Data: map[string][]byte{
+                       "admin":  adminPassword,
+                       username: operPassword,
+                       "solr":   solrPassword,
+               },
+               Type: "Opaque",
+       }
+}
+
+func randomPassword() []byte {
+       rand.Seed(time.Now().UnixNano())
+       lower := "abcdefghijklmnpqrstuvwxyz" // no 'o'
+       upper := strings.ToUpper(lower)
+       digits := "0123456789"
+       chars := lower + upper + digits + "()[]%#@-()[]%#@-"
+       pass := make([]byte, 16)
+       // start with a lower char and end with an upper
+       pass[0] = lower[rand.Intn(len(lower))]
+       pass[len(pass)-1] = upper[rand.Intn(len(upper))]
+       perm := rand.Perm(len(chars))
+       for i := 1; i < len(pass)-1; i++ {
+               pass[i] = chars[perm[i]]
+       }
+       return pass
+}
+
+// this mimics the password hash generation approach used by Solr
+func solrPasswordHash(passBytes []byte) string {

Review comment:
       See Solr's Sha256AuthenticationProvider: 
https://github.com/apache/lucene-solr/blob/master/solr/core/src/java/org/apache/solr/security/Sha256AuthenticationProvider.java#L114




----------------------------------------------------------------
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.

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



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org
For additional commands, e-mail: issues-h...@lucene.apache.org

Reply via email to