m/n/core: factor out gRPC/TLS into rpc and identity libraries

This is an annoying large change, which started its life as me pulling
the 'let's add tests for authentication' thread, and ended up in
unifying a whole bunch of dispersed logic under two new libraries.

Notable changes:

 - m/n/core/identity now contains the NodeCertificate (now called Node)
   and NodeCredentials types. These used to exist in the cluster code,
   but were factored out to prevent loops between the curator, the
   cluster enrolment logic, and other code. They can now be shared by
   nearly all of the node code, removing the need for some conversions
   between subsystems/packages.
 - Alongside Node{,Credentials} types, the identity package contains
   code that creates x509 certificate templates and verifies x509
   certificates, and has functions specific to nodes and users - not
   clients and servers. This allows moving most of the rest of
   certificate checking code into a single set of functions, and allows
   us to test this logic thoroughly.
 - pki.{Client,Server,CA} are not used by the node core code anymore,
   and can now be moved to kubernetes-specific code (as that was their
   original purpose and that's their only current use).
 - m/n/core/rpc has been refactored to deduplicate code between the
   local/external gRPC servers and unary/stream interceptors for these
   servers, also allowing for more thorough testing and unified
   behaviour between all.
 - A PeerInfo structure is now injected into all gRPC handlers, and is
   unified to contain information both about nodes, users, and possibly
   unauthenticated callers.
 - The AAA.Escrow implementation now makes use of PeerInfo in order to
   retrieve the client's certificate, instead of rolling its own logic.
 - The EphemeralClusterCredentials test helper has been moved to the rpc
   library, and now returns identity objects, allowing for simplified
   test code (less juggling of bare public keys and
   {x509,tls}.Certificate objects).

Change-Id: I9284966b4f18c0d7628167ca3168b4b4037808c1
Reviewed-on: https://review.monogon.dev/c/monogon/+/325
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/core/rpc/testhelpers.go b/metropolis/node/core/rpc/testhelpers.go
new file mode 100644
index 0000000..93e4b46
--- /dev/null
+++ b/metropolis/node/core/rpc/testhelpers.go
@@ -0,0 +1,100 @@
+package rpc
+
+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
+}