4
0
Fork 2
mirror of https://gerrit.hackerspace.pl/hscloud synced 2025-01-24 17:43:54 +00:00
hscloud/cluster/prodaccess/kubernetes.go
radex 63f0adde2f cluster/prodaccess: add multi-cluster support
- allow passing -cluster to select another cluster (k0 remains the default for the time being)
- default prodvider dns to prodvider.<cluster>.hswaw.net
- scope kube config username and certs storage by cluster name

additionally:

- force username to be lowercase (LDAP is case-insensitive, but e.g. kubernetes namespaces are not)
- fix some Go deprecations

Change-Id: Ibf4a6ced7a635940f6a7c568c79714cd8ac60ce9
Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/2101
Reviewed-by: radex <radex@hackerspace.pl>
2025-01-11 15:22:45 +00:00

115 lines
2.8 KiB
Go

package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"time"
"github.com/golang/glog"
"code.hackerspace.pl/hscloud/cluster/clustercfg/clusters"
pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
"code.hackerspace.pl/hscloud/go/workspace"
)
func kubernetesPaths(cluster clusters.Cluster) (string, string, string) {
ws, err := workspace.Get()
if err != nil {
glog.Exitf("%v", err)
}
root := path.Join(ws, ".kubectl", cluster.Name)
localKey := path.Join(root, fmt.Sprintf("%s.key", flagUsername))
localCert := path.Join(root, fmt.Sprintf("%s.crt", flagUsername))
localCA := path.Join(root, fmt.Sprintf("ca.crt"))
return localKey, localCert, localCA
}
func needKubernetesCreds(cluster clusters.Cluster) bool {
localKey, localCert, _ := kubernetesPaths(cluster)
// Check for existence of cert/key.
if _, err := os.Stat(localKey); os.IsNotExist(err) {
return true
}
if _, err := os.Stat(localCert); os.IsNotExist(err) {
return true
}
// Cert/key exist, try to load and parse.
creds, err := tls.LoadX509KeyPair(localCert, localKey)
if err != nil {
return true
}
if len(creds.Certificate) != 1 {
return true
}
cert, err := x509.ParseCertificate(creds.Certificate[0])
if err != nil {
return true
}
creds.Leaf = cert
// Check if certificate will still be valid in 2 hours.
target := time.Now().Add(2 * time.Hour)
if creds.Leaf.NotAfter.Before(target) {
return true
}
return false
}
func useKubernetesKeys(keys *pb.KubernetesKeys, cluster clusters.Cluster) {
localKey, localCert, localCA := kubernetesPaths(cluster)
parent := filepath.Dir(localKey)
if _, err := os.Stat(parent); os.IsNotExist(err) {
os.MkdirAll(parent, 0700)
}
if err := os.WriteFile(localKey, keys.Key, 0600); err != nil {
glog.Exitf("WriteFile(%q): %v", localKey, err)
}
if err := os.WriteFile(localCert, keys.Cert, 0600); err != nil {
glog.Exitf("WriteFile(%q): %v", localCert, err)
}
if err := os.WriteFile(localCA, keys.Ca, 0600); err != nil {
glog.Exitf("WriteFile(%q): %v", localCA, err)
}
kubectl := func(args ...string) {
cmd := exec.Command("kubectl", args...)
out, err := cmd.CombinedOutput()
if err != nil {
glog.Exitf("kubectl %v: %v: %v", args, err, string(out))
}
}
kubectl("config",
"set-cluster", keys.Cluster,
"--certificate-authority="+localCA,
"--embed-certs=true",
"--server=https://"+keys.Cluster+":4001")
clusterUsername := fmt.Sprintf("%s@%s", flagUsername, keys.Cluster)
kubectl("config",
"set-credentials", clusterUsername,
"--client-certificate="+localCert,
"--client-key="+localKey,
"--embed-certs=true")
kubectl("config",
"set-context", keys.Cluster,
"--cluster="+keys.Cluster,
"--user="+clusterUsername)
kubectl("config", "use-context", keys.Cluster)
}