From 74aa0bc6779af38018a03fd2cf4419fe85917904 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 07:31:45 +0200 Subject: Adding upstream version 2.9.4. Signed-off-by: Daniel Baumann --- src/tests/pyhbac-test.py | 586 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 586 insertions(+) create mode 100755 src/tests/pyhbac-test.py (limited to 'src/tests/pyhbac-test.py') diff --git a/src/tests/pyhbac-test.py b/src/tests/pyhbac-test.py new file mode 100755 index 0000000..3fd5d15 --- /dev/null +++ b/src/tests/pyhbac-test.py @@ -0,0 +1,586 @@ +#!/usr/bin/env python +# SSSD +# +# SSSD HBAC python API tests +# +# Copyright (C) Red Hat +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import print_function + +import unittest +import sys +import os +import copy +import tempfile + +BUILD_DIR = os.getenv('builddir') or "." +TEST_DIR = os.path.realpath(os.getenv('SSS_TEST_DIR') or ".") +MODPATH = tempfile.mkdtemp(prefix="tp_pyhbac_", dir=TEST_DIR) + + +if sys.version_info[0] > 2: + unicode = str + + +def compat_assertIsInstance(this, obj, cls, msg=None): + return this.assertTrue(isinstance(obj, cls)) + + +def compat_assertItemsEqual(this, expected_seq, actual_seq, msg=None): + return this.assertEqual(sorted(expected_seq), sorted(actual_seq)) + + +# add compat assertIsInstance for old unittest.TestCase versions +# (python < 2.7, RHEL6 for instance) +if not hasattr(unittest.TestCase, "assertIsInstance"): + setattr(unittest.TestCase, "assertIsInstance", compat_assertIsInstance) + +# Python3 renamed assertItemsEqual to assertCountEqual but at the same time +# Python2 doesn't have assertCountEqual, see http://bugs.python.org/issue17866 +if not hasattr(unittest.TestCase, "assertCountEqual"): + if not hasattr(unittest.TestCase, "assertItemsEqual"): + # This is RHEL-6 + setattr(unittest.TestCase, "assertItemsEqual", compat_assertItemsEqual) + + setattr(unittest.TestCase, + "assertCountEqual", + unittest.TestCase.assertItemsEqual) + + +class PyHbacImport(unittest.TestCase): + def setUp(self): + " Make sure we load the in-tree module " + self.system_path = sys.path[:] + sys.path = [MODPATH] + + def tearDown(self): + " Restore the system path " + sys.path = self.system_path + + def testImport(self): + " Import the module and assert it comes from tree " + try: + dest_module_path = MODPATH + "/pyhbac.so" + + if sys.version_info[0] > 2: + src_module_path = BUILD_DIR + "/.libs/_py3hbac.so" + else: + src_module_path = BUILD_DIR + "/.libs/_py2hbac.so" + + src_module_path = os.path.abspath(src_module_path) + os.symlink(src_module_path, dest_module_path) + + import pyhbac + except ImportError as e: + print("Could not load the pyhbac module. Please check if it is " + "compiled", file=sys.stderr) + raise e + self.assertEqual(os.path.realpath(pyhbac.__file__), + os.path.realpath(MODPATH + "/pyhbac.so")) + + +class PyHbacRuleElementTest(unittest.TestCase): + def testInstantiateEmpty(self): + el = pyhbac.HbacRuleElement() + self.assertCountEqual(el.names, []) + self.assertCountEqual(el.groups, []) + self.assertCountEqual(el.category, set([pyhbac.HBAC_CATEGORY_NULL])) + + def testInit(self): + names = ["foo", "bar"] + el = pyhbac.HbacRuleElement(names=names) + self.assertCountEqual(el.names, names) + + groups = ["abc", "def"] + el = pyhbac.HbacRuleElement(groups=groups) + self.assertCountEqual(el.groups, groups) + + def testGetSet(self): + names = ["foo", "bar"] + el = pyhbac.HbacRuleElement() + self.assertCountEqual(el.names, []) + el.names = names + self.assertCountEqual(el.names, names) + + groups = ["abc", "def"] + el = pyhbac.HbacRuleElement() + self.assertCountEqual(el.groups, []) + el.groups = groups + self.assertCountEqual(el.groups, groups) + + # Test other iterables than list + groups = ("abc", "def") + el = pyhbac.HbacRuleElement() + self.assertCountEqual(el.groups, []) + el.groups = groups + self.assertCountEqual(el.groups, groups) + + def testCategory(self): + el = pyhbac.HbacRuleElement() + assert pyhbac.HBAC_CATEGORY_NULL in el.category + assert pyhbac.HBAC_CATEGORY_ALL not in el.category + + el.category.add(pyhbac.HBAC_CATEGORY_ALL) + assert pyhbac.HBAC_CATEGORY_ALL in el.category + + el.category = set([pyhbac.HBAC_CATEGORY_ALL]) + assert pyhbac.HBAC_CATEGORY_ALL in el.category + + # negative tests + self.assertRaises(TypeError, el.__setattr__, "category", + [pyhbac.HBAC_CATEGORY_ALL]) + self.assertRaises(TypeError, el.__setattr__, "category", None) + self.assertRaises(TypeError, el.__setattr__, "category", 1) + + def testNotIterable(self): + self.assertRaises(TypeError, pyhbac.HbacRuleElement, names=123) + self.assertRaises(TypeError, pyhbac.HbacRuleElement, names=None) + + def testRuleElementReference(self): + def _get_rule(): + users = ["foo", "bar"] + user_groups = ["abc", "def"] + return pyhbac.HbacRuleElement(names=users, groups=user_groups) + + el = _get_rule() + self.assertCountEqual(el.names, ["foo", "bar"]) + self.assertCountEqual(el.groups, ["abc", "def"]) + + def testRepr(self): + el = pyhbac.HbacRuleElement() + self.assertEqual(el.__repr__(), u'') + + el.category.add(pyhbac.HBAC_CATEGORY_ALL) + el.names = ['foo'] + el.groups = ['bar, baz'] + self.assertEqual(el.__repr__(), + u'') + + +class PyHbacRuleTest(unittest.TestCase): + def testRuleGetSetName(self): + name = "testGetRule" + new_name = "testGetNewRule" + + rule = pyhbac.HbacRule(name) + self.assertEqual(rule.name, unicode(name)) + + rule.name = new_name + self.assertEqual(rule.name, unicode(new_name)) + + def testRuleGetSetEnabled(self): + rule = pyhbac.HbacRule("testRuleGetSetEnabled") + + rule.enabled = True + self.assertEqual(rule.enabled, True) + rule.enabled = False + self.assertEqual(rule.enabled, False) + + rule.enabled = "TRUE" + self.assertEqual(rule.enabled, True) + rule.enabled = "FALSE" + self.assertEqual(rule.enabled, False) + + rule.enabled = "true" + self.assertEqual(rule.enabled, True) + rule.enabled = "false" + self.assertEqual(rule.enabled, False) + + rule.enabled = "True" + self.assertEqual(rule.enabled, True) + rule.enabled = "False" + self.assertEqual(rule.enabled, False) + + rule.enabled = 1 + self.assertEqual(rule.enabled, True) + rule.enabled = 0 + self.assertEqual(rule.enabled, False) + + # negative test + self.assertRaises(TypeError, rule.__setattr__, "enabled", None) + self.assertRaises(TypeError, rule.__setattr__, "enabled", []) + self.assertRaises(ValueError, rule.__setattr__, "enabled", "foo") + self.assertRaises(ValueError, rule.__setattr__, "enabled", 5) + + def testRuleElementInRule(self): + users = ["foo", "bar"] + user_groups = ["abc", "def"] + + # rule should contain empty elements after instantiation + rule = pyhbac.HbacRule("testRuleElement") + self.assertIsInstance(rule.users, pyhbac.HbacRuleElement) + self.assertIsInstance(rule.services, pyhbac.HbacRuleElement) + self.assertIsInstance(rule.targethosts, pyhbac.HbacRuleElement) + self.assertIsInstance(rule.srchosts, pyhbac.HbacRuleElement) + + self.assertIsInstance(rule.users.names, list) + self.assertIsInstance(rule.users.groups, list) + self.assertCountEqual(rule.users.names, []) + self.assertCountEqual(rule.users.groups, []) + + # Assign by copying a HbacRuleElement + user_el = pyhbac.HbacRuleElement(names=users, groups=user_groups) + rule = pyhbac.HbacRule("testRuleElement") + rule.users = user_el + self.assertCountEqual(rule.users.names, users) + self.assertCountEqual(rule.users.groups, user_groups) + + # Assign directly + rule = pyhbac.HbacRule("testRuleElement") + rule.users.names = users + rule.users.groups = user_groups + self.assertCountEqual(rule.users.names, users) + self.assertCountEqual(rule.users.groups, user_groups) + + def testRuleElementInRuleReference(self): + " Test that references to RuleElement are kept even if element goes" + " out of scope " + def _get_rule(): + users = ["foo", "bar"] + user_groups = ["abc", "def"] + el = pyhbac.HbacRuleElement(names=users, groups=user_groups) + rule = pyhbac.HbacRule("testRuleElement") + rule.users = el + return rule + + rule = _get_rule() + self.assertCountEqual(rule.users.names, ["foo", "bar"]) + self.assertCountEqual(rule.users.groups, ["abc", "def"]) + + def testRepr(self): + r = pyhbac.HbacRule('foo') + self.assertEqual(r.__repr__(), + u" " + "services " + "targethosts " + "srchosts >") + + name = "someuser" + service = "ssh" + srchost = "host1" + targethost = "host2" + + r.users.names = [name] + r.services.names = [service] + r.srchosts.names = [srchost] + r.targethosts.names = [targethost] + + self.assertEqual(r.__repr__(), + u" " + "services " + "targethosts " + "srchosts >" % + (name, service, targethost, srchost)) + + def testValidate(self): + r = pyhbac.HbacRule('valid_rule') + + valid, missing = r.validate() + self.assertEqual(valid, False) + self.assertCountEqual(missing, (pyhbac.HBAC_RULE_ELEMENT_USERS, + pyhbac.HBAC_RULE_ELEMENT_SERVICES, + pyhbac.HBAC_RULE_ELEMENT_TARGETHOSTS, + pyhbac.HBAC_RULE_ELEMENT_SOURCEHOSTS)) + + r.users.names = ["someuser"] + r.services.names = ["ssh"] + + valid, missing = r.validate() + self.assertEqual(valid, False) + self.assertCountEqual(missing, (pyhbac.HBAC_RULE_ELEMENT_TARGETHOSTS, + pyhbac.HBAC_RULE_ELEMENT_SOURCEHOSTS)) + + r.srchosts.names = ["host1"] + r.targethosts.names = ["host2"] + + valid, missing = r.validate() + self.assertEqual(valid, True) + + +class PyHbacRequestElementTest(unittest.TestCase): + def testInstantiateEmpty(self): + el = pyhbac.HbacRequestElement() + self.assertCountEqual(el.name, "") + self.assertCountEqual(el.groups, []) + + def testInit(self): + name = "foo" + el = pyhbac.HbacRequestElement(name=name) + self.assertCountEqual(el.name, name) + + groups = ["abc", "def"] + el = pyhbac.HbacRequestElement(groups=groups) + self.assertCountEqual(el.groups, groups) + + def testGetSet(self): + name = "foo" + el = pyhbac.HbacRequestElement() + self.assertCountEqual(el.name, "") + el.name = name + self.assertCountEqual(el.name, name) + + groups = ["abc", "def"] + el = pyhbac.HbacRequestElement() + self.assertCountEqual(el.groups, []) + el.groups = groups + self.assertCountEqual(el.groups, groups) + + # Test other iterables than list + groups = ("abc", "def") + el = pyhbac.HbacRequestElement() + self.assertCountEqual(el.groups, []) + el.groups = groups + self.assertCountEqual(el.groups, groups) + + def testGroupsNotIterable(self): + self.assertRaises(TypeError, pyhbac.HbacRequestElement, groups=None) + self.assertRaises(TypeError, pyhbac.HbacRequestElement, groups=123) + + def testRepr(self): + r = pyhbac.HbacRequestElement() + self.assertEqual(r.__repr__(), u"") + + r.name = 'foo' + r.groups = ['bar', 'baz'] + self.assertEqual(r.__repr__(), u"") + + +class PyHbacRequestTest(unittest.TestCase): + def testRequestElementHandling(self): + name = "req_name" + groups = ["g1", "g2"] + + # The request should be empty after instantiation + req = pyhbac.HbacRequest() + self.assertIsInstance(req.user, pyhbac.HbacRequestElement) + self.assertIsInstance(req.service, pyhbac.HbacRequestElement) + self.assertIsInstance(req.targethost, pyhbac.HbacRequestElement) + self.assertIsInstance(req.srchost, pyhbac.HbacRequestElement) + + self.assertEqual(req.user.name, "") + self.assertIsInstance(req.user.groups, list) + self.assertCountEqual(req.user.groups, []) + + # Assign by copying a HbacRequestElement + user_el = pyhbac.HbacRequestElement(name=name, groups=groups) + req = pyhbac.HbacRequest() + req.user = user_el + self.assertCountEqual(req.user.name, name) + self.assertCountEqual(req.user.groups, groups) + + # Assign directly + req = pyhbac.HbacRequest() + req.user.name = name + req.user.groups = groups + self.assertCountEqual(req.user.name, name) + self.assertCountEqual(req.user.groups, groups) + + def testRuleName(self): + req = pyhbac.HbacRequest() + self.assertEqual(req.rule_name, None) + # python 2.4 raises TypError, 2.7 raises AttributeError + self.assertRaises((TypeError, AttributeError), req.__setattr__, + "rule_name", "foo") + + def testEvaluate(self): + name = "someuser" + service = "ssh" + srchost = "host1" + targethost = "host2" + + allow_rule = pyhbac.HbacRule("allowRule", enabled=True) + allow_rule.users.names = [name] + allow_rule.services.names = [service] + allow_rule.srchosts.names = [srchost] + allow_rule.targethosts.names = [targethost] + + req = pyhbac.HbacRequest() + req.user.name = name + req.service.name = service + req.srchost.name = srchost + req.targethost.name = targethost + + # Test that an allow rule on its own allows access + res = req.evaluate((allow_rule,)) + self.assertEqual(res, pyhbac.HBAC_EVAL_ALLOW) + self.assertEqual(req.rule_name, "allowRule") + + # Test that a user not in the rule is not allowed + req.user.name = "someotheruser" + res = req.evaluate((allow_rule, )) + self.assertEqual(res, pyhbac.HBAC_EVAL_DENY) + self.assertEqual(req.rule_name, None) + + # But allows if the rule is an ALL rule + allow_rule.users.category.add(pyhbac.HBAC_CATEGORY_ALL) + res = req.evaluate((allow_rule, )) + self.assertEqual(res, pyhbac.HBAC_EVAL_ALLOW) + + def testRepr(self): + name = "someuser" + service = "ssh" + srchost = "host1" + targethost = "host2" + + req = pyhbac.HbacRequest() + + self.assertEqual(req.__repr__(), " " + "service " + "targethost " + "srchost >") + + req.user.name = name + req.service.name = service + req.srchost.name = srchost + req.targethost.name = targethost + + self.assertEqual(req.__repr__(), " " + "service " + "targethost " + "srchost >" % + (name, service, targethost, srchost)) + + def testEvaluateNegative(self): + name = "someuser" + service = "ssh" + srchost = "host1" + targethost = "host2" + + allow_rule = pyhbac.HbacRule("allowRule", enabled=True) + allow_rule.users.names = [name] + allow_rule.services.names = [service] + allow_rule.srchosts.names = [srchost] + allow_rule.targethosts.names = [targethost] + + req = pyhbac.HbacRequest() + req.service.name = service + req.srchost.name = srchost + req.targethost.name = targethost + req.user.name = name + + saveuser = req.user + req.user = None # need to catch this + + # catch invalid category value + savecat = copy.copy(allow_rule.users.category) + allow_rule.users.category.add(pyhbac.HBAC_EVAL_ERROR) + self.assertRaises(ValueError, req.evaluate, (allow_rule,)) + allow_rule.users.category = savecat + + # Test that invalid type is raised + self.assertRaises(TypeError, req.evaluate, (allow_rule,)) + + req.user = saveuser + allow_rule.users = None # need to catch this + self.assertRaises(TypeError, req.evaluate, (allow_rule,)) + + # catch invalid rule type + self.assertRaises(TypeError, req.evaluate, (allow_rule, None)) + + +class PyHbacModuleTest(unittest.TestCase): + @classmethod + def tearDownClass(cls): + os.unlink(MODPATH + "/pyhbac.so") + os.rmdir(MODPATH) + + def testHasResultTypes(self): + assert hasattr(pyhbac, "HBAC_EVAL_ALLOW") + assert hasattr(pyhbac, "HBAC_EVAL_DENY") + assert hasattr(pyhbac, "HBAC_EVAL_ERROR") + + def testHasErrorTypes(self): + assert hasattr(pyhbac, "HBAC_ERROR_UNKNOWN") + assert hasattr(pyhbac, "HBAC_SUCCESS") + assert hasattr(pyhbac, "HBAC_ERROR_NOT_IMPLEMENTED") + assert hasattr(pyhbac, "HBAC_ERROR_OUT_OF_MEMORY") + assert hasattr(pyhbac, "HBAC_ERROR_UNPARSEABLE_RULE") + + def testHasCategories(self): + assert hasattr(pyhbac, "HBAC_CATEGORY_NULL") + assert hasattr(pyhbac, "HBAC_CATEGORY_ALL") + + def testHasRuleElementTypes(self): + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_USERS") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_SERVICES") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_TARGETHOSTS") + assert hasattr(pyhbac, "HBAC_RULE_ELEMENT_SOURCEHOSTS") + + def testHbacResultString(self): + results = [pyhbac.HBAC_EVAL_ALLOW, pyhbac.HBAC_EVAL_DENY, + pyhbac.HBAC_EVAL_ERROR] + for r in results: + s = pyhbac.hbac_result_string(r) + self.assertIsInstance(s, unicode) + assert len(s) > 0 + + def testHbacErrorString(self): + errors = [pyhbac.HBAC_ERROR_UNKNOWN, + pyhbac.HBAC_SUCCESS, + pyhbac.HBAC_ERROR_NOT_IMPLEMENTED, + pyhbac.HBAC_ERROR_OUT_OF_MEMORY, + pyhbac.HBAC_ERROR_UNPARSEABLE_RULE] + for e in errors: + s = pyhbac.hbac_error_string(e) + self.assertIsInstance(s, unicode) + assert len(s) > 0 + + +if __name__ == "__main__": + error = 0 + + suite = unittest.TestLoader().loadTestsFromTestCase(PyHbacImport) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x1 + # need to bail out here because pyhbac could not be imported + sys.exit(error) + + # import the pyhbac module into the global namespace, but make sure it's + # the one in tree + sys.path.insert(0, MODPATH) + import pyhbac + + loadTestsFromTestCase = unittest.TestLoader().loadTestsFromTestCase + + suite = loadTestsFromTestCase(PyHbacRuleElementTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x2 + + suite = loadTestsFromTestCase(PyHbacRuleTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x3 + + suite = loadTestsFromTestCase(PyHbacRequestElementTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x4 + + suite = loadTestsFromTestCase(PyHbacRequestTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x5 + + suite = loadTestsFromTestCase(PyHbacModuleTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x6 + + sys.exit(error) -- cgit v1.2.3