mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-12 17:59:06 +02:00
110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
// Package certtest builds throwaway CAs and leaf certificates for certificate posture tests.
|
|
package certtest
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/ed25519"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type CA struct {
|
|
Cert *x509.Certificate
|
|
Key crypto.Signer
|
|
PEM string
|
|
}
|
|
|
|
func NewCA(t *testing.T, name string) *CA {
|
|
t.Helper()
|
|
return newCA(t, name, nil)
|
|
}
|
|
|
|
// NewIntermediate creates a CA signed by parent.
|
|
func NewIntermediate(t *testing.T, parent *CA, name string) *CA {
|
|
t.Helper()
|
|
return newCA(t, name, parent)
|
|
}
|
|
|
|
func newCA(t *testing.T, name string, parent *CA) *CA {
|
|
t.Helper()
|
|
key := ECDSAKey(t)
|
|
tmpl := &x509.Certificate{
|
|
SerialNumber: big.NewInt(time.Now().UnixNano()),
|
|
Subject: pkix.Name{CommonName: name},
|
|
NotBefore: time.Now().Add(-24 * time.Hour),
|
|
NotAfter: time.Now().Add(48 * time.Hour),
|
|
IsCA: true,
|
|
BasicConstraintsValid: true,
|
|
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
|
|
}
|
|
issuer, issuerKey := tmpl, key
|
|
if parent != nil {
|
|
issuer, issuerKey = parent.Cert, parent.Key
|
|
}
|
|
der, err := x509.CreateCertificate(rand.Reader, tmpl, issuer, key.Public(), issuerKey)
|
|
require.NoError(t, err)
|
|
cert, err := x509.ParseCertificate(der)
|
|
require.NoError(t, err)
|
|
return &CA{Cert: cert, Key: key, PEM: CertPEM(cert)}
|
|
}
|
|
|
|
// Issue signs a leaf certificate for key with the CA.
|
|
func (ca *CA) Issue(t *testing.T, key crypto.Signer, cn string) *x509.Certificate {
|
|
t.Helper()
|
|
tmpl := &x509.Certificate{
|
|
SerialNumber: big.NewInt(time.Now().UnixNano()),
|
|
Subject: pkix.Name{CommonName: cn},
|
|
NotBefore: time.Now().Add(-24 * time.Hour),
|
|
NotAfter: time.Now().Add(48 * time.Hour),
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
|
}
|
|
der, err := x509.CreateCertificate(rand.Reader, tmpl, ca.Cert, key.Public(), ca.Key)
|
|
require.NoError(t, err)
|
|
cert, err := x509.ParseCertificate(der)
|
|
require.NoError(t, err)
|
|
return cert
|
|
}
|
|
|
|
func ECDSAKey(t *testing.T) crypto.Signer {
|
|
t.Helper()
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
require.NoError(t, err)
|
|
return key
|
|
}
|
|
|
|
func RSAKey(t *testing.T) crypto.Signer {
|
|
t.Helper()
|
|
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
require.NoError(t, err)
|
|
return key
|
|
}
|
|
|
|
func Ed25519Key(t *testing.T) crypto.Signer {
|
|
t.Helper()
|
|
_, key, err := ed25519.GenerateKey(rand.Reader)
|
|
require.NoError(t, err)
|
|
return key
|
|
}
|
|
|
|
func CertPEM(cert *x509.Certificate) string {
|
|
return string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}))
|
|
}
|
|
|
|
func KeyPEM(t *testing.T, key crypto.Signer) string {
|
|
t.Helper()
|
|
der, err := x509.MarshalPKCS8PrivateKey(key)
|
|
require.NoError(t, err)
|
|
return string(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der}))
|
|
}
|