mirror of
				https://github.com/1Panel-dev/KubePi.git
				synced 2025-10-31 18:42:41 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package kubernetes
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	v1Cluster "github.com/KubeOperator/ekko/internal/model/v1/cluster"
 | |
| 	"github.com/KubeOperator/ekko/pkg/certificate"
 | |
| 	v1 "k8s.io/api/authorization/v1"
 | |
| 	certv1 "k8s.io/api/certificates/v1"
 | |
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | |
| 	"k8s.io/apimachinery/pkg/version"
 | |
| 	"k8s.io/client-go/kubernetes"
 | |
| 	"k8s.io/client-go/rest"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| type Interface interface {
 | |
| 	Ping() error
 | |
| 	Version() (*version.Info, error)
 | |
| 	Client() (*kubernetes.Clientset, error)
 | |
| 	HasPermission(attributes v1.ResourceAttributes) (PermissionCheckResult, error)
 | |
| 	CreateCommonUser(commonName string) ([]byte, error)
 | |
| 	CreateDefaultClusterRoles() error
 | |
| }
 | |
| 
 | |
| type Kubernetes struct {
 | |
| 	*v1Cluster.Cluster
 | |
| }
 | |
| 
 | |
| type PermissionCheckResult struct {
 | |
| 	Resource v1.ResourceAttributes
 | |
| 	Allowed  bool
 | |
| }
 | |
| 
 | |
| func NewKubernetes(cluster v1Cluster.Cluster) Interface {
 | |
| 	return &Kubernetes{Cluster: &cluster}
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) CreateDefaultClusterRoles() error {
 | |
| 
 | |
| 	client, err := k.Client()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	for i := range initClusterRoles {
 | |
| 		instance, err := client.RbacV1().ClusterRoles().Get(context.TODO(), initClusterRoles[i].Name, metav1.GetOptions{})
 | |
| 		if err != nil {
 | |
| 			if !strings.Contains(strings.ToLower(err.Error()), "not found") {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 		if instance == nil || instance.Name == "" {
 | |
| 			_, err = client.RbacV1().ClusterRoles().Create(context.TODO(), &initClusterRoles[i], metav1.CreateOptions{})
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) CreateCommonUser(commonName string) ([]byte, error) {
 | |
| 	// 生成用户证书申请
 | |
| 	cert, err := certificate.CreateClientCertificateRequest(commonName, k.PrivateKey)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	csr := certv1.CertificateSigningRequest{
 | |
| 		ObjectMeta: metav1.ObjectMeta{
 | |
| 			Name: fmt.Sprintf("%s-%s-%d", commonName, "ekko", time.Now().Unix()),
 | |
| 		},
 | |
| 		Spec: certv1.CertificateSigningRequestSpec{
 | |
| 			SignerName: "kubernetes.io/kube-apiserver-client",
 | |
| 			Request:    cert,
 | |
| 			Groups: []string{
 | |
| 				"system:authenticated",
 | |
| 			},
 | |
| 			Usages: []certv1.KeyUsage{
 | |
| 				"client auth",
 | |
| 			},
 | |
| 		},
 | |
| 	}
 | |
| 	client, err := k.Client()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	createResp, err := client.CertificatesV1().CertificateSigningRequests().Create(context.TODO(), &csr, metav1.CreateOptions{})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	// 审批证书
 | |
| 	createResp.Status.Conditions = append(createResp.Status.Conditions, certv1.CertificateSigningRequestCondition{
 | |
| 		Reason:         "Approved by Ekko",
 | |
| 		Type:           certv1.CertificateApproved,
 | |
| 		LastUpdateTime: metav1.Now(),
 | |
| 		Status:         "True",
 | |
| 	})
 | |
| 
 | |
| 	updateResp, err := client.CertificatesV1().CertificateSigningRequests().UpdateApproval(context.TODO(), createResp.Name, createResp, metav1.UpdateOptions{})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	var data []byte
 | |
| 	for i := 0; i < 10; i++ {
 | |
| 		time.Sleep(1 * time.Second)
 | |
| 		getResp, err := client.CertificatesV1().CertificateSigningRequests().Get(context.TODO(), updateResp.Name, metav1.GetOptions{})
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if getResp.Status.Certificate != nil {
 | |
| 			data = getResp.Status.Certificate
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 	if data == nil {
 | |
| 		return nil, errors.New("csr approve time out")
 | |
| 	}
 | |
| 
 | |
| 	return data, nil
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) HasPermission(attributes v1.ResourceAttributes) (PermissionCheckResult, error) {
 | |
| 	client, err := k.Client()
 | |
| 	if err != nil {
 | |
| 		return PermissionCheckResult{}, err
 | |
| 	}
 | |
| 	resp, err := client.AuthorizationV1().SelfSubjectAccessReviews().Create(context.TODO(), &v1.SelfSubjectAccessReview{
 | |
| 		Spec: v1.SelfSubjectAccessReviewSpec{
 | |
| 			ResourceAttributes: &attributes,
 | |
| 		},
 | |
| 	}, metav1.CreateOptions{})
 | |
| 	if err != nil {
 | |
| 		return PermissionCheckResult{}, err
 | |
| 	}
 | |
| 	return PermissionCheckResult{
 | |
| 		Resource: attributes,
 | |
| 		Allowed:  resp.Status.Allowed,
 | |
| 	}, nil
 | |
| 
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) Client() (*kubernetes.Clientset, error) {
 | |
| 	if k.Spec.Connect.Direction == "forward" {
 | |
| 		kubeConf := &rest.Config{
 | |
| 			Host: k.Spec.Connect.Forward.ApiServer,
 | |
| 		}
 | |
| 		if len(k.CaCertificate.CertData) > 0 {
 | |
| 			kubeConf.CAData = k.CaCertificate.CertData
 | |
| 		} else {
 | |
| 			kubeConf.Insecure = true
 | |
| 		}
 | |
| 		switch k.Spec.Authentication.Mode {
 | |
| 		case strings.ToLower("bearer"):
 | |
| 			kubeConf.BearerToken = k.Spec.Authentication.BearerToken
 | |
| 		case strings.ToLower("certificate"):
 | |
| 			kubeConf.TLSClientConfig.CertData = k.Spec.Authentication.Certificate.CertData
 | |
| 			kubeConf.TLSClientConfig.KeyData = k.Spec.Authentication.Certificate.KeyData
 | |
| 		}
 | |
| 		return kubernetes.NewForConfig(kubeConf)
 | |
| 
 | |
| 	}
 | |
| 	return nil, errors.New("")
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) Version() (*version.Info, error) {
 | |
| 	client, err := k.Client()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return client.ServerVersion()
 | |
| 
 | |
| }
 | |
| 
 | |
| func (k *Kubernetes) Ping() error {
 | |
| 	client, err := k.Client()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	_, err = client.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
 | |
| 	client.AuthorizationV1().SelfSubjectAccessReviews()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | 
