prod{access,vider}: implement
Prodaccess/Prodvider allow issuing short-lived certificates for all SSO
users to access the kubernetes cluster.
Currently, all users get a personal-$username namespace in which they
have adminitrative rights. Otherwise, they get no access.
In addition, we define a static CRB to allow some admins access to
everything. In the future, this will be more granular.
We also update relevant documentation.
Change-Id: Ia18594eea8a9e5efbb3e9a25a04a28bbd6a42153
diff --git a/cluster/prodaccess/prodaccess.go b/cluster/prodaccess/prodaccess.go
new file mode 100644
index 0000000..e0e8ec2
--- /dev/null
+++ b/cluster/prodaccess/prodaccess.go
@@ -0,0 +1,114 @@
+package main
+
+import (
+ "context"
+ "crypto/x509"
+ "flag"
+ "fmt"
+ "os"
+ "os/user"
+ "syscall"
+
+ "github.com/golang/glog"
+ "golang.org/x/crypto/ssh/terminal"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials"
+
+ "code.hackerspace.pl/cluster/certs"
+ pb "code.hackerspace.pl/hscloud/cluster/prodvider/proto"
+)
+
+var (
+ flagProdvider string
+ flagUsername string
+ flagForce bool
+)
+
+func init() {
+ flag.Set("logtostderr", "true")
+}
+
+func main() {
+ user, err := user.Current()
+ if err == nil {
+ flagUsername = user.Username
+ }
+
+ flag.StringVar(&flagProdvider, "prodvider", "prodvider.hswaw.net:443", "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()
+
+ if flagUsername == "" {
+ glog.Exitf("Username could not be detected, please provide with -username flag")
+ }
+
+ cp := x509.NewCertPool()
+ if ok := cp.AppendCertsFromPEM(certs.Data["ca-kube.crt"]); !ok {
+ glog.Exitf("Could not load k8s CA")
+ }
+
+ creds := credentials.NewClientTLSFromCert(cp, "")
+ conn, err := grpc.Dial(flagProdvider, grpc.WithTransportCredentials(creds))
+ if err != nil {
+ glog.Exitf("Could not dial prodvider: %v", err)
+ }
+
+ prodvider := pb.NewProdviderClient(conn)
+ ctx := context.Background()
+
+ if !needKubernetesCreds() && !flagForce {
+ fmt.Printf("Kubernetes credentials exist. Use `prodaccess -force` to force update.\n")
+ os.Exit(0)
+ }
+
+ attempts := 0
+ for {
+ ok := authenticate(ctx, prodvider)
+ attempts += 1
+ if !ok {
+ if attempts >= 3 {
+ os.Exit(1)
+ }
+ } else {
+ fmt.Printf("Good evening professor. I see you have driven here in your Ferrari.\n")
+ os.Exit(0)
+ }
+ }
+}
+
+func authenticate(ctx context.Context, prodvider pb.ProdviderClient) bool {
+ req := &pb.AuthenticateRequest{
+ Username: flagUsername,
+ Password: password(),
+ }
+
+ res, err := prodvider.Authenticate(ctx, req)
+ if err != nil {
+ glog.Exitf("Prodvider error: %v", err)
+ }
+
+ switch res.Result {
+ case pb.AuthenticateResponse_RESULT_AUTHENTICATED:
+ break
+ case pb.AuthenticateResponse_RESULT_INVALID_CREDENTIALS:
+ fmt.Printf("Invalid username or password.\n")
+ return false
+ default:
+ glog.Exitf("Unknown authentication result: %v", res.Result)
+ }
+
+ useKubernetesKeys(res.KubernetesKeys)
+
+ return true
+}
+
+func password() string {
+ fmt.Printf("Enter SSO/LDAP password for %s@hackerspace.pl: ", flagUsername)
+ bytePassword, err := terminal.ReadPassword(int(syscall.Stdin))
+ if err != nil {
+ return ""
+ }
+ fmt.Printf("\n")
+ return string(bytePassword)
+}