m/proto: switch from CA pubkey to CA certificate in ClusterDirectory/Register

A CA certificate is a strict superset of the public key, and using it
instead of a public key allows us to connect to the cluster securely by
reusing standard/existing x509 CA auth, instead of having to implement a
check based on just a public key.

Backwards-incompatible proto change, but we're pre-MVP, and this flow is
just being implemented.

Change-Id: I014780a6ec3e5e8c6e81532531b18ad1438c8258
Reviewed-on: https://review.monogon.dev/c/monogon/+/424
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/core/curator/impl_leader_management.go b/metropolis/node/core/curator/impl_leader_management.go
index 676688d..dfc07a8 100644
--- a/metropolis/node/core/curator/impl_leader_management.go
+++ b/metropolis/node/core/curator/impl_leader_management.go
@@ -3,7 +3,6 @@
 import (
 	"bytes"
 	"context"
-	"crypto/ed25519"
 	"sort"
 
 	"google.golang.org/grpc/codes"
@@ -106,6 +105,6 @@
 
 	return &apb.GetClusterInfoResponse{
 		ClusterDirectory: directory,
-		CaPublicKey:      l.node.ClusterCA().PublicKey.(ed25519.PublicKey),
+		CaCertificate:    l.node.ClusterCA().Raw,
 	}, nil
 }
diff --git a/metropolis/node/core/curator/impl_leader_test.go b/metropolis/node/core/curator/impl_leader_test.go
index 97ea58e..2e1dfe8 100644
--- a/metropolis/node/core/curator/impl_leader_test.go
+++ b/metropolis/node/core/curator/impl_leader_test.go
@@ -5,6 +5,7 @@
 	"context"
 	"crypto/ed25519"
 	"crypto/rand"
+	"crypto/x509"
 	"encoding/hex"
 	"testing"
 
@@ -588,7 +589,11 @@
 	}
 
 	// Cluster CA public key should match
-	if want, got := cl.caPubKey, res.CaPublicKey; !bytes.Equal(want, got) {
+	ca, err := x509.ParseCertificate(res.CaCertificate)
+	if err != nil {
+		t.Fatalf("CaCertificate could not be parsed: %v", err)
+	}
+	if want, got := cl.caPubKey, ca.PublicKey.(ed25519.PublicKey); !bytes.Equal(want, got) {
 		t.Fatalf("CaPublicKey mismatch (wanted %s, got %s)", hex.EncodeToString(want), hex.EncodeToString(got))
 	}
 }
diff --git a/metropolis/proto/api/configuration.proto b/metropolis/proto/api/configuration.proto
index 62d5094..9ff1c43 100644
--- a/metropolis/proto/api/configuration.proto
+++ b/metropolis/proto/api/configuration.proto
@@ -51,10 +51,11 @@
         // begin registering it into a cluster. It can be retrieved by an
         // operator from a running cluster via Management.GetRegisterTicket.
         bytes register_ticket = 2;
-        // ca_public_key is the public key of the CA of the cluster that the
+        // ca_certificate is the DER-encoded x509 CA of the cluster that the
         // node should expect when contacting nodes in cluster_directory and
-        // attempting to register into a cluster.
-        bytes ca_public_key = 3;
+        // attempting to register into a cluster. It can be retrieved by
+        // an operator from a running cluster via Management.GetClusterInfo.
+        bytes ca_certificate = 3;
     }
     oneof cluster {
         ClusterBootstrap cluster_bootstrap = 1;
diff --git a/metropolis/proto/api/management.proto b/metropolis/proto/api/management.proto
index 9f0e646..44db0c5 100644
--- a/metropolis/proto/api/management.proto
+++ b/metropolis/proto/api/management.proto
@@ -45,6 +45,6 @@
     // cluster that can be used to dial the cluster's services.
     metropolis.proto.common.ClusterDirectory cluster_directory = 1;
 
-    // ca_public_key is the Ed25519 public key of the CA of the cluster.
-    bytes ca_public_key = 2;
+    // ca_certificate is the x509 DER encoded CA certificate of the cluster.
+    bytes ca_certificate = 2;
 }