Skip to content

Commit 429f968

Browse files
committed
config: add security section to schema
The following box.cfg options were described in instance_config with defaults similar to ones in box.cfg: * auth_type * auth_delay * disable_guest * password_lifetime_days * password_min_length * password_enforce_uppercase * password_enforce_lowercase * password_enforce_digits * password_enforce_specialchars * password_history_length Part of tarantool#8861 NO_DOC=tarantool/doc#3544 links the most actual schema, no need to update the issue.
1 parent 40231ce commit 429f968

File tree

5 files changed

+195
-12
lines changed

5 files changed

+195
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## feature/config
2+
3+
* All security hardening `box.cfg{}` options are now supported by
4+
config (gh-8861).

src/box/lua/config/instance_config.lua

+62
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,68 @@ return schema.new('instance_config', schema.record({
12951295
default = 16384,
12961296
})),
12971297
}),
1298+
security = schema.record({
1299+
auth_type = schema.enum({
1300+
'chap-sha1',
1301+
'pap-sha256',
1302+
}, {
1303+
box_cfg = 'auth_type',
1304+
default = 'chap-sha1',
1305+
validate = function(auth_type, w)
1306+
if auth_type ~= 'chap-sha1' and
1307+
tarantool.package ~= 'Tarantool Enterprise' then
1308+
w.error('"chap-sha1" is the only authentication method ' ..
1309+
'(auth_type) available in Tarantool Community ' ..
1310+
'Edition (%q requested)', auth_type)
1311+
end
1312+
end,
1313+
}),
1314+
auth_delay = enterprise_edition(schema.scalar({
1315+
type = 'number',
1316+
default = 0,
1317+
box_cfg = 'auth_delay',
1318+
})),
1319+
disable_guest = enterprise_edition(schema.scalar({
1320+
type = 'boolean',
1321+
default = false,
1322+
box_cfg = 'disable_guest',
1323+
})),
1324+
password_lifetime_days = enterprise_edition(schema.scalar({
1325+
type = 'integer',
1326+
default = 0,
1327+
box_cfg = 'password_lifetime_days',
1328+
})),
1329+
password_min_length = enterprise_edition(schema.scalar({
1330+
type = 'integer',
1331+
default = 0,
1332+
box_cfg = 'password_min_length',
1333+
})),
1334+
password_enforce_uppercase = enterprise_edition(schema.scalar({
1335+
type = 'boolean',
1336+
default = false,
1337+
box_cfg = 'password_enforce_uppercase',
1338+
})),
1339+
password_enforce_lowercase = enterprise_edition(schema.scalar({
1340+
type = 'boolean',
1341+
default = false,
1342+
box_cfg = 'password_enforce_lowercase',
1343+
})),
1344+
password_enforce_digits = enterprise_edition(schema.scalar({
1345+
type = 'boolean',
1346+
default = false,
1347+
box_cfg = 'password_enforce_digits',
1348+
})),
1349+
password_enforce_specialchars = enterprise_edition(schema.scalar({
1350+
type = 'boolean',
1351+
default = false,
1352+
box_cfg = 'password_enforce_specialchars',
1353+
})),
1354+
password_history_length = enterprise_edition(schema.scalar({
1355+
type = 'integer',
1356+
default = 0,
1357+
box_cfg = 'password_history_length',
1358+
})),
1359+
}),
12981360
}, {
12991361
-- This kind of validation cannot be implemented as the
13001362
-- 'validate' annotation of a particular schema node. There

test/config-luatest/cluster_config_schema_test.lua

+14
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ g.test_defaults = function()
245245
interval = 3600,
246246
metrics_limit = 1024*1024,
247247
} or nil,
248+
security = is_enterprise and {
249+
auth_delay = 0,
250+
auth_type = "chap-sha1",
251+
disable_guest = false,
252+
password_enforce_digits = false,
253+
password_enforce_lowercase = false,
254+
password_enforce_specialchars = false,
255+
password_enforce_uppercase = false,
256+
password_history_length = 0,
257+
password_lifetime_days = 0,
258+
password_min_length = 0,
259+
} or {
260+
auth_type = "chap-sha1"
261+
},
248262
}
249263
local res = cluster_config:apply_default({})
250264
t.assert_equals(res, exp)

test/config-luatest/config_test.lua

