mirror of
https://gerrit.hackerspace.pl/hscloud
synced 2025-02-10 23:06:45 +00:00
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>
This commit is contained in:
parent
0565af617a
commit
63f0adde2f
4 changed files with 44 additions and 25 deletions
|
@ -12,12 +12,13 @@ go_library(
|
|||
deps = [
|
||||
"//cluster/certs",
|
||||
"//cluster/prodvider/proto",
|
||||
"//cluster/clustercfg/clusters",
|
||||
"//go/pki",
|
||||
"//go/workspace",
|
||||
"@com_github_golang_glog//:glog",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//credentials",
|
||||
"@org_golang_x_crypto//ssh/terminal",
|
||||
"@org_golang_x_term//:term",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
@ -28,7 +27,7 @@ func useHSPKIKeys(keys *pb.HSPKIKeys) {
|
|||
{path + "/tls.crt", keys.Cert},
|
||||
{path + "/tls.key", keys.Key},
|
||||
} {
|
||||
err := ioutil.WriteFile(el.target, el.data, 400)
|
||||
err := os.WriteFile(el.target, el.data, 400)
|
||||
if err != nil {
|
||||
glog.Exitf("Failed to write %q: %v", el.target, err)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
@ -13,25 +12,28 @@ import (
|
|||
|
||||
"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() (string, string, string) {
|
||||
func kubernetesPaths(cluster clusters.Cluster) (string, string, string) {
|
||||
ws, err := workspace.Get()
|
||||
if err != nil {
|
||||
glog.Exitf("%v", err)
|
||||
}
|
||||
|
||||
localKey := path.Join(ws, ".kubectl", fmt.Sprintf("%s.key", flagUsername))
|
||||
localCert := path.Join(ws, ".kubectl", fmt.Sprintf("%s.crt", flagUsername))
|
||||
localCA := path.Join(ws, ".kubectl", fmt.Sprintf("ca.crt"))
|
||||
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() bool {
|
||||
localKey, localCert, _ := kubernetesPaths()
|
||||
func needKubernetesCreds(cluster clusters.Cluster) bool {
|
||||
localKey, localCert, _ := kubernetesPaths(cluster)
|
||||
|
||||
// Check for existence of cert/key.
|
||||
if _, err := os.Stat(localKey); os.IsNotExist(err) {
|
||||
|
@ -64,21 +66,21 @@ func needKubernetesCreds() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func useKubernetesKeys(keys *pb.KubernetesKeys) {
|
||||
localKey, localCert, localCA := kubernetesPaths()
|
||||
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 := ioutil.WriteFile(localKey, keys.Key, 0600); err != nil {
|
||||
if err := os.WriteFile(localKey, keys.Key, 0600); err != nil {
|
||||
glog.Exitf("WriteFile(%q): %v", localKey, err)
|
||||
}
|
||||
if err := ioutil.WriteFile(localCert, keys.Cert, 0600); err != nil {
|
||||
if err := os.WriteFile(localCert, keys.Cert, 0600); err != nil {
|
||||
glog.Exitf("WriteFile(%q): %v", localCert, err)
|
||||
}
|
||||
if err := ioutil.WriteFile(localCA, keys.Ca, 0600); err != nil {
|
||||
if err := os.WriteFile(localCA, keys.Ca, 0600); err != nil {
|
||||
glog.Exitf("WriteFile(%q): %v", localCA, err)
|
||||
}
|
||||
|
||||
|
@ -96,8 +98,10 @@ func useKubernetesKeys(keys *pb.KubernetesKeys) {
|
|||
"--embed-certs=true",
|
||||
"--server=https://"+keys.Cluster+":4001")
|
||||
|
||||
clusterUsername := fmt.Sprintf("%s@%s", flagUsername, keys.Cluster)
|
||||
|
||||
kubectl("config",
|
||||
"set-credentials", flagUsername,
|
||||
"set-credentials", clusterUsername,
|
||||
"--client-certificate="+localCert,
|
||||
"--client-key="+localKey,
|
||||
"--embed-certs=true")
|
||||
|
@ -105,7 +109,7 @@ func useKubernetesKeys(keys *pb.KubernetesKeys) {
|
|||
kubectl("config",
|
||||
"set-context", keys.Cluster,
|
||||
"--cluster="+keys.Cluster,
|
||||
"--user="+flagUsername)
|
||||
"--user="+clusterUsername)
|
||||
|
||||
kubectl("config", "use-context", keys.Cluster)
|
||||
}
|
||||
|
|
|
@ -4,22 +4,25 @@ import (
|
|||
"context"
|
||||
"crypto/x509"
|
||||
"flag"
|
||||
"strings"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/user"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
|
||||
"code.hackerspace.pl/hscloud/cluster/certs"
|
||||
"code.hackerspace.pl/hscloud/cluster/clustercfg/clusters"
|
||||
pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
|
||||
)
|
||||
|
||||
var (
|
||||
flagCluster string
|
||||
flagProdvider string
|
||||
flagUsername string
|
||||
flagForce bool
|
||||
|
@ -35,16 +38,28 @@ func main() {
|
|||
flagUsername = user.Username
|
||||
}
|
||||
|
||||
flag.StringVar(&flagProdvider, "prodvider", "prodvider.hswaw.net:443", "Prodvider endpoint")
|
||||
flag.StringVar(&flagCluster, "cluster", "k0", "Cluster short name")
|
||||
flag.StringVar(&flagProdvider, "prodvider", "", "Prodvider endpoint")
|
||||
flag.StringVar(&flagUsername, "username", flagUsername, "Username to authenticate with")
|
||||
flag.BoolVar(&flagForce, "force", false, "Force retrieving certificates even if they already exist")
|
||||
flag.Parse()
|
||||
|
||||
flagUsername = strings.ToLower(flagUsername)
|
||||
if flagUsername == "" {
|
||||
glog.Exitf("Username could not be detected, please provide with -username flag")
|
||||
}
|
||||
|
||||
cluster, ok := clusters.Clusters[flagCluster]
|
||||
if !ok {
|
||||
log.Fatalf("Unknown cluster: %q", flagCluster)
|
||||
}
|
||||
|
||||
if flagProdvider == "" {
|
||||
flagProdvider = "prodvider." + cluster.Name + ".hswaw.net:443"
|
||||
}
|
||||
|
||||
cp := x509.NewCertPool()
|
||||
// TODO(radex): vary certs based on cluster
|
||||
if ok := cp.AppendCertsFromPEM(certs.Data["ca-kube.crt"]); !ok {
|
||||
glog.Exitf("Could not load k8s CA")
|
||||
}
|
||||
|
@ -58,14 +73,14 @@ func main() {
|
|||
prodvider := pb.NewProdviderClient(conn)
|
||||
ctx := context.Background()
|
||||
|
||||
if !needKubernetesCreds() && !flagForce {
|
||||
if !needKubernetesCreds(cluster) && !flagForce {
|
||||
fmt.Printf("Kubernetes credentials exist. Use `prodaccess -force` to force update.\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
attempts := 0
|
||||
for {
|
||||
ok := authenticate(ctx, prodvider)
|
||||
ok := authenticate(ctx, prodvider, cluster)
|
||||
attempts += 1
|
||||
if !ok {
|
||||
if attempts >= 3 {
|
||||
|
@ -78,7 +93,7 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func authenticate(ctx context.Context, prodvider pb.ProdviderClient) bool {
|
||||
func authenticate(ctx context.Context, prodvider pb.ProdviderClient, cluster clusters.Cluster) bool {
|
||||
req := &pb.AuthenticateRequest{
|
||||
Username: flagUsername,
|
||||
Password: password(),
|
||||
|
@ -99,7 +114,7 @@ func authenticate(ctx context.Context, prodvider pb.ProdviderClient) bool {
|
|||
glog.Exitf("Unknown authentication result: %v", res.Result)
|
||||
}
|
||||
|
||||
useKubernetesKeys(res.KubernetesKeys)
|
||||
useKubernetesKeys(res.KubernetesKeys, cluster)
|
||||
fmt.Printf("-> Kubernetes credentials installed\n")
|
||||
useHSPKIKeys(res.HspkiKeys)
|
||||
fmt.Printf("-> HSPKI credentials installed\n")
|
||||
|
@ -109,7 +124,7 @@ func authenticate(ctx context.Context, prodvider pb.ProdviderClient) bool {
|
|||
|
||||
func password() string {
|
||||
fmt.Printf("Enter SSO/LDAP password for %s@hackerspace.pl: ", flagUsername)
|
||||
bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
|
||||
bytePassword, err := term.ReadPassword(int(syscall.Stdin))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue