Просмотр исходного кода

Merge pull request #401 from kubecost/bolt/cluster-manager-auth

Authentication for Cluster Manager
Ajay Tripathy 6 лет назад
Родитель
Сommit
301fcce6c1
1 измененных файлов с 86 добавлено и 3 удалено
  1. 86 3
      pkg/clustermanager/clustermanager.go

+ 86 - 3
pkg/clustermanager/clustermanager.go

@@ -1,8 +1,11 @@
 package clustermanager
 
 import (
+	"encoding/base64"
 	"encoding/json"
+	"fmt"
 	"io/ioutil"
+	"strings"
 
 	"github.com/google/uuid"
 
@@ -12,10 +15,31 @@ import (
 	"sigs.k8s.io/yaml"
 )
 
+// The details key used to provide auth information
+const DetailsAuthKey = "auth"
+
+// Authentication Information
+type ClusterConfigEntryAuth struct {
+	// The type of authentication provider to use
+	Type string `yaml:"type"`
+
+	// Data expressed as a secret
+	SecretName string `yaml:"secretName,omitempty"`
+
+	// Any data specifically needed by the auth provider
+	Data string `yaml:"data,omitempty"`
+
+	// User and Password as a possible input
+	User string `yaml:"user,omitempty"`
+	Pass string `yaml:"pass,omitempty"`
+}
+
 // Cluster definition from a configuration yaml
 type ClusterConfigEntry struct {
-	Name    string `yaml:"name"`
-	Address string `yaml:"address"`
+	Name    string                  `yaml:"name"`
+	Address string                  `yaml:"address"`
+	Auth    *ClusterConfigEntryAuth `yaml:"auth,omitempty"`
+	Details map[string]interface{}  `yaml:"details,omitempty"`
 }
 
 // ClusterDefinition
@@ -77,17 +101,32 @@ func NewConfiguredClusterManager(storage ClusterStorage, config string) *Cluster
 		return clusterManager
 	}
 
-	var entries []ClusterConfigEntry
+	var entries []*ClusterConfigEntry
 	err = yaml.Unmarshal(data, &entries)
 	if err != nil {
 		return clusterManager
 	}
 
 	for _, entry := range entries {
+		details := entry.Details
+		if details == nil {
+			details = make(map[string]interface{})
+		}
+
+		if entry.Auth != nil {
+			authData, err := getAuth(entry.Auth)
+			if err != nil {
+				klog.V(1).Infof("[Error]: %s", err)
+			} else {
+				details[DetailsAuthKey] = authData
+			}
+		}
+
 		clusterManager.Add(ClusterDefinition{
 			ID:      entry.Name,
 			Name:    entry.Name,
 			Address: entry.Address,
+			Details: details,
 		})
 	}
 
@@ -162,3 +201,47 @@ func (cm *ClusterManager) GetAll() []*ClusterDefinition {
 func (cm *ClusterManager) Close() error {
 	return cm.storage.Close()
 }
+
+func toBasicAuth(user, pass string) string {
+	return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, pass)))
+}
+
+func fileFromSecret(secretName string) string {
+	return fmt.Sprintf("/var/secrets/%s/auth", secretName)
+}
+
+func fromSecret(secretName string) (string, error) {
+	file := fileFromSecret(secretName)
+	exists, err := util.FileExists(file)
+	if !exists || err != nil {
+		return "", fmt.Errorf("Failed to locate secret: %s", file)
+	}
+
+	data, err := ioutil.ReadFile(file)
+	if err != nil {
+		return "", fmt.Errorf("Failed to load secret: %s", file)
+	}
+
+	return string(data), nil
+}
+
+func getAuth(auth *ClusterConfigEntryAuth) (string, error) {
+	// We only support basic auth currently
+	if !strings.EqualFold(auth.Type, "basic") {
+		return "", fmt.Errorf("Authentication Type: '%s' is not supported", auth.Type)
+	}
+
+	if auth.SecretName != "" {
+		return fromSecret(auth.SecretName)
+	}
+
+	if auth.Data != "" {
+		return auth.Data, nil
+	}
+
+	if auth.User != "" && auth.Pass != "" {
+		return toBasicAuth(auth.User, auth.Pass), nil
+	}
+
+	return "", fmt.Errorf("No valid basic auth parameters provided.")
+}