Package omero :: Package plugins :: Module ldap
[hide private]
[frames] | no frames]

Source Code for Module omero.plugins.ldap

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  """ 
  4     User administration plugin (LDAP extension) 
  5   
  6     Copyright 2011 Glencoe Software, Inc. All rights reserved. 
  7     Use is subject to license terms supplied in LICENSE.txt 
  8   
  9  """ 
 10   
 11  import sys 
 12   
 13  from omero.cli import BaseControl, CLI, ExceptionHandler 
 14   
 15  HELP = """Administrative support for managing users' LDAP settings 
 16   
 17  Most of these commands should be run as an OMERO administrator such as root. 
 18   
 19  Examples: 
 20   
 21    bin/omero login root 
 22    bin/omero ldap active 
 23    bin/omero ldap active     || echo "Not active!" 
 24    bin/omero ldap list 
 25    bin/omero ldap getdn jack 
 26    bin/omero ldap getdn beth || echo "No DN" 
 27    bin/omero ldap setdn jack uid=me,ou=example,o=com 
 28    bin/omero ldap setdn jack ""                        # Disables LDAP login. 
 29    bin/omero ldap discover --commands                  # Requires "ldap" module 
 30   
 31  """ 
 32   
 33   
34 -class LdapControl(BaseControl):
35
36 - def _configure(self, parser):
37 38 self.exc = ExceptionHandler() 39 40 sub = parser.sub() 41 42 active = parser.add( 43 sub, self.active, 44 help="Return code shows if LDAP is configured (admins-only)") 45 46 list = parser.add( 47 sub, self.list, 48 help="List all OMERO users with DNs") 49 50 getdn = parser.add(sub, self.getdn, help="Get DN for user on stdout") 51 setdn = parser.add( 52 sub, self.setdn, 53 help="""Set DN for user (admins only) 54 55 Once the DN is set for a user, the password set via OMERO is 56 ignored, and any attempt to change it will result in an error. When 57 you remove the DN, the previous password will be in effect, but if the 58 user never had a password, one will need to be set!""") 59 60 for x in (getdn, setdn): 61 x.add_argument("username", help="User's OMERO login name") 62 setdn.add_argument( 63 "dn", help="User's LDAP distinguished name. If empty, LDAP will" 64 " be disabled for the user") 65 66 discover = parser.add( 67 sub, self.discover, 68 help="Discover distinguished names for existing OMERO users") 69 discover.add_argument( 70 "--commands", action="store_true", default=False, 71 help="Print setdn commands on standard out") 72 discover.add_argument( 73 "--urls", help="Override OMERO omero.ldap.urls setting") 74 discover.add_argument( 75 "--base", help="Override OMERO omero.ldap.base setting") 76 77 for x in (active, list, getdn, setdn, discover): 78 x.add_login_arguments()
79
80 - def __import_ldap__(self):
81 try: 82 import ldap 83 except: 84 self.ctx.die(155, """Python "ldap" module is not installed""") 85 return ldap
86
87 - def active(self, args):
88 c = self.ctx.conn(args) 89 ildap = c.sf.getLdapService() 90 91 import omero 92 try: 93 if ildap.getSetting(): 94 self.ctx.out("Yes") 95 else: 96 self.ctx.die(1, "No") 97 except omero.SecurityViolation: 98 self.ctx.die(111, "SecurityViolation: Admins only!")
99
100 - def list(self, args):
101 c = self.ctx.conn(args) 102 iadmin = c.sf.getAdminService() 103 104 import omero 105 from omero.rtypes import unwrap 106 from omero.util.text import TableBuilder 107 try: 108 109 list_of_dn_user_maps = unwrap(iadmin.lookupLdapAuthExperimenters()) 110 if list_of_dn_user_maps is None: 111 return 112 113 count = 0 114 tb = TableBuilder("#") 115 tb.cols(["Id", "OmeName", "DN"]) 116 for map in list_of_dn_user_maps: 117 for dn, id in map.items(): 118 try: 119 exp = iadmin.getExperimenter(id) 120 except: 121 self.ctx.err("Bad experimenter: %s" % id) 122 123 tb.row(count, *(id, exp.omeName.val, dn)) 124 count += 1 125 self.ctx.out(str(tb.build())) 126 127 except omero.SecurityViolation: 128 self.ctx.die(131, 129 "SecurityViolation: Must be an admin to lists DNs")
130
131 - def getdn(self, args):
132 c = self.ctx.conn(args) 133 iadmin = c.sf.getAdminService() 134 135 try: 136 exp = iadmin.lookupExperimenter(args.username) 137 except: 138 self.ctx.die(134, "Unknown user: %s" % args.username) 139 140 dn = iadmin.lookupLdapAuthExperimenter(exp.id.val) 141 if dn is not None and dn.strip(): 142 self.ctx.out(dn) 143 else: 144 self.ctx.die(136, "DN Not found: %s" % dn)
145
146 - def setdn(self, args):
147 c = self.ctx.conn(args) 148 ildap = c.sf.getLdapService() 149 iadmin = c.sf.getAdminService() 150 151 try: 152 exp = iadmin.lookupExperimenter(args.username) 153 except: 154 self.ctx.die(134, "Unknown user: %s" % args.username) 155 156 import omero 157 try: 158 ildap.setDN(exp.id, args.dn) 159 except omero.SecurityViolation: 160 self.ctx.die(135, "SecurityViolation: Admins only!")
161
162 - def discover(self, args):
163 164 import omero 165 ldap = self.__import_ldap__() 166 167 c = self.ctx.conn(args) 168 iconfig = c.sf.getConfigService() 169 iadmin = c.sf.getAdminService() 170 iquery = c.sf.getQueryService() 171 172 LDAP_PROPERTIES = """ 173 omero.ldap.urls 174 omero.ldap.username 175 omero.ldap.password 176 omero.ldap.base 177 omero.ldap.user_filter 178 omero.ldap.user_mapping 179 omero.ldap.group_filter 180 omero.ldap.group_mapping 181 omero.ldap.new_user_group 182 """.split() 183 184 cfg = dict() 185 for key in LDAP_PROPERTIES: 186 cfg[key.split(".")[-1]] = iconfig.getConfigValue(key) 187 188 urls = args.urls and args.urls or cfg["urls"] 189 basedn = args.base and args.base or cfg["base"] 190 191 for url in urls.split(","): 192 193 self.ctx.err("Connecting to %s..." % url) 194 195 ld = ldap.initialize(url) 196 ld.simple_bind_s(cfg['username'], cfg['password']) 197 198 user_filter = cfg["user_filter"] 199 user_mapping = cfg["user_mapping"] 200 user_mapping = user_mapping.split(",") 201 omeName_mapping = None 202 for um in user_mapping: 203 parts = um.split("=") 204 if parts[0] == "omeName": 205 omeName_mapping = parts[1] 206 207 from ldap.controls import SimplePagedResultsControl 208 209 cookie = '' 210 # This is the limit for Active Directory, 1000. However 211 # the LDAP connection has a sizeLimit that overrides 212 # this value if the page_size exceeds it so it is safe 213 # to enter pretty much anything here when using paged results. 214 page_size = 1000 215 216 results = [] 217 first = True 218 page_control = SimplePagedResultsControl(False, page_size, cookie) 219 220 while first or page_control.cookie: 221 first = False 222 try: 223 msgid = ld.search_ext( 224 basedn, ldap.SCOPE_SUBTREE, 225 user_filter, serverctrls=[page_control] 226 ) 227 except: 228 self.ctx.die(1, "Failed to execute LDAP search") 229 230 result_type, results, msgid, serverctrls = ld.result3(msgid) 231 if serverctrls: 232 page_control.cookie = serverctrls[0].cookie 233 234 user_names = set() 235 user_dns = {} 236 for dn, entry in results: 237 omeName = entry[omeName_mapping] 238 if isinstance(omeName, (list, tuple)): 239 if len(omeName) == 1: 240 omeName = omeName[0] 241 user_names.add(omeName) 242 user_dns[omeName] = dn 243 else: 244 self.ctx.err("Failed to unwrap omeName: %s" % 245 omeName) 246 continue 247 248 if not user_names: 249 continue # Early exit! 250 251 from omero.rtypes import rlist 252 from omero.rtypes import rstring 253 from omero.rtypes import unwrap 254 params = omero.sys.ParametersI() 255 params.add("names", rlist([rstring(x) for x in user_names])) 256 id_names = unwrap(iquery.projection( 257 "select id, omeName from Experimenter " 258 "where omeName in (:names)", params)) 259 260 for eid, omeName in id_names: 261 try: 262 olddn = iadmin.lookupLdapAuthExperimenter(eid) 263 dn = user_dns[omeName] 264 except omero.ApiUsageException: 265 continue # Unknown user 266 267 if olddn: 268 if olddn.lower() != dn.lower(): 269 self.ctx.err("Found different DN for %s: %s" 270 % (omeName, olddn)) 271 else: 272 self.ctx.dbg("DN already set for %s: %s" 273 % (omeName, olddn)) 274 else: 275 if args.commands: 276 self.ctx.out("%s ldap setdn %s %s" 277 % (sys.argv[0], omeName, dn)) 278 else: 279 self.ctx.out("Experimenter:%s\tomeName=%s\t%s" 280 % (eid, omeName, dn))
281 282 try: 283 register("ldap", LdapControl, HELP) 284 except NameError: 285 if __name__ == "__main__": 286 cli = CLI() 287 cli.register("ldap", LdapControl, HELP) 288 cli.invoke(sys.argv[1:]) 289