[202205] Check config file not empty after modify it in hostcfgd. (#14115)
What I did Check /etc/pam.d/sshd integrity after modify it in hostcfgd. Why I did it Found some incident that /etc/pam.d/sshd become empty file during OR upgrade. How I verified it Pass all UT. Add new UT to cover new code.
This commit is contained in:
parent
1ccad8f0b3
commit
b715894dc8
@ -780,11 +780,28 @@ class AaaCfg(object):
|
|||||||
interface_ip = ipv4_addr
|
interface_ip = ipv4_addr
|
||||||
return interface_ip
|
return interface_ip
|
||||||
|
|
||||||
|
|
||||||
|
def check_file_not_empty(self, filename):
|
||||||
|
exists = os.path.exists(filename)
|
||||||
|
if not exists:
|
||||||
|
syslog.syslog(syslog.LOG_ERR, "file size check failed: {} is missing".format(filename))
|
||||||
|
return
|
||||||
|
|
||||||
|
size = os.path.getsize(filename)
|
||||||
|
if size == 0:
|
||||||
|
syslog.syslog(syslog.LOG_ERR, "file size check failed: {} is empty, file corrupted".format(filename))
|
||||||
|
return
|
||||||
|
|
||||||
|
syslog.syslog(syslog.LOG_INFO, "file size check pass: {} size is ({}) bytes".format(filename, size))
|
||||||
|
|
||||||
|
|
||||||
def modify_single_file(self, filename, operations=None):
|
def modify_single_file(self, filename, operations=None):
|
||||||
if operations:
|
if operations:
|
||||||
cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}".format(' -e '.join(operations), filename)
|
cmd = "sed -e {0} {1} > {1}.new; mv -f {1} {1}.old; mv -f {1}.new {1}".format(' -e '.join(operations), filename)
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
|
self.check_file_not_empty(filename)
|
||||||
|
|
||||||
def modify_conf_file(self):
|
def modify_conf_file(self):
|
||||||
authentication = self.authentication_default.copy()
|
authentication = self.authentication_default.copy()
|
||||||
authentication.update(self.authentication)
|
authentication.update(self.authentication)
|
||||||
|
@ -42,13 +42,10 @@ class TestHostcfgdTACACS(TestCase):
|
|||||||
return subprocess.check_output('diff -uR {} {} || true'.format(file1, file2), shell=True)
|
return subprocess.check_output('diff -uR {} {} || true'.format(file1, file2), shell=True)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Check different config
|
Mock hostcfgd
|
||||||
"""
|
"""
|
||||||
def check_config(self, test_name, test_data, config_name):
|
def mock_hostcfgd(self, test_data, config_name, op_path, sop_path):
|
||||||
t_path = templates_path
|
t_path = templates_path
|
||||||
op_path = output_path + "/" + test_name + "_" + config_name
|
|
||||||
sop_path = sample_output_path + "/" + test_name + "_" + config_name
|
|
||||||
|
|
||||||
hostcfgd.PAM_AUTH_CONF_TEMPLATE = t_path + "/common-auth-sonic.j2"
|
hostcfgd.PAM_AUTH_CONF_TEMPLATE = t_path + "/common-auth-sonic.j2"
|
||||||
hostcfgd.NSS_TACPLUS_CONF_TEMPLATE = t_path + "/tacplus_nss.conf.j2"
|
hostcfgd.NSS_TACPLUS_CONF_TEMPLATE = t_path + "/tacplus_nss.conf.j2"
|
||||||
hostcfgd.NSS_RADIUS_CONF_TEMPLATE = t_path + "/radius_nss.conf.j2"
|
hostcfgd.NSS_RADIUS_CONF_TEMPLATE = t_path + "/radius_nss.conf.j2"
|
||||||
@ -68,8 +65,12 @@ class TestHostcfgdTACACS(TestCase):
|
|||||||
shutil.copyfile( sop_path + "/login.old", op_path + "/login")
|
shutil.copyfile( sop_path + "/login.old", op_path + "/login")
|
||||||
|
|
||||||
MockConfigDb.set_config_db(test_data[config_name])
|
MockConfigDb.set_config_db(test_data[config_name])
|
||||||
host_config_daemon = hostcfgd.HostConfigDaemon()
|
return hostcfgd.HostConfigDaemon()
|
||||||
|
|
||||||
|
"""
|
||||||
|
Render different config
|
||||||
|
"""
|
||||||
|
def render_config_file(self, host_config_daemon):
|
||||||
aaa = host_config_daemon.config_db.get_table('AAA')
|
aaa = host_config_daemon.config_db.get_table('AAA')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -83,6 +84,17 @@ class TestHostcfgdTACACS(TestCase):
|
|||||||
tacacs_server = []
|
tacacs_server = []
|
||||||
|
|
||||||
host_config_daemon.aaacfg.load(aaa,tacacs_global,tacacs_server,[],[])
|
host_config_daemon.aaacfg.load(aaa,tacacs_global,tacacs_server,[],[])
|
||||||
|
|
||||||
|
"""
|
||||||
|
Check different config
|
||||||
|
"""
|
||||||
|
def check_config(self, test_name, test_data, config_name):
|
||||||
|
op_path = output_path + "/" + test_name + "_" + config_name
|
||||||
|
sop_path = sample_output_path + "/" + test_name + "_" + config_name
|
||||||
|
host_config_daemon = self.mock_hostcfgd(test_data, config_name, op_path, sop_path)
|
||||||
|
|
||||||
|
self.render_config_file(host_config_daemon)
|
||||||
|
|
||||||
dcmp = filecmp.dircmp(sop_path, op_path)
|
dcmp = filecmp.dircmp(sop_path, op_path)
|
||||||
diff_output = ""
|
diff_output = ""
|
||||||
for name in dcmp.diff_files:
|
for name in dcmp.diff_files:
|
||||||
@ -114,3 +126,68 @@ class TestHostcfgdTACACS(TestCase):
|
|||||||
self.check_config(test_name, test_data, "config_db_local_and_tacacs")
|
self.check_config(test_name, test_data, "config_db_local_and_tacacs")
|
||||||
# test disable accounting
|
# test disable accounting
|
||||||
self.check_config(test_name, test_data, "config_db_disable_accounting")
|
self.check_config(test_name, test_data, "config_db_disable_accounting")
|
||||||
|
|
||||||
|
@parameterized.expand(HOSTCFGD_TEST_TACACS_VECTOR)
|
||||||
|
def test_hostcfgd_sshd_not_empty(self, test_name, test_data):
|
||||||
|
"""
|
||||||
|
Test hostcfd sshd config file not empty check
|
||||||
|
|
||||||
|
Args:
|
||||||
|
test_name(str): test name
|
||||||
|
test_data(dict): test data which contains initial Config Db tables, and expected results
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
config_name = "config_db_local"
|
||||||
|
op_path = output_path + "/" + test_name + "_" + config_name
|
||||||
|
sop_path = sample_output_path + "/" + test_name + "_" + config_name
|
||||||
|
host_config_daemon = self.mock_hostcfgd(test_data, config_name, op_path, sop_path)
|
||||||
|
|
||||||
|
# test sshd empty case
|
||||||
|
hostcfgd.ETC_PAMD_SSHD = op_path + "/sshd_empty"
|
||||||
|
shutil.copyfile( sop_path + "/sshd_empty.old", op_path + "/sshd_empty")
|
||||||
|
|
||||||
|
# render with empty sshd config file and check error log
|
||||||
|
original_syslog = hostcfgd.syslog
|
||||||
|
with mock.patch('hostcfgd.syslog.syslog') as mocked_syslog:
|
||||||
|
mocked_syslog.LOG_ERR = original_syslog.LOG_ERR
|
||||||
|
self.render_config_file(host_config_daemon)
|
||||||
|
|
||||||
|
# check sys log
|
||||||
|
expected = [
|
||||||
|
mock.call(mocked_syslog.LOG_ERR, "file size check failed: {} is empty, file corrupted".format(hostcfgd.ETC_PAMD_SSHD))
|
||||||
|
]
|
||||||
|
mocked_syslog.assert_has_calls(expected)
|
||||||
|
|
||||||
|
# test sshd missing case
|
||||||
|
hostcfgd.ETC_PAMD_SSHD = op_path + "/sshd_missing"
|
||||||
|
|
||||||
|
with mock.patch('hostcfgd.syslog.syslog') as mocked_syslog:
|
||||||
|
mocked_syslog.LOG_ERR = original_syslog.LOG_ERR
|
||||||
|
|
||||||
|
# missing file can't test by render config file,
|
||||||
|
# because missing file case difficult to reproduce: code always generate a empty file.
|
||||||
|
host_config_daemon.aaacfg.check_file_not_empty(hostcfgd.ETC_PAMD_SSHD)
|
||||||
|
|
||||||
|
# check sys log
|
||||||
|
expected = [
|
||||||
|
mock.call(mocked_syslog.LOG_ERR, "file size check failed: {} is missing".format(hostcfgd.ETC_PAMD_SSHD))
|
||||||
|
]
|
||||||
|
mocked_syslog.assert_has_calls(expected)
|
||||||
|
|
||||||
|
# test sshd exist and not empty case
|
||||||
|
hostcfgd.ETC_PAMD_SSHD = op_path + "/sshd_not_empty"
|
||||||
|
shutil.copyfile( sop_path + "/sshd_not_empty.old", op_path + "/sshd_not_empty")
|
||||||
|
|
||||||
|
# render with empty sshd config file and check error log
|
||||||
|
original_syslog = hostcfgd.syslog
|
||||||
|
with mock.patch('hostcfgd.syslog.syslog') as mocked_syslog:
|
||||||
|
mocked_syslog.LOG_INFO = original_syslog.LOG_INFO
|
||||||
|
self.render_config_file(host_config_daemon)
|
||||||
|
|
||||||
|
# check sys log
|
||||||
|
expected = [
|
||||||
|
mock.call(mocked_syslog.LOG_INFO, "file size check pass: {} size is ({}) bytes".format(hostcfgd.ETC_PAMD_SSHD, 21))
|
||||||
|
]
|
||||||
|
mocked_syslog.assert_has_calls(expected)
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
#SSHD NOT EMPTY TEST
|
Reference in New Issue
Block a user