Commit 0e04e3f8 authored by Lucas Carvalho's avatar Lucas Carvalho

Added a plugin to login using certificate authority.

ERP5CertificateAuthorityAuthenticationPlugin uses the REMOTE_USER
header, to extract the user login information, which is sent by the
apache if the cert and key provided are correct.
parent b92f0e38
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (c) 2011 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
from zLOG import LOG, PROBLEM, WARNING
from Products.ERP5Type.Globals import InitializeClass
from AccessControl import ClassSecurityInfo
import sys
from AccessControl.SecurityManagement import newSecurityManager,\
getSecurityManager, setSecurityManager
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from Products.PluggableAuthService.PluggableAuthService import \
_SWALLOWABLE_PLUGIN_EXCEPTIONS
from Products.PluggableAuthService.interfaces import plugins
from Products.PluggableAuthService.utils import classImplements
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
from Products.ERP5Type.Cache import transactional_cached
from Products.ERP5Security.ERP5UserManager import ERP5UserManager, SUPER_USER
from ZODB.POSException import ConflictError
from Products.PluggableAuthService.PluggableAuthService import DumbHTTPExtractor
from Products.ERP5Security.ERP5GroupManager import ConsistencyError, NO_CACHE_MODE
from Products.ERP5Type.ERP5Type \
import ERP5TYPE_SECURITY_GROUP_ID_GENERATION_SCRIPT
from Products.ERP5Type.Cache import CachingMethod
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
#Form for new plugin in ZMI
manage_addERP5CertificateAuthorityAuthenticationPluginForm = PageTemplateFile(
'www/ERP5Security_addERP5CertificateAuthorityAuthenticationPlugin', globals(),
__name__='manage_addERP5CertificateAuthorityAuthenticationPluginForm')
def addERP5CertificateAuthorityAuthenticationPlugin(dispatcher, id, title=None, REQUEST=None):
""" Add a ERP5CertificateAuthorityAuthenticationPlugin to a Pluggable Auth Service. """
plugin = ERP5CertificateAuthorityAuthenticationPlugin(id, title)
dispatcher._setObject(plugin.getId(), plugin)
if REQUEST is not None:
REQUEST['RESPONSE'].redirect(
'%s/manage_workspace'
'?manage_tabs_message='
'ERP5CertificateAuthorityAuthenticationPlugin+added.'
% dispatcher.absolute_url())
class ERP5CertificateAuthorityAuthenticationPlugin(ERP5UserManager):
"""
Plugin to authenicate as machines.
"""
meta_type = "ERP5 Certificate Authority Authentication Plugin"
security = ClassSecurityInfo()
def __init__(self, id, title=None):
#Register value
self._setId(id)
self.title = title
####################################
#ILoginPasswordHostExtractionPlugin#
####################################
security.declarePrivate('extractCredentials')
def extractCredentials(self, request):
""" Extract credentials from the request header. """
creds = {}
getHeader = getattr(request, 'getHeader', None)
if getHeader is None:
# use get_header instead for Zope-2.8
getHeader = request.get_header
user_id = getHeader('REMOTE_USER')
if user_id is not None:
creds['login'] = user_id
creds['remote_host'] = request.get('REMOTE_HOST', '')
try:
creds['remote_address'] = request.getClientAddr()
except AttributeError:
creds['remote_address'] = request.get('REMOTE_ADDR', '')
return creds
else:
# fallback to default way
return DumbHTTPExtractor().extractCredentials(request)
################################
# IAuthenticationPlugin #
################################
security.declarePrivate('authenticateCredentials')
def authenticateCredentials(self, credentials):
"""Authentificate with credentials"""
login = credentials.get('login', None)
# Forbidden the usage of the super user.
if login == SUPER_USER:
return None
#Search the user by his login
user_list = self.getUserByLogin(login)
if len(user_list) != 1:
return None
return (login, login)
#List implementation of class
classImplements(ERP5CertificateAuthorityAuthenticationPlugin,
plugins.IAuthenticationPlugin)
classImplements( ERP5CertificateAuthorityAuthenticationPlugin,
plugins.ILoginPasswordHostExtractionPlugin
)
InitializeClass(ERP5CertificateAuthorityAuthenticationPlugin)
......@@ -27,6 +27,7 @@ import ERP5RoleManager
import ERP5UserFactory
import ERP5KeyAuthPlugin
import ERP5ExternalAuthenticationPlugin
import ERP5CertificateAuthorityAuthenticationPlugin
def mergedLocalRoles(object):
"""Returns a merging of object and its ancestors'
......@@ -62,6 +63,7 @@ registerMultiPlugin(ERP5RoleManager.ERP5RoleManager.meta_type)
registerMultiPlugin(ERP5UserFactory.ERP5UserFactory.meta_type)
registerMultiPlugin(ERP5KeyAuthPlugin.ERP5KeyAuthPlugin.meta_type)
registerMultiPlugin(ERP5ExternalAuthenticationPlugin.ERP5ExternalAuthenticationPlugin.meta_type)
registerMultiPlugin(ERP5CertificateAuthorityAuthenticationPlugin.ERP5CertificateAuthorityAuthenticationPlugin.meta_type)
def initialize(context):
......@@ -119,6 +121,16 @@ def initialize(context):
, icon='www/portal.gif'
)
context.registerClass( ERP5CertificateAuthorityAuthenticationPlugin.ERP5CertificateAuthorityAuthenticationPlugin
, permission=ManageUsers
, constructors=(
ERP5CertificateAuthorityAuthenticationPlugin.manage_addERP5CertificateAuthorityAuthenticationPluginForm,
ERP5CertificateAuthorityAuthenticationPlugin.addERP5CertificateAuthorityAuthenticationPlugin, )
, visibility=None
, icon='www/portal.gif'
)
from AccessControl.SecurityInfo import ModuleSecurityInfo
ModuleSecurityInfo('Products.ERP5Security.ERP5UserManager').declarePublic(
'getUserByLogin')
......@@ -824,6 +824,42 @@ class TestLocalRoleManagement(ERP5TypeTestCase):
self.assertEqual(response.getStatus(), 200)
self.assertTrue(reference in response.getBody())
def testERP5CertificateAuthorityAuthenticationPlugin(self):
"""
Make sure that we can grant security using a
ERP5 Certificate Authority Authentication Plugin.
"""
portal = self.portal
uf = portal.acl_users
uf.manage_addProduct['ERP5Security'].\
addERP5CertificateAuthorityAuthenticationPlugin(
id='erp5_certificate_authority_authentication_plugin',
title='ERP5 Certificate Authority Authentication Plugin',)
plugin = getattr(uf, 'erp5_certificate_authority_authentication_plugin')
plugin.manage_activateInterfaces(interfaces=['IExtractionPlugin',
'IAuthenticationPlugin'])
self.stepTic()
reference = 'external_auth_person'
loginable_person = self.getPersonModule().newContent(portal_type='Person',
reference=reference,
password='guest')
assignment = loginable_person.newContent(portal_type='Assignment',
function='another_subcat')
assignment.open()
self.stepTic()
base_url = portal.absolute_url(relative=1)
response = self.publish(base_url)
self.assertEqual(response.getStatus(), 302)
response = self.publish(base_url, env={"REMOTE_USER": reference})
self.assertEqual(response.getStatus(), 200)
self.assertTrue(reference in response.getBody())
def _createZodbUser(self, login, role_list=None):
if role_list is None:
role_list = ['Member', 'Assignee', 'Assignor', 'Author', 'Auditor',
......
<h1 tal:replace="structure here/manage_page_header">Header</h1>
<h2 tal:define="form_title string:Add ERP5 Remote Authentication Plugin"
tal:replace="structure here/manage_form_title">Form Title</h2>
<p class="form-help">
ERP5 CertificateAuthority Authentication Plugin allows to login with remote
user.
</p>
<form action="addERP5CertificateAuthorityAuthenticationPlugin" method="post">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Title
</div>
</td>
<td align="left" valign="top">
<input type="text" name="title" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value=" Add " />
</div>
</td>
</tr>
</table>
</form>
<h1 tal:replace="structure here/manage_page_footer">Footer</h1>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment