boulder/cmd/config_test.go

194 lines
5.9 KiB
Go

package cmd
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"os"
"path"
"regexp"
"strings"
"testing"
"time"
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/test"
)
func TestDBConfigURL(t *testing.T) {
tests := []struct {
conf DBConfig
expected string
}{
{
// Test with one config file that has no trailing newline
conf: DBConfig{DBConnectFile: "testdata/test_dburl"},
expected: "test@tcp(testhost:3306)/testDB?readTimeout=800ms&writeTimeout=800ms",
},
{
// Test with a config file that *has* a trailing newline
conf: DBConfig{DBConnectFile: "testdata/test_dburl_newline"},
expected: "test@tcp(testhost:3306)/testDB?readTimeout=800ms&writeTimeout=800ms",
},
}
for _, tc := range tests {
url, err := tc.conf.URL()
test.AssertNotError(t, err, "Failed calling URL() on DBConfig")
test.AssertEquals(t, url, tc.expected)
}
}
func TestPasswordConfig(t *testing.T) {
tests := []struct {
pc PasswordConfig
expected string
}{
{pc: PasswordConfig{}, expected: ""},
{pc: PasswordConfig{PasswordFile: "testdata/test_secret"}, expected: "secret"},
}
for _, tc := range tests {
password, err := tc.pc.Pass()
test.AssertNotError(t, err, "Failed to retrieve password")
test.AssertEquals(t, password, tc.expected)
}
}
func TestTLSConfigLoad(t *testing.T) {
null := "/dev/null"
nonExistent := "[nonexistent]"
tmp := t.TempDir()
cert := path.Join(tmp, "TestTLSConfigLoad.cert.pem")
key := path.Join(tmp, "TestTLSConfigLoad.key.pem")
caCert := path.Join(tmp, "TestTLSConfigLoad.cacert.pem")
rootKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
test.AssertNotError(t, err, "creating test root key")
rootTemplate := &x509.Certificate{
Subject: pkix.Name{CommonName: "test root"},
SerialNumber: big.NewInt(12345),
NotBefore: time.Now().Add(-24 * time.Hour),
NotAfter: time.Now().Add(24 * time.Hour),
IsCA: true,
}
rootCert, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, rootKey.Public(), rootKey)
test.AssertNotError(t, err, "creating test root cert")
err = os.WriteFile(caCert, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert}), os.ModeAppend)
test.AssertNotError(t, err, "writing test root cert to disk")
intKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
test.AssertNotError(t, err, "creating test intermediate key")
intKeyBytes, err := x509.MarshalECPrivateKey(intKey)
test.AssertNotError(t, err, "marshalling test intermediate key")
err = os.WriteFile(key, pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: intKeyBytes}), os.ModeAppend)
test.AssertNotError(t, err, "writing test intermediate key cert to disk")
intTemplate := &x509.Certificate{
Subject: pkix.Name{CommonName: "test intermediate"},
SerialNumber: big.NewInt(67890),
NotBefore: time.Now().Add(-12 * time.Hour),
NotAfter: time.Now().Add(12 * time.Hour),
IsCA: true,
}
intCert, err := x509.CreateCertificate(rand.Reader, intTemplate, rootTemplate, intKey.Public(), rootKey)
test.AssertNotError(t, err, "creating test intermediate cert")
err = os.WriteFile(cert, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: intCert}), os.ModeAppend)
test.AssertNotError(t, err, "writing test intermediate cert to disk")
testCases := []struct {
TLSConfig
want string
}{
{TLSConfig{"", null, null}, "nil CertFile in TLSConfig"},
{TLSConfig{null, "", null}, "nil KeyFile in TLSConfig"},
{TLSConfig{null, null, ""}, "nil CACertFile in TLSConfig"},
{TLSConfig{nonExistent, key, caCert}, "loading key pair.*no such file or directory"},
{TLSConfig{cert, nonExistent, caCert}, "loading key pair.*no such file or directory"},
{TLSConfig{cert, key, nonExistent}, "reading CA cert from.*no such file or directory"},
{TLSConfig{null, key, caCert}, "loading key pair.*failed to find any PEM data"},
{TLSConfig{cert, null, caCert}, "loading key pair.*failed to find any PEM data"},
{TLSConfig{cert, key, null}, "parsing CA certs"},
{TLSConfig{cert, key, caCert}, ""},
}
for _, tc := range testCases {
title := [3]string{tc.CertFile, tc.KeyFile, tc.CACertFile}
for i := range title {
if title[i] == "" {
title[i] = "nil"
}
}
t.Run(strings.Join(title[:], "_"), func(t *testing.T) {
_, err := tc.TLSConfig.Load(metrics.NoopRegisterer)
if err == nil && tc.want == "" {
return
}
if err == nil {
t.Errorf("got no error")
}
if matched, _ := regexp.MatchString(tc.want, err.Error()); !matched {
t.Errorf("got error %q, wanted %q", err, tc.want)
}
})
}
}
func TestHMACKeyConfigLoad(t *testing.T) {
t.Parallel()
tests := []struct {
name string
content string
expectedErr bool
}{
{
name: "Valid key",
content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
expectedErr: false,
},
{
name: "Empty file",
content: "",
expectedErr: true,
},
{
name: "Just under 256-bit",
content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab",
expectedErr: true,
},
{
name: "Just over 256-bit",
content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01",
expectedErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
tempKeyFile, err := os.CreateTemp("", "*")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tempKeyFile.Name())
_, err = tempKeyFile.WriteString(tt.content)
if err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tempKeyFile.Close()
hmacKeyConfig := HMACKeyConfig{KeyFile: tempKeyFile.Name()}
_, err = hmacKeyConfig.Load()
if (err != nil) != tt.expectedErr {
t.Errorf("expected error: %v, got: %v", tt.expectedErr, err)
}
})
}
}