cloud/bmaas/server: init

This adds the BMaaS server alongside its first functionality: serving an
Agent heartbeat API.

This allows (untrusted) Agents to communicate with the rest of the
system by submitting heartbeats which may include a hardware report.

The BMaaS server will likely grow to implement further functionality as
described in its README.

Change-Id: I1ede02121b3700079cbb11295525f4c167ee1e7d
Reviewed-on: https://review.monogon.dev/c/monogon/+/988
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/lib/component/component.go b/cloud/lib/component/component.go
index 831d099..dee4703 100644
--- a/cloud/lib/component/component.go
+++ b/cloud/lib/component/component.go
@@ -106,3 +106,37 @@
 		grpc.Creds(credentials.NewTLS(tlsConf)),
 	}
 }
+
+// GRPCServerOptionsPublic returns pre-built grpc.ServerOptions that this
+// component should use to serve public gRPC. Any client will be allowed to
+// connect, and it's up to the server implementation to authenticate incoming
+// requests.
+func (c *ComponentConfig) GRPCServerOptionsPublic() []grpc.ServerOption {
+	var certPath, keyPath string
+	if c.DevCerts {
+		// Use devcerts if requested.
+		certPath, keyPath, _ = c.GetDevCerts()
+	} else {
+		// Otherwise, use data from flags.
+		if c.GRPCKeyPath == "" {
+			klog.Exitf("-grpc_key_path must be set")
+		}
+		if c.GRPCCertificatePath == "" {
+			klog.Exitf("-grpc_certificate_path must be set")
+		}
+		keyPath = c.GRPCKeyPath
+		certPath = c.GRPCCertificatePath
+	}
+
+	pair, err := tls.LoadX509KeyPair(certPath, keyPath)
+	if err != nil {
+		klog.Exitf("Could not load GRPC TLS keypair: %v", err)
+	}
+	tlsConf := &tls.Config{
+		Certificates: []tls.Certificate{pair},
+		ClientAuth:   tls.RequestClientCert,
+	}
+	return []grpc.ServerOption{
+		grpc.Creds(credentials.NewTLS(tlsConf)),
+	}
+}