|
| 1 | +import logging |
| 2 | +import os |
| 3 | +import difflib |
| 4 | +from tests.common.helpers.assertions import pytest_assert |
| 5 | + |
| 6 | +CURR_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 7 | + |
| 8 | +# Sample/Expected files |
| 9 | +PAM_PASSWORD_CONF_DEFAULT_EXPECTED = CURR_DIR + '/sample/passw_hardening_default/common-password' |
| 10 | +PAM_PASSWORD_CONF_EXPECTED = CURR_DIR + '/sample/passw_hardening_enable/common-password' |
| 11 | +PAM_PASSWORD_CONF_HISTORY_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_history/common-password' |
| 12 | +PAM_PASSWORD_CONF_REJECT_USER_PASSW_MATCH_EXPECTED = CURR_DIR + '/sample/passw_hardening_reject_user_passw_match/common-password' |
| 13 | +PAM_PASSWORD_CONF_DIGITS_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_digits/common-password' |
| 14 | +PAM_PASSWORD_CONF_LOWER_LETTER_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_lower_letter/common-password' |
| 15 | +PAM_PASSWORD_CONF_UPPER_LETTER_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_upper_letter/common-password' |
| 16 | +PAM_PASSWORD_CONF_SPECIAL_LETTER_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_special_letter/common-password' |
| 17 | +PAM_PASSWORD_CONF_LEN_MIN_ONLY_EXPECTED = CURR_DIR + '/sample/passw_hardening_min_len/common-password' |
| 18 | +PAM_PASSWORD_CONF_OUTPUT = CURR_DIR + '/output/login.def' |
| 19 | +PAM_PASSWORD_CONF = "/etc/pam.d/common-password" |
| 20 | + |
| 21 | +# users |
| 22 | +USERNAME_STRONG = 'user_strong_test' |
| 23 | +USERNAME_SIMPLE_0 = 'user_simple_0_test' |
| 24 | +USERNAME_SIMPLE_1 = 'user_simple_1_test' |
| 25 | +USERNAME_ONE_POLICY = 'user_one_policy_test' |
| 26 | +USERNAME_AGE = 'user_test' |
| 27 | +USERNAME_HISTORY = 'user_history_test' |
| 28 | +USERNAME_LEN_MIN = 'user_test' |
| 29 | + |
| 30 | + |
| 31 | +class PasswHardening: |
| 32 | + def __init__(self, state='disabled', expiration='100', expiration_warning='15', history='12', |
| 33 | + len_min='8', reject_user_passw_match='true', lower_class='true', |
| 34 | + upper_class='true', digit_class='true', special_class='true'): |
| 35 | + self.policies = { |
| 36 | + "state": state, |
| 37 | + "expiration": expiration, |
| 38 | + "expiration-warning": expiration_warning, |
| 39 | + "history-cnt": history, |
| 40 | + "len-min": len_min, |
| 41 | + "reject-user-passw-match": reject_user_passw_match, |
| 42 | + "lower-class": lower_class, |
| 43 | + "upper-class": upper_class, |
| 44 | + "digits-class": digit_class, |
| 45 | + "special-class": special_class |
| 46 | + } |
| 47 | + |
| 48 | + |
| 49 | +def config_user(duthost, username, mode='add'): |
| 50 | + """ Function add or rm users using useradd/userdel tool. """ |
| 51 | + |
| 52 | + username = username.strip() |
| 53 | + command = "user{} {}".format(mode, username) |
| 54 | + user_cmd = duthost.shell(command, module_ignore_errors=True) |
| 55 | + return user_cmd |
| 56 | + |
| 57 | + |
| 58 | +def configure_passw_policies(duthost, passw_hardening_ob): |
| 59 | + for key, value in passw_hardening_ob.policies.items(): |
| 60 | + logging.debug("configuration to be set: key={}, value={}".format(key, value)) |
| 61 | + # cmd_config = 'sudo config passw-hardening policies ' + key + ' ' + value |
| 62 | + |
| 63 | + cmd_config = 'sudo config passw-hardening policies {} {}'.format(key, value) |
| 64 | + |
| 65 | + duthost.command(cmd_config) |
| 66 | + return True |
| 67 | + |
| 68 | + |
| 69 | +def compare_passw_policies_in_linux(duthost, pam_file_expected=PAM_PASSWORD_CONF_EXPECTED): |
| 70 | + """Compare DUT common-password with the expected one.""" |
| 71 | + |
| 72 | + command_password_stdout = '' |
| 73 | + read_command_password = 'cat {}'.format(PAM_PASSWORD_CONF) |
| 74 | + |
| 75 | + logging.debug('DUT command = {}'.format(read_command_password)) |
| 76 | + read_command_password_cmd = duthost.command(read_command_password) |
| 77 | + command_password_stdout = read_command_password_cmd["stdout_lines"] |
| 78 | + command_password_stdout = [line.encode('utf-8') for line in command_password_stdout] |
| 79 | + |
| 80 | + common_password_expected = [] |
| 81 | + with open(pam_file_expected, 'r') as expected_common_password_file: |
| 82 | + for line in expected_common_password_file: |
| 83 | + line = line.strip() |
| 84 | + line = line.strip('\n') |
| 85 | + line = line.strip('\t') |
| 86 | + common_password_expected.append(line) |
| 87 | + |
| 88 | + common_password_diff = [li for li in difflib.ndiff(command_password_stdout, common_password_expected) if |
| 89 | + li[0] != ' '] |
| 90 | + pytest_assert(len(common_password_diff) == 0, common_password_diff) |
| 91 | + |
| 92 | + |
| 93 | +def config_and_review_policies(duthost, passw_hardening_ob, pam_file_expected): |
| 94 | + """ |
| 95 | + 1. Config passw hardening policies |
| 96 | + 2. Show passw hardening policies |
| 97 | + 3. Compare passw hardening polices from show cli to the expected (configured) |
| 98 | + 4. Verify polices in PAM files was set according the configured |
| 99 | + """ |
| 100 | + FIRST_LINE = 0 |
| 101 | + configure_passw_policies(duthost, passw_hardening_ob) |
| 102 | + |
| 103 | + curr_show_policies = duthost.show_and_parse('show passw-hardening policies')[FIRST_LINE] |
| 104 | + exp_show_policies = dict((k.replace('-', ' '), v) for k, v in passw_hardening_ob.policies.items()) |
| 105 | + |
| 106 | + # ~~ test passw policies in show CLI ~~ |
| 107 | + cli_passw_policies_cmp = cmp(exp_show_policies, curr_show_policies) |
| 108 | + pytest_assert(cli_passw_policies_cmp == 0, "Fail: exp_show_policies='{}',not equal to curr_show_policies='{}'" |
| 109 | + .format(exp_show_policies, curr_show_policies)) |
| 110 | + |
| 111 | + # ~~ test passw policies in PAM files ~~ |
| 112 | + compare_passw_policies_in_linux(duthost, pam_file_expected) |
0 commit comments