m/n/c/curator: listen on public gRPC

This enables listening on CuratorPort (which was called
NodeServicePort) using TLS node certificates. No service is yet running
on the new gRPC listener.

Change-Id: I436ac1ae9cbdb257419ad114262fc2a7516396b1
Reviewed-on: https://review.monogon.dev/c/monogon/+/288
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/metropolis/node/core/cluster/BUILD.bazel b/metropolis/node/core/cluster/BUILD.bazel
index 322a337..a68f63c 100644
--- a/metropolis/node/core/cluster/BUILD.bazel
+++ b/metropolis/node/core/cluster/BUILD.bazel
@@ -23,6 +23,7 @@
         "//metropolis/proto/api:go_default_library",
         "//metropolis/proto/common:go_default_library",
         "//metropolis/proto/private:go_default_library",
+        "@org_golang_google_grpc//credentials:go_default_library",
         "@org_golang_google_protobuf//proto:go_default_library",
     ],
 )
diff --git a/metropolis/node/core/cluster/node.go b/metropolis/node/core/cluster/node.go
index 0d4daac..0e3c29a 100644
--- a/metropolis/node/core/cluster/node.go
+++ b/metropolis/node/core/cluster/node.go
@@ -3,9 +3,12 @@
 import (
 	"crypto/ed25519"
 	"crypto/subtle"
+	"crypto/tls"
 	"crypto/x509"
 	"fmt"
 
+	"google.golang.org/grpc/credentials"
+
 	"source.monogon.dev/metropolis/node/core/curator"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 )
@@ -138,3 +141,22 @@
 func (nc *NodeCertificate) ID() string {
 	return curator.NodeID(nc.PublicKey())
 }
+
+// PublicGRPCServerCredentials returns gRPC TransportCredentials that should be
+// used by this node to run public gRPC services (ie. the AAA service and any
+// other management/user services).
+//
+// SECURITY: The returned TransportCredentials accepts _any_ client certificate
+// served by the client and does not perform any verification. The gRPC service
+// instance (via per-method checks or middleware) should perform user
+// authentication/authorization.
+func (nc *NodeCredentials) PublicGRPCServerCredentials() credentials.TransportCredentials {
+	tlsCert := tls.Certificate{
+		Certificate: [][]byte{nc.node.Raw},
+		PrivateKey:  nc.private,
+	}
+	return credentials.NewTLS(&tls.Config{
+		Certificates: []tls.Certificate{tlsCert},
+		ClientAuth:   tls.RequireAnyClientCert,
+	})
+}