metropolis/cli/metroctl: add cert export command

To scrape metrics we currently need the owner certificate in a usable format.

Change-Id: Ic6695b14a764d71d9c7b698c113fe0109d5820bf
Reviewed-on: https://review.monogon.dev/c/monogon/+/1932
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/BUILD.bazel b/metropolis/cli/metroctl/BUILD.bazel
index de7b759..3b6dc25 100644
--- a/metropolis/cli/metroctl/BUILD.bazel
+++ b/metropolis/cli/metroctl/BUILD.bazel
@@ -3,6 +3,7 @@
 go_library(
     name = "metroctl_lib",
     srcs = [
+        "cmd_certs.go",
         "cmd_install.go",
         "cmd_k8s_configure.go",
         "cmd_k8scredplugin.go",
diff --git a/metropolis/cli/metroctl/cmd_certs.go b/metropolis/cli/metroctl/cmd_certs.go
new file mode 100644
index 0000000..e0bfd41
--- /dev/null
+++ b/metropolis/cli/metroctl/cmd_certs.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+	"crypto/x509"
+	"encoding/pem"
+	"log"
+	"os"
+
+	"github.com/spf13/cobra"
+
+	"source.monogon.dev/metropolis/cli/metroctl/core"
+)
+
+func init() {
+	certCmd.AddCommand(certExportCmd)
+
+	rootCmd.AddCommand(certCmd)
+}
+
+var certCmd = &cobra.Command{
+	Short: "Certificate utilities",
+	Use:   "cert",
+}
+
+var certExportCmd = &cobra.Command{
+	Short:   "Exports certificates for use in other programs",
+	Use:     "export",
+	Example: "metroctl cert export",
+	Run: func(cmd *cobra.Command, args []string) {
+		ocert, opkey, err := core.GetOwnerCredentials(flags.configPath)
+		if err == core.NoCredentialsError {
+			log.Fatalf("You have to take ownership of the cluster first: %v", err)
+		}
+
+		pkcs8Key, err := x509.MarshalPKCS8PrivateKey(opkey)
+		if err != nil {
+			// We explicitly pass an Ed25519 private key in, so this can't happen
+			panic(err)
+		}
+
+		if err := os.WriteFile("owner.crt", pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: ocert.Raw}), 0755); err != nil {
+			log.Fatal(err)
+		}
+
+		if err := os.WriteFile("owner.key", pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: pkcs8Key}), 0755); err != nil {
+			log.Fatal(err)
+		}
+		log.Println("Wrote files to current dir: cert.pem, key.pem")
+	},
+	Args: cobra.NoArgs,
+}