summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorBjörn Baumbach <bb@sernet.de>2019-03-20 17:17:05 +0100
committerAndrew Bartlett <abartlet@samba.org>2019-07-04 02:07:21 +0000
commit78e78a4092569978e79a661bcd6e6631e4868245 (patch)
tree13eb1b4e4ffb95cd32ce0ef57f8814a8cff59683 /python
parent3f10c8f25cf1655b4facf190f61acb4098919609 (diff)
downloadsamba-78e78a4092569978e79a661bcd6e6631e4868245.tar.gz
samba-tool tests: add tests for contact management
Signed-off-by: Björn Baumbach <bb@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'python')
-rw-r--r--python/samba/tests/samba_tool/contact.py319
-rwxr-xr-xpython/samba/tests/samba_tool/contact_edit.sh164
2 files changed, 483 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 00000000000..626277ce8f1
--- /dev/null
+++ b/python/samba/tests/samba_tool/contact.py
@@ -0,0 +1,319 @@
+# 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(ContactCmdTestCase, self).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' created successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ self.assertIsNotNone(found)
+
+ contactname = contact["expectedname"]
+ self.assertEquals("%s" % found.get("name"), contactname)
+ self.assertEquals("%s" % found.get("description"),
+ contact["description"])
+
+ def tearDown(self):
+ super(ContactCmdTestCase, self).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 created
+ 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.assertEquals(err, "", "There shouldn't be any error message")
+ self.assertIn("Contact '%s' created successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ contactname = contact["expectedname"]
+ self.assertEquals("%s" % found.get("name"), contactname)
+ self.assertEquals("%s" % found.get("description"),
+ contact["description"])
+
+ # try to delete all the contacts we just created, 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.assertEquals(err, "", "There shouldn't be any error message")
+ self.assertIn("Contact '%s' created successfully" %
+ contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+
+ contactname = contact["expectedname"]
+ self.assertEquals("%s" % found.get("name"), contactname)
+ self.assertEquals("%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_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.assertEquals(err, "", "There shouldn't be any error message")
+ self.assertIn('Moved contact "%s"' % contact["expectedname"], out)
+
+ found = self._find_contact(contact["expectedname"])
+ self.assertNotEquals(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.assertEquals(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 _randomContact(self, base={}):
+ """Create a contact with random attribute values, you can specify base
+ attributes"""
+
+ # 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={}):
+ """Create an ou with random attribute values, you can specify base
+ attributes."""
+
+ 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
diff --git a/python/samba/tests/samba_tool/contact_edit.sh b/python/samba/tests/samba_tool/contact_edit.sh
new file mode 100755
index 00000000000..ca38900062a
--- /dev/null
+++ b/python/samba/tests/samba_tool/contact_edit.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+#
+# Test for 'samba-tool contact edit'
+
+if [ $# -lt 3 ]; then
+cat <<EOF
+Usage: contact_edit.sh SERVER USERNAME PASSWORD
+EOF
+exit 1;
+fi
+
+SERVER="$1"
+USERNAME="$2"
+PASSWORD="$3"
+
+STpath=$(pwd)
+. $STpath/testprogs/blackbox/subunit.sh
+
+display_name="Björn"
+display_name_b64="QmrDtnJu"
+display_name_new="Renamed Bjoern"
+# attribute value including control character
+# echo -e "test \a string" | base64
+display_name_con_b64="dGVzdCAHIHN0cmluZwo="
+
+tmpeditor=$(mktemp --suffix .sh -p $STpath/bin samba-tool-editor-XXXXXXXX)
+chmod +x $tmpeditor
+
+create_test_contact() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool \
+ contact create testcontact1 \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+# Test edit contact - add base64 attributes
+add_attribute_base64() {
+ # create editor.sh
+ cat >$tmpeditor <<EOF
+#!/usr/bin/env bash
+contact_ldif="\$1"
+
+grep -v '^$' \$contact_ldif > \${contact_ldif}.tmp
+echo "displayName:: $display_name_b64" >> \${contact_ldif}.tmp
+
+mv \${contact_ldif}.tmp \$contact_ldif
+EOF
+
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact edit \
+ testcontact1 --editor=$tmpeditor \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+get_attribute_base64() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact show \
+ testcontact1 --attributes=displayName \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+delete_attribute() {
+ # create editor.sh
+ cat >$tmpeditor <<EOF
+#!/usr/bin/env bash
+contact_ldif="\$1"
+
+grep -v '^displayName' \$contact_ldif >> \${contact_ldif}.tmp
+mv \${contact_ldif}.tmp \$contact_ldif
+EOF
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact edit \
+ testcontact1 --editor=$tmpeditor \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+# Test edit contact - add base64 attribute value including control character
+add_attribute_base64_control() {
+ # create editor.sh
+ cat >$tmpeditor <<EOF
+#!/usr/bin/env bash
+contact_ldif="\$1"
+
+grep -v '^$' \$contact_ldif > \${contact_ldif}.tmp
+echo "displayName:: $display_name_con_b64" >> \${contact_ldif}.tmp
+
+mv \${contact_ldif}.tmp \$contact_ldif
+EOF
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact edit \
+ testcontact1 --editor=$tmpeditor \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+get_attribute_base64_control() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact show \
+ testcontact1 --attributes=displayName \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+
+# Test edit contact - change base64 attribute value including control character
+change_attribute_base64_control() {
+ # create editor.sh
+ cat >$tmpeditor <<EOF
+#!/usr/bin/env bash
+contact_ldif="\$1"
+
+sed -i -e 's/displayName:: $display_name_con_b64/displayName: $display_name/' \
+ \$contact_ldif
+EOF
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact edit \
+ testcontact1 --editor=$tmpeditor \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+get_attribute_base64_control() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact show \
+ testcontact1 --attributes=displayName \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+# Test edit contact - change attributes with LDB_FLAG_FORCE_NO_BASE64_LDIF
+change_attribute_force_no_base64() {
+ # create editor.sh
+ # Expects that the original attribute is available as clear text,
+ # because the LDB_FLAG_FORCE_NO_BASE64_LDIF should be used here.
+ cat >$tmpeditor <<EOF
+#!/usr/bin/env bash
+contact_ldif="\$1"
+
+sed -i -e 's/displayName: $display_name/displayName: $display_name_new/' \
+ \$contact_ldif
+EOF
+
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact edit \
+ testcontact1 --editor=$tmpeditor \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+get_changed_attribute_force_no_base64() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool contact show \
+ testcontact1 --attributes=displayName \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+delete_contact() {
+ $PYTHON ${STpath}/source4/scripting/bin/samba-tool \
+ contact delete testcontact1 \
+ -H "ldap://$SERVER" "-U$USERNAME" "--password=$PASSWORD"
+}
+
+failed=0
+
+testit "create_test_contact" create_test_contact || failed=`expr $failed + 1`
+testit "add_attribute_base64" add_attribute_base64 || failed=`expr $failed + 1`
+testit_grep "get_attribute_base64" "^displayName:: $display_name_b64" get_attribute_base64 || failed=`expr $failed + 1`
+testit "delete_attribute" delete_attribute || failed=`expr $failed + 1`
+testit "add_attribute_base64_control" add_attribute_base64_control || failed=`expr $failed + 1`
+testit_grep "get_attribute_base64_control" "^displayName:: $display_name_con_b64" get_attribute_base64_control || failed=`expr $failed + 1`
+testit "change_attribute_base64_control" change_attribute_base64_control || failed=`expr $failed + 1`
+testit_grep "get_attribute_base64_control" "^displayName:: $display_name_b64" get_attribute_base64_control || failed=`expr $failed + 1`
+testit "change_attribute_force_no_base64" change_attribute_force_no_base64 || failed=`expr $failed + 1`
+testit_grep "get_changed_attribute_force_no_base64" "^displayName: $display_name_new" get_changed_attribute_force_no_base64 || failed=`expr $failed + 1`
+testit "delete_contact" delete_contact || failed=`expr $failed + 1`
+
+rm -f $tmpeditor
+
+exit $failed