Pull request 2371: AGDNS-2714-tls-manager
Merge in DNS/adguard-home from AGDNS-2714-tls-manager to master
Squashed commit of the following:
commit 5c7cd1fa6d8a9bc1fd0f891818589b48bee641dc
Merge: 381f7666b 810ae9483
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Mar 26 14:13:49 2025 +0300
Merge branch 'master' into AGDNS-2714-tls-manager
commit 381f7666b063d225b114976a280e65df736495fe
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 25 19:53:12 2025 +0300
home: imp code
commit 20be72abd449fcc76417381edf7d375248a11e9e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 25 19:19:51 2025 +0300
home: imp code
commit b5a06e6a15b0f8511819267133a551a56e051499
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Mar 24 21:45:41 2025 +0300
home: imp code
commit a6a5ba727ebbc59d6de4d3762ac196d2cf194875
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Mar 20 21:06:34 2025 +0300
home: imp docs
commit 71d379bafc3f42377ce72add2cab3a56a796941d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Thu Mar 20 20:47:15 2025 +0300
all: upd chlog
commit be69a5b85d4cd4295a9b68e1c2c2205179a3e7f2
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Mar 19 20:14:20 2025 +0300
home: imp docs
commit 85b28db73b59b90365ff23fc5fc90dc1a10cc152
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Mar 19 20:07:59 2025 +0300
home: imp code
commit c11e4c9e500f7ead96a84575dac08e198569c14d
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Wed Mar 19 19:11:59 2025 +0300
home: imp code
commit 60eff2c66369ca8705a6bb859b5a65d3e6d0df5e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 21:27:49 2025 +0300
home: imp code
commit fa9d57b2834fe3df85630d95b9eb022f1db372b1
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 21:14:56 2025 +0300
home: imp docs
commit 3f561b64750ab57ef83793522a0b313225245e1e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 20:59:59 2025 +0300
home: imp code
commit 927296c49f861d102dad8d24e8b67e6204a6c17a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 18:19:22 2025 +0300
home: imp naming
commit e35f742e42a7304993a924928b51f2452634e258
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 17:53:17 2025 +0300
home: tls manager web api
commit 85a4de7931fea68464fe36c1fb27686eb5b50066
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Tue Mar 18 15:06:34 2025 +0300
home: tls manager config
commit 515b26d6bd6d837d3db937354f74d895b5793206
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon Mar 17 22:15:25 2025 +0300
home: tls manager
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TODO(s.chzhen): Consider moving to testdata.
|
||||
var testCertChainData = []byte(`-----BEGIN CERTIFICATE-----
|
||||
MIICKzCCAZSgAwIBAgIJAMT9kPVJdM7LMA0GCSqGSIb3DQEBCwUAMC0xFDASBgNV
|
||||
BAoMC0FkR3VhcmQgTHRkMRUwEwYDVQQDDAxBZEd1YXJkIEhvbWUwHhcNMTkwMjI3
|
||||
@@ -66,7 +67,11 @@ func TestValidateCertificates(t *testing.T) {
|
||||
ctx := testutil.ContextWithTimeout(t, testTimeout)
|
||||
logger := slogutil.NewDiscardLogger()
|
||||
|
||||
m, err := newTLSManager(ctx, logger, tlsConfigSettings{}, false)
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
servePlainDNS: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("bad_certificate", func(t *testing.T) {
|
||||
@@ -112,7 +117,6 @@ func TestValidateCertificates(t *testing.T) {
|
||||
// - [homeContext.clients.storage]
|
||||
// - [homeContext.dnsServer]
|
||||
// - [homeContext.mux]
|
||||
// - [homeContext.web]
|
||||
//
|
||||
// TODO(s.chzhen): Remove this once the TLS manager no longer accesses global
|
||||
// variables. Make tests that use this helper concurrent.
|
||||
@@ -123,14 +127,12 @@ func storeGlobals(tb testing.TB) {
|
||||
storage := globalContext.clients.storage
|
||||
dnsServer := globalContext.dnsServer
|
||||
mux := globalContext.mux
|
||||
web := globalContext.web
|
||||
|
||||
tb.Cleanup(func() {
|
||||
config = prevConfig
|
||||
globalContext.clients.storage = storage
|
||||
globalContext.dnsServer = dnsServer
|
||||
globalContext.mux = mux
|
||||
globalContext.web = web
|
||||
})
|
||||
}
|
||||
|
||||
@@ -221,9 +223,6 @@ func TestTLSManager_Reload(t *testing.T) {
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
globalContext.web, err = initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
const (
|
||||
snBefore int64 = 1
|
||||
snAfter int64 = 2
|
||||
@@ -236,15 +235,25 @@ func TestTLSManager_Reload(t *testing.T) {
|
||||
certDER, key := newCertAndKey(t, snBefore)
|
||||
writeCertAndKey(t, certDER, certPath, key, keyPath)
|
||||
|
||||
m, err := newTLSManager(ctx, logger, tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificatePath: certPath,
|
||||
PrivateKeyPath: keyPath,
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
tlsSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificatePath: certPath,
|
||||
PrivateKeyPath: keyPath,
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
servePlainDNS: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
web, err := initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
m.setWebAPI(web)
|
||||
|
||||
conf := &tlsConfigSettings{}
|
||||
m.WriteDiskConfig(conf)
|
||||
assertCertSerialNumber(t, conf, snBefore)
|
||||
@@ -265,13 +274,18 @@ func TestTLSManager_HandleTLSStatus(t *testing.T) {
|
||||
err error
|
||||
)
|
||||
|
||||
m, err := newTLSManager(ctx, logger, tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificateChain: string(testCertChainData),
|
||||
PrivateKey: string(testPrivateKeyData),
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
tlsSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificateChain: string(testCertChainData),
|
||||
PrivateKey: string(testPrivateKeyData),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
servePlainDNS: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
@@ -291,26 +305,42 @@ func TestTLSManager_HandleTLSStatus(t *testing.T) {
|
||||
func TestValidateTLSSettings(t *testing.T) {
|
||||
storeGlobals(t)
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
var (
|
||||
logger = slogutil.NewDiscardLogger()
|
||||
ctx = testutil.ContextWithTimeout(t, testTimeout)
|
||||
err error
|
||||
)
|
||||
|
||||
ln, err := net.Listen("tcp", ":0")
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
servePlainDNS: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, ln.Close)
|
||||
|
||||
addr := testutil.RequireTypeAssert[*net.TCPAddr](t, ln.Addr())
|
||||
|
||||
busyPort := addr.Port
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
globalContext.web, err = initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
web, err := initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
m.setWebAPI(web)
|
||||
|
||||
tcpLn, err := net.Listen("tcp", ":0")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, tcpLn.Close)
|
||||
|
||||
tcpAddr := testutil.RequireTypeAssert[*net.TCPAddr](t, tcpLn.Addr())
|
||||
busyTCPPort := tcpAddr.Port
|
||||
|
||||
udpLn, err := net.ListenPacket("udp", ":0")
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.CleanupAndRequireSuccess(t, udpLn.Close)
|
||||
|
||||
udpAddr := testutil.RequireTypeAssert[*net.UDPAddr](t, udpLn.LocalAddr())
|
||||
busyUDPPort := udpAddr.Port
|
||||
|
||||
testCases := []struct {
|
||||
setts tlsConfigSettingsExt
|
||||
name string
|
||||
@@ -329,11 +359,29 @@ func TestValidateTLSSettings(t *testing.T) {
|
||||
setts: tlsConfigSettingsExt{
|
||||
tlsConfigSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
PortHTTPS: uint16(busyPort),
|
||||
PortHTTPS: uint16(busyTCPPort),
|
||||
},
|
||||
},
|
||||
name: "busy_port",
|
||||
wantErr: fmt.Sprintf("port %d is not available, cannot enable HTTPS on it", busyPort),
|
||||
name: "busy_https_port",
|
||||
wantErr: fmt.Sprintf("port %d for HTTPS is not available", busyTCPPort),
|
||||
}, {
|
||||
setts: tlsConfigSettingsExt{
|
||||
tlsConfigSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
PortDNSOverTLS: uint16(busyTCPPort),
|
||||
},
|
||||
},
|
||||
name: "busy_dot_port",
|
||||
wantErr: fmt.Sprintf("port %d for DNS-over-TLS is not available", busyTCPPort),
|
||||
}, {
|
||||
setts: tlsConfigSettingsExt{
|
||||
tlsConfigSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
PortDNSOverQUIC: uint16(busyUDPPort),
|
||||
},
|
||||
},
|
||||
name: "busy_doq_port",
|
||||
wantErr: fmt.Sprintf("port %d for DNS-over-QUIC is not available", busyUDPPort),
|
||||
}, {
|
||||
setts: tlsConfigSettingsExt{
|
||||
tlsConfigSettings: tlsConfigSettings{
|
||||
@@ -348,7 +396,7 @@ func TestValidateTLSSettings(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err = validateTLSSettings(tc.setts)
|
||||
err = m.validateTLSSettings(tc.setts)
|
||||
testutil.AssertErrorMsg(t, tc.wantErr, err)
|
||||
})
|
||||
}
|
||||
@@ -357,26 +405,33 @@ func TestValidateTLSSettings(t *testing.T) {
|
||||
func TestTLSManager_HandleTLSValidate(t *testing.T) {
|
||||
storeGlobals(t)
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
var (
|
||||
logger = slogutil.NewDiscardLogger()
|
||||
ctx = testutil.ContextWithTimeout(t, testTimeout)
|
||||
err error
|
||||
)
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
globalContext.web, err = initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := newTLSManager(ctx, logger, tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificateChain: string(testCertChainData),
|
||||
PrivateKey: string(testPrivateKeyData),
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
tlsSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificateChain: string(testCertChainData),
|
||||
PrivateKey: string(testPrivateKeyData),
|
||||
},
|
||||
},
|
||||
}, false)
|
||||
servePlainDNS: false,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
web, err := initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
m.setWebAPI(web)
|
||||
|
||||
setts := &tlsConfigSettingsExt{
|
||||
tlsConfigSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
@@ -438,9 +493,6 @@ func TestTLSManager_HandleTLSConfigure(t *testing.T) {
|
||||
|
||||
globalContext.mux = http.NewServeMux()
|
||||
|
||||
globalContext.web, err = initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
config.DNS.BindHosts = []netip.Addr{netip.MustParseAddr("127.0.0.1")}
|
||||
config.DNS.Port = 0
|
||||
|
||||
@@ -455,15 +507,25 @@ func TestTLSManager_HandleTLSConfigure(t *testing.T) {
|
||||
writeCertAndKey(t, certDER, certPath, key, keyPath)
|
||||
|
||||
// Initialize the TLS manager and assert its configuration.
|
||||
m, err := newTLSManager(ctx, logger, tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificatePath: certPath,
|
||||
PrivateKeyPath: keyPath,
|
||||
m, err := newTLSManager(ctx, &tlsManagerConfig{
|
||||
logger: logger,
|
||||
configModified: func() {},
|
||||
tlsSettings: tlsConfigSettings{
|
||||
Enabled: true,
|
||||
TLSConfig: dnsforward.TLSConfig{
|
||||
CertificatePath: certPath,
|
||||
PrivateKeyPath: keyPath,
|
||||
},
|
||||
},
|
||||
}, true)
|
||||
servePlainDNS: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
web, err := initWeb(ctx, options{}, nil, nil, logger, nil, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
m.setWebAPI(web)
|
||||
|
||||
conf := &tlsConfigSettings{}
|
||||
m.WriteDiskConfig(conf)
|
||||
assertCertSerialNumber(t, conf, wantSerialNumber)
|
||||
@@ -509,10 +571,10 @@ func TestTLSManager_HandleTLSConfigure(t *testing.T) {
|
||||
//
|
||||
// TODO(s.chzhen): Remove when [httpsServer.cond] is removed.
|
||||
assert.Eventually(t, func() bool {
|
||||
globalContext.web.httpsServer.condLock.Lock()
|
||||
defer globalContext.web.httpsServer.condLock.Unlock()
|
||||
web.httpsServer.condLock.Lock()
|
||||
defer web.httpsServer.condLock.Unlock()
|
||||
|
||||
cert = globalContext.web.httpsServer.cert
|
||||
cert = web.httpsServer.cert
|
||||
if cert.Leaf == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user