samba-tool: Some more unifications...
[Samba.git] / source4 / scripting / python / samba / netcmd / spn.py
blob03d072ec9b6a7bd29eead1bd07a1aef1400b0ac7
1 # spn management
3 # Copyright Matthieu Patou mat@samba.org 2010
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
21 from samba import provision
22 from samba.samdb import SamDB
23 from samba.auth import system_session
24 from samba.netcmd.common import _get_user_realm_domain
25 from samba.netcmd import (
26 Command,
27 CommandError,
28 SuperCommand,
29 Option
33 class cmd_spn_list(Command):
34 """List spns of a given user."""
36 synopsis = "%prog <user> [options]"
38 takes_optiongroups = {
39 "sambaopts": options.SambaOptions,
40 "credopts": options.CredentialsOptions,
41 "versionopts": options.VersionOptions,
44 takes_args = ["user"]
46 def run(self, user, credopts=None, sambaopts=None, versionopts=None):
47 lp = sambaopts.get_loadparm()
48 creds = credopts.get_credentials(lp)
49 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
50 sam = SamDB(paths.samdb, session_info=system_session(),
51 credentials=creds, lp=lp)
52 # TODO once I understand how, use the domain info to naildown
53 # to the correct domain
54 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
55 self.outf.write(cleaneduser+"\n")
56 res = sam.search(
57 expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
58 scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
59 if len(res) >0:
60 spns = res[0].get("servicePrincipalName")
61 found = False
62 flag = ldb.FLAG_MOD_ADD
63 if spns is not None:
64 self.outf.write(
65 "User %s has the following servicePrincipalName: \n" %
66 res[0].dn)
67 for e in spns:
68 self.outf.write("\t %s\n" % e)
69 else:
70 self.outf.write("User %s has no servicePrincipalName" %
71 res[0].dn)
72 else:
73 raise CommandError("User %s not found" % user)
76 class cmd_spn_add(Command):
77 """Create a new spn."""
79 synopsis = "%prog <name> <user> [options]"
81 takes_optiongroups = {
82 "sambaopts": options.SambaOptions,
83 "credopts": options.CredentialsOptions,
84 "versionopts": options.VersionOptions,
86 takes_options = [
87 Option("--force", help="Force the addition of the spn"
88 " even it exists already", action="store_true"),
90 takes_args = ["name", "user"]
92 def run(self, name, user, force=False, credopts=None, sambaopts=None,
93 versionopts=None):
94 lp = sambaopts.get_loadparm()
95 creds = credopts.get_credentials(lp)
96 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
97 sam = SamDB(paths.samdb, session_info=system_session(),
98 credentials=creds, lp=lp)
99 res = sam.search(
100 expression="servicePrincipalName=%s" % ldb.binary_encode(name),
101 scope=ldb.SCOPE_SUBTREE)
102 if len(res) != 0 and not force:
103 raise CommandError("Service principal %s already"
104 " affected to another user" % name)
106 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
107 res = sam.search(
108 expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
109 scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
110 if len(res) >0:
111 res[0].dn
112 msg = ldb.Message()
113 spns = res[0].get("servicePrincipalName")
114 tab = []
115 found = False
116 flag = ldb.FLAG_MOD_ADD
117 if spns is not None:
118 for e in spns:
119 if str(e) == name:
120 found = True
121 tab.append(str(e))
122 flag = ldb.FLAG_MOD_REPLACE
123 tab.append(name)
124 msg.dn = res[0].dn
125 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
126 "servicePrincipalName")
127 if not found:
128 sam.modify(msg)
129 else:
130 raise CommandError("Service principal %s already"
131 " affected to %s" % (name, user))
132 else:
133 raise CommandError("User %s not found" % user)
136 class cmd_spn_delete(Command):
137 """Delete a spn."""
139 synopsis = "%prog <name> [user] [options]"
141 takes_optiongroups = {
142 "sambaopts": options.SambaOptions,
143 "credopts": options.CredentialsOptions,
144 "versionopts": options.VersionOptions,
147 takes_args = ["name", "user?"]
149 def run(self, name, user=None, credopts=None, sambaopts=None,
150 versionopts=None):
151 lp = sambaopts.get_loadparm()
152 creds = credopts.get_credentials(lp)
153 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
154 sam = SamDB(paths.samdb, session_info=system_session(),
155 credentials=creds, lp=lp)
156 res = sam.search(
157 expression="servicePrincipalName=%s" % ldb.binary_encode(name),
158 scope=ldb.SCOPE_SUBTREE,
159 attrs=["servicePrincipalName", "samAccountName"])
160 if len(res) >0:
161 result = None
162 if user is not None:
163 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
164 for elem in res:
165 if str(elem["samAccountName"]).lower() == cleaneduser:
166 result = elem
167 if result is None:
168 raise CommandError("Unable to find user %s with"
169 " spn %s" % (user, name))
170 else:
171 if len(res) != 1:
172 listUser = ""
173 for r in res:
174 listUser = "%s\n%s" % (listUser, str(r.dn))
175 raise CommandError("More than one user has the spn %s "
176 "and no specific user was specified, list of users"
177 " with this spn:%s" % (name, listUser))
178 else:
179 result=res[0]
182 msg = ldb.Message()
183 spns = result.get("servicePrincipalName")
184 tab = []
185 if spns is not None:
186 for e in spns:
187 if str(e) != name:
188 tab.append(str(e))
189 flag = ldb.FLAG_MOD_REPLACE
190 msg.dn = result.dn
191 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
192 "servicePrincipalName")
193 sam.modify(msg)
194 else:
195 raise CommandError("Service principal %s not affected" % name)
198 class cmd_spn(SuperCommand):
199 """Service Principal Name (SPN) management."""
201 subcommands = {}
202 subcommands["add"] = cmd_spn_add()
203 subcommands["list"] = cmd_spn_list()
204 subcommands["delete"] = cmd_spn_delete()