github.com/letsencrypt/boulder@v0.20251208.0/cmd/config_test.go (about) 1 package cmd 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rand" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/pem" 10 "math/big" 11 "os" 12 "path" 13 "regexp" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/letsencrypt/boulder/metrics" 19 "github.com/letsencrypt/boulder/test" 20 ) 21 22 func TestDBConfigURL(t *testing.T) { 23 tests := []struct { 24 conf DBConfig 25 expected string 26 }{ 27 { 28 // Test with one config file that has no trailing newline 29 conf: DBConfig{DBConnectFile: "testdata/test_dburl"}, 30 expected: "test@tcp(testhost:3306)/testDB?readTimeout=800ms&writeTimeout=800ms", 31 }, 32 { 33 // Test with a config file that *has* a trailing newline 34 conf: DBConfig{DBConnectFile: "testdata/test_dburl_newline"}, 35 expected: "test@tcp(testhost:3306)/testDB?readTimeout=800ms&writeTimeout=800ms", 36 }, 37 } 38 39 for _, tc := range tests { 40 url, err := tc.conf.URL() 41 test.AssertNotError(t, err, "Failed calling URL() on DBConfig") 42 test.AssertEquals(t, url, tc.expected) 43 } 44 } 45 46 func TestPasswordConfig(t *testing.T) { 47 tests := []struct { 48 pc PasswordConfig 49 expected string 50 }{ 51 {pc: PasswordConfig{}, expected: ""}, 52 {pc: PasswordConfig{PasswordFile: "testdata/test_secret"}, expected: "secret"}, 53 } 54 55 for _, tc := range tests { 56 password, err := tc.pc.Pass() 57 test.AssertNotError(t, err, "Failed to retrieve password") 58 test.AssertEquals(t, password, tc.expected) 59 } 60 } 61 62 func TestTLSConfigLoad(t *testing.T) { 63 null := "/dev/null" 64 nonExistent := "[nonexistent]" 65 tmp := t.TempDir() 66 cert := path.Join(tmp, "TestTLSConfigLoad.cert.pem") 67 key := path.Join(tmp, "TestTLSConfigLoad.key.pem") 68 caCert := path.Join(tmp, "TestTLSConfigLoad.cacert.pem") 69 70 rootKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) 71 test.AssertNotError(t, err, "creating test root key") 72 rootTemplate := &x509.Certificate{ 73 Subject: pkix.Name{CommonName: "test root"}, 74 SerialNumber: big.NewInt(12345), 75 NotBefore: time.Now().Add(-24 * time.Hour), 76 NotAfter: time.Now().Add(24 * time.Hour), 77 IsCA: true, 78 } 79 rootCert, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, rootKey.Public(), rootKey) 80 test.AssertNotError(t, err, "creating test root cert") 81 err = os.WriteFile(caCert, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: rootCert}), os.ModeAppend) 82 test.AssertNotError(t, err, "writing test root cert to disk") 83 84 intKey, err := ecdsa.GenerateKey(elliptic.P224(), rand.Reader) 85 test.AssertNotError(t, err, "creating test intermediate key") 86 intKeyBytes, err := x509.MarshalECPrivateKey(intKey) 87 test.AssertNotError(t, err, "marshalling test intermediate key") 88 err = os.WriteFile(key, pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: intKeyBytes}), os.ModeAppend) 89 test.AssertNotError(t, err, "writing test intermediate key cert to disk") 90 91 intTemplate := &x509.Certificate{ 92 Subject: pkix.Name{CommonName: "test intermediate"}, 93 SerialNumber: big.NewInt(67890), 94 NotBefore: time.Now().Add(-12 * time.Hour), 95 NotAfter: time.Now().Add(12 * time.Hour), 96 IsCA: true, 97 } 98 intCert, err := x509.CreateCertificate(rand.Reader, intTemplate, rootTemplate, intKey.Public(), rootKey) 99 test.AssertNotError(t, err, "creating test intermediate cert") 100 err = os.WriteFile(cert, pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: intCert}), os.ModeAppend) 101 test.AssertNotError(t, err, "writing test intermediate cert to disk") 102 103 testCases := []struct { 104 TLSConfig 105 want string 106 }{ 107 {TLSConfig{"", null, null}, "nil CertFile in TLSConfig"}, 108 {TLSConfig{null, "", null}, "nil KeyFile in TLSConfig"}, 109 {TLSConfig{null, null, ""}, "nil CACertFile in TLSConfig"}, 110 {TLSConfig{nonExistent, key, caCert}, "loading key pair.*no such file or directory"}, 111 {TLSConfig{cert, nonExistent, caCert}, "loading key pair.*no such file or directory"}, 112 {TLSConfig{cert, key, nonExistent}, "reading CA cert from.*no such file or directory"}, 113 {TLSConfig{null, key, caCert}, "loading key pair.*failed to find any PEM data"}, 114 {TLSConfig{cert, null, caCert}, "loading key pair.*failed to find any PEM data"}, 115 {TLSConfig{cert, key, null}, "parsing CA certs"}, 116 {TLSConfig{cert, key, caCert}, ""}, 117 } 118 for _, tc := range testCases { 119 title := [3]string{tc.CertFile, tc.KeyFile, tc.CACertFile} 120 for i := range title { 121 if title[i] == "" { 122 title[i] = "nil" 123 } 124 } 125 t.Run(strings.Join(title[:], "_"), func(t *testing.T) { 126 _, err := tc.TLSConfig.Load(metrics.NoopRegisterer) 127 if err == nil && tc.want == "" { 128 return 129 } 130 if err == nil { 131 t.Errorf("got no error") 132 } 133 if matched, _ := regexp.MatchString(tc.want, err.Error()); !matched { 134 t.Errorf("got error %q, wanted %q", err, tc.want) 135 } 136 }) 137 } 138 } 139 140 func TestHMACKeyConfigLoad(t *testing.T) { 141 t.Parallel() 142 143 tests := []struct { 144 name string 145 content string 146 expectedErr bool 147 }{ 148 { 149 name: "Valid key", 150 content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 151 expectedErr: false, 152 }, 153 { 154 name: "Empty file", 155 content: "", 156 expectedErr: true, 157 }, 158 { 159 name: "Just under 256-bit", 160 content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab", 161 expectedErr: true, 162 }, 163 { 164 name: "Just over 256-bit", 165 content: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01", 166 expectedErr: true, 167 }, 168 } 169 170 for _, tt := range tests { 171 t.Run(tt.name, func(t *testing.T) { 172 t.Parallel() 173 174 tempKeyFile, err := os.CreateTemp("", "*") 175 if err != nil { 176 t.Fatalf("failed to create temp file: %v", err) 177 } 178 defer os.Remove(tempKeyFile.Name()) 179 180 _, err = tempKeyFile.WriteString(tt.content) 181 if err != nil { 182 t.Fatalf("failed to write to temp file: %v", err) 183 } 184 tempKeyFile.Close() 185 186 hmacKeyConfig := HMACKeyConfig{KeyFile: tempKeyFile.Name()} 187 _, err = hmacKeyConfig.Load() 188 if (err != nil) != tt.expectedErr { 189 t.Errorf("expected error: %v, got: %v", tt.expectedErr, err) 190 } 191 }) 192 } 193 }