diff --git a/api/v1beta1/auth_types.go b/api/v1beta1/auth_types.go index a7a73735..1264deb2 100644 --- a/api/v1beta1/auth_types.go +++ b/api/v1beta1/auth_types.go @@ -42,6 +42,12 @@ type Auth struct { // +optional PrivateKeyPath string `yaml:"privateKeyPath,omitempty" json:"privateKeyPath,omitempty"` + // Secret is the secret of the PrivateKey or Password for SSH authentication.It should in the same namespace as capkk. + // When Password is empty, replace it with data.password. + // When PrivateKey is empty, replace it with data.privateKey + // +optional + Secret string `yaml:"secret,omitempty" json:"secret,omitempty"` + // Timeout is the timeout for establish an SSH connection. // +optional Timeout *time.Duration `yaml:"timeout,omitempty" json:"timeout,omitempty"` diff --git a/api/v1beta1/kkcluster_webhook.go b/api/v1beta1/kkcluster_webhook.go index 98ff6915..0af9fb58 100644 --- a/api/v1beta1/kkcluster_webhook.go +++ b/api/v1beta1/kkcluster_webhook.go @@ -195,7 +195,7 @@ func validateLoadBalancer(loadBalancer *KKLoadBalancerSpec) []*field.Error { func validateClusterNodes(nodes Nodes) []*field.Error { var errs field.ErrorList - if nodes.Auth.Password == "" && nodes.Auth.PrivateKey == "" && nodes.Auth.PrivateKeyPath == "" { + if nodes.Auth.Password == "" && nodes.Auth.PrivateKey == "" && nodes.Auth.PrivateKeyPath == "" && nodes.Auth.Secret == "" { errs = append(errs, field.Required(field.NewPath("spec", "nodes", "auth"), "password and privateKey can't both be empty")) } diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclusters.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclusters.yaml index f2adfbb5..ba2bf021 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclusters.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclusters.yaml @@ -154,6 +154,12 @@ spec: description: PrivateKeyFile is the path to the private key for SSH authentication. type: string + secret: + description: Secret is the secret of the PrivateKey or Password + for SSH authentication.It should in the same namespace as + capkk. When Password is empty, replace it with data.password. + When PrivateKey is empty, replace it with data.privateKey + type: string timeout: description: Timeout is the timeout for establish an SSH connection. format: int64 @@ -193,6 +199,13 @@ spec: description: PrivateKeyFile is the path to the private key for SSH authentication. type: string + secret: + description: Secret is the secret of the PrivateKey + or Password for SSH authentication.It should in the + same namespace as capkk. When Password is empty, replace + it with data.password. When PrivateKey is empty, replace + it with data.privateKey + type: string timeout: description: Timeout is the timeout for establish an SSH connection. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclustertemplates.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclustertemplates.yaml index 6d9f5c97..098b2aaf 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclustertemplates.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkclustertemplates.yaml @@ -175,6 +175,13 @@ spec: description: PrivateKeyFile is the path to the private key for SSH authentication. type: string + secret: + description: Secret is the secret of the PrivateKey + or Password for SSH authentication.It should in + the same namespace as capkk. When Password is empty, + replace it with data.password. When PrivateKey is + empty, replace it with data.privateKey + type: string timeout: description: Timeout is the timeout for establish an SSH connection. @@ -218,6 +225,13 @@ spec: description: PrivateKeyFile is the path to the private key for SSH authentication. type: string + secret: + description: Secret is the secret of the PrivateKey + or Password for SSH authentication.It should + in the same namespace as capkk. When Password + is empty, replace it with data.password. When + PrivateKey is empty, replace it with data.privateKey + type: string timeout: description: Timeout is the timeout for establish an SSH connection. diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkinstances.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkinstances.yaml index 62bfdca4..1f6285b2 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_kkinstances.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_kkinstances.yaml @@ -85,6 +85,12 @@ spec: description: PrivateKeyFile is the path to the private key for SSH authentication. type: string + secret: + description: Secret is the secret of the PrivateKey or Password + for SSH authentication.It should in the same namespace as capkk. + When Password is empty, replace it with data.password. When + PrivateKey is empty, replace it with data.privateKey + type: string timeout: description: Timeout is the timeout for establish an SSH connection. format: int64 diff --git a/controllers/kkinstance/kkinstance_controller.go b/controllers/kkinstance/kkinstance_controller.go index efdc3476..b4846938 100644 --- a/controllers/kkinstance/kkinstance_controller.go +++ b/controllers/kkinstance/kkinstance_controller.go @@ -19,6 +19,8 @@ package kkinstance import ( "context" "fmt" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" "reflect" "time" @@ -95,6 +97,19 @@ func (r *Reconciler) getSSHClient(scope *scope.InstanceScope) ssh.Interface { if r.sshClientFactory != nil { return r.sshClientFactory(scope) } + if scope.KKInstance.Spec.Auth.Secret != "" { + secret := &corev1.Secret{} + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer cancel() + if err := r.Get(ctx, types.NamespacedName{Namespace: scope.Cluster.Namespace, Name: scope.KKInstance.Spec.Auth.Secret}, secret); err == nil { + if scope.KKInstance.Spec.Auth.PrivateKey == "" { // replace PrivateKey by secret + scope.KKInstance.Spec.Auth.PrivateKey = string(secret.Data["privateKey"]) + } + if scope.KKInstance.Spec.Auth.Password == "" { // replace password by secret + scope.KKInstance.Spec.Auth.Password = string(secret.Data["password"]) + } + } + } return ssh.NewClient(scope.KKInstance.Spec.Address, scope.KKInstance.Spec.Auth, &scope.Logger) }