105 lines
3.3 KiB
Go
105 lines
3.3 KiB
Go
package rotator
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"encoding/pem"
|
|
"math/big"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestGenerateRequest(t *testing.T) {
|
|
addresses := []net.IP{net.ParseIP("10.0.0.1"), net.ParseIP("172.30.1.1")}
|
|
privateKey, encoded, err := generateRequest(addresses)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block, _ := pem.Decode(encoded)
|
|
request, err := x509.ParseCertificateRequest(block.Bytes)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := request.CheckSignature(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(request.IPAddresses) != len(addresses) || !request.IPAddresses[0].Equal(addresses[0]) || !request.IPAddresses[1].Equal(addresses[1]) {
|
|
t.Fatalf("unexpected IP SANs: %v", request.IPAddresses)
|
|
}
|
|
publicKey := request.PublicKey.(*ecdsa.PublicKey)
|
|
if !publicKey.Equal(&privateKey.PublicKey) {
|
|
t.Fatal("request does not contain the generated public key")
|
|
}
|
|
}
|
|
|
|
func TestRequiredURL(t *testing.T) {
|
|
t.Setenv("OPNSENSE_URL", "https://172.30.1.1:8443")
|
|
if value, err := requiredURL("OPNSENSE_URL"); err != nil || value != "https://172.30.1.1:8443" {
|
|
t.Fatalf("unexpected URL result: value=%q error=%v", value, err)
|
|
}
|
|
|
|
for _, value := range []string{"", "http://172.30.1.1:8443", "https://[email protected]:8443", "https://172.30.1.1:8443/api"} {
|
|
t.Run(value, func(t *testing.T) {
|
|
t.Setenv("OPNSENSE_URL", value)
|
|
if _, err := requiredURL("OPNSENSE_URL"); err == nil {
|
|
t.Fatalf("accepted invalid URL %q", value)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVerifySignedCertificate(t *testing.T) {
|
|
addresses := []net.IP{net.ParseIP("10.0.0.1"), net.ParseIP("172.30.1.1")}
|
|
now := time.Now()
|
|
rootKey, root := createCertificate(t, nil, nil, &x509.Certificate{
|
|
SerialNumber: big.NewInt(1),
|
|
Subject: pkix.Name{CommonName: "root"},
|
|
NotBefore: now.Add(-time.Hour),
|
|
NotAfter: now.Add(24 * time.Hour),
|
|
IsCA: true,
|
|
BasicConstraintsValid: true,
|
|
KeyUsage: x509.KeyUsageCertSign,
|
|
})
|
|
leafKey, leaf := createCertificate(t, root, rootKey, &x509.Certificate{
|
|
SerialNumber: big.NewInt(2),
|
|
NotBefore: now.Add(-time.Hour),
|
|
NotAfter: now.Add(12 * time.Hour),
|
|
IPAddresses: addresses,
|
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
|
})
|
|
rootPEM := string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: root.Raw}))
|
|
trustedRoots := x509.NewCertPool()
|
|
trustedRoots.AddCert(root)
|
|
if err := verifySignedCertificate(leaf, []string{rootPEM}, trustedRoots, addresses, leafKey); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := verifySignedCertificate(leaf, []string{rootPEM}, trustedRoots, []net.IP{net.ParseIP("10.0.0.1"), net.ParseIP("172.30.1.2")}, leafKey); err == nil {
|
|
t.Fatal("wrong IP SAN was accepted")
|
|
}
|
|
}
|
|
|
|
func createCertificate(t *testing.T, parent *x509.Certificate, parentKey *ecdsa.PrivateKey, template *x509.Certificate) (*ecdsa.PrivateKey, *x509.Certificate) {
|
|
t.Helper()
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if parent == nil {
|
|
parent = template
|
|
parentKey = key
|
|
}
|
|
encoded, err := x509.CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
certificate, err := x509.ParseCertificate(encoded)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return key, certificate
|
|
}
|