cluster/prodvider: rewrite against x509 lib for ed25519 support

This gets rid of cfssl for the kubernetes bits of prodvider, instead
using plain crypto/x509. This also allows to support our new fancy
ED25519 CA.

Change-Id: If677b3f4523014f56ea802b87499d1c0eb6d92e9
Reviewed-on: https://gerrit.hackerspace.pl/c/hscloud/+/1489
Reviewed-by: q3k <q3k@hackerspace.pl>
diff --git a/cluster/prodvider/main.go b/cluster/prodvider/main.go
index 7222a86..ca114f0 100644
--- a/cluster/prodvider/main.go
+++ b/cluster/prodvider/main.go
@@ -1,15 +1,16 @@
 package main
 
 import (
+	"crypto/ed25519"
+	"crypto/x509"
+	"encoding/pem"
 	"flag"
-	"io/ioutil"
+	"fmt"
 	"math/rand"
 	"net"
 	"os"
 	"time"
 
-	"github.com/cloudflare/cfssl/config"
-	"github.com/cloudflare/cfssl/signer/local"
 	"github.com/golang/glog"
 	"google.golang.org/grpc"
 	"k8s.io/client-go/kubernetes"
@@ -36,44 +37,66 @@
 }
 
 type prodvider struct {
-	sign      *local.Signer
-	k8s       *kubernetes.Clientset
-	srv       *grpc.Server
-	kubeCAPEM []byte
+	k8s *kubernetes.Clientset
+	srv *grpc.Server
+
+	intermediateCAKey  ed25519.PrivateKey
+	intermediateCACert *x509.Certificate
+	kubeCACert         *x509.Certificate
+}
+
+func loadCert(path string) (*x509.Certificate, error) {
+	b, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+
+	block, _ := pem.Decode(b)
+	if block == nil {
+		return nil, fmt.Errorf("no PEM block found")
+	}
+	if block.Type != "CERTIFICATE" {
+		return nil, fmt.Errorf("unexpected PEM block: %q", block.Type)
+	}
+	return x509.ParseCertificate(block.Bytes)
+}
+
+func loadKey(path string) (ed25519.PrivateKey, error) {
+	bytes, err := os.ReadFile(path)
+	if err != nil {
+		return nil, err
+	}
+	block, _ := pem.Decode(bytes)
+	if block == nil {
+		return nil, fmt.Errorf("no PEM block found")
+	}
+	if block.Type != "PRIVATE KEY" {
+		return nil, fmt.Errorf("unexpected PEM block: %q", block.Type)
+	}
+	key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+	if err != nil {
+		return nil, err
+	}
+	if k, ok := key.(ed25519.PrivateKey); ok {
+		return k, nil
+	}
+	return nil, fmt.Errorf("not an ED25519 key")
 }
 
 func newProdvider() *prodvider {
-	policy := &config.Signing{
-		Profiles: map[string]*config.SigningProfile{
-			"server": &config.SigningProfile{
-				Usage:        []string{"signing", "key encipherment", "server auth"},
-				ExpiryString: "30d",
-			},
-			"client": &config.SigningProfile{
-				Usage:        []string{"signing", "key encipherment", "client auth"},
-				ExpiryString: "30d",
-			},
-			"client-server": &config.SigningProfile{
-				Usage:        []string{"signing", "key encipherment", "server auth", "client auth"},
-				ExpiryString: "30d",
-			},
-		},
-		Default: config.DefaultConfig(),
-	}
-
-	sign, err := local.NewSignerFromFile(flagCACertificatePath, flagCAKeyPath, policy)
+	kubeCACert, err := loadCert(flagKubeCACertificatePath)
 	if err != nil {
-		glog.Exitf("Could not create signer: %v", err)
+		glog.Exitf("Loading kube CA certificate failed: %v", err)
 	}
-
-	kubeCAPEM, err := ioutil.ReadFile(flagKubeCACertificatePath)
+	intermediateCACert, err := loadCert(flagCACertificatePath)
 	if err != nil {
-		glog.Exitf("Could not read kube CA cert path: %v")
+		glog.Exitf("Loading intermediate CAcertificate failed: %v", err)
 	}
-
+	intermediateCAKey, err := loadKey(flagCAKeyPath)
 	return &prodvider{
-		sign:      sign,
-		kubeCAPEM: kubeCAPEM,
+		intermediateCAKey:  intermediateCAKey,
+		intermediateCACert: intermediateCACert,
+		kubeCACert:         kubeCACert,
 	}
 }