Skip to content

Commit f6149a6

Browse files
committed
ssl: check no sensitive ssl data in logs
The `safe_uri` function is used in vshard to get a purged uri. Before tarantool/tarantool#11810 patch sensitive ssl data may leaked into logs as `uri.format` function didn't handle ssl params of uri. Since ssl related problems occurred in large numbers of tarantool verions, we decided not to backport it. Vshard will work safely with ssl only on 3.5 or above versions. This patch add some tests which check that sensitive ssl data doesn't leak into logs of vshard storage and router. Also we move all ssl related testcases into the `router_2_2_ssl_test`. NO_DOC=bugfix Closes #593
1 parent 0fdccab commit f6149a6

File tree

2 files changed

+151
-55
lines changed

2 files changed

+151
-55
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
local t = require('luatest')
2+
local vtest = require('test.luatest_helpers.vtest')
3+
local vutil = require('vshard.util')
4+
local fio = require('fio')
5+
6+
local g = t.group('router_ssl')
7+
local cfg_template = {
8+
sharding = {
9+
{
10+
replicas = {
11+
replica_1_a = {
12+
master = true,
13+
},
14+
replica_1_b = {},
15+
},
16+
},
17+
{
18+
replicas = {
19+
replica_2_a = {
20+
master = true,
21+
},
22+
replica_2_b = {},
23+
},
24+
},
25+
},
26+
bucket_count = 100,
27+
}
28+
local global_cfg = vtest.config_new(cfg_template)
29+
30+
g.before_all(function()
31+
t.run_only_if(vutil.feature.ssl)
32+
vtest.cluster_new(g, global_cfg)
33+
vtest.cluster_bootstrap(g, global_cfg)
34+
vtest.cluster_rebalancer_disable(g)
35+
36+
local new_cfg_template = table.deepcopy(cfg_template)
37+
new_cfg_template.sharding[1].is_ssl = true
38+
local new_global_cfg = vtest.config_new(new_cfg_template)
39+
40+
g.router = vtest.router_new(g, 'router', new_global_cfg)
41+
vtest.cluster_cfg(g, new_global_cfg)
42+
vtest.router_cfg(g.router, new_global_cfg)
43+
44+
local cert_dir = fio.pathjoin(fio.cwd(), './test/certs')
45+
g.sensitive_ssl_data = {
46+
ssl_cert_file = fio.pathjoin(cert_dir, 'server.crt'),
47+
ssl_key_file = fio.pathjoin(cert_dir, 'server.key'),
48+
ssl_ca_file = fio.pathjoin(cert_dir, 'ca.crt'),
49+
ssl_password = 'P4ssw0rd',
50+
ssl_password_file = 'PATH_TO_PASSWORD_FILE',
51+
ssl_ciphers = {'TLS_AES_256_GCM_SHA384', 'TLS_RSA_POLY1305_SHA256'}
52+
}
53+
vtest.cluster_wait_fullsync(g)
54+
end)
55+
56+
g.after_all(function()
57+
g.cluster:drop()
58+
end)
59+
60+
local function callrw_get_uuid(bid, timeout)
61+
timeout = timeout ~= nil and timeout or iwait_timeout
62+
return ivshard.router.callrw(bid, 'get_uuid', {}, {timeout = timeout})
63+
end
64+
65+
local function assert_no_sensitive_data_in_server_logs(server, sensitive_data)
66+
assert(type(sensitive_data) == 'table')
67+
for sensitive_key, sensitive_value in pairs(sensitive_data) do
68+
t.assert_not(server:grep_log(sensitive_key))
69+
if type(sensitive_value) == 'table' then
70+
for _, sub_value in pairs(sensitive_value) do
71+
t.assert_not(server:grep_log(sub_value))
72+
end
73+
else
74+
t.assert_not(server:grep_log(sensitive_value))
75+
end
76+
end
77+
end
78+
79+
g.test_no_ssl_sensitive_data_in_storage_logs = function(g)
80+
assert_no_sensitive_data_in_server_logs(g.replica_1_a,
81+
g.sensitive_ssl_data)
82+
end
83+
84+
g.test_no_ssl_sensitive_data_in_router_logs = function(g)
85+
local replica_1_a_uri = g.router:exec(function(replicaset_id, master_uuid)
86+
local replicasets = ivshard.router.internal.static_router.replicasets
87+
local replica_1_a = replicasets[replicaset_id].replicas[master_uuid]
88+
return replica_1_a:safe_uri()
89+
end, {g.replica_1_a:replicaset_uuid(), g.replica_1_a:instance_uuid()})
90+
91+
t.assert_not(string.match(replica_1_a_uri, 'password'))
92+
for sensitive_key, _ in pairs(g.sensitive_ssl_data) do
93+
t.assert_not(string.match(replica_1_a_uri, sensitive_key))
94+
end
95+
assert_no_sensitive_data_in_server_logs(g.router, g.sensitive_ssl_data)
96+
end
97+
98+
g.test_ssl = function(g)
99+
t.run_only_if(vutil.feature.ssl)
100+
101+
-- So as not to assume where buckets are located, find first bucket of the
102+
-- first replicaset.
103+
local bid1 = vtest.storage_first_bucket(g.replica_1_a)
104+
local bid2 = vtest.storage_first_bucket(g.replica_2_a)
105+
106+
-- Enable SSL everywhere.
107+
local new_cfg_template = table.deepcopy(cfg_template)
108+
local sharding_templ = new_cfg_template.sharding
109+
local rs_1_templ = sharding_templ[1]
110+
local rs_2_templ = sharding_templ[2]
111+
rs_1_templ.is_ssl = true
112+
rs_2_templ.is_ssl = true
113+
114+
local new_global_cfg = vtest.config_new(new_cfg_template)
115+
vtest.cluster_cfg(g, new_global_cfg)
116+
vtest.router_cfg(g.router, new_global_cfg)
117+
118+
local rep_1_a_uuid = g.replica_1_a:instance_uuid()
119+
local res, err = g.router:exec(callrw_get_uuid, {bid1})
120+
t.assert_equals(err, nil)
121+
t.assert_equals(res, rep_1_a_uuid, 'went to 1_a')
122+
123+
local rep_2_a_uuid = g.replica_2_a:instance_uuid()
124+
res, err = g.router:exec(callrw_get_uuid, {bid2})
125+
t.assert_equals(err, nil)
126+
t.assert_equals(res, rep_2_a_uuid, 'went to 2_a')
127+
128+
-- Ensure that non-encrypted connection won't work.
129+
rs_2_templ.is_ssl = nil
130+
new_global_cfg = vtest.config_new(new_cfg_template)
131+
vtest.router_cfg(g.router, new_global_cfg)
132+
133+
res, err = g.router:exec(callrw_get_uuid, {bid2, 0.01})
134+
t.assert_equals(res, nil, 'rw failed on non-encrypted connection')
135+
t.assert_covers(err, {code = box.error.NO_CONNECTION}, 'got error')
136+
137+
-- Works again when the replicaset also disables SSL.
138+
vtest.cluster_cfg(g, new_global_cfg)
139+
140+
-- Force a reconnect right now instead of waiting until it happens
141+
-- automatically.
142+
vtest.router_disconnect(g.router)
143+
res, err = g.router:exec(callrw_get_uuid, {bid2})
144+
t.assert_equals(err, nil, 'no error')
145+
t.assert_equals(res, rep_2_a_uuid, 'went to 2_a')
146+
147+
-- Restore everything back.
148+
vtest.cluster_cfg(g, global_cfg)
149+
vtest.router_cfg(g.router, global_cfg)
150+
vtest.cluster_wait_fullsync(g)
151+
end

