48a5eb1eaf224a53b4c8c0bba3d4f80022c893df
[metze/samba/wip.git] / python / samba / tests / blackbox / downgradedatabase.py
1 # Blackbox tests for sambadowngradedatabase
2 #
3 # Copyright (C) Catalyst IT Ltd. 2019
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 from __future__ import print_function
19 from samba.tests import BlackboxTestCase
20 import os
21 import ldb
22 from subprocess import check_output
23 from samba.samdb import SamDB
24
25 COMMAND = os.path.join(os.path.dirname(__file__),
26                "../../../../../source4/scripting/bin/sambadowngradedatabase")
27
28
29 class DowngradeTest(BlackboxTestCase):
30     """Test that sambadowngradedatabase downgrades the samba database"""
31     backend = 'tdb'
32
33     def setUp(self):
34         super(DowngradeTest, self).setUp()
35
36         # Don't assert on empty tempdir contents on tearDown
37         self.check_tempdir_empty = False
38
39         prov_cmd = "samba-tool domain provision " +\
40                    "--domain FOO --realm foo.example.com " +\
41                    "--targetdir {self.tempdir} " +\
42                    "--backend-store {self.backend} " +\
43                    "--host-name downgradetest " +\
44                    "--option=\"vfs objects=fake_acls xattr_tdb\""
45         prov_cmd = prov_cmd.format(self=self)
46         self.check_run(prov_cmd, "Provisioning for downgrade")
47
48         private_dir = os.path.join(self.tempdir, "private")
49         self.sam_path = os.path.join(private_dir, "sam.ldb")
50         self.ldb = ldb.Ldb(self.sam_path, options=["modules:"])
51
52         partitions = self.ldb.search(base="@PARTITION",
53                                        scope=ldb.SCOPE_BASE,
54                                        attrs=["partition"])
55         partitions = partitions[0]['partition']
56         partitions = [str(p).split(":")[1] for p in partitions]
57         self.dbs = [os.path.join(private_dir, p)
58                     for p in partitions]
59         self.dbs.append(self.sam_path)
60
61     # Parse out the comments above each record that ldbdump produces
62     # containing pack format version and KV level key for each record.
63     # Return all GUID keys and DN keys (without @attrs)
64     def ldbdump_keys_pack_formats(self):
65         # Get all comments from all partition dbs
66         comments = []
67         for db in self.dbs:
68             dump = check_output(["bin/ldbdump", "-i", db])
69             dump = dump.decode("utf-8")
70             dump = dump.split("\n")
71             comments += [s for s in dump if s.startswith("#")]
72
73         guid_key_tag = "# key: GUID="
74         guid_keys = {c[len(guid_key_tag):] for c in comments
75                      if c.startswith(guid_key_tag)}
76
77         dn_key_tag = "# key: DN="
78         dn_keys = {c[len(dn_key_tag):] for c in comments
79                    if c.startswith(dn_key_tag)}
80
81         # Ignore @ attributes, they are always DN keyed
82         dn_keys_no_at_attrs = {d for d in dn_keys if not d.startswith("@")}
83
84         return dn_keys_no_at_attrs, guid_keys
85
86     # Check that sambadowngradedatabase replaces all GUID keys with DN keys
87     def test_downgrade_database(self):
88         dn_keys, guid_keys = self.ldbdump_keys_pack_formats()
89         self.assertGreater(len(guid_keys), 20)
90         self.assertEqual(len(dn_keys), 0)
91
92         num_guid_keys_before_downgrade = len(guid_keys)
93
94         self.check_run("%s -H %s" % (COMMAND, self.sam_path),
95                        msg="Running sambadowngradedatabase")
96
97         dn_keys, guid_keys = self.ldbdump_keys_pack_formats()
98         self.assertEqual(len(guid_keys), 0)
99         self.assertEqual(len(dn_keys), num_guid_keys_before_downgrade)