m/pkg/pki: forbid External/Managed certificates without name

This ensures any stored certificates must have a name set - otherwise
they end up being created with an empty string as a name, and end up
colliding with eachother.

Change-Id: I9e415b6ff89dbda179526920d58e33e638a28cec
Reviewed-on: https://review.monogon.dev/c/monogon/+/286
Reviewed-by: Mateusz Zalega <mateusz@monogon.tech>
diff --git a/metropolis/node/core/curator/bootstrap.go b/metropolis/node/core/curator/bootstrap.go
index 6147125..c764104 100644
--- a/metropolis/node/core/curator/bootstrap.go
+++ b/metropolis/node/core/curator/bootstrap.go
@@ -39,6 +39,7 @@
 		Template:  pki.Server([]string{id}, nil),
 		Mode:      pki.CertificateExternal,
 		PublicKey: pubkey,
+		Name:      fmt.Sprintf("node-%s", id),
 	}
 	node, err = nodeCert.Ensure(ctx, etcd)
 	if err != nil {
diff --git a/metropolis/pkg/pki/certificate.go b/metropolis/pkg/pki/certificate.go
index 4ec3bf0..e7788b1 100644
--- a/metropolis/pkg/pki/certificate.go
+++ b/metropolis/pkg/pki/certificate.go
@@ -177,6 +177,14 @@
 		return nil, fmt.Errorf("invalid certificate mode %v", c.Mode)
 	}
 
+	if c.Name == "" {
+		if c.Mode == CertificateExternal {
+			return nil, fmt.Errorf("external certificate must have name set")
+		} else {
+			return nil, fmt.Errorf("managed certificate must have name set")
+		}
+	}
+
 	certPath := c.Namespace.etcdPath("%s-cert.der", c.Name)
 
 	// Try loading certificate from etcd.