metropolis/test/util: move in NewEphemeralClusterCredentials from rpc

Change-Id: I41603b19a76ea91c2191b0118183957973fc9ccd
Reviewed-on: https://review.monogon.dev/c/monogon/+/1960
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/test/util/BUILD.bazel b/metropolis/test/util/BUILD.bazel
index 16ed382..d431dbe 100644
--- a/metropolis/test/util/BUILD.bazel
+++ b/metropolis/test/util/BUILD.bazel
@@ -2,8 +2,15 @@
 
 go_library(
     name = "util",
-    srcs = ["runners.go"],
+    srcs = [
+        "rpc.go",
+        "runners.go",
+    ],
     importpath = "source.monogon.dev/metropolis/test/util",
     visibility = ["//metropolis:__subpackages__"],
-    deps = ["//metropolis/test/launch"],
+    deps = [
+        "//metropolis/node/core/identity",
+        "//metropolis/pkg/pki",
+        "//metropolis/test/launch",
+    ],
 )
diff --git a/metropolis/test/util/rpc.go b/metropolis/test/util/rpc.go
new file mode 100644
index 0000000..e4caece
--- /dev/null
+++ b/metropolis/test/util/rpc.go
@@ -0,0 +1,100 @@
+package util
+
+import (
+	"context"
+	"crypto/ed25519"
+	"crypto/rand"
+	"crypto/tls"
+	"crypto/x509"
+	"testing"
+
+	"source.monogon.dev/metropolis/node/core/identity"
+	"source.monogon.dev/metropolis/pkg/pki"
+)
+
+// NewEphemeralClusterCredentials creates a set of TLS certificates for use in a
+// test Metropolis cluster. These are a CA certificate, a Manager certificate
+// and an arbitrary amount of Node certificates (per the nodes argument).
+//
+// All of these are ephemeral, ie. not stored anywhere - including the CA
+// certificate. This function is for use by tests which want to bring up a
+// minimum set of PKI credentials for a fake Metropolis cluster.
+func NewEphemeralClusterCredentials(t *testing.T, nodes int) *EphemeralClusterCredentials {
+	ctx := context.Background()
+	t.Helper()
+
+	ns := pki.Namespaced("unused")
+	caCert := pki.Certificate{
+		Namespace: &ns,
+		Issuer:    pki.SelfSigned,
+		Template:  identity.CACertificate("test cluster ca"),
+		Mode:      pki.CertificateEphemeral,
+	}
+	caBytes, err := caCert.Ensure(ctx, nil)
+	if err != nil {
+		t.Fatalf("Could not ensure CA certificate: %v", err)
+	}
+	ca, err := x509.ParseCertificate(caBytes)
+	if err != nil {
+		t.Fatalf("Could not parse new CA certificate: %v", err)
+	}
+
+	managerCert := pki.Certificate{
+		Namespace: &ns,
+		Issuer:    &caCert,
+		Template:  identity.UserCertificate("owner"),
+		Mode:      pki.CertificateEphemeral,
+	}
+	managerBytes, err := managerCert.Ensure(ctx, nil)
+	if err != nil {
+		t.Fatalf("Could not ensure manager certificate: %v", err)
+	}
+	res := &EphemeralClusterCredentials{
+		Nodes: make([]*identity.NodeCredentials, nodes),
+		Manager: tls.Certificate{
+			Certificate: [][]byte{managerBytes},
+			PrivateKey:  managerCert.PrivateKey,
+		},
+		CA: ca,
+	}
+
+	for i := 0; i < nodes; i++ {
+		npk, npr, err := ed25519.GenerateKey(rand.Reader)
+		if err != nil {
+			t.Fatalf("Could not generate node keypair: %v", err)
+		}
+		nodeCert := pki.Certificate{
+			Namespace: &ns,
+			Issuer:    &caCert,
+			Template:  identity.NodeCertificate(npk),
+			Mode:      pki.CertificateEphemeral,
+			PublicKey: npk,
+			Name:      "",
+		}
+		nodeBytes, err := nodeCert.Ensure(ctx, nil)
+		if err != nil {
+			t.Fatalf("Could not ensure node certificate: %v", err)
+		}
+		node, err := identity.NewNodeCredentials(npr, nodeBytes, caBytes)
+		if err != nil {
+			t.Fatalf("Could not build node credentials: %v", err)
+		}
+		res.Nodes[i] = node
+	}
+
+	return res
+}
+
+// EphemeralClusterCredentials are TLS/PKI credentials for use in a Metropolis
+// test cluster.
+type EphemeralClusterCredentials struct {
+	// Nodes are the node credentials for the cluster. Each contains a private
+	// key and x509 certificate authenticating the bearer as a Metropolis node.
+	Nodes []*identity.NodeCredentials
+	// Manager TLS certificate for the cluster. Contains a private key and x509
+	// certificate authenticating the bearer as a Metropolis manager.
+	Manager tls.Certificate
+	// CA is the x509 certificate of the CA certificate for the cluster. Manager and
+	// Node certificates are signed by this CA.
+	CA *x509.Certificate
+}