Skip to content

Commit

Permalink
Check config file not empty after modify it in hostcfgd. (#36)
Browse files Browse the repository at this point in the history
**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.

**Details if related**
  • Loading branch information
liuh-80 authored and StormLiangMS committed Apr 20, 2023
1 parent ee2a565 commit 63fed10
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 6 deletions.
17 changes: 17 additions & 0 deletions scripts/hostcfgd
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,21 @@ 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:
e_list = ['-e'] * len(operations)
Expand All @@ -801,6 +816,8 @@ class AaaCfg(object):
subprocess.call(["mv", '-f', filename, filename+'.old'])
subprocess.call(['mv', '-f', filename+'.new', filename])

self.check_file_not_empty(filename)

def modify_conf_file(self):
authentication = self.authentication_default.copy()
authentication.update(self.authentication)
Expand Down
90 changes: 84 additions & 6 deletions tests/hostcfgd/hostcfgd_tacacs_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,10 @@ def run_diff(self, file1, file2):
return output

"""
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"
Expand All @@ -69,8 +66,12 @@ def check_config(self, test_name, test_data, config_name):
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:
Expand All @@ -84,6 +85,17 @@ def check_config(self, test_name, test_data, config_name):
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:
Expand Down Expand Up @@ -115,3 +127,69 @@ def test_hostcfgd_tacacs(self, test_name, test_data):
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)

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#SSHD NOT EMPTY TEST

0 comments on commit 63fed10

Please sign in to comment.