s4 net: Add spn module to list/add/remove spn on objects
[Samba/gebeck_regimport.git] / source4 / scripting / python / samba / netcmd / spn.py
blobe2eb05d9d2c8c4f32b3d82e0029315792c72c4e8
1 #!/usr/bin/env python
3 # spn management
5 # Copyright Matthieu Patou mat@samba.org 2010
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 import samba.getopt as options
22 import ldb
23 import re
24 from samba import provision
25 from samba.samdb import SamDB
26 from samba.auth import system_session
27 from samba.netcmd import (
28 Command,
29 CommandError,
30 SuperCommand,
31 Option
34 def _get_user_realm_domain(user):
35 """ get the realm or the domain and the base user
36 from user like:
37 * username
38 * DOMAIN\username
39 * username@REALM
40 """
41 baseuser = user
42 realm = ""
43 domain = ""
44 m = re.match(r"(\w+)\\(\w+$)", user)
45 if m:
46 domain = m.group(1)
47 baseuser = m.group(2)
48 return (baseuser.lower(), domain.upper(), realm)
49 m = re.match(r"(\w+)@(\w+)", user)
50 if m:
51 baseuser = m.group(1)
52 realm = m.group(2)
53 return (baseuser.lower(), domain, realm.upper())
55 class cmd_spn_list(Command):
56 """List spns of a given user."""
57 synopsis = "%prog spn list <user>"
59 takes_optiongroups = {
60 "sambaopts": options.SambaOptions,
61 "credopts": options.CredentialsOptions,
62 "versionopts": options.VersionOptions,
65 takes_args = ["user"]
67 def run(self, user, credopts=None, sambaopts=None, versionopts=None):
68 lp = sambaopts.get_loadparm()
69 creds = credopts.get_credentials(lp)
70 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
71 sam = SamDB(paths.samdb, session_info=system_session(),
72 credentials=creds, lp=lp)
73 # TODO once I understand how, use the domain info to naildown
74 # to the correct domain
75 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
76 print cleaneduser
77 res = sam.search(expression="samaccountname=%s" % cleaneduser,
78 scope=ldb.SCOPE_SUBTREE,
79 attrs=["servicePrincipalName"])
80 if len(res) >0:
81 spns = res[0].get("servicePrincipalName")
82 found = False
83 flag = ldb.FLAG_MOD_ADD
84 if spns != None:
85 print "User %s has the following servicePrincipalName: " % str(res[0].dn)
86 for e in spns:
87 print "\t %s" % (str(e))
89 else:
90 print "User %s has no servicePrincipalName" % str(res[0].dn)
91 else:
92 raise CommandError("User %s not found" % user)
94 class cmd_spn_add(Command):
95 """Create a new spn."""
96 synopsis = "%prog spn add [--force] <name> <user>"
98 takes_optiongroups = {
99 "sambaopts": options.SambaOptions,
100 "credopts": options.CredentialsOptions,
101 "versionopts": options.VersionOptions,
103 takes_options = [
104 Option("--force", help="Force the addition of the spn"\
105 " even it exists already", action="store_true"),
107 takes_args = ["name", "user"]
109 def run(self, name, user, force=False, credopts=None, sambaopts=None, versionopts=None):
110 lp = sambaopts.get_loadparm()
111 creds = credopts.get_credentials(lp)
112 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
113 sam = SamDB(paths.samdb, session_info=system_session(),
114 credentials=creds, lp=lp)
115 res = sam.search(expression="servicePrincipalName=%s" % name,
116 scope=ldb.SCOPE_SUBTREE,
118 if len(res) != 0 and not force:
119 raise CommandError("Service principal %s already"
120 " affected to another user" % name)
122 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
123 res = sam.search(expression="samaccountname=%s" % cleaneduser,
124 scope=ldb.SCOPE_SUBTREE,
125 attrs=["servicePrincipalName"])
126 if len(res) >0:
127 res[0].dn
128 msg = ldb.Message()
129 spns = res[0].get("servicePrincipalName")
130 tab = []
131 found = False
132 flag = ldb.FLAG_MOD_ADD
133 if spns != None:
134 for e in spns:
135 if str(e) == name:
136 found = True
137 tab.append(str(e))
138 flag = ldb.FLAG_MOD_REPLACE
139 tab.append(name)
140 msg.dn = res[0].dn
141 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
142 "servicePrincipalName")
143 if not found:
144 sam.modify(msg)
145 else:
146 raise CommandError("Service principal %s already"
147 " affected to %s" % (name, user))
148 else:
149 raise CommandError("User %s not found" % user)
152 class cmd_spn_delete(Command):
153 """Delete a spn."""
154 synopsis = "%prog spn delete <name> [user]"
156 takes_optiongroups = {
157 "sambaopts": options.SambaOptions,
158 "credopts": options.CredentialsOptions,
159 "versionopts": options.VersionOptions,
162 takes_args = ["name", "user?"]
164 def run(self, name, user=None, credopts=None, sambaopts=None, versionopts=None):
165 lp = sambaopts.get_loadparm()
166 creds = credopts.get_credentials(lp)
167 paths = provision.provision_paths_from_lp(lp, lp.get("realm"))
168 sam = SamDB(paths.samdb, session_info=system_session(),
169 credentials=creds, lp=lp)
170 res = sam.search(expression="servicePrincipalName=%s" % name,
171 scope=ldb.SCOPE_SUBTREE,
172 attrs=["servicePrincipalName", "samAccountName"])
173 if len(res) >0:
174 result = None
175 if user is not None:
176 (cleaneduser, realm, domain) = _get_user_realm_domain(user)
177 for elem in res:
178 if str(elem["samAccountName"]).lower() == cleaneduser:
179 result = elem
180 if result is None:
181 raise CommandError("Unable to find user %s with"
182 " spn %s" % (user, name))
183 else:
184 if len(res) != 1:
185 listUser = ""
186 for r in res:
187 listUser = "%s\n%s" % (listUser, str(r.dn))
188 raise CommandError("More than one user has the spn %s "\
189 "and no specific user was specified, list of users"\
190 " with this spn:%s" % (name, listUser))
191 else:
192 result=res[0]
195 msg = ldb.Message()
196 spns = result.get("servicePrincipalName")
197 tab = []
198 if spns != None:
199 for e in spns:
200 if str(e) != name:
201 tab.append(str(e))
202 flag = ldb.FLAG_MOD_REPLACE
203 msg.dn = result.dn
204 msg["servicePrincipalName"] = ldb.MessageElement(tab, flag,
205 "servicePrincipalName")
206 sam.modify(msg)
207 else:
208 raise CommandError("Service principal %s not affected" % name)
210 class cmd_spn(SuperCommand):
211 """User management [server connection needed]"""
213 subcommands = {}
214 subcommands["add"] = cmd_spn_add()
215 subcommands["list"] = cmd_spn_list()
216 subcommands["delete"] = cmd_spn_delete()