+56
Original file line numberDiff line numberDiff line change
@@ -632,3 +632,59 @@ g.test_flightrec_options = function()
632632
t.assert_equals(box.cfg.flightrec_requests_size, 2000000)
633633
end)
634634
end
635+
636+
g.test_security_options = function()
637+
t.tarantool.skip_if_not_enterprise()
638+
local dir = treegen.prepare_directory(g, {}, {})
639+
-- guest user is required for luatest.server helper to function properly,
640+
-- so it is enabled (`disable_guest: false`) unlike other options.
641+
local config = [[
642+
credentials:
643+
users:
644+
guest:
645+
roles:
646+
- super
647+
648+
iproto:
649+
listen: unix/:./{{ instance_name }}.iproto
650+
651+
security:
652+
auth_type: pap-sha256
653+
auth_delay: 5
654+
disable_guest: false
655+
password_lifetime_days: 90
656+
password_min_length: 14
657+
password_enforce_uppercase: true
658+
password_enforce_lowercase: true
659+
password_enforce_digits: true
660+
password_enforce_specialchars: true
661+
password_history_length: 3
662+
663+
groups:
664+
group-001:
665+
replicasets:
666+
replicaset-001:
667+
instances:
668+
instance-001: {}
669+
]]
670+
local config_file = treegen.write_script(dir, 'config.yaml', config)
671+
local opts = {
672+
config_file = config_file,
673+
alias = 'instance-001',
674+
chdir = dir,
675+
}
676+
g.server = server:new(opts)
677+
g.server:start()
678+
g.server:exec(function()
679+
t.assert_equals(box.cfg.auth_type, 'pap-sha256')
680+
t.assert_equals(box.cfg.auth_delay, 5)
681+
t.assert_equals(box.cfg.disable_guest, false)
682+
t.assert_equals(box.cfg.password_lifetime_days, 90)
683+
t.assert_equals(box.cfg.password_min_length, 14)
684+
t.assert_equals(box.cfg.password_enforce_uppercase, true)
685+
t.assert_equals(box.cfg.password_enforce_lowercase, true)
686+
t.assert_equals(box.cfg.password_enforce_digits, true)
687+
t.assert_equals(box.cfg.password_enforce_specialchars, true)
688+
t.assert_equals(box.cfg.password_history_length, 3)
689+
end)
690+
end

test/config-luatest/instance_config_schema_test.lua

+59-12
Original file line numberDiff line numberDiff line change
@@ -1037,18 +1037,6 @@ g.test_box_cfg_coverage = function()
10371037
audit_format = true,
10381038
audit_filter = true,
10391039

1040-
-- TODO: Will be added in the scope of gh-8861.
1041-
auth_type = true,
1042-
auth_delay = true,
1043-
disable_guest = true,
1044-
password_lifetime_days = true,
1045-
password_min_length = true,
1046-
password_enforce_uppercase = true,
1047-
password_enforce_lowercase = true,
1048-
password_enforce_digits = true,
1049-
password_enforce_specialchars = true,
1050-
password_history_length = true,
1051-
10521040
-- TODO: Will be added in the scope of gh-8861.
10531041
metrics = true,
10541042
}
@@ -1233,3 +1221,62 @@ g.test_flightrec = function()
12331221
local res = instance_config:apply_default({}).flightrec
12341222
t.assert_equals(res, exp)
12351223
end
1224+
1225+
g.test_security_enterprise = function()
1226+
t.tarantool.skip_if_not_enterprise()
1227+
1228+
local iconfig = {
1229+
security = {
1230+
auth_type = 'pap-sha256',
1231+
auth_delay = 5,
1232+
disable_guest = true,
1233+
password_lifetime_days = 90,
1234+
password_min_length = 10,
1235+
password_enforce_uppercase = true,
1236+
password_enforce_lowercase = true,
1237+
password_enforce_digits = true,
1238+
password_enforce_specialchars = true,
1239+
password_history_length = 3,
1240+
}
1241+
}
1242+
1243+
instance_config:validate(iconfig)
1244+
validate_fields(iconfig.security, instance_config.schema.fields.security)
1245+
end
1246+
1247+
g.test_security_community = function()
1248+
t.tarantool.skip_if_enterprise()
1249+
local iconfig = {
1250+
security = {
1251+
auth_type = 'pap-sha256',
1252+
}
1253+
}
1254+
1255+
local ok, err = pcall(instance_config.validate, instance_config, iconfig)
1256+
t.assert_not(ok)
1257+
local exp = '[instance_config] security.auth_type: "chap-sha1" is the ' ..
1258+
'only authentication method (auth_type) available in ' ..
1259+
'Tarantool Community Edition (\"pap-sha256\" requested)'
1260+
t.assert_equals(err, exp)
1261+
1262+
iconfig = {
1263+
security = {
1264+
auth_type = 'chap-sha1',
1265+
auth_delay = 5,
1266+
}
1267+
}
1268+
1269+
ok, err = pcall(instance_config.validate, instance_config, iconfig)
1270+
t.assert_not(ok)
1271+
exp = '[instance_config] security.auth_delay: This configuration ' ..
1272+
'parameter is available only in Tarantool Enterprise Edition'
1273+
t.assert_equals(err, exp)
1274+
1275+
iconfig = {
1276+
security = {
1277+
auth_type = 'chap-sha1',
1278+
}
1279+
}
1280+
1281+
instance_config:validate(iconfig)
1282+
end

0 commit comments

Comments
 (0)