saml2: add extraction of roles from assertions

- Accept syntax xxx::yyy::role name
- Allows to select on a prefix
- Create new ones
- Set allows_backoffice_access attribute if the role path contains
	backoffice as penultimate part.
- Special role named « Admin » set is_admin=True on the user
This commit is contained in:
Benjamin Dauvergne 2013-06-18 12:38:05 +02:00
parent 89b23dd36c
commit 1ce5bb617c
1 changed files with 49 additions and 1 deletions

View File

@ -5,7 +5,9 @@ except ImportError:
from quixote import get_publisher
from qommon import get_cfg, get_logger
from wcs.roles import Role
from qommon import get_cfg
import qommon.saml2
@ -23,10 +25,14 @@ class Saml2Directory(qommon.saml2.Saml2Directory):
return user
d = {}
m = {}
try:
for attribute in assertion.attributeStatement[0].attribute:
try:
d[attribute.name] = attribute.attributeValue[0].any[0].content
for attribute_value in attribute.attributeValue:
l = m.setdefault(attribute.name, [])
l.append(attribute_value.any[0].content)
except IndexError:
pass
except IndexError:
@ -92,6 +98,48 @@ class Saml2Directory(qommon.saml2.Saml2Directory):
if d.get('local-admin') == 'true':
user.is_admin = True
# extract roles from assertion attribute named 'role':
# - to activate add « saml2_use_role = true » to your site-options.cfg fie
# - only role starting with the prefix AuQuo:: will be considered (the
# compare is case-insensitive) the role string will be split on the
# symbol :: and only the last part will be used as the role name
# - if the next to last parts is named backoffice (the compare is
# case-insensitive) the role is given access to the backoffice
# - the role prefix can be changed by setting the saml2_role_prefix key
# in the site-options.cfg
# - the special role named admin (the compare is case-insensitive)
# gives administrator access to the user
if get_publisher().has_site_option('saml2_use_role'):
user_roles = []
roles = Role.values()
role_prefix = get_publisher().get_site_option('saml2_role_prefix') or 'AuQuo::'
is_admin = False
for full_path in m.get('role', []):
role_name_parts = full_path.split('::')
role_name = role_name_parts[-1]
if len(role_name_parts) < 2:
continue
if not full_path.lower().startswith(role_prefix.lower()):
continue
if role_name.lower() == 'admin':
is_admin = True
continue
allows_backoffice_access = len(role_name_parts) > 2 \
and role_name_parts[-2].lower() == 'backoffice'
for role in roles:
if role.name == role_name:
break
else:
role = Role()
role.name = role_name
role.store()
if role.allows_backoffice_access != allows_backoffice_access:
role.allows_backoffice_access = allows_backoffice_access
role.store()
user_roles.append(role.id)
user.is_admin = is_admin
user.roles = user_roles
if not login.nameIdentifier.content in user.name_identifiers:
user.name_identifiers.append(login.nameIdentifier.content)
user.store()