downgradedatabase: blackbox test
authorAaron Haslett <aaronhaslett@catalyst.net.nz>
Thu, 23 May 2019 01:21:19 +0000 (13:21 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 29 May 2019 04:41:24 +0000 (04:41 +0000)
This test confirms that running downgradedatabase causes all GUID keys to be
replaced with DN keys at the KV level

Signed-off-by: Aaron Haslett <aaronhaslett@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
python/samba/tests/__init__.py
python/samba/tests/blackbox/downgradedatabase.py [new file with mode: 0644]
source4/selftest/tests.py

index cbd164de1f9d19bd637e5fcf6ba327e9cbf18b9c..03c21c2bc889759a5b7f8fd57a06a1bfbb2dfac2 100644 (file)
@@ -19,6 +19,7 @@
 """Samba Python tests."""
 from __future__ import print_function
 import os
+import shutil
 import tempfile
 import warnings
 import ldb
@@ -294,11 +295,15 @@ class TestCaseInTempDir(TestCase):
         super(TestCaseInTempDir, self).setUp()
         self.tempdir = tempfile.mkdtemp()
         self.addCleanup(self._remove_tempdir)
+        self.check_tempdir_empty = True
 
     def _remove_tempdir(self):
         # Note asserting here is treated as an error rather than a test failure
-        self.assertEquals([], os.listdir(self.tempdir))
-        os.rmdir(self.tempdir)
+        if self.check_tempdir_empty:
+            self.assertEquals([], os.listdir(self.tempdir))
+            os.rmdir(self.tempdir)
+        else:
+            shutil.rmtree(self.tempdir)
         self.tempdir = None
 
     @contextmanager
diff --git a/python/samba/tests/blackbox/downgradedatabase.py b/python/samba/tests/blackbox/downgradedatabase.py
new file mode 100644 (file)
index 0000000..48a5eb1
--- /dev/null
@@ -0,0 +1,99 @@
+# Blackbox tests for sambadowngradedatabase
+#
+# Copyright (C) Catalyst IT Ltd. 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/>.
+#
+from __future__ import print_function
+from samba.tests import BlackboxTestCase
+import os
+import ldb
+from subprocess import check_output
+from samba.samdb import SamDB
+
+COMMAND = os.path.join(os.path.dirname(__file__),
+               "../../../../../source4/scripting/bin/sambadowngradedatabase")
+
+
+class DowngradeTest(BlackboxTestCase):
+    """Test that sambadowngradedatabase downgrades the samba database"""
+    backend = 'tdb'
+
+    def setUp(self):
+        super(DowngradeTest, self).setUp()
+
+        # Don't assert on empty tempdir contents on tearDown
+        self.check_tempdir_empty = False
+
+        prov_cmd = "samba-tool domain provision " +\
+                   "--domain FOO --realm foo.example.com " +\
+                   "--targetdir {self.tempdir} " +\
+                   "--backend-store {self.backend} " +\
+                   "--host-name downgradetest " +\
+                   "--option=\"vfs objects=fake_acls xattr_tdb\""
+        prov_cmd = prov_cmd.format(self=self)
+        self.check_run(prov_cmd, "Provisioning for downgrade")
+
+        private_dir = os.path.join(self.tempdir, "private")
+        self.sam_path = os.path.join(private_dir, "sam.ldb")
+        self.ldb = ldb.Ldb(self.sam_path, options=["modules:"])
+
+        partitions = self.ldb.search(base="@PARTITION",
+                                       scope=ldb.SCOPE_BASE,
+                                       attrs=["partition"])
+        partitions = partitions[0]['partition']
+        partitions = [str(p).split(":")[1] for p in partitions]
+        self.dbs = [os.path.join(private_dir, p)
+                    for p in partitions]
+        self.dbs.append(self.sam_path)
+
+    # Parse out the comments above each record that ldbdump produces
+    # containing pack format version and KV level key for each record.
+    # Return all GUID keys and DN keys (without @attrs)
+    def ldbdump_keys_pack_formats(self):
+        # Get all comments from all partition dbs
+        comments = []
+        for db in self.dbs:
+            dump = check_output(["bin/ldbdump", "-i", db])
+            dump = dump.decode("utf-8")
+            dump = dump.split("\n")
+            comments += [s for s in dump if s.startswith("#")]
+
+        guid_key_tag = "# key: GUID="
+        guid_keys = {c[len(guid_key_tag):] for c in comments
+                     if c.startswith(guid_key_tag)}
+
+        dn_key_tag = "# key: DN="
+        dn_keys = {c[len(dn_key_tag):] for c in comments
+                   if c.startswith(dn_key_tag)}
+
+        # Ignore @ attributes, they are always DN keyed
+        dn_keys_no_at_attrs = {d for d in dn_keys if not d.startswith("@")}
+
+        return dn_keys_no_at_attrs, guid_keys
+
+    # Check that sambadowngradedatabase replaces all GUID keys with DN keys
+    def test_downgrade_database(self):
+        dn_keys, guid_keys = self.ldbdump_keys_pack_formats()
+        self.assertGreater(len(guid_keys), 20)
+        self.assertEqual(len(dn_keys), 0)
+
+        num_guid_keys_before_downgrade = len(guid_keys)
+
+        self.check_run("%s -H %s" % (COMMAND, self.sam_path),
+                       msg="Running sambadowngradedatabase")
+
+        dn_keys, guid_keys = self.ldbdump_keys_pack_formats()
+        self.assertEqual(len(guid_keys), 0)
+        self.assertEqual(len(dn_keys), num_guid_keys_before_downgrade)
index f807bf75519e6718c2f08cb45cb4160a552e61c2..156bd2003721cc15fc3c92b43e8b94f89c7f31bf 100755 (executable)
@@ -834,6 +834,8 @@ for env in ["ad_dc_ntvfs:local", "ad_dc:local",
             "promoted_dc:local"]:
     planoldpythontestsuite(env, "samba.tests.blackbox.smbcontrol")
 
+planoldpythontestsuite("none", "samba.tests.blackbox.downgradedatabase")
+
 plantestsuite_loadlist("samba4.ldap.python(ad_dc_default)", "ad_dc_default", [python, os.path.join(DSDB_PYTEST_DIR, "ldap.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT'])
 
 plantestsuite_loadlist("samba4.ldap_modify_order.python(ad_dc_default)",