summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2015-02-12 11:49:20 -0500
committerSimo Sorce <simo@redhat.com>2015-02-13 18:10:51 -0500
commit0e53d1f95b3bb04f82f9ceefde1ac17484986e4d (patch)
treed6923083b5d633abe8abe39108ebeecd431bb153
parent438dce6a6cb99eb3cc8028dff15cd02b6829e4b0 (diff)
downloadipsilon-0e53d1f95b3bb04f82f9ceefde1ac17484986e4d.tar.gz
ipsilon-0e53d1f95b3bb04f82f9ceefde1ac17484986e4d.tar.xz
ipsilon-0e53d1f95b3bb04f82f9ceefde1ac17484986e4d.zip
Add info plugin that utilizes Apache mod_lookup_identity plugin
mod_look_identity looks up identity information from sssd over dbus, making additional identity attributes available. https://fedorahosted.org/ipsilon/ticket/31 Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
-rw-r--r--contrib/fedora/ipsilon.spec20
-rw-r--r--ipsilon/info/infosssd.py180
2 files changed, 199 insertions, 1 deletions
diff --git a/contrib/fedora/ipsilon.spec b/contrib/fedora/ipsilon.spec
index 4b17aa7..3e0343b 100644
--- a/contrib/fedora/ipsilon.spec
+++ b/contrib/fedora/ipsilon.spec
@@ -2,7 +2,7 @@
Name: ipsilon
Version: 0.3.0
-Release: 5%{?dist}
+Release: 6%{?dist}
Summary: An Identity Provider Server
Group: System Environment/Base
@@ -159,6 +159,19 @@ BuildArch: noarch
%description authldap
Provides a login plugin to allow authentication and info retrieval via LDAP.
+%package infosssd
+Summary: SSSD & mod_lookup_identity-based identity plugin
+Group: System Environment/Base
+License: GPLv3+
+Requires: %{name} = %{version}-%{release}
+Requires: mod_lookup_identity
+Requires: libsss_simpleifp
+Requires; sssd >= 1.12.4
+BuildArch: noarch
+
+%description infosssd
+Provides an info plugin to allow retrieval via mod_lookup_identity and
+SSSD.
%prep
%setup -q
@@ -287,8 +300,13 @@ fi
%{python2_sitelib}/ipsilon/login/authldap*
%{python2_sitelib}/ipsilon/info/infoldap*
+%files infosssd
+%{python2_sitelib}/ipsilon/info/infosssd.*
%changelog
+* Thu Feb 12 2015 Rob Crittenden <rcritten@redhat.com> - 0.3.0-6
+- Add mod_identity_lookup info plugin package
+
* Wed Jan 28 2015 Patrick Uiterwijk <puiterwijk@redhat.com> - 0.3.0-5
- Split IPA tools
diff --git a/ipsilon/info/infosssd.py b/ipsilon/info/infosssd.py
new file mode 100644
index 0000000..b187567
--- /dev/null
+++ b/ipsilon/info/infosssd.py
@@ -0,0 +1,180 @@
+# Copyright (C) 2014 Ipsilon Project Contributors
+#
+# See the file named COPYING for the project license
+
+# Info plugin for mod_lookup_identity Apache module via SSSD
+# http://www.adelton.com/apache/mod_lookup_identity/
+
+from ipsilon.info.common import InfoProviderBase
+from ipsilon.info.common import InfoProviderInstaller
+from ipsilon.info.common import InfoMapping
+from ipsilon.util.plugin import PluginObject
+from string import Template
+import cherrypy
+import time
+import subprocess
+import SSSDConfig
+
+SSSD_CONF = '/etc/sssd/sssd.conf'
+
+# LDAP attributes to tell SSSD to fetch over the InfoPipe
+SSSD_ATTRS = ['mail',
+ 'street',
+ 'locality',
+ 'postalCode',
+ 'telephoneNumber',
+ 'givenname',
+ 'sn']
+
+# Map the mod_lookup_identity env variables to Ipsilon. The inverse of
+# this is in the httpd template.
+sssd_mapping = {
+ 'REMOTE_USER_GECOS': 'fullname',
+ 'REMOTE_USER_EMAIL': 'email',
+ 'REMOTE_USER_FIRSTNAME': 'givenname',
+ 'REMOTE_USER_LASTNAME': 'surname',
+ 'REMOTE_USER_STREET': 'street',
+ 'REMOTE_USER_STATE': 'state',
+ 'REMOTE_USER_POSTALCODE': 'postcode',
+ 'REMOTE_USER_TELEPHONENUMBER': 'phone',
+}
+
+
+class InfoProvider(InfoProviderBase):
+
+ def __init__(self, *pargs):
+ super(InfoProvider, self).__init__(*pargs)
+ self.mapper = InfoMapping()
+ self.mapper.set_mapping(sssd_mapping)
+ self.name = 'sssd'
+ self.new_config(self.name)
+
+ 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_attrs(attrs)
+ reply['userdata'] = userattrs
+ reply['groups'] = groups
+ reply['extras'] = {'sssd': extras}
+
+ except KeyError:
+ pass
+
+ return reply
+
+
+CONF_TEMPLATE = """
+LoadModule lookup_identity_module modules/mod_lookup_identity.so
+
+<Location /${instance}>
+ LookupUserAttr sn REMOTE_USER_LASTNAME
+ LookupUserAttr locality REMOTE_USER_STATE
+ LookupUserAttr street REMOTE_USER_STREET
+ LookupUserAttr telephoneNumber REMOTE_USER_TELEPHONENUMBER
+ LookupUserAttr givenname REMOTE_USER_FIRSTNAME
+ LookupUserAttr mail REMOTE_USER_EMAIL
+ LookupUserAttr postalCode REMOTE_USER_POSTALCODE
+ LookupUserGroupsIter REMOTE_USER_GROUP
+</Location>
+"""
+
+
+class Installer(InfoProviderInstaller):
+
+ def __init__(self, *pargs):
+ super(Installer, self).__init__()
+ self.name = 'sssd'
+ self.pargs = pargs
+
+ def install_args(self, group):
+ group.add_argument('--info-sssd', choices=['yes', 'no'],
+ default='no',
+ help='Use mod_lookup_identity and SSSD to populate'
+ ' user attrs')
+ group.add_argument('--info-sssd-domain', action='store',
+ help='SSSD domain to enable mod_lookup_identity'
+ ' for')
+
+ def configure(self, opts):
+ if opts['info_sssd'] != 'yes':
+ return
+
+ if not opts['info_sssd_domain']:
+ print 'info-identity-domain is required'
+ return False
+
+ confopts = {'instance': opts['instance']}
+
+ tmpl = Template(CONF_TEMPLATE)
+ hunk = tmpl.substitute(**confopts) # pylint: disable=star-args
+ with open(opts['httpd_conf'], 'a') as httpd_conf:
+ httpd_conf.write(hunk)
+
+ try:
+ sssdconfig = SSSDConfig.SSSDConfig()
+ sssdconfig.import_config()
+ except Exception as e: # pylint: disable=broad-except
+ # Unable to read existing SSSD config so it is probably not
+ # configured.
+ print 'Loading SSSD config failed: %s' % e
+ return False
+
+ try:
+ domain = sssdconfig.get_domain(opts['info_sssd_domain'])
+ except SSSDConfig.NoDomainError:
+ print 'No domain %s' % opts['info_sssd_domain']
+ return False
+
+ domain.set_option('ldap_user_extra_attrs', ', '.join(SSSD_ATTRS))
+
+ try:
+ sssdconfig.new_service('ifp')
+ except SSSDConfig.ServiceAlreadyExists:
+ pass
+
+ sssdconfig.activate_service('ifp')
+
+ ifp = sssdconfig.get_service('ifp')
+ ifp.set_option('allowed_uids', 'apache, root')
+ ifp.set_option('user_attributes', '+' + ', +'.join(SSSD_ATTRS))
+
+ sssdconfig.save_service(ifp)
+ sssdconfig.save_domain(domain)
+ sssdconfig.write(SSSD_CONF)
+
+ try:
+ subprocess.call(['/sbin/service', 'sssd', 'restart'])
+ except Exception: # pylint: disable=broad-except
+ pass
+
+ # Give SSSD a chance to restart
+ time.sleep(5)
+
+ # Add configuration data to database
+ po = PluginObject(*self.pargs)
+ po.name = 'sssd'
+ po.wipe_data()
+ po.wipe_config_values()
+
+ # Update global config to add info plugin
+ po.is_enabled = True
+ po.save_enabled_state()