summaryrefslogtreecommitdiffstats
path: root/python/samba/tests/samba_tool/contact.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/samba/tests/samba_tool/contact.py')
-rw-r--r--python/samba/tests/samba_tool/contact.py468
1 files changed, 468 insertions, 0 deletions
diff --git a/python/samba/tests/samba_tool/contact.py b/python/samba/tests/samba_tool/contact.py
new file mode 100644
index 0000000..2bec813
--- /dev/null
+++ b/python/samba/tests/samba_tool/contact.py
@@ -0,0 +1,468 @@
+# Unix SMB/CIFS implementation.
+#
+# Tests for samba-tool contact management commands
+#
+# Copyright (C) Bjoern Baumbach <bbaumbach@samba.org> 2019
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+
+import os
+import ldb
+from samba.tests.samba_tool.base import SambaToolCmdTest
+
+class ContactCmdTestCase(SambaToolCmdTest):
+ """Tests for samba-tool contact subcommands"""
+ contacts = []
+ samdb = None
+
+ def setUp(self):
+ super().setUp()
+ self.creds = "-U%s%%%s" % (os.environ["DC_USERNAME"],
+ os.environ["DC_PASSWORD"])
+ self.samdb = self.getSamDB("-H",
+ "ldap://%s" % os.environ["DC_SERVER"],
+ self.creds)
+ contact = None
+ self.contacts = []
+
+ contact = self._randomContact({"expectedname": "contact1",
+ "name": "contact1"})
+ self.contacts.append(contact)
+
+ # No 'name' is given here, so the name will be made from givenname.
+ contact = self._randomContact({"expectedname": "contact2",
+ "givenName": "contact2"})
+ self.contacts.append(contact)
+
+ contact = self._randomContact({"expectedname": "contact3",
+ "name": "contact3",
+ "displayName": "contact3displayname",
+ "givenName": "not_contact3",
+ "initials": "I",
+ "sn": "not_contact3",
+ "mobile": "12345"})
+ self.contacts.append(contact)
+
+ # No 'name' is given here, so the name will be made from the the
+ # sn, initials and givenName attributes.
+ contact = self._randomContact({"expectedname": "James T. Kirk",
+ "sn": "Kirk",
+ "initials": "T",
+ "givenName": "James"})
+ self.contacts.append(contact)
+
+ # setup the 4 contacts and ensure they are correct
+ for contact in self.contacts:
+ (result, out, err) = self._create_contact(contact)
+
+ self.assertCmdSuccess(result, out, err)
+ self.assertNotIn(
+ "ERROR", err, "There shouldn't be any error message")
+ self.assertIn("Contact '%s' added successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ self.assertIsNotNone(found)
+
+ contactname = contact["expectedname"]
+ self.assertEqual("%s" % found.get("name"), contactname)
+ self.assertEqual("%s" % found.get("description"),
+ contact["description"])
+
+ def tearDown(self):
+ super().tearDown()
+ # clean up all the left over contacts, just in case
+ for contact in self.contacts:
+ if self._find_contact(contact["expectedname"]):
+ (result, out, err) = self.runsubcmd(
+ "contact", "delete", "%s" % contact["expectedname"])
+ self.assertCmdSuccess(result, out, err,
+ "Failed to delete contact '%s'" %
+ contact["expectedname"])
+
+ def test_newcontact(self):
+ """This tests the "contact create" and "contact delete" commands"""
+ # try to create all the contacts again, this should fail
+ for contact in self.contacts:
+ (result, out, err) = self._create_contact(contact)
+ self.assertCmdFail(result, "Succeeded to create existing contact")
+ self.assertIn("already exists", err)
+
+ # try to delete all the contacts we just added
+ for contact in self.contacts:
+ (result, out, err) = self.runsubcmd("contact", "delete", "%s" %
+ contact["expectedname"])
+ self.assertCmdSuccess(result, out, err,
+ "Failed to delete contact '%s'" %
+ contact["expectedname"])
+ found = self._find_contact(contact["expectedname"])
+ self.assertIsNone(found,
+ "Deleted contact '%s' still exists" %
+ contact["expectedname"])
+
+ # test creating contacts in an specified OU
+ parentou = self._randomOU({"name": "testOU"})
+ (result, out, err) = self._create_ou(parentou)
+ self.assertCmdSuccess(result, out, err)
+
+ for contact in self.contacts:
+ (result, out, err) = self._create_contact(contact, ou="OU=testOU")
+
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "There shouldn't be any error message")
+ self.assertIn("Contact '%s' added successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ contactname = contact["expectedname"]
+ self.assertEqual("%s" % found.get("name"), contactname)
+ self.assertEqual("%s" % found.get("description"),
+ contact["description"])
+
+ # try to delete all the contacts we just added, by DN
+ for contact in self.contacts:
+ expecteddn = ldb.Dn(self.samdb,
+ "CN=%s,OU=%s,%s" %
+ (contact["expectedname"],
+ parentou["name"],
+ self.samdb.domain_dn()))
+ (result, out, err) = self.runsubcmd("contact", "delete", "%s" %
+ expecteddn)
+ self.assertCmdSuccess(result, out, err,
+ "Failed to delete contact '%s'" %
+ contact["expectedname"])
+ found = self._find_contact(contact["expectedname"])
+ self.assertIsNone(found,
+ "Deleted contact '%s' still exists" %
+ contact["expectedname"])
+
+ (result, out, err) = self.runsubcmd("ou", "delete",
+ "OU=%s" % parentou["name"])
+ self.assertCmdSuccess(result, out, err,
+ "Failed to delete ou '%s'" % parentou["name"])
+
+ # creating contacts, again for further tests
+ for contact in self.contacts:
+ (result, out, err) = self._create_contact(contact)
+
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "There shouldn't be any error message")
+ self.assertIn("Contact '%s' added successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ contactname = contact["expectedname"]
+ self.assertEqual("%s" % found.get("name"), contactname)
+ self.assertEqual("%s" % found.get("description"),
+ contact["description"])
+
+ def test_list(self):
+ (result, out, err) = self.runsubcmd("contact", "list")
+ self.assertCmdSuccess(result, out, err, "Error running list")
+
+ search_filter = "(objectClass=contact)"
+ contactlist = self.samdb.search(base=self.samdb.domain_dn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression=search_filter,
+ attrs=["name"])
+
+ self.assertTrue(len(contactlist) > 0, "no contacts found in samdb")
+
+ for contactobj in contactlist:
+ name = contactobj.get("name", idx=0)
+ self.assertMatch(out, str(name),
+ "contact '%s' not found" % name)
+
+ def test_list_full_dn(self):
+ (result, out, err) = self.runsubcmd("contact", "list", "--full-dn")
+ self.assertCmdSuccess(result, out, err, "Error running list")
+
+ search_filter = "(objectClass=contact)"
+ contactlist = self.samdb.search(base=self.samdb.domain_dn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression=search_filter,
+ attrs=["dn"])
+
+ self.assertTrue(len(contactlist) > 0, "no contacts found in samdb")
+
+ for contactobj in contactlist:
+ self.assertMatch(out, str(contactobj.dn),
+ "contact '%s' not found" % str(contactobj.dn))
+
+ def test_list_base_dn(self):
+ base_dn = str(self.samdb.domain_dn())
+ (result, out, err) = self.runsubcmd("contact", "list",
+ "-b", base_dn)
+ self.assertCmdSuccess(result, out, err, "Error running list")
+
+ search_filter = "(objectClass=contact)"
+ contactlist = self.samdb.search(base=base_dn,
+ scope=ldb.SCOPE_SUBTREE,
+ expression=search_filter,
+ attrs=["name"])
+
+ self.assertTrue(len(contactlist) > 0, "no contacts found in samdb")
+
+ for contactobj in contactlist:
+ name = contactobj.get("name", idx=0)
+ self.assertMatch(out, str(name),
+ "contact '%s' not found" % name)
+
+ def test_move(self):
+ parentou = self._randomOU({"name": "parentOU"})
+ (result, out, err) = self._create_ou(parentou)
+ self.assertCmdSuccess(result, out, err)
+
+ for contact in self.contacts:
+ olddn = self._find_contact(contact["expectedname"]).get("dn")
+
+ (result, out, err) = self.runsubcmd("contact", "move",
+ "%s" % contact["expectedname"],
+ "OU=%s" % parentou["name"])
+ self.assertCmdSuccess(result, out, err,
+ "Failed to move contact '%s'" %
+ contact["expectedname"])
+ self.assertEqual(err, "", "There shouldn't be any error message")
+ self.assertIn('Moved contact "%s"' % contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+ self.assertNotEqual(found.get("dn"), olddn,
+ ("Moved contact '%s' still exists with the "
+ "same dn" % contact["expectedname"]))
+ contactname = contact["expectedname"]
+ newexpecteddn = ldb.Dn(self.samdb,
+ "CN=%s,OU=%s,%s" %
+ (contactname,
+ parentou["name"],
+ self.samdb.domain_dn()))
+ self.assertEqual(found.get("dn"), newexpecteddn,
+ "Moved contact '%s' does not exist" %
+ contact["expectedname"])
+
+ (result, out, err) = self.runsubcmd("contact", "move",
+ "%s" % contact["expectedname"],
+ "%s" % olddn.parent())
+ self.assertCmdSuccess(result, out, err,
+ "Failed to move contact '%s'" %
+ contact["expectedname"])
+
+ (result, out, err) = self.runsubcmd("ou", "delete",
+ "OU=%s" % parentou["name"])
+ self.assertCmdSuccess(result, out, err,
+ "Failed to delete ou '%s'" % parentou["name"])
+
+ def test_rename_givenname_initials_surname(self):
+ """rename and remove given name, initials and surname for all contacts"""
+ for contact in self.contacts:
+ name = contact["name"] if "name" in contact else contact["expectedname"]
+
+ new_givenname = "new_given_name_of_" + name
+ new_initials = "A"
+ new_surname = "new_surname_of_" + name
+ new_cn = "new_cn_of_" + name
+ expected_cn = "%s %s. %s" % (new_givenname, new_initials, new_surname)
+
+ # rename given name, initials and surname
+ (result, out, err) = self.runsubcmd("contact", "rename", name,
+ "--reset-cn",
+ "--surname=%s" % new_surname,
+ "--initials=%s" % new_initials,
+ "--given-name=%s" % new_givenname)
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "Shouldn't be any error messages")
+ self.assertIn('successfully', out)
+
+ found = self._find_contact(expected_cn)
+ self.assertEqual("%s" % found.get("givenName"), new_givenname)
+ self.assertEqual("%s" % found.get("initials"), new_initials)
+ self.assertEqual("%s" % found.get("sn"), new_surname)
+ self.assertEqual("%s" % found.get("name"), expected_cn)
+ self.assertEqual("%s" % found.get("cn"), expected_cn)
+
+ # remove given name, initials and surname
+ # (must force new cn, because en empty new CN throws an error)
+ (result, out, err) = self.runsubcmd("contact", "rename", expected_cn,
+ "--force-new-cn=%s" % expected_cn,
+ "--surname=",
+ "--initials=",
+ "--given-name=")
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "Shouldn't be any error messages")
+ self.assertIn('successfully', out)
+
+ found = self._find_contact(expected_cn)
+ self.assertEqual(found.get("givenName"), None)
+ self.assertEqual(found.get("initials"), None)
+ self.assertEqual(found.get("sn"), None)
+
+ # reset changes (initials are already removed)
+ old_surname = contact["sn"] if "sn" in contact else ""
+ old_initials = contact["initials"] if "initials" in contact else ""
+ old_givenname = contact["givenName"] if "givenName" in contact else ""
+ old_cn = contact["cn"] if "cn" in contact else name
+ (result, out, err) = self.runsubcmd("contact", "rename", expected_cn,
+ "--force-new-cn=%s" % old_cn,
+ "--surname=%s" % old_surname,
+ "--initials=%s" % old_initials,
+ "--given-name=%s" % old_givenname)
+ self.assertCmdSuccess(result, out, err)
+
+ def test_rename_cn(self):
+ """rename and try to remove the cn of all contacts"""
+ for contact in self.contacts:
+ name = contact["name"] if "name" in contact else contact["expectedname"]
+ new_cn = "new_cn_of_" + name
+
+ # rename cn
+ (result, out, err) = self.runsubcmd("contact", "rename", name,
+ "--force-new-cn=%s" % new_cn)
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "Shouldn't be any error messages")
+ self.assertIn('successfully', out)
+
+ found = self._find_contact(new_cn)
+ self.assertEqual("%s" % found.get("cn"), new_cn)
+
+ # trying to remove cn (throws an error)
+ (result, out, err) = self.runsubcmd("contact", "rename", new_cn,
+ "--force-new-cn=")
+ self.assertCmdFail(result)
+ self.assertIn('Failed to rename contact', err)
+ self.assertIn("delete protected attribute", err)
+
+ # reset changes (cn must be the name)
+ (result, out, err) = self.runsubcmd("contact", "rename", new_cn,
+ "--force-new-cn=%s" % name)
+ self.assertCmdSuccess(result, out, err)
+
+
+ def test_rename_mailaddress_displayname(self):
+ """rename and remove the mail and the displayname attribute of all contacts"""
+ for contact in self.contacts:
+ name = contact["name"] if "name" in contact else contact["expectedname"]
+ new_mail = "new_mailaddress_of_" + name
+ new_displayname = "new displayname of " + name
+
+ # change mail and displayname
+ (result, out, err) = self.runsubcmd("contact", "rename", name,
+ "--mail-address=%s"
+ % new_mail,
+ "--display-name=%s"
+ % new_displayname)
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "Shouldn't be any error messages")
+ self.assertIn('successfully', out)
+
+ found = self._find_contact(name)
+ self.assertEqual("%s" % found.get("mail"), new_mail)
+ self.assertEqual("%s" % found.get("displayName"), new_displayname)
+
+ # remove mail and displayname
+ (result, out, err) = self.runsubcmd("contact", "rename", name,
+ "--mail-address=",
+ "--display-name=")
+ self.assertCmdSuccess(result, out, err)
+ self.assertEqual(err, "", "Shouldn't be any error messages")
+ self.assertIn('successfully', out)
+
+ found = self._find_contact(name)
+ self.assertEqual(found.get("mail"), None)
+ self.assertEqual(found.get("displayName"), None)
+
+ # reset changes
+ old_mail = contact["givenName"] if "givenName" in contact else ""
+ old_displayname = contact["cn"] if "cn" in contact else ""
+ (result, out, err) = self.runsubcmd("contact", "rename", name,
+ "--mail-address=%s" % old_mail,
+ "--display-name=%s" % old_displayname)
+ self.assertCmdSuccess(result, out, err)
+
+ def _randomContact(self, base=None):
+ """Create a contact with random attribute values, you can specify base
+ attributes"""
+ if base is None:
+ base = {}
+
+ # No name attributes are given here, because the object name will
+ # be made from the sn, givenName and initials attributes, if no name
+ # is given.
+ contact = {
+ "description": self.randomName(count=100),
+ }
+ contact.update(base)
+ return contact
+
+ def _randomOU(self, base=None):
+ """Create an ou with random attribute values, you can specify base
+ attributes."""
+ if base is None:
+ base = {}
+
+ ou = {
+ "name": self.randomName(),
+ "description": self.randomName(count=100),
+ }
+ ou.update(base)
+ return ou
+
+ def _create_contact(self, contact, ou=None):
+ args = ""
+
+ if "name" in contact:
+ args += '{0}'.format(contact['name'])
+
+ args += ' {0}'.format(self.creds)
+
+ if ou is not None:
+ args += ' --ou={0}'.format(ou)
+
+ if "description" in contact:
+ args += ' --description={0}'.format(contact["description"])
+ if "sn" in contact:
+ args += ' --surname={0}'.format(contact["sn"])
+ if "initials" in contact:
+ args += ' --initials={0}'.format(contact["initials"])
+ if "givenName" in contact:
+ args += ' --given-name={0}'.format(contact["givenName"])
+ if "displayName" in contact:
+ args += ' --display-name={0}'.format(contact["displayName"])
+ if "mobile" in contact:
+ args += ' --mobile-number={0}'.format(contact["mobile"])
+
+ args = args.split()
+
+ return self.runsubcmd('contact', 'create', *args)
+
+ def _create_ou(self, ou):
+ return self.runsubcmd("ou",
+ "create",
+ "OU=%s" % ou["name"],
+ "--description=%s" % ou["description"])
+
+ def _find_contact(self, name):
+ contactname = name
+ search_filter = ("(&(objectClass=contact)(name=%s))" %
+ ldb.binary_encode(contactname))
+ contactlist = self.samdb.search(base=self.samdb.domain_dn(),
+ scope=ldb.SCOPE_SUBTREE,
+ expression=search_filter,
+ attrs=[])
+ if contactlist:
+ return contactlist[0]
+ else:
+ return None