[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
|
||||
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):
|
||||
if operations:
|
||||
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)
|
||||
|
||||
self.check_file_not_empty(filename)
|
||||
|
||||
def modify_conf_file(self):
|
||||
authentication = self.authentication_default.copy()
|
||||
authentication.update(self.authentication)
|
||||
|
@ -42,13 +42,10 @@ class TestHostcfgdTACACS(TestCase):
|
||||
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
|
||||
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.NSS_TACPLUS_CONF_TEMPLATE = t_path + "/tacplus_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")
|
||||
|
||||
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')
|
||||
|
||||
try:
|
||||
@ -83,6 +84,17 @@ class TestHostcfgdTACACS(TestCase):
|
||||
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)
|
||||
diff_output = ""
|
||||
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")
|
||||
# test 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