test/router-luatest/router_2_2_test.lua

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -334,61 +334,6 @@ g.test_multilisten = function(g)
334334
vtest.router_cfg(g.router, global_cfg)
335335
end
336336

337-
g.test_ssl = function(g)
338-
t.run_only_if(vutil.feature.ssl)
339-
340-
-- So as not to assume where buckets are located, find first bucket of the
341-
-- first replicaset.
342-
local bid1 = vtest.storage_first_bucket(g.replica_1_a)
343-
local bid2 = vtest.storage_first_bucket(g.replica_2_a)
344-
345-
-- Enable SSL everywhere.
346-
local new_cfg_template = table.deepcopy(cfg_template)
347-
local sharding_templ = new_cfg_template.sharding
348-
local rs_1_templ = sharding_templ[1]
349-
local rs_2_templ = sharding_templ[2]
350-
rs_1_templ.is_ssl = true
351-
rs_2_templ.is_ssl = true
352-
353-
local new_global_cfg = vtest.config_new(new_cfg_template)
354-
vtest.cluster_cfg(g, new_global_cfg)
355-
vtest.router_cfg(g.router, new_global_cfg)
356-
357-
local rep_1_a_uuid = g.replica_1_a:instance_uuid()
358-
local res, err = g.router:exec(callrw_get_uuid, {bid1})
359-
t.assert_equals(err, nil)
360-
t.assert_equals(res, rep_1_a_uuid, 'went to 1_a')
361-
362-
local rep_2_a_uuid = g.replica_2_a:instance_uuid()
363-
res, err = g.router:exec(callrw_get_uuid, {bid2})
364-
t.assert_equals(err, nil)
365-
t.assert_equals(res, rep_2_a_uuid, 'went to 2_a')
366-
367-
-- Ensure that non-encrypted connection won't work.
368-
rs_2_templ.is_ssl = nil
369-
new_global_cfg = vtest.config_new(new_cfg_template)
370-
vtest.router_cfg(g.router, new_global_cfg)
371-
372-
res, err = g.router:exec(callrw_get_uuid, {bid2, 0.01})
373-
t.assert_equals(res, nil, 'rw failed on non-encrypted connection')
374-
t.assert_covers(err, {code = box.error.NO_CONNECTION}, 'got error')
375-
376-
-- Works again when the replicaset also disables SSL.
377-
vtest.cluster_cfg(g, new_global_cfg)
378-
379-
-- Force a reconnect right now instead of waiting until it happens
380-
-- automatically.
381-
vtest.router_disconnect(g.router)
382-
res, err = g.router:exec(callrw_get_uuid, {bid2})
383-
t.assert_equals(err, nil, 'no error')
384-
t.assert_equals(res, rep_2_a_uuid, 'went to 2_a')
385-
386-
-- Restore everything back.
387-
vtest.cluster_cfg(g, global_cfg)
388-
vtest.router_cfg(g.router, global_cfg)
389-
vtest.cluster_wait_fullsync(g)
390-
end
391-
392337
g.test_enable_disable = function(g)
393338
--
394339
-- gh-291: router enable/disable

0 commit comments

Comments
 (0)