ldb: Free memory when repacking database
[garming/samba-autobuild/.git] / python / samba / tests / samba_tool / ou.py
1 # Unix SMB/CIFS implementation.
2 #
3 # Copyright (C) Bjoern Baumbach <bb@sernet.de> 2018
4 #
5 # based on group.py:
6 # Copyright (C) Michael Adam 2012
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21
22 import os
23 import ldb
24 from samba.tests.samba_tool.base import SambaToolCmdTest
25
26
27 class OUCmdTestCase(SambaToolCmdTest):
28     """Tests for samba-tool ou subcommands"""
29     ous = []
30     samdb = None
31
32     def setUp(self):
33         super(OUCmdTestCase, self).setUp()
34         self.samdb = self.getSamDB("-H", "ldap://%s" % os.environ["DC_SERVER"],
35                                    "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
36         self.ous = []
37         self.ous.append(self._randomOU({"name": "testou1"}))
38         self.ous.append(self._randomOU({"name": "testou2"}))
39         self.ous.append(self._randomOU({"name": "testou3"}))
40         self.ous.append(self._randomOU({"name": "testou4"}))
41
42         # setup the 4 ous and ensure they are correct
43         for ou in self.ous:
44             (result, out, err) = self._create_ou(ou)
45
46             self.assertCmdSuccess(result, out, err)
47             self.assertEquals(err, "", "There shouldn't be any error message")
48             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
49             self.assertIn('Created ou "%s"' % full_ou_dn, out)
50
51             found = self._find_ou(ou["name"])
52
53             self.assertIsNotNone(found)
54
55             self.assertEquals("%s" % found.get("name"), ou["name"])
56             self.assertEquals("%s" % found.get("description"),
57                               ou["description"])
58
59     def tearDown(self):
60         super(OUCmdTestCase, self).tearDown()
61         # clean up all the left over ous, just in case
62         for ou in self.ous:
63             if self._find_ou(ou["name"]):
64                 (result, out, err) = self.runsubcmd("ou", "delete",
65                                                     "OU=%s" % ou["name"])
66                 self.assertCmdSuccess(result, out, err,
67                                       "Failed to delete ou '%s'" % ou["name"])
68
69     def test_newou(self):
70         """This tests the "ou create" and "ou delete" commands"""
71         # try to create all the ous again, this should fail
72         for ou in self.ous:
73             (result, out, err) = self._create_ou(ou)
74             self.assertCmdFail(result, "Succeeded to create existing ou")
75             self.assertIn("already exists", err)
76
77         # try to delete all the ous we just created
78         for ou in self.ous:
79             (result, out, err) = self.runsubcmd("ou", "delete", "OU=%s" %
80                                                 ou["name"])
81             self.assertCmdSuccess(result, out, err,
82                                   "Failed to delete ou '%s'" % ou["name"])
83             found = self._find_ou(ou["name"])
84             self.assertIsNone(found,
85                               "Deleted ou '%s' still exists" % ou["name"])
86
87         # test creating ous
88         for ou in self.ous:
89             (result, out, err) = self.runsubcmd(
90                 "ou", "create", "OU=%s" % ou["name"],
91                 "--description=%s" % ou["description"])
92
93             self.assertCmdSuccess(result, out, err)
94             self.assertEquals(err, "", "There shouldn't be any error message")
95             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
96             self.assertIn('Created ou "%s"' % full_ou_dn, out)
97
98             found = self._find_ou(ou["name"])
99
100             self.assertEquals("%s" % found.get("ou"),
101                               "%s" % ou["name"])
102
103         # try to delete all the ous we just created (with full dn)
104         for ou in self.ous:
105             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
106             (result, out, err) = self.runsubcmd("ou", "delete", str(full_ou_dn))
107             self.assertCmdSuccess(result, out, err,
108                                   "Failed to delete ou '%s'" % ou["name"])
109             found = self._find_ou(ou["name"])
110             self.assertIsNone(found,
111                               "Deleted ou '%s' still exists" % ou["name"])
112
113         # test creating ous (with full dn)
114         for ou in self.ous:
115             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
116             (result, out, err) = self.runsubcmd(
117                 "ou", "create", str(full_ou_dn),
118                 "--description=%s" % ou["description"])
119
120             self.assertCmdSuccess(result, out, err)
121             self.assertEquals(err, "", "There shouldn't be any error message")
122             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
123             self.assertIn('Created ou "%s"' % full_ou_dn, out)
124
125             found = self._find_ou(ou["name"])
126
127             self.assertEquals("%s" % found.get("ou"),
128                               "%s" % ou["name"])
129
130     def test_list(self):
131         (result, out, err) = self.runsubcmd("ou", "list")
132         self.assertCmdSuccess(result, out, err, "Error running list")
133
134         search_filter = "(objectClass=organizationalUnit)"
135
136         oulist = self.samdb.search(base=self.samdb.domain_dn(),
137                                    scope=ldb.SCOPE_SUBTREE,
138                                    expression=search_filter,
139                                    attrs=["name"])
140
141         self.assertTrue(len(oulist) > 0, "no ous found in samdb")
142
143         for ouobj in oulist:
144             name = ouobj.get("name", idx=0)
145             found = self.assertMatch(out, str(name),
146                                      "ou '%s' not found" % name)
147
148     def test_rename(self):
149         for ou in self.ous:
150             ousuffix = "RenameTest"
151             newouname = ou["name"] + ousuffix
152             (result, out, err) = self.runsubcmd("ou", "rename",
153                                                 "OU=%s" % ou["name"],
154                                                 "OU=%s" % newouname)
155             self.assertCmdSuccess(result, out, err,
156                                   "Failed to rename ou '%s'" % ou["name"])
157             found = self._find_ou(ou["name"])
158             self.assertIsNone(found,
159                               "Renamed ou '%s' still exists" % ou["name"])
160             found = self._find_ou(newouname)
161             self.assertIsNotNone(found,
162                                  "Renamed ou '%s' does not exist" % newouname)
163
164             (result, out, err) = self.runsubcmd("ou", "rename",
165                                                 "OU=%s" % newouname,
166                                                 "OU=%s" % ou["name"])
167             self.assertCmdSuccess(result, out, err,
168                                   "Failed to rename ou '%s'" % newouname)
169
170     def test_move(self):
171         parentou = self._randomOU({"name": "parentOU"})
172         (result, out, err) = self._create_ou(parentou)
173         self.assertCmdSuccess(result, out, err)
174
175         for ou in self.ous:
176             olddn = self._find_ou(ou["name"]).get("dn")
177
178             (result, out, err) = self.runsubcmd("ou", "move",
179                                                 "OU=%s" % ou["name"],
180                                                 "OU=%s" % parentou["name"])
181             self.assertCmdSuccess(result, out, err,
182                                   "Failed to move ou '%s'" % ou["name"])
183             self.assertEquals(err, "", "There shouldn't be any error message")
184             full_ou_dn = self.samdb.normalize_dn_in_domain("OU=%s" % ou["name"])
185             self.assertIn('Moved ou "%s"' % full_ou_dn, out)
186
187             found = self._find_ou(ou["name"])
188             self.assertNotEquals(found.get("dn"), olddn,
189                                  "Moved ou '%s' still exists with the same dn" %
190                                  ou["name"])
191             newexpecteddn = ldb.Dn(self.samdb,
192                                    "OU=%s,OU=%s,%s" %
193                                    (ou["name"], parentou["name"],
194                                     self.samdb.domain_dn()))
195             self.assertEquals(found.get("dn"), newexpecteddn,
196                               "Moved ou '%s' does not exist" %
197                               ou["name"])
198
199             (result, out, err) = self.runsubcmd("ou", "move",
200                                                 "%s" % newexpecteddn,
201                                                 "%s" % olddn.parent())
202             self.assertCmdSuccess(result, out, err,
203                                   "Failed to move ou '%s'" % ou["name"])
204
205         (result, out, err) = self.runsubcmd("ou", "delete",
206                                             "OU=%s" % parentou["name"])
207         self.assertCmdSuccess(result, out, err,
208                               "Failed to delete ou '%s'" % parentou["name"])
209
210     def test_listobjects(self):
211         (result, out, err) = self.runsubcmd("ou", "listobjects",
212                                             "%s" % self.samdb.domain_dn(),
213                                             "--full-dn")
214         self.assertCmdSuccess(result, out, err,
215                               "Failed to list ou's objects")
216         self.assertEquals(err, "", "There shouldn't be any error message")
217
218         objlist = self.samdb.search(base=self.samdb.domain_dn(),
219                                     scope=ldb.SCOPE_ONELEVEL,
220                                     attrs=[])
221         self.assertTrue(len(objlist) > 0, "no objects found")
222
223         for obj in objlist:
224             found = self.assertMatch(out, str(obj.dn),
225                                      "object '%s' not found" % obj.dn)
226
227     def test_list_full_dn(self):
228         (result, out, err) = self.runsubcmd("ou", "list",
229                                             "--full-dn")
230         self.assertCmdSuccess(result, out, err,
231                               "Failed to list ous")
232         self.assertEquals(err, "", "There shouldn't be any error message")
233
234         filter = "(objectClass=organizationalUnit)"
235         objlist = self.samdb.search(base=self.samdb.domain_dn(),
236                                     scope=ldb.SCOPE_SUBTREE,
237                                     expression=filter,
238                                     attrs=[])
239         self.assertTrue(len(objlist) > 0, "no ou objects found")
240
241         for obj in objlist:
242             found = self.assertMatch(out, str(obj.dn),
243                                      "object '%s' not found" % obj.dn)
244
245     def _randomOU(self, base={}):
246         """create an ou with random attribute values, you can specify base
247         attributes"""
248
249         ou = {
250             "name": self.randomName(),
251             "description": self.randomName(count=100),
252         }
253         ou.update(base)
254         return ou
255
256     def _create_ou(self, ou):
257         return self.runsubcmd("ou", "create", "OU=%s" % ou["name"],
258                               "--description=%s" % ou["description"])
259
260     def _find_ou(self, name):
261         search_filter = ("(&(name=%s)(objectCategory=%s,%s))" %
262                          (ldb.binary_encode(name),
263                           "CN=Organizational-Unit,CN=Schema,CN=Configuration",
264                           self.samdb.domain_dn()))
265         oulist = self.samdb.search(base=self.samdb.domain_dn(),
266                                    scope=ldb.SCOPE_SUBTREE,
267                                    expression=search_filter)
268         if oulist:
269             return oulist[0]
270         else:
271             return None