| package util | 
 |  | 
 | import ( | 
 | 	"context" | 
 | 	"crypto/ed25519" | 
 | 	"crypto/rand" | 
 | 	"crypto/tls" | 
 | 	"crypto/x509" | 
 | 	"testing" | 
 |  | 
 | 	"source.monogon.dev/metropolis/node/core/identity" | 
 | 	"source.monogon.dev/metropolis/pkg/pki" | 
 | ) | 
 |  | 
 | // NewEphemeralClusterCredentials creates a set of TLS certificates for use in a | 
 | // test Metropolis cluster. These are a CA certificate, a Manager certificate | 
 | // and an arbitrary amount of Node certificates (per the nodes argument). | 
 | // | 
 | // All of these are ephemeral, ie. not stored anywhere - including the CA | 
 | // certificate. This function is for use by tests which want to bring up a | 
 | // minimum set of PKI credentials for a fake Metropolis cluster. | 
 | func NewEphemeralClusterCredentials(t *testing.T, nodes int) *EphemeralClusterCredentials { | 
 | 	ctx := context.Background() | 
 | 	t.Helper() | 
 |  | 
 | 	ns := pki.Namespaced("unused") | 
 | 	caCert := pki.Certificate{ | 
 | 		Namespace: &ns, | 
 | 		Issuer:    pki.SelfSigned, | 
 | 		Template:  identity.CACertificate("test cluster ca"), | 
 | 		Mode:      pki.CertificateEphemeral, | 
 | 	} | 
 | 	caBytes, err := caCert.Ensure(ctx, nil) | 
 | 	if err != nil { | 
 | 		t.Fatalf("Could not ensure CA certificate: %v", err) | 
 | 	} | 
 | 	ca, err := x509.ParseCertificate(caBytes) | 
 | 	if err != nil { | 
 | 		t.Fatalf("Could not parse new CA certificate: %v", err) | 
 | 	} | 
 |  | 
 | 	managerCert := pki.Certificate{ | 
 | 		Namespace: &ns, | 
 | 		Issuer:    &caCert, | 
 | 		Template:  identity.UserCertificate("owner"), | 
 | 		Mode:      pki.CertificateEphemeral, | 
 | 	} | 
 | 	managerBytes, err := managerCert.Ensure(ctx, nil) | 
 | 	if err != nil { | 
 | 		t.Fatalf("Could not ensure manager certificate: %v", err) | 
 | 	} | 
 | 	res := &EphemeralClusterCredentials{ | 
 | 		Nodes: make([]*identity.NodeCredentials, nodes), | 
 | 		Manager: tls.Certificate{ | 
 | 			Certificate: [][]byte{managerBytes}, | 
 | 			PrivateKey:  managerCert.PrivateKey, | 
 | 		}, | 
 | 		CA: ca, | 
 | 	} | 
 |  | 
 | 	for i := 0; i < nodes; i++ { | 
 | 		npk, npr, err := ed25519.GenerateKey(rand.Reader) | 
 | 		if err != nil { | 
 | 			t.Fatalf("Could not generate node keypair: %v", err) | 
 | 		} | 
 | 		nodeCert := pki.Certificate{ | 
 | 			Namespace: &ns, | 
 | 			Issuer:    &caCert, | 
 | 			Template:  identity.NodeCertificate(npk), | 
 | 			Mode:      pki.CertificateEphemeral, | 
 | 			PublicKey: npk, | 
 | 			Name:      "", | 
 | 		} | 
 | 		nodeBytes, err := nodeCert.Ensure(ctx, nil) | 
 | 		if err != nil { | 
 | 			t.Fatalf("Could not ensure node certificate: %v", err) | 
 | 		} | 
 | 		node, err := identity.NewNodeCredentials(npr, nodeBytes, caBytes) | 
 | 		if err != nil { | 
 | 			t.Fatalf("Could not build node credentials: %v", err) | 
 | 		} | 
 | 		res.Nodes[i] = node | 
 | 	} | 
 |  | 
 | 	return res | 
 | } | 
 |  | 
 | // EphemeralClusterCredentials are TLS/PKI credentials for use in a Metropolis | 
 | // test cluster. | 
 | type EphemeralClusterCredentials struct { | 
 | 	// Nodes are the node credentials for the cluster. Each contains a private | 
 | 	// key and x509 certificate authenticating the bearer as a Metropolis node. | 
 | 	Nodes []*identity.NodeCredentials | 
 | 	// Manager TLS certificate for the cluster. Contains a private key and x509 | 
 | 	// certificate authenticating the bearer as a Metropolis manager. | 
 | 	Manager tls.Certificate | 
 | 	// CA is the x509 certificate of the CA certificate for the cluster. Manager and | 
 | 	// Node certificates are signed by this CA. | 
 | 	CA *x509.Certificate | 
 | } |