django-mellon/mellon/utils.py

114 lines
3.5 KiB
Python
Raw Normal View History

2014-04-28 14:33:04 +02:00
import re
import time
import datetime
import importlib
from functools import wraps
from xml.etree import ElementTree as ET
from django.core.urlresolvers import reverse
from django.template.loader import render_to_string
import lasso
from . import app_settings
METADATA = {}
def create_metadata(request):
entity_id = reverse('mellon_metadata')
if entity_id not in METADATA:
login_url = reverse('mellon_login')
logout_url = reverse('mellon_logout')
public_keys = []
for public_key in app_settings.PUBLIC_KEYS:
if public_key.startswith('/'):
public_key = file(public_key).read()
public_keys.append(public_key)
name_id_formats = app_settings.NAME_ID_FORMATS
return render_to_string('mellon/metadata.xml', {
'entity_id': request.build_absolute_uri(entity_id),
'login_url': request.build_absolute_uri(login_url),
'logout_url': request.build_absolute_uri(logout_url),
'public_keys': public_keys,
'name_id_formats': name_id_formats,
})
return METADATA[entity_id]
SERVERS = {}
def create_server(request):
root = request.build_absolute_uri('/')
if root not in SERVERS:
idps = app_settings.IDENTITY_PROVIDERS
metadata = create_metadata(request)
server = lasso.Server.newFromBuffers(metadata,
private_key_content=app_settings.PRIVATE_KEY,
private_key_password=app_settings.PRIVATE_KEY_PASSWORD)
for idp in idps:
metadata = idp['METADATA']
if metadata.startswith('/'):
metadata = file(metadata).read()
idp['ENTITY_ID'] = ET.fromstring(metadata).attrib['entityID']
server.addProviderFromBuffer(lasso.PROVIDER_ROLE_IDP, metadata)
SERVERS[root] = server
return SERVERS[root]
def create_login(request):
server = create_server(request)
login = lasso.Login(server)
if not app_settings.PRIVATE_KEY:
login.setSignatureHint(lasso.PROFILE_SIGNATURE_HINT_FORBID)
return login
def get_idp(entity_id):
for idp in app_settings.IDENTITY_PROVIDERS:
if idp['ENTITY_ID'] == entity_id:
return idp
def flatten_datetime(d):
for key, value in d.iteritems():
if isinstance(value, datetime.datetime):
d[key] = value.isoformat() + 'Z'
return d
def iso8601_to_datetime(date_string):
'''Convert a string formatted as an ISO8601 date into a time_t
value.
This function ignores the sub-second resolution'''
m = re.match(r'(\d+-\d+-\d+T\d+:\d+:\d+)(?:\.\d+)?Z$', date_string)
if not m:
raise ValueError('Invalid ISO8601 date')
tm = time.strptime(m.group(1)+'Z', "%Y-%m-%dT%H:%M:%SZ")
return datetime.datetime.fromtimestamp(time.mktime(tm))
def to_list(func):
@wraps(func)
def f(*args, **kwargs):
return list(func(*args, **kwargs))
return f
def import_object(path):
module, name = path.rsplit('.', 1)
module = importlib.import_module(module)
return getattr(module, name)
@to_list
def get_adapters(idp):
idp = idp or {}
adapters = idp.get('ADAPTER') or app_settings.ADAPTER
for adapter in adapters:
yield import_object(adapter)()
def get_values(saml_attributes, name):
values = saml_attributes.get(name)
if values is None:
return ()
if not isinstance(values, (list, tuple)):
return (values,)
return values
def get_parameter(idp, name):
return idp.get(name) or getattr(app_settings, name)