ctdb-scripts: Improve update and listing code
[samba4-gss.git] / python / samba / netcmd / spn.py
blobab79e9ceeab1d1a793317040ec842549f54f132d
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.samdb import SamDB
22 from samba.auth import system_session
23 from samba.netcmd.common import _get_user_realm_domain
24 from samba.netcmd import (
25 Command,
26 CommandError,
27 SuperCommand,
28 Option
32 class cmd_spn_list(Command):
33 """List spns of a given user."""
35 synopsis = "%prog <user> [options]"
37 takes_optiongroups = {
38 "sambaopts": options.SambaOptions,
39 "credopts": options.CredentialsOptions,
40 "versionopts": options.VersionOptions,
42 takes_options = [
43 Option("-H", "--URL", help="LDB URL for database or target server",
44 type=str, metavar="URL", dest="H"),
47 takes_args = ["user"]
49 def run(self, user, H=None,
50 credopts=None,
51 sambaopts=None,
52 versionopts=None):
53 lp = sambaopts.get_loadparm()
54 creds = credopts.get_credentials(lp)
55 sam = SamDB(H, session_info=system_session(),
56 credentials=creds, lp=lp)
57 # TODO once I understand how, use the domain info to naildown
58 # to the correct domain
59 (cleaneduser, realm, domain) = _get_user_realm_domain(user, sam)
60 self.outf.write(cleaneduser + "\n")
61 res = sam.search(
62 expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
63 scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
64 if len(res) > 0:
65 spns = res[0].get("servicePrincipalName")
66 if spns is not None:
67 self.outf.write(
68 "User %s has the following servicePrincipalName: \n" %
69 res[0].dn)
70 for e in spns:
71 self.outf.write("\t %s\n" % e)
72 else:
73 self.outf.write("User %s has no servicePrincipalName\n" %
74 res[0].dn)
75 else:
76 raise CommandError("User %s not found" % user)
79 class cmd_spn_add(Command):
80 """Create a new spn."""
82 synopsis = "%prog <name> <user> [options]"
84 takes_optiongroups = {
85 "sambaopts": options.SambaOptions,
86 "credopts": options.CredentialsOptions,
87 "versionopts": options.VersionOptions,
89 takes_options = [
90 Option("-H", "--URL", help="LDB URL for database or target server",
91 type=str, metavar="URL", dest="H"),
93 takes_args = ["name", "user"]
95 def run(self, name, user, H=None,
96 credopts=None,
97 sambaopts=None,
98 versionopts=None):
99 lp = sambaopts.get_loadparm()
100 creds = credopts.get_credentials(lp)
101 sam = SamDB(H, session_info=system_session(),
102 credentials=creds, lp=lp)
103 res = sam.search(
104 expression="servicePrincipalName=%s" % ldb.binary_encode(name),
105 scope=ldb.SCOPE_SUBTREE)
106 if len(res) != 0:
107 raise CommandError("Service principal %s already"
108 " affected to another user" % name)
110 (cleaneduser, realm, domain) = _get_user_realm_domain(user, sam)
111 res = sam.search(
112 expression="samaccountname=%s" % ldb.binary_encode(cleaneduser),
113 scope=ldb.SCOPE_SUBTREE, attrs=["servicePrincipalName"])
114 if len(res) > 0:
115 res[0].dn
116 msg = ldb.Message()
117 spns = res[0].get("servicePrincipalName")
118 tab = []
119 found = False
120 flag = ldb.FLAG_MOD_ADD
121 if spns is not None:
122 for e in spns:
123 if str(e) == name:
124 found = True
125 tab.append(str(e))
126 flag = ldb.FLAG_MOD_REPLACE
127 tab.append(name)
128 msg.dn = res[0].dn
129 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
130 "servicePrincipalName")
131 if not found:
132 sam.modify(msg)
133 else:
134 raise CommandError("Service principal %s already"
135 " affected to %s" % (name, user))
136 else:
137 raise CommandError("User %s not found" % user)
140 class cmd_spn_delete(Command):
141 """Delete a spn."""
143 synopsis = "%prog <name> [user] [options]"
145 takes_optiongroups = {
146 "sambaopts": options.SambaOptions,
147 "credopts": options.CredentialsOptions,
148 "versionopts": options.VersionOptions,
150 takes_options = [
151 Option("-H", "--URL", help="LDB URL for database or target server",
152 type=str, metavar="URL", dest="H"),
155 takes_args = ["name", "user?"]
157 def run(self, name, user=None, H=None, credopts=None, sambaopts=None,
158 versionopts=None):
159 lp = sambaopts.get_loadparm()
160 creds = credopts.get_credentials(lp)
161 sam = SamDB(H, session_info=system_session(),
162 credentials=creds, lp=lp)
163 res = sam.search(
164 expression="servicePrincipalName=%s" % ldb.binary_encode(name),
165 scope=ldb.SCOPE_SUBTREE,
166 attrs=["servicePrincipalName", "samAccountName"])
167 if len(res) > 0:
168 result = None
169 if user is not None:
170 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
171 for elem in res:
172 if str(elem["samAccountName"]).lower() == cleaneduser:
173 result = elem
174 if result is None:
175 raise CommandError("Unable to find user %s with"
176 " spn %s" % (user, name))
177 else:
178 if len(res) != 1:
179 listUser = ""
180 for r in res:
181 listUser = "%s\n%s" % (listUser, str(r.dn))
182 raise CommandError("More than one user has the spn %s "
183 "and no specific user was specified, list of users"
184 " with this spn:%s" % (name, listUser))
185 else:
186 result = res[0]
188 msg = ldb.Message()
189 spns = result.get("servicePrincipalName")
190 tab = []
191 if spns is not None:
192 for e in spns:
193 if str(e) != name:
194 tab.append(str(e))
195 flag = ldb.FLAG_MOD_REPLACE
196 msg.dn = result.dn
197 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
198 "servicePrincipalName")
199 sam.modify(msg)
200 else:
201 raise CommandError("Service principal %s not affected" % name)
204 class cmd_spn(SuperCommand):
205 """Service Principal Name (SPN) management."""
207 subcommands = {}
208 subcommands["add"] = cmd_spn_add()
209 subcommands["list"] = cmd_spn_list()
210 subcommands["delete"] = cmd_spn_delete()