|
8 | 8 | "crypto/x509" |
9 | 9 | "encoding/pem" |
10 | 10 | "math/big" |
| 11 | + "net" |
11 | 12 | "os" |
12 | 13 | "path/filepath" |
13 | 14 | "testing" |
@@ -164,6 +165,35 @@ func newCertWithoutIP(tb testing.TB) ( |
164 | 165 | return caCert, buf.Bytes(), leafKeyPEM |
165 | 166 | } |
166 | 167 |
|
| 168 | +// newCertWithIP generates a self-signed certificate with an IP address in its |
| 169 | +// SAN extension and returns the PEM-encoded certificate and private key. |
| 170 | +func newCertWithIP(tb testing.TB) (certPEM, keyPEM []byte) { |
| 171 | + tb.Helper() |
| 172 | + |
| 173 | + key, err := rsa.GenerateKey(rand.Reader, 2048) |
| 174 | + require.NoError(tb, err) |
| 175 | + |
| 176 | + now := time.Now() |
| 177 | + tmpl := &x509.Certificate{ |
| 178 | + SerialNumber: big.NewInt(1), |
| 179 | + NotBefore: now.Add(-time.Hour), |
| 180 | + NotAfter: now.Add(time.Hour), |
| 181 | + KeyUsage: x509.KeyUsageDigitalSignature, |
| 182 | + IPAddresses: []net.IP{net.ParseIP("192.0.2.1")}, |
| 183 | + } |
| 184 | + |
| 185 | + certDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) |
| 186 | + require.NoError(tb, err) |
| 187 | + |
| 188 | + certPEM = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER}) |
| 189 | + keyPEM = pem.EncodeToMemory(&pem.Block{ |
| 190 | + Type: "RSA PRIVATE KEY", |
| 191 | + Bytes: x509.MarshalPKCS1PrivateKey(key), |
| 192 | + }) |
| 193 | + |
| 194 | + return certPEM, keyPEM |
| 195 | +} |
| 196 | + |
167 | 197 | // newCertAndKey is a helper function that generates certificate and key. |
168 | 198 | func newCertAndKey(tb testing.TB, n int64) (certDER []byte, key *rsa.PrivateKey) { |
169 | 199 | tb.Helper() |
@@ -312,3 +342,77 @@ func TestTLSManager_Reload(t *testing.T) { |
312 | 342 | extTLSConf = m.extendedTLSConfig() |
313 | 343 | assertCertSerialNumber(t, extTLSConf, snAfter) |
314 | 344 | } |
| 345 | + |
| 346 | +func TestTLSManager_HasIPAddrs(t *testing.T) { |
| 347 | + ctx := testutil.ContextWithTimeout(t, testTimeout) |
| 348 | + |
| 349 | + _, noIPChainPEM, noIPKeyPEM := newCertWithoutIP(t) |
| 350 | + ipChainPEM, ipKeyPEM := newCertWithIP(t) |
| 351 | + |
| 352 | + noIPSettings := tlsConfigSettings{ |
| 353 | + Enabled: true, |
| 354 | + CertificateChain: string(noIPChainPEM), |
| 355 | + PrivateKey: string(noIPKeyPEM), |
| 356 | + } |
| 357 | + ipSettings := tlsConfigSettings{ |
| 358 | + Enabled: true, |
| 359 | + CertificateChain: string(ipChainPEM), |
| 360 | + PrivateKey: string(ipKeyPEM), |
| 361 | + } |
| 362 | + |
| 363 | + testCases := []struct { |
| 364 | + name string |
| 365 | + settings tlsConfigSettings |
| 366 | + update *tlsConfigSettings |
| 367 | + want bool |
| 368 | + }{{ |
| 369 | + name: "no_ip_in_cert", |
| 370 | + settings: noIPSettings, |
| 371 | + update: nil, |
| 372 | + want: false, |
| 373 | + }, { |
| 374 | + name: "has_ip_in_cert", |
| 375 | + settings: ipSettings, |
| 376 | + update: nil, |
| 377 | + want: true, |
| 378 | + }, { |
| 379 | + name: "updated_to_ip", |
| 380 | + settings: noIPSettings, |
| 381 | + update: &tlsConfigSettings{ |
| 382 | + CertificateChainData: ipChainPEM, |
| 383 | + PrivateKeyData: ipKeyPEM, |
| 384 | + }, |
| 385 | + want: true, |
| 386 | + }, { |
| 387 | + name: "updated_to_no_ip", |
| 388 | + settings: ipSettings, |
| 389 | + update: &tlsConfigSettings{ |
| 390 | + CertificateChainData: noIPChainPEM, |
| 391 | + PrivateKeyData: noIPKeyPEM, |
| 392 | + }, |
| 393 | + want: false, |
| 394 | + }} |
| 395 | + |
| 396 | + for _, tc := range testCases { |
| 397 | + t.Run(tc.name, func(t *testing.T) { |
| 398 | + m, err := newTLSManager(ctx, &tlsManagerConfig{ |
| 399 | + logger: testLogger, |
| 400 | + confModifier: agh.EmptyConfigModifier{}, |
| 401 | + manager: aghtls.EmptyManager{}, |
| 402 | + tlsSettings: tc.settings, |
| 403 | + servePlainDNS: false, |
| 404 | + }) |
| 405 | + require.NoError(t, err) |
| 406 | + |
| 407 | + if tc.update != nil { |
| 408 | + m.mu.Lock() |
| 409 | + err = m.updateTLSCert(tc.update) |
| 410 | + m.mu.Unlock() |
| 411 | + |
| 412 | + require.NoError(t, err) |
| 413 | + } |
| 414 | + |
| 415 | + assert.Equal(t, tc.want, m.HasIPAddrs()) |
| 416 | + }) |
| 417 | + } |
| 418 | +} |
0 commit comments