def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(ldap_mapping) self.name = 'ldap' self.description = """ Info plugin that uses LDAP to retrieve user data. """ self.new_config( self.name, pconfig.String('server url', 'The LDAP server url.', 'ldap://example.com'), pconfig.Template('user dn template', 'Template to turn username into DN.', 'uid=%(username)s,ou=People,dc=example,dc=com'), pconfig.Pick('tls', 'What TLS level show be required', ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'], 'Demand'), pconfig.String('bind dn', 'DN to bind as, if empty uses anonymous bind.', 'uid=ipsilon,ou=People,dc=example,dc=com'), pconfig.String('bind password', 'Password to use for bind operation'), pconfig.String('base dn', 'The base dn to look for users and groups', 'dc=example,dc=com'), )
def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(posix_map) self.name = 'nss' self.description = """ Info plugin that uses the system NSS functions to retrieve user data.""" self.new_config(self.name)
def _source_attributes(self, session): policy = Policy(self.cfg.default_attribute_mapping, self.cfg.default_allowed_attributes) userattrs = session.get_user_attrs() mappedattrs, _ = policy.map_attributes(userattrs) attributes = policy.filter_attributes(mappedattrs) self.debug('Filterd attributes: %s' % repr(attributes)) return attributes
def _source_attributes(self, session): policy = Policy(self.cfg.default_attribute_mapping, self.cfg.default_allowed_attributes) userattrs = session.get_user_attrs() if 'email' not in userattrs and self.cfg.default_email_domain: userattrs['email'] = '%s@%s' % (userattrs['username'], self.cfg.default_email_domain) mappedattrs, _ = policy.map_attributes(userattrs) attributes = policy.filter_attributes(mappedattrs) self.debug('Filterd attributes: %s' % repr(attributes)) return attributes
def _source_attributes(self, session): policy = Policy(self.cfg.default_attribute_mapping, self.cfg.default_allowed_attributes) userattrs = session.get_user_attrs() if 'email' not in userattrs and self.cfg.default_email_domain: userattrs['email'] = '%s@%s' % (userattrs['_username'], self.cfg.default_email_domain) mappedattrs, _ = policy.map_attributes(userattrs) attributes = policy.filter_attributes(mappedattrs) self.debug('Filterd attributes: %s' % repr(attributes)) return attributes
def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(sssd_mapping) self.name = 'sssd' self.description = """ Info plugin that uses DBus to retrieve user data from SSSd.""" self.bus = None self.new_config( self.name, pconfig.Condition('preconfigured', 'SSSD can only be used when pre-configured', False), )
def __init__(self, *args): super(InfoProvider, self).__init__(*args) self.mapper = Policy(fasjson_mapping) self.name = 'fasjson' self.description = """ Info plugin that retrieves user data from FASJSON. """ self.new_config( self.name, pconfig.String('FASJSON url', 'The FASJSON Url.', 'http://fasjson.tinystage.test/fasjson/'), )
def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(ldap_mapping) self.name = 'ldap' self.description = """ Info plugin that uses LDAP to retrieve user data. """ self.new_config( self.name, pconfig.String( 'server url', 'The LDAP server url.', 'ldap://example.com'), pconfig.Template( 'user dn template', 'Template to turn username into DN.', 'uid=%(username)s,ou=People,dc=example,dc=com'), pconfig.Pick( 'tls', 'What TLS level show be required', ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'], 'Demand'), pconfig.String( 'bind dn', 'DN to bind as, if empty uses anonymous bind.', 'uid=ipsilon,ou=People,dc=example,dc=com'), pconfig.String( 'bind password', 'Password to use for bind operation'), pconfig.String( 'base dn', 'The base dn to look for users and groups', 'dc=example,dc=com'), )
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(posix_map) self.name = 'nss' self.description = """ Info plugin that uses the system NSS functions to retrieve user data.""" self.new_config(self.name) def _get_posix_user(self, user): p = pwd.getpwnam(user) return { 'username': p.pw_name, 'uidNumber': p.pw_uid, 'gidNumber': p.pw_gid, 'gecos': p.pw_gecos, 'homeDirectory': p.pw_dir, 'loginShell': p.pw_shell } def _get_posix_groups(self, user, group): groups = set() getgrouplist = getattr(os, 'getgrouplist', None) if getgrouplist: ids = getgrouplist(user, group) for i in ids: try: g = grp.getgrgid(i) groups.add(g.gr_name) except KeyError: pass else: g = grp.getgrgid(group) groups.add(g.gr_name) allg = grp.getgrall() for g in allg: if user in g.gr_mem: groups.add(g.gr_name) return list(groups) def get_user_attrs(self, user): reply = dict() try: posix_user = self._get_posix_user(user) userattrs, extras = self.mapper.map_attributes(posix_user) groups = self._get_posix_groups(posix_user['username'], posix_user['gidNumber']) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'posix': extras} except KeyError: pass return reply
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(sssd_mapping) self.name = 'sssd' self.new_config( self.name, pconfig.Condition( 'preconfigured', 'SSSD can only be used when pre-configured', False), ) def _get_user_data(self, user): reply = dict() groups = [] expectgroups = int(cherrypy.request.wsgi_environ.get( 'REMOTE_USER_GROUP_N', 0)) for key in cherrypy.request.wsgi_environ: if key.startswith('REMOTE_USER_'): if key == 'REMOTE_USER_GROUP_N': continue if key.startswith('REMOTE_USER_GROUP_'): groups.append(cherrypy.request.wsgi_environ[key]) else: reply[key] = cherrypy.request.wsgi_environ[key] if len(groups) != expectgroups: self.error('Number of groups expected was not found. Expected' ' %d got %d' % (expectgroups, len(groups))) return reply, groups def get_user_attrs(self, user): reply = dict() try: attrs, groups = self._get_user_data(user) userattrs, extras = self.mapper.map_attributes(attrs) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'sssd': extras} except KeyError: pass return reply def save_plugin_config(self, *args, **kwargs): raise ValueError('Configuration cannot be modified live for SSSD') def get_config_obj(self): return None def enable(self): self.refresh_plugin_config() if not self.get_config_value('preconfigured'): raise Exception("SSSD Can be enabled only if pre-configured") super(InfoProvider, self).enable()
def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(sssd_mapping) self.name = 'sssd' self.new_config( self.name, pconfig.Condition( 'preconfigured', 'SSSD can only be used when pre-configured', False), )
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(posix_map) self.name = 'nss' self.new_config(self.name) def _get_posix_user(self, user): p = pwd.getpwnam(user) return {'username': p.pw_name, 'uidNumber': p.pw_uid, 'gidNumber': p.pw_gid, 'gecos': p.pw_gecos, 'homeDirectory': p.pw_dir, 'loginShell': p.pw_shell} def _get_posix_groups(self, user, group): groups = set() getgrouplist = getattr(os, 'getgrouplist', None) if getgrouplist: ids = getgrouplist(user, group) for i in ids: try: g = grp.getgrgid(i) groups.add(g.gr_name) except KeyError: pass else: g = grp.getgrgid(group) groups.add(g.gr_name) allg = grp.getgrall() for g in allg: if user in g.gr_mem: groups.add(g.gr_name) return list(groups) def get_user_attrs(self, user): reply = dict() try: posix_user = self._get_posix_user(user) userattrs, extras = self.mapper.map_attributes(posix_user) groups = self._get_posix_groups(posix_user['username'], posix_user['gidNumber']) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'posix': extras} except KeyError: pass return reply
class InfoProvider(InfoProviderBase): def __init__(self, *args): super(InfoProvider, self).__init__(*args) self.mapper = Policy(fasjson_mapping) self.name = 'fasjson' self.description = """ Info plugin that retrieves user data from FASJSON. """ self.new_config( self.name, pconfig.String('FASJSON url', 'The FASJSON Url.', 'http://fasjson.tinystage.test/fasjson/'), ) @property def fasjson_url(self): return self.get_config_value('FASJSON url') def get_user_attrs(self, user): try: client = fasjson_client.Client(url=self.fasjson_url) user_data = client.get_user(username=user).result user_group_data = client.list_user_groups(username=user).result user_agreements_data = client.list_user_agreements( username=user).result except Exception as e: self.error(f'FASJSON error: {e}') return # assumption that first email is the default user_data['email'] = user_data['emails'][0] # add the groups to the user_data user_data['groups'] = [g['groupname'] for g in user_group_data] # add the agreements to the user_data user_data['agreements'] = [g['name'] for g in user_agreements_data] userattrs, extras = self.mapper.map_attributes(user_data) self.debug(f'user_data: {user_data}') self.debug(f'Userattrs: {userattrs}') return userattrs
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(sssd_mapping) self.name = 'sssd' self.description = """ Info plugin that uses DBus to retrieve user data from SSSd.""" self.bus = None self.new_config( self.name, pconfig.Condition('preconfigured', 'SSSD can only be used when pre-configured', False), ) def _get_user_data(self, user): reply = dict() groups = [] # Get object for sssd infopipe infosssd_obj = self.bus.get_object('org.freedesktop.sssd.infopipe', '/org/freedesktop/sssd/infopipe') # Get Users object and interface from DBus users_obj = self.bus.get_object( 'org.freedesktop.sssd.infopipe', '/org/freedesktop/sssd/infopipe/Users') users_if = dbus.Interface(users_obj, 'org.freedesktop.sssd.infopipe.Users') # Get path, object, and interface for specific user user_path = users_if.FindByName(user) user_obj = self.bus.get_object('org.freedesktop.sssd.infopipe', user_path) # Get GECOS, attributes, and groups reply['gecos'] = user_obj.Get( 'org.freedesktop.sssd.infopipe.Users.User', 'gecos', dbus_interface=dbus.PROPERTIES_IFACE) user_attrs = user_obj.Get('org.freedesktop.sssd.infopipe.Users.User', 'extraAttributes', dbus_interface=dbus.PROPERTIES_IFACE) user_groups = infosssd_obj.GetUserGroups( user, dbus_interface='org.freedesktop.sssd.infopipe') for group in user_groups: groups.append(group) for attr_name in user_attrs: attr_name = attr_name if len(user_attrs[attr_name]) == 1: reply[attr_name] = user_attrs[attr_name][0] else: reply[attr_name] = [] for attr_val in user_attrs[attr_name]: reply[attr_name].append(attr_val) return reply, groups def get_user_attrs(self, user): reply = dict() try: attrs, groups = self._get_user_data(user) userattrs, extras = self.mapper.map_attributes(attrs) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'sssd': extras} except KeyError: pass return reply def save_plugin_config(self, *args, **kwargs): raise ValueError('Configuration cannot be modified live for SSSD') def get_config_obj(self): return None def enable(self): self.refresh_plugin_config() if not self.get_config_value('preconfigured'): raise Exception("SSSD Can be enabled only if pre-configured") self.bus = dbus.SystemBus() super(InfoProvider, self).enable()
} except ImportError: CLA_GROUPS = dict() fas_mapping = [ ['username', 'nickname'], ['telephone', 'phone'], ['country_code', 'country'], ['human_name', 'fullname'], ['email', 'email'], ['timezone', 'timezone'], ['ssh_key', 'ssh_key'], ['gpg_keyid', 'gpg_keyid'], ] fas_mapper = Policy(fas_mapping) aws_idp_arn = 'arn:aws:iam::125523088429:saml-provider/id.fedoraproject.org' aws_groups = { 'aws-master': 'arn:aws:iam::125523088429:role/aws-master', 'aws-iam': 'arn:aws:iam::125523088429:role/aws-iam', 'aws-billing': 'arn:aws:iam::125523088429:role/aws-billing', 'aws-atomic': 'arn:aws:iam::125523088429:role/aws-atomic', 'aws-s3-readonly': 'arn:aws:iam::125523088429:role/aws-s3-readonly', 'aws-fedoramirror': 'arn:aws:iam::125523088429:role/aws-fedoramirror', 'aws-s3': 'arn:aws:iam::125523088429:role/aws-s3', 'aws-cloud-poc': 'arn:aws:iam::125523088429:role/aws-cloud-poc', 'aws-infra': 'arn:aws:iam::125523088429:role/aws-infra', 'aws-docs': 'arn:aws:iam::125523088429:role/aws-docs', 'aws-copr': 'arn:aws:iam::125523088429:role/aws-copr', }
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(ldap_mapping) self.name = 'ldap' self.description = """ Info plugin that uses LDAP to retrieve user data. """ self.new_config( self.name, pconfig.String('server url', 'The LDAP server url.', 'ldap://example.com'), pconfig.Template('user dn template', 'Template to turn username into DN.', 'uid=%(username)s,ou=People,dc=example,dc=com'), pconfig.Pick('tls', 'What TLS level show be required', ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'], 'Demand'), pconfig.String('bind dn', 'DN to bind as, if empty uses anonymous bind.', 'uid=ipsilon,ou=People,dc=example,dc=com'), pconfig.String('bind password', 'Password to use for bind operation'), pconfig.String('base dn', 'The base dn to look for users and groups', 'dc=example,dc=com'), ) @property def server_url(self): return self.get_config_value('server url') @property def tls(self): return self.get_config_value('tls') @property def bind_dn(self): return self.get_config_value('bind dn') @property def bind_password(self): return self.get_config_value('bind password') @property def user_dn_tmpl(self): return self.get_config_value('user dn template') @property def base_dn(self): return self.get_config_value('base dn') def _ldap_bind(self): tls = self.tls.lower() tls_req_opt = None if tls == "never": tls_req_opt = ldap.OPT_X_TLS_NEVER elif tls == "demand": tls_req_opt = ldap.OPT_X_TLS_DEMAND elif tls == "allow": tls_req_opt = ldap.OPT_X_TLS_ALLOW elif tls == "try": tls_req_opt = ldap.OPT_X_TLS_TRY if tls_req_opt is not None: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_req_opt) conn = ldap.initialize(self.server_url) if tls != "notls": if not self.server_url.startswith("ldaps"): conn.start_tls_s() if ((self.bind_dn is None and self.bind_password is None) or (self.bind_dn == '' and self.bind_password == '')): conn.simple_bind_s() else: conn.simple_bind_s(self.bind_dn, self.bind_password) return conn def _get_user_data(self, conn, dn): result = conn.search_s(dn, ldap.SCOPE_BASE) if result is None or result == []: raise Exception('User object could not be found!') elif len(result) > 1: raise Exception('No unique user object could be found!') data = dict() for name, value in result[0][1].iteritems(): if isinstance(value, list) and len(value) == 1: value = value[0] data[name] = value return data def _get_user_groups(self, conn, base, username): # TODO: fixme to support RFC2307bis schemas results = conn.search_s(base, ldap.SCOPE_SUBTREE, filterstr='memberuid=%s' % username) if results is None or results == []: self.debug('No groups for %s' % username) return [] groups = [] for r in results: if 'cn' in r[1]: groups.append(r[1]['cn'][0]) return groups def get_user_data_from_conn(self, conn, dn, base, username): reply = dict() try: ldapattrs = self._get_user_data(conn, dn) self.debug('LDAP attrs for %s: %s' % (dn, ldapattrs)) userattrs, extras = self.mapper.map_attributes(ldapattrs) groups = self._get_user_groups(conn, base, username) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'ldap': extras} except Exception as e: # pylint: disable=broad-except self.error('Error fetching/mapping LDAP user data: %s' % e) return reply def get_user_attrs(self, user): try: dn = self.user_dn_tmpl % {'username': user} except ValueError as e: self.error('DN generation failed with template %s, user %s: %s' % (self.user_dn_tmpl, user, e)) return {} except Exception as e: # pylint: disable=broad-except self.error('Unhandled error generating DN from %s, user %s: %s' % (self.user_dn_tmpl, user, e)) return {} try: base = self.base_dn conn = self._ldap_bind() return self.get_user_data_from_conn(conn, dn, base, user) except ldap.LDAPError as e: self.error('LDAP search failed for DN %s on base %s: %s' % (dn, base, e)) return {} except Exception as e: # pylint: disable=broad-except self.error('Unhandled LDAP error for DN %s on base %s: %s' % (dn, base, e)) return {}
class InfoProvider(InfoProviderBase): def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(ldap_mapping) self.name = 'ldap' self.description = """ Info plugin that uses LDAP to retrieve user data. """ self.new_config( self.name, pconfig.String( 'server url', 'The LDAP server url.', 'ldap://example.com'), pconfig.Template( 'user dn template', 'Template to turn username into DN.', 'uid=%(username)s,ou=People,dc=example,dc=com'), pconfig.Pick( 'tls', 'What TLS level show be required', ['Demand', 'Allow', 'Try', 'Never', 'NoTLS'], 'Demand'), pconfig.String( 'bind dn', 'DN to bind as, if empty uses anonymous bind.', 'uid=ipsilon,ou=People,dc=example,dc=com'), pconfig.String( 'bind password', 'Password to use for bind operation'), pconfig.String( 'base dn', 'The base dn to look for users and groups', 'dc=example,dc=com'), ) @property def server_url(self): return self.get_config_value('server url') @property def tls(self): return self.get_config_value('tls') @property def bind_dn(self): return self.get_config_value('bind dn') @property def bind_password(self): return self.get_config_value('bind password') @property def user_dn_tmpl(self): return self.get_config_value('user dn template') @property def base_dn(self): return self.get_config_value('base dn') def _ldap_bind(self): tls = self.tls.lower() tls_req_opt = None if tls == "never": tls_req_opt = ldap.OPT_X_TLS_NEVER elif tls == "demand": tls_req_opt = ldap.OPT_X_TLS_DEMAND elif tls == "allow": tls_req_opt = ldap.OPT_X_TLS_ALLOW elif tls == "try": tls_req_opt = ldap.OPT_X_TLS_TRY if tls_req_opt is not None: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, tls_req_opt) conn = ldap.initialize(self.server_url) if tls != "notls": if not self.server_url.startswith("ldaps"): conn.start_tls_s() if ((self.bind_dn is None and self.bind_password is None) or (self.bind_dn == '' and self.bind_password == '')): conn.simple_bind_s() else: conn.simple_bind_s(self.bind_dn, self.bind_password) return conn def _get_user_data(self, conn, dn): result = conn.search_s(dn, ldap.SCOPE_BASE) if result is None or result == []: raise Exception('User object could not be found!') elif len(result) > 1: raise Exception('No unique user object could be found!') data = dict() for name, value in result[0][1].iteritems(): if isinstance(value, list) and len(value) == 1: value = value[0] data[name] = value return data def _get_user_groups(self, conn, base, username): # TODO: fixme to support RFC2307bis schemas results = conn.search_s(base, ldap.SCOPE_SUBTREE, filterstr='memberuid=%s' % username) if results is None or results == []: self.debug('No groups for %s' % username) return [] groups = [] for r in results: if 'cn' in r[1]: groups.append(r[1]['cn'][0]) return groups def get_user_data_from_conn(self, conn, dn, base, username): reply = dict() try: ldapattrs = self._get_user_data(conn, dn) self.debug('LDAP attrs for %s: %s' % (dn, ldapattrs)) userattrs, extras = self.mapper.map_attributes(ldapattrs) groups = self._get_user_groups(conn, base, username) reply = userattrs reply['_groups'] = groups reply['_extras'] = {'ldap': extras} except Exception, e: # pylint: disable=broad-except self.error('Error fetching/mapping LDAP user data: %s' % e) return reply
def saml2checks(self, login): us = UserSession() user = us.get_user() if user.is_anonymous: if self.stage == 'init': returl = '%s/saml2/SSO/Continue?%s' % ( self.basepath, self.trans.get_GET_arg()) data = { 'saml2_stage': 'auth', 'saml2_request': login.dump(), 'login_return': returl, 'login_target': login.remoteProviderId } self.trans.store(data) redirect = '%s/login?%s' % (self.basepath, self.trans.get_GET_arg()) raise cherrypy.HTTPRedirect(redirect) else: raise AuthenticationError("Unknown user", lasso.SAML2_STATUS_CODE_AUTHN_FAILED) self._audit("Logged in user: %s [%s]" % (user.name, user.fullname)) # We can wipe the transaction now, as this is the last step self.trans.wipe() # TODO: check if this is the first time this user access this SP # If required by user prefs, ask user for consent once and then # record it consent = True # TODO: check destination try: provider = ServiceProvider(self.cfg, login.remoteProviderId) nameidfmt = provider.get_valid_nameid(login.request.nameIdPolicy) except NameIdNotAllowed as e: raise AuthenticationError( str(e), lasso.SAML2_STATUS_CODE_INVALID_NAME_ID_POLICY) except InvalidProviderId as e: raise AuthenticationError(str(e), lasso.SAML2_STATUS_CODE_AUTHN_FAILED) # TODO: check login.request.forceAuthn login.validateRequestMsg(not user.is_anonymous, consent) authtime = datetime.datetime.utcnow() skew = datetime.timedelta(0, 60) authtime_notbefore = authtime - skew authtime_notafter = authtime + skew # Let's first do the attribute mapping, so we could map the username # Check attribute policy and perform mapping and filtering. # If the SP has its own mapping or filtering policy use that # instead of the global policy. if (provider.attribute_mappings is not None and len(provider.attribute_mappings) > 0): attribute_mappings = provider.attribute_mappings else: attribute_mappings = self.cfg.default_attribute_mapping if (provider.allowed_attributes is not None and len(provider.allowed_attributes) > 0): allowed_attributes = provider.allowed_attributes else: allowed_attributes = self.cfg.default_allowed_attributes self.debug("Allowed attrs: %s" % allowed_attributes) self.debug("Mapping: %s" % attribute_mappings) policy = Policy(attribute_mappings, allowed_attributes) userattrs = us.get_user_attrs() mappedattrs, _ = policy.map_attributes(userattrs) attributes = policy.filter_attributes(mappedattrs) if '_groups' in attributes and 'groups' not in attributes: attributes['groups'] = attributes['_groups'] self.debug("%s's attributes: %s" % (user.name, attributes)) # Perform authorization check. # We use the raw userattrs here so that we can make decisions based # on attributes we don't want to send to the SP provinfo = { 'name': provider.name, 'url': provider.splink, 'owner': provider.owner } if not self._site['authz'].authorize_user('saml2', provinfo, user.name, userattrs): self.trans.wipe() self.error('Authorization denied by authorization provider') raise AuthenticationError("Authorization denied", lasso.SAML2_STATUS_CODE_AUTHN_FAILED) # TODO: get authentication type fnd name format from session # need to save which login manager authenticated and map it to a # saml2 authentication context authn_context = lasso.SAML2_AUTHN_CONTEXT_UNSPECIFIED timeformat = '%Y-%m-%dT%H:%M:%SZ' login.buildAssertion(authn_context, authtime.strftime(timeformat), None, authtime_notbefore.strftime(timeformat), authtime_notafter.strftime(timeformat)) nameid = None if nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT: idpsalt = self.cfg.idp_nameid_salt if idpsalt is None: raise AuthenticationError( "idp nameid salt is not set in configuration") value = hashlib.sha512() value.update(idpsalt) value.update(login.remoteProviderId) value.update(mappedattrs.get('_username')) nameid = '_' + value.hexdigest() elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT: nameid = '_' + uuid.uuid4().hex elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_KERBEROS: nameid = userattrs.get('gssapi_principal_name') elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_EMAIL: nameid = mappedattrs.get('email') if not nameid: nameid = '%s@%s' % (user.name, self.cfg.default_email_domain) elif nameidfmt == lasso.SAML2_NAME_IDENTIFIER_FORMAT_UNSPECIFIED: nameid = provider.normalize_username(mappedattrs.get('_username')) if nameid: login.assertion.subject.nameId.format = nameidfmt login.assertion.subject.nameId.content = nameid else: self.trans.wipe() self.error('Authentication succeeded but it was not ' + 'provided by NameID %s' % nameidfmt) raise AuthenticationError("Unavailable Name ID type", lasso.SAML2_STATUS_CODE_AUTHN_FAILED) # The saml-core-2.0-os specification section 2.7.3 requires # the AttributeStatement element to be non-empty. if attributes: if not login.assertion.attributeStatement: attrstat = lasso.Saml2AttributeStatement() login.assertion.attributeStatement = [attrstat] else: attrstat = login.assertion.attributeStatement[0] if not attrstat.attribute: attrstat.attribute = () for key in attributes: # skip internal info if key[0] == '_': continue values = attributes[key] if isinstance(values, dict): continue if not isinstance(values, list): values = [values] attr = lasso.Saml2Attribute() attr.name = key attr.nameFormat = lasso.SAML2_ATTRIBUTE_NAME_FORMAT_BASIC attr.attributeValue = [] vals = [] for value in values: if value is None: self.log('Ignoring None value for attribute %s' % key) continue self.debug('value %s' % value) node = lasso.MiscTextNode.newWithString(value) node.textChild = True attrvalue = lasso.Saml2AttributeValue() attrvalue.any = [node] vals.append(attrvalue) attr.attributeValue = vals attrstat.attribute = attrstat.attribute + (attr, ) self.debug('Assertion: %s' % login.assertion.dump()) saml_sessions = self.cfg.idp.sessionfactory lasso_session = lasso.Session() lasso_session.addAssertion(login.remoteProviderId, login.assertion) provider = ServiceProvider(self.cfg, login.remoteProviderId) saml_sessions.add_session(login.assertion.id, login.remoteProviderId, user.name, lasso_session.dump(), None, provider.logout_mechs)
def __init__(self, *pargs): super(InfoProvider, self).__init__(*pargs) self.mapper = Policy(posix_map) self.name = 'nss' self.new_config(self.name)