Init commit
This commit is contained in:
		
							
								
								
									
										212
									
								
								internal/controllers/accounts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								internal/controllers/accounts.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
			
		||||
package controllers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/google/uuid"
 | 
			
		||||
	"golang.org/x/crypto/bcrypt"
 | 
			
		||||
	corev1 "k8s.io/api/core/v1"
 | 
			
		||||
	rbacv1 "k8s.io/api/rbac/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
	"k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	ctrl "sigs.k8s.io/controller-runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Account struct {
 | 
			
		||||
	Controller ctrl.Manager
 | 
			
		||||
	Data       *AccountData
 | 
			
		||||
	Kubeconfig string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AccountData struct {
 | 
			
		||||
	Username string
 | 
			
		||||
	Password string
 | 
			
		||||
	Email    string
 | 
			
		||||
	UUID     string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func HashPassword(password string) (string, error) {
 | 
			
		||||
	bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
 | 
			
		||||
	return string(bytes), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CheckPasswordHash(password, hash string) bool {
 | 
			
		||||
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
 | 
			
		||||
    return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (acc *Account) Create(ctx context.Context) error {
 | 
			
		||||
	client := acc.Controller.GetClient()
 | 
			
		||||
	acc.Data.UUID = uuid.New().String()
 | 
			
		||||
	passwordHash, err := HashPassword(acc.Data.Password)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	namespace := corev1.Namespace{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name: acc.Data.UUID,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	if err := client.Create(ctx, &namespace); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err := client.Get(ctx, types.NamespacedName{
 | 
			
		||||
		Name:      acc.Data.UUID,
 | 
			
		||||
	}, &namespace); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Create a secret with the account data
 | 
			
		||||
	secret := corev1.Secret{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:                       acc.Data.Username,
 | 
			
		||||
			Namespace: "softplayer-accounts",
 | 
			
		||||
			OwnerReferences:            []metav1.OwnerReference{
 | 
			
		||||
				metav1.OwnerReference{
 | 
			
		||||
					APIVersion:         "v1",
 | 
			
		||||
					Kind:               "Namespace",
 | 
			
		||||
					Name:               acc.Data.UUID,
 | 
			
		||||
					UID:                namespace.UID,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		StringData: map[string]string{
 | 
			
		||||
			"uuid":     acc.Data.UUID,
 | 
			
		||||
			"email":    acc.Data.Email,
 | 
			
		||||
			"password": passwordHash,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	if err := client.Create(ctx, &secret); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	// Create a namespace to be managed by the account
 | 
			
		||||
	role := &rbacv1.Role{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{Name: acc.Data.Username, Namespace: acc.Data.UUID},
 | 
			
		||||
		Rules:      []rbacv1.PolicyRule{{Verbs: []string{"get", "watch", "list", "create", "patch", "delete"}, APIGroups: []string{""}, Resources: []string{"configmaps", "secrets"}}},
 | 
			
		||||
	}
 | 
			
		||||
	if err := client.Create(ctx, role); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	sa := &corev1.ServiceAccount{
 | 
			
		||||
		ObjectMeta:                   metav1.ObjectMeta{
 | 
			
		||||
			Name: acc.Data.UUID,
 | 
			
		||||
			Namespace: acc.Data.UUID,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	rb := &rbacv1.RoleBinding{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:                       acc.Data.UUID,
 | 
			
		||||
			Namespace:                  acc.Data.UUID,
 | 
			
		||||
		},
 | 
			
		||||
		Subjects:   []rbacv1.Subject{
 | 
			
		||||
			rbacv1.Subject{
 | 
			
		||||
				Kind:      "ServiceAccount",
 | 
			
		||||
				Name:      acc.Data.UUID,
 | 
			
		||||
				Namespace: acc.Data.UUID,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		RoleRef:    rbacv1.RoleRef{
 | 
			
		||||
			APIGroup: "rbac.authorization.k8s.io",
 | 
			
		||||
			Kind:     "Role",
 | 
			
		||||
			Name:     acc.Data.Username,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := client.Create(ctx, rb); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := client.Create(ctx, sa); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tokenName := fmt.Sprintf("sa-%s", acc.Data.UUID)
 | 
			
		||||
	saSec := &corev1.Secret{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:                       tokenName,
 | 
			
		||||
			Namespace: acc.Data.UUID,
 | 
			
		||||
			Annotations: map[string]string{
 | 
			
		||||
				"kubernetes.io/service-account.name": acc.Data.UUID,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Type:       "kubernetes.io/service-account-token",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := client.Create(ctx, saSec); err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	acc.Kubeconfig, err = acc.getToken(ctx, saSec)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err := client.Delete(ctx, &namespace); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (acc *Account) Login (ctx context.Context) error {
 | 
			
		||||
	client := acc.Controller.GetClient()
 | 
			
		||||
	sec := &corev1.Secret{}
 | 
			
		||||
	if err := client.Get(ctx, types.NamespacedName{
 | 
			
		||||
		Namespace: "softplayer-accounts",
 | 
			
		||||
		Name:      acc.Data.Username,
 | 
			
		||||
	}, sec); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !CheckPasswordHash(acc.Data.Password, string(sec.Data["password"])){
 | 
			
		||||
		err := errors.New("wrong password")
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	acc.Data.UUID = string(sec.Data["uuid"])
 | 
			
		||||
	tokenName := fmt.Sprintf("sa-%s", acc.Data.UUID)
 | 
			
		||||
	saSec := &corev1.Secret{
 | 
			
		||||
		ObjectMeta: metav1.ObjectMeta{
 | 
			
		||||
			Name:                       tokenName,
 | 
			
		||||
			Namespace: acc.Data.UUID,
 | 
			
		||||
			Annotations: map[string]string{
 | 
			
		||||
				"kubernetes.io/service-account.name": acc.Data.UUID,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Type:       "kubernetes.io/service-account-token",
 | 
			
		||||
	}
 | 
			
		||||
	var err error
 | 
			
		||||
	acc.Kubeconfig, err = acc.getToken(ctx, saSec)
 | 
			
		||||
	if err != nil{ 
 | 
			
		||||
	return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (acc *Account) getToken (ctx context.Context, saSec *corev1.Secret) (string, error) {
 | 
			
		||||
	client := acc.Controller.GetClient()
 | 
			
		||||
	if err := client.Get(ctx, types.NamespacedName{
 | 
			
		||||
		Namespace: acc.Data.UUID,
 | 
			
		||||
		Name:     saSec.ObjectMeta.Name,
 | 
			
		||||
	}, saSec); err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return string(saSec.Data["token"]), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								internal/controllers/environments.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								internal/controllers/environments.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
package controllers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	ctrl "sigs.k8s.io/controller-runtime"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Environemnt struct {
 | 
			
		||||
	Controller ctrl.Manager
 | 
			
		||||
	Data       *EnvironemntData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EnvironemntData struct {
 | 
			
		||||
	Name     string
 | 
			
		||||
	Provider string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (env *Environemnt) Create(ctx context.Context) error {
 | 
			
		||||
	log.Printf("%s", env.Data.Name)
 | 
			
		||||
	log.Printf("%s", env.Data.Provider)
 | 
			
		||||
 | 
			
		||||
	// Create a configmap
 | 
			
		||||
	//
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user