-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ldap: Add LDAP unittests in hostcfgd
- Loading branch information
1 parent
c897c79
commit f1843e2
Showing
13 changed files
with
801 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import importlib.machinery | ||
import importlib.util | ||
import filecmp | ||
import shutil | ||
import os | ||
import sys | ||
from swsscommon import swsscommon | ||
|
||
from parameterized import parameterized | ||
from unittest import TestCase, mock | ||
from tests.hostcfgd.test_ldap_vectors import HOSTCFGD_TEST_LDAP_VECTOR | ||
from tests.common.mock_configdb import MockConfigDb, MockDBConnector | ||
from sonic_py_common.general import getstatusoutput_noshell | ||
|
||
|
||
test_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | ||
modules_path = os.path.dirname(test_path) | ||
scripts_path = os.path.join(modules_path, "scripts") | ||
src_path = os.path.dirname(modules_path) | ||
templates_path = os.path.join(src_path, "sonic-host-services-data/templates") | ||
output_path = os.path.join(test_path, "hostcfgd/output") | ||
sample_output_path = os.path.join(test_path, "hostcfgd/sample_output") | ||
sys.path.insert(0, modules_path) | ||
|
||
# Load the file under test | ||
hostcfgd_path = os.path.join(scripts_path, 'hostcfgd') | ||
loader = importlib.machinery.SourceFileLoader('hostcfgd', hostcfgd_path) | ||
spec = importlib.util.spec_from_loader(loader.name, loader) | ||
hostcfgd = importlib.util.module_from_spec(spec) | ||
loader.exec_module(hostcfgd) | ||
sys.modules['hostcfgd'] = hostcfgd | ||
|
||
# Mock swsscommon classes | ||
hostcfgd.ConfigDBConnector = MockConfigDb | ||
hostcfgd.DBConnector = MockDBConnector | ||
hostcfgd.Table = mock.Mock() | ||
|
||
class TestHostcfgdLDAP(TestCase): | ||
""" | ||
Test hostcfd daemon - LDAP | ||
""" | ||
def run_diff(self, file1, file2): | ||
_, output = getstatusoutput_noshell(['diff', '-uR', file1, file2]) | ||
return output | ||
|
||
|
||
@parameterized.expand(HOSTCFGD_TEST_LDAP_VECTOR) | ||
def test_hostcfgd_ldap(self, test_name, test_data): | ||
""" | ||
Test LDAP hostcfd daemon initialization | ||
Args: | ||
test_name(str): test name | ||
test_data(dict): test data which contains initial Config Db tables, and expected results | ||
Returns: | ||
None | ||
""" | ||
|
||
t_path = templates_path | ||
op_path = output_path + "/" + test_name | ||
sop_path = sample_output_path + "/" + test_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" | ||
hostcfgd.PAM_RADIUS_AUTH_CONF_TEMPLATE = t_path + "/pam_radius_auth.conf.j2" | ||
hostcfgd.PAM_AUTH_CONF = op_path + "/common-auth-sonic" | ||
hostcfgd.NSS_TACPLUS_CONF = op_path + "/tacplus_nss.conf" | ||
hostcfgd.NSS_RADIUS_CONF = op_path + "/radius_nss.conf" | ||
hostcfgd.NSS_CONF = op_path + "/nsswitch.conf" | ||
hostcfgd.NSLCD_CONF = op_path + "/nslcd.conf" | ||
hostcfgd.NSLCD_CONF_TEMPLATE = t_path + "/nslcd.conf.j2" | ||
hostcfgd.ETC_PAMD_SSHD = op_path + "/sshd" | ||
hostcfgd.ETC_PAMD_LOGIN = op_path + "/login" | ||
hostcfgd.RADIUS_PAM_AUTH_CONF_DIR = op_path + "/" | ||
|
||
shutil.rmtree( op_path, ignore_errors=True) | ||
os.mkdir( op_path) | ||
|
||
shutil.copyfile( sop_path + "/sshd.old", op_path + "/sshd") | ||
shutil.copyfile( sop_path + "/login.old", op_path + "/login") | ||
|
||
MockConfigDb.set_config_db(test_data["config_db"]) | ||
host_config_daemon = hostcfgd.HostConfigDaemon() | ||
|
||
aaa = host_config_daemon.config_db.get_table('AAA') | ||
|
||
try: | ||
ldap_global = host_config_daemon.config_db.get_table('LDAP') | ||
except: | ||
ldap_global = [] | ||
try: | ||
ldap_server = \ | ||
host_config_daemon.config_db.get_table('LDAP_SERVER') | ||
except: | ||
ldap_server = [] | ||
|
||
host_config_daemon.aaacfg.load(aaa,[],[],[] ,[] , ldap_global, ldap_server) | ||
|
||
diff_output = "" | ||
files_to_compare = ['common-auth-sonic', 'nslcd.conf'] | ||
|
||
# check output files exists | ||
for name in files_to_compare: | ||
if not os.path.isfile(sop_path + "/" + name): | ||
raise ValueError('filename: %s not exit' % (sop_path + "/" + name)) | ||
if not os.path.isfile(op_path + "/" + name): | ||
raise ValueError('filename: %s not exit' % (op_path + "/" + name)) | ||
|
||
# deep comparison | ||
match, mismatch, errors = filecmp.cmpfiles(sop_path, op_path, files_to_compare, shallow=False) | ||
|
||
if not match: | ||
for name in files_to_compare: | ||
diff_output += self.run_diff( sop_path + "/" + name,\ | ||
op_path + "/" + name).decode('utf-8') | ||
|
||
self.assertTrue(len(diff_output) == 0, diff_output) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#THIS IS AN AUTO-GENERATED FILE | ||
# | ||
# /etc/pam.d/common-auth- authentication settings common to all services | ||
# This file is included from other service-specific PAM config files, | ||
# and should contain a list of the authentication modules that define | ||
# the central authentication scheme for use on the system | ||
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the | ||
# traditional Unix authentication mechanisms. | ||
# | ||
# here are the per-package modules (the "Primary" block) | ||
|
||
auth [success=2 default=ignore] pam_ldap.so minimum_uid=1000 try_first_pass | ||
auth [success=1 default=ignore] pam_unix.so nullok try_first_pass | ||
# | ||
# here's the fallback if no module succeeds | ||
auth requisite pam_deny.so | ||
# prime the stack with a positive return value if there isn't one already; | ||
# this avoids us returning an error just because nothing sets a success code | ||
# since the modules above will each just jump around | ||
auth required pam_permit.so | ||
# and here are more per-package modules (the "Additional" block) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
uri ldap://10.10.10.2/ | ||
uri ldap://10.10.10.1/ | ||
|
||
|
||
base ou=users,dc=example,dc=com | ||
|
||
ldap_version 3 | ||
|
||
binddn | ||
|
||
bindpw pass | ||
|
||
port 389 | ||
|
||
scope sub | ||
|
||
timelimit 3 | ||
|
||
bind_timelimit 5 | ||
|
||
pam_check_host_attr no |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# | ||
# The PAM configuration file for the Shadow `login' service | ||
# | ||
|
||
# Enforce a minimal delay in case of failure (in microseconds). | ||
# (Replaces the `FAIL_DELAY' setting from login.defs) | ||
# Note that other modules may require another minimal delay. (for example, | ||
# to disable any delay, you should add the nodelay option to pam_unix) | ||
auth optional pam_faildelay.so delay=3000000 | ||
|
||
# Outputs an issue file prior to each login prompt (Replaces the | ||
# ISSUE_FILE option from login.defs). Uncomment for use | ||
# auth required pam_issue.so issue=/etc/issue | ||
|
||
# Disallows root logins except on tty's listed in /etc/securetty | ||
# (Replaces the `CONSOLE' setting from login.defs) | ||
# | ||
# With the default control of this module: | ||
# [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] | ||
# root will not be prompted for a password on insecure lines. | ||
# if an invalid username is entered, a password is prompted (but login | ||
# will eventually be rejected) | ||
# | ||
# You can change it to a "requisite" module if you think root may mis-type | ||
# her login and should not be prompted for a password in that case. But | ||
# this will leave the system as vulnerable to user enumeration attacks. | ||
# | ||
# You can change it to a "required" module if you think it permits to | ||
# guess valid user names of your system (invalid user names are considered | ||
# as possibly being root on insecure lines), but root passwords may be | ||
# communicated over insecure lines. | ||
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so | ||
|
||
# Disallows other than root logins when /etc/nologin exists | ||
# (Replaces the `NOLOGINS_FILE' option from login.defs) | ||
auth requisite pam_nologin.so | ||
|
||
# SELinux needs to be the first session rule. This ensures that any | ||
# lingering context has been cleared. Without this it is possible | ||
# that a module could execute code in the wrong domain. | ||
# When the module is present, "required" would be sufficient (When SELinux | ||
# is disabled, this returns success.) | ||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close | ||
|
||
# Sets the loginuid process attribute | ||
session required pam_loginuid.so | ||
|
||
# SELinux needs to intervene at login time to ensure that the process | ||
# starts in the proper default security context. Only sessions which are | ||
# intended to run in the user's context should be run after this. | ||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open | ||
# When the module is present, "required" would be sufficient (When SELinux | ||
# is disabled, this returns success.) | ||
|
||
# This module parses environment configuration file(s) | ||
# and also allows you to use an extended config | ||
# file /etc/security/pam_env.conf. | ||
# | ||
# parsing /etc/environment needs "readenv=1" | ||
session required pam_env.so readenv=1 | ||
# locale variables are also kept into /etc/default/locale in etch | ||
# reading this file *in addition to /etc/environment* does not hurt | ||
session required pam_env.so readenv=1 envfile=/etc/default/locale | ||
|
||
# Standard Un*x authentication. | ||
@include common-auth-sonic | ||
|
||
# This allows certain extra groups to be granted to a user | ||
# based on things like time of day, tty, service, and user. | ||
# Please edit /etc/security/group.conf to fit your needs | ||
# (Replaces the `CONSOLE_GROUPS' option in login.defs) | ||
auth optional pam_group.so | ||
|
||
# Uncomment and edit /etc/security/time.conf if you need to set | ||
# time restraint on logins. | ||
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs | ||
# as well as /etc/porttime) | ||
# account requisite pam_time.so | ||
|
||
# Uncomment and edit /etc/security/access.conf if you need to | ||
# set access limits. | ||
# (Replaces /etc/login.access file) | ||
# account required pam_access.so | ||
|
||
# Sets up user limits according to /etc/security/limits.conf | ||
# (Replaces the use of /etc/limits in old login) | ||
session required pam_limits.so | ||
|
||
# Prints the last login info upon successful login | ||
# (Replaces the `LASTLOG_ENAB' option from login.defs) | ||
session optional pam_lastlog.so | ||
|
||
# Prints the message of the day upon successful login. | ||
# (Replaces the `MOTD_FILE' option in login.defs) | ||
# This includes a dynamically generated part from /run/motd.dynamic | ||
# and a static (admin-editable) part from /etc/motd. | ||
session optional pam_motd.so motd=/run/motd.dynamic | ||
session optional pam_motd.so noupdate | ||
|
||
# Prints the status of the user's mailbox upon successful login | ||
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). | ||
# | ||
# This also defines the MAIL environment variable | ||
# However, userdel also needs MAIL_DIR and MAIL_FILE variables | ||
# in /etc/login.defs to make sure that removing a user | ||
# also removes the user's mail spool file. | ||
# See comments in /etc/login.defs | ||
session optional pam_mail.so standard | ||
|
||
# Create a new session keyring. | ||
session optional pam_keyinit.so force revoke | ||
|
||
# Standard Un*x account and session | ||
@include common-account | ||
@include common-session | ||
@include common-password |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# | ||
# The PAM configuration file for the Shadow `login' service | ||
# | ||
|
||
# Enforce a minimal delay in case of failure (in microseconds). | ||
# (Replaces the `FAIL_DELAY' setting from login.defs) | ||
# Note that other modules may require another minimal delay. (for example, | ||
# to disable any delay, you should add the nodelay option to pam_unix) | ||
auth optional pam_faildelay.so delay=3000000 | ||
|
||
# Outputs an issue file prior to each login prompt (Replaces the | ||
# ISSUE_FILE option from login.defs). Uncomment for use | ||
# auth required pam_issue.so issue=/etc/issue | ||
|
||
# Disallows root logins except on tty's listed in /etc/securetty | ||
# (Replaces the `CONSOLE' setting from login.defs) | ||
# | ||
# With the default control of this module: | ||
# [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] | ||
# root will not be prompted for a password on insecure lines. | ||
# if an invalid username is entered, a password is prompted (but login | ||
# will eventually be rejected) | ||
# | ||
# You can change it to a "requisite" module if you think root may mis-type | ||
# her login and should not be prompted for a password in that case. But | ||
# this will leave the system as vulnerable to user enumeration attacks. | ||
# | ||
# You can change it to a "required" module if you think it permits to | ||
# guess valid user names of your system (invalid user names are considered | ||
# as possibly being root on insecure lines), but root passwords may be | ||
# communicated over insecure lines. | ||
auth [success=ok new_authtok_reqd=ok ignore=ignore user_unknown=bad default=die] pam_securetty.so | ||
|
||
# Disallows other than root logins when /etc/nologin exists | ||
# (Replaces the `NOLOGINS_FILE' option from login.defs) | ||
auth requisite pam_nologin.so | ||
|
||
# SELinux needs to be the first session rule. This ensures that any | ||
# lingering context has been cleared. Without this it is possible | ||
# that a module could execute code in the wrong domain. | ||
# When the module is present, "required" would be sufficient (When SELinux | ||
# is disabled, this returns success.) | ||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close | ||
|
||
# Sets the loginuid process attribute | ||
session required pam_loginuid.so | ||
|
||
# SELinux needs to intervene at login time to ensure that the process | ||
# starts in the proper default security context. Only sessions which are | ||
# intended to run in the user's context should be run after this. | ||
session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open | ||
# When the module is present, "required" would be sufficient (When SELinux | ||
# is disabled, this returns success.) | ||
|
||
# This module parses environment configuration file(s) | ||
# and also allows you to use an extended config | ||
# file /etc/security/pam_env.conf. | ||
# | ||
# parsing /etc/environment needs "readenv=1" | ||
session required pam_env.so readenv=1 | ||
# locale variables are also kept into /etc/default/locale in etch | ||
# reading this file *in addition to /etc/environment* does not hurt | ||
session required pam_env.so readenv=1 envfile=/etc/default/locale | ||
|
||
# Standard Un*x authentication. | ||
@include common-auth | ||
|
||
# This allows certain extra groups to be granted to a user | ||
# based on things like time of day, tty, service, and user. | ||
# Please edit /etc/security/group.conf to fit your needs | ||
# (Replaces the `CONSOLE_GROUPS' option in login.defs) | ||
auth optional pam_group.so | ||
|
||
# Uncomment and edit /etc/security/time.conf if you need to set | ||
# time restraint on logins. | ||
# (Replaces the `PORTTIME_CHECKS_ENAB' option from login.defs | ||
# as well as /etc/porttime) | ||
# account requisite pam_time.so | ||
|
||
# Uncomment and edit /etc/security/access.conf if you need to | ||
# set access limits. | ||
# (Replaces /etc/login.access file) | ||
# account required pam_access.so | ||
|
||
# Sets up user limits according to /etc/security/limits.conf | ||
# (Replaces the use of /etc/limits in old login) | ||
session required pam_limits.so | ||
|
||
# Prints the last login info upon successful login | ||
# (Replaces the `LASTLOG_ENAB' option from login.defs) | ||
session optional pam_lastlog.so | ||
|
||
# Prints the message of the day upon successful login. | ||
# (Replaces the `MOTD_FILE' option in login.defs) | ||
# This includes a dynamically generated part from /run/motd.dynamic | ||
# and a static (admin-editable) part from /etc/motd. | ||
session optional pam_motd.so motd=/run/motd.dynamic | ||
session optional pam_motd.so noupdate | ||
|
||
# Prints the status of the user's mailbox upon successful login | ||
# (Replaces the `MAIL_CHECK_ENAB' option from login.defs). | ||
# | ||
# This also defines the MAIL environment variable | ||
# However, userdel also needs MAIL_DIR and MAIL_FILE variables | ||
# in /etc/login.defs to make sure that removing a user | ||
# also removes the user's mail spool file. | ||
# See comments in /etc/login.defs | ||
session optional pam_mail.so standard | ||
|
||
# Create a new session keyring. | ||
session optional pam_keyinit.so force revoke | ||
|
||
# Standard Un*x account and session | ||
@include common-account | ||
@include common-session | ||
@include common-password |
Oops, something went wrong.