s4:kdc: adjust formatting of samba_kdc_update_pac() documentation
[Samba.git] / python / samba / netcmd / ou.py
blob71f61e42ab6e8f9e4d7553a513c70acbba561a08
1 # implement samba-tool ou commands
3 # Copyright Bjoern Baumbach 2018-2019 <bb@samba.org>
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.
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.
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/>.
19 import samba.getopt as options
20 import ldb
22 from samba.auth import system_session
23 from samba.netcmd import (
24 Command,
25 CommandError,
26 Option,
27 SuperCommand,
29 from samba.samdb import SamDB
30 from operator import attrgetter
33 class cmd_rename(Command):
34 """Rename an organizational unit.
36 The name of the organizational units can be specified as a full DN
37 or without the domainDN component.
39 Examples:
40 samba-tool ou rename 'OU=OrgUnit,DC=samdom,DC=example,DC=com' \\
41 'OU=NewNameOfOrgUnit,DC=samdom,DC=example,DC=com'
42 samba-tool ou rename 'OU=OrgUnit' 'OU=NewNameOfOrgUnit'
44 The examples show how an administrator would rename an ou 'OrgUnit'
45 to 'NewNameOfOrgUnit'. The new DN would be
46 'OU=NewNameOfOrgUnit,DC=samdom,DC=example,DC=com'
47 """
49 synopsis = "%prog <old_ou_dn> <new_ou_dn> [options]"
51 takes_options = [
52 Option("-H", "--URL", help="LDB URL for database or target server",
53 type=str, metavar="URL", dest="H"),
56 takes_args = ["old_ou_dn", "new_ou_dn"]
57 takes_optiongroups = {
58 "sambaopts": options.SambaOptions,
59 "credopts": options.CredentialsOptions,
60 "versionopts": options.VersionOptions,
63 def run(self, old_ou_dn, new_ou_dn, credopts=None, sambaopts=None,
64 versionopts=None, H=None):
65 lp = sambaopts.get_loadparm()
66 creds = credopts.get_credentials(lp, fallback_machine=True)
67 samdb = SamDB(url=H, session_info=system_session(),
68 credentials=creds, lp=lp)
70 try:
71 full_old_ou_dn = samdb.normalize_dn_in_domain(old_ou_dn)
72 except Exception as e:
73 raise CommandError('Invalid old_ou_dn "%s": %s' %
74 (old_ou_dn, e))
75 try:
76 full_new_ou_dn = samdb.normalize_dn_in_domain(new_ou_dn)
77 except Exception as e:
78 raise CommandError('Invalid new_ou_dn "%s": %s' %
79 (new_ou_dn, e))
81 try:
82 res = samdb.search(base=full_old_ou_dn,
83 expression="(objectclass=organizationalUnit)",
84 scope=ldb.SCOPE_BASE, attrs=[])
85 if len(res) == 0:
86 self.outf.write('Unable to find ou "%s"\n' % old_ou_dn)
87 return
89 samdb.rename(full_old_ou_dn, full_new_ou_dn)
90 except Exception as e:
91 raise CommandError('Failed to rename ou "%s"' % full_old_ou_dn, e)
92 self.outf.write('Renamed ou "%s" to "%s"\n' % (full_old_ou_dn,
93 full_new_ou_dn))
96 class cmd_move(Command):
97 """Move an organizational unit.
99 The name of the organizational units can be specified as a full DN
100 or without the domainDN component.
102 Examples:
103 samba-tool ou move 'OU=OrgUnit,DC=samdom,DC=example,DC=com' \\
104 'OU=NewParentOfOrgUnit,DC=samdom,DC=example,DC=com'
105 samba-tool ou rename 'OU=OrgUnit' 'OU=NewParentOfOrgUnit'
107 The examples show how an administrator would move an ou 'OrgUnit'
108 into the ou 'NewParentOfOrgUnit'. The ou 'OrgUnit' would become
109 a child of the 'NewParentOfOrgUnit' ou. The new DN would be
110 'OU=OrgUnit,OU=NewParentOfOrgUnit,DC=samdom,DC=example,DC=com'
113 synopsis = "%prog <old_ou_dn> <new_parent_dn> [options]"
115 takes_options = [
116 Option("-H", "--URL", help="LDB URL for database or target server",
117 type=str, metavar="URL", dest="H"),
120 takes_args = ["old_ou_dn", "new_parent_dn"]
121 takes_optiongroups = {
122 "sambaopts": options.SambaOptions,
123 "credopts": options.CredentialsOptions,
124 "versionopts": options.VersionOptions,
127 def run(self, old_ou_dn, new_parent_dn, credopts=None, sambaopts=None,
128 versionopts=None, H=None):
129 lp = sambaopts.get_loadparm()
130 creds = credopts.get_credentials(lp, fallback_machine=True)
131 samdb = SamDB(url=H, session_info=system_session(),
132 credentials=creds, lp=lp)
134 try:
135 full_old_ou_dn = samdb.normalize_dn_in_domain(old_ou_dn)
136 except Exception as e:
137 raise CommandError('Invalid old_ou_dn "%s": %s' %
138 (old_ou_dn, e))
139 try:
140 full_new_parent_dn = samdb.normalize_dn_in_domain(new_parent_dn)
141 except Exception as e:
142 raise CommandError('Invalid new_parent_dn "%s": %s' %
143 (new_parent_dn, e))
145 full_new_ou_dn = ldb.Dn(samdb, str(full_old_ou_dn))
146 full_new_ou_dn.remove_base_components(len(full_old_ou_dn) - 1)
147 full_new_ou_dn.add_base(full_new_parent_dn)
149 try:
150 res = samdb.search(base=full_old_ou_dn,
151 expression="(objectclass=organizationalUnit)",
152 scope=ldb.SCOPE_BASE, attrs=[])
153 if len(res) == 0:
154 self.outf.write('Unable to find ou "%s"\n' % full_old_ou_dn)
155 return
156 samdb.rename(full_old_ou_dn, full_new_ou_dn)
157 except Exception as e:
158 raise CommandError('Failed to move ou "%s"' % full_old_ou_dn, e)
159 self.outf.write('Moved ou "%s" into "%s"\n' %
160 (full_old_ou_dn, full_new_parent_dn))
163 class cmd_add(Command):
164 """Add a new organizational unit.
166 The name of the new ou can be specified as a full DN or without the
167 domainDN component.
169 Examples:
170 samba-tool ou add 'OU=OrgUnit'
171 samba-tool ou add 'OU=SubOU,OU=OrgUnit,DC=samdom,DC=example,DC=com'
173 The examples show how an administrator would add a new ou 'OrgUnit'
174 and a new ou 'SubOU' as a child of the ou 'OrgUnit'.
177 synopsis = "%prog <ou_dn> [options]"
179 takes_options = [
180 Option("-H", "--URL", help="LDB URL for database or target server",
181 type=str, metavar="URL", dest="H"),
182 Option("--description", help="OU's description",
183 type=str, dest="description"),
186 takes_args = ["ou_dn"]
187 takes_optiongroups = {
188 "sambaopts": options.SambaOptions,
189 "credopts": options.CredentialsOptions,
190 "versionopts": options.VersionOptions,
193 def run(self, ou_dn, credopts=None, sambaopts=None, versionopts=None,
194 H=None, description=None):
195 lp = sambaopts.get_loadparm()
196 creds = credopts.get_credentials(lp, fallback_machine=True)
197 samdb = SamDB(url=H, session_info=system_session(),
198 credentials=creds, lp=lp)
200 try:
201 full_ou_dn = samdb.normalize_dn_in_domain(ou_dn)
202 except Exception as e:
203 raise CommandError('Invalid ou_dn "%s": %s' % (ou_dn, e))
205 try:
206 samdb.create_ou(full_ou_dn, description=description)
207 except Exception as e:
208 raise CommandError('Failed to add ou "%s"' % full_ou_dn, e)
210 self.outf.write('Added ou "%s"\n' % full_ou_dn)
213 class cmd_listobjects(Command):
214 """List all objects in an organizational unit.
216 The name of the organizational unit can be specified as a full DN
217 or without the domainDN component.
219 Examples:
220 samba-tool ou listobjects 'OU=OrgUnit,DC=samdom,DC=example,DC=com'
221 samba-tool ou listobjects 'OU=OrgUnit'
223 The examples show how an administrator would list all child objects
224 of the ou 'OrgUnit'.
226 synopsis = "%prog <ou_dn> [options]"
228 takes_options = [
229 Option("-H", "--URL", help="LDB URL for database or target server",
230 type=str, metavar="URL", dest="H"),
231 Option("--full-dn", dest="full_dn", default=False, action='store_true',
232 help="Display DNs including the base DN."),
233 Option("-r", "--recursive", dest="recursive", default=False,
234 action='store_true', help="List objects recursively."),
237 takes_args = ["ou_dn"]
238 takes_optiongroups = {
239 "sambaopts": options.SambaOptions,
240 "credopts": options.CredentialsOptions,
241 "versionopts": options.VersionOptions,
244 def run(self, ou_dn, credopts=None, sambaopts=None, versionopts=None,
245 H=None, full_dn=False, recursive=False):
246 lp = sambaopts.get_loadparm()
247 creds = credopts.get_credentials(lp, fallback_machine=True)
248 samdb = SamDB(url=H, session_info=system_session(),
249 credentials=creds, lp=lp)
250 domain_dn = ldb.Dn(samdb, samdb.domain_dn())
252 try:
253 full_ou_dn = samdb.normalize_dn_in_domain(ou_dn)
254 except Exception as e:
255 raise CommandError('Invalid ou_dn "%s": %s' % (ou_dn, e))
257 minchildren = 0
258 scope = ldb.SCOPE_ONELEVEL
259 if recursive:
260 minchildren = 1
261 scope = ldb.SCOPE_SUBTREE
263 try:
264 children = samdb.search(base=full_ou_dn,
265 expression="(objectclass=*)",
266 scope=scope, attrs=[])
267 if len(children) <= minchildren:
268 self.outf.write('ou "%s" is empty\n' % ou_dn)
269 return
271 for child in sorted(children, key=attrgetter('dn')):
272 if child.dn == full_ou_dn:
273 continue
274 if not full_dn:
275 child.dn.remove_base_components(len(domain_dn))
276 self.outf.write("%s\n" % child.dn)
278 except Exception as e:
279 raise CommandError('Failed to list contents of ou "%s"' %
280 full_ou_dn, e)
283 class cmd_list(Command):
284 """List all organizational units.
286 Example:
287 samba-tool ou listobjects
289 The example shows how an administrator would list all organizational
290 units.
293 synopsis = "%prog [options]"
295 takes_options = [
296 Option("-H", "--URL", help="LDB URL for database or target server",
297 type=str, metavar="URL", dest="H"),
298 Option("-b", "--base-dn",
299 help="Specify base DN to use.",
300 type=str),
301 Option("--full-dn", dest="full_dn", default=False, action='store_true',
302 help="Display DNs including the base DN."),
305 takes_optiongroups = {
306 "sambaopts": options.SambaOptions,
307 "credopts": options.CredentialsOptions,
308 "versionopts": options.VersionOptions,
311 def run(self,
312 sambaopts=None,
313 credopts=None,
314 versionopts=None,
315 H=None,
316 base_dn=None,
317 full_dn=False):
318 lp = sambaopts.get_loadparm()
319 creds = credopts.get_credentials(lp, fallback_machine=True)
320 samdb = SamDB(url=H, session_info=system_session(),
321 credentials=creds, lp=lp)
323 search_dn = ldb.Dn(samdb, samdb.domain_dn())
324 if base_dn:
325 search_dn = samdb.normalize_dn_in_domain(base_dn)
327 res = samdb.search(search_dn,
328 scope=ldb.SCOPE_SUBTREE,
329 expression="(objectClass=organizationalUnit)",
330 attrs=[])
331 if (len(res) == 0):
332 return
334 for msg in sorted(res, key=attrgetter('dn')):
335 if not full_dn:
336 domain_dn = ldb.Dn(samdb, samdb.domain_dn())
337 msg.dn.remove_base_components(len(domain_dn))
338 self.outf.write("%s\n" % str(msg.dn))
341 class cmd_delete(Command):
342 """Delete an organizational unit.
344 The name of the organizational unit can be specified as a full DN
345 or without the domainDN component.
347 Examples:
348 samba-tool ou delete 'OU=OrgUnit,DC=samdom,DC=example,DC=com'
349 samba-tool ou delete 'OU=OrgUnit'
351 The examples show how an administrator would delete the ou 'OrgUnit'.
354 synopsis = "%prog <ou_dn> [options]"
356 takes_options = [
357 Option("-H", "--URL", help="LDB URL for database or target server",
358 type=str, metavar="URL", dest="H"),
359 Option("--force-subtree-delete", dest="force_subtree_delete",
360 default=False, action='store_true',
361 help="Delete organizational unit and all children recursively"),
364 takes_args = ["ou_dn"]
365 takes_optiongroups = {
366 "sambaopts": options.SambaOptions,
367 "credopts": options.CredentialsOptions,
368 "versionopts": options.VersionOptions,
371 def run(self, ou_dn, credopts=None, sambaopts=None, versionopts=None,
372 H=None, force_subtree_delete=False):
373 lp = sambaopts.get_loadparm()
374 creds = credopts.get_credentials(lp, fallback_machine=True)
375 samdb = SamDB(url=H, session_info=system_session(),
376 credentials=creds, lp=lp)
378 try:
379 full_ou_dn = samdb.normalize_dn_in_domain(ou_dn)
380 except Exception as e:
381 raise CommandError('Invalid ou_dn "%s": %s' % (ou_dn, e))
383 controls = []
384 if force_subtree_delete:
385 controls = ["tree_delete:1"]
387 try:
388 res = samdb.search(base=full_ou_dn,
389 expression="(objectclass=organizationalUnit)",
390 scope=ldb.SCOPE_BASE, attrs=[])
391 if len(res) == 0:
392 self.outf.write('Unable to find ou "%s"\n' % ou_dn)
393 return
394 samdb.delete(full_ou_dn, controls)
395 except Exception as e:
396 raise CommandError('Failed to delete ou "%s"' % full_ou_dn, e)
398 self.outf.write('Deleted ou "%s"\n' % full_ou_dn)
401 class cmd_ou(SuperCommand):
402 """Organizational Units (OU) management."""
404 subcommands = {}
405 subcommands["add"] = cmd_add()
406 subcommands["create"] = cmd_add()
407 subcommands["delete"] = cmd_delete()
408 subcommands["move"] = cmd_move()
409 subcommands["rename"] = cmd_rename()
410 subcommands["list"] = cmd_list()
411 subcommands["listobjects"] = cmd_listobjects()