Effects of refactoring.
This commit is contained in:
153
src/saml2/binding.py
Normal file
153
src/saml2/binding.py
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2010 Umeå University
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""Contains classes and functions that are necessary to implement
|
||||||
|
different bindings.
|
||||||
|
|
||||||
|
Bindings normally consists of three parts:
|
||||||
|
- rules about what to send
|
||||||
|
- how to package the information
|
||||||
|
- which protocol to use
|
||||||
|
"""
|
||||||
|
import httplib2
|
||||||
|
|
||||||
|
try:
|
||||||
|
from xml.etree import cElementTree as ElementTree
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import cElementTree as ElementTree
|
||||||
|
except ImportError:
|
||||||
|
from elementtree import ElementTree
|
||||||
|
|
||||||
|
from saml2.samlp import NAMESPACE as SAMLP_NAMESPACE
|
||||||
|
|
||||||
|
import saml2
|
||||||
|
|
||||||
|
NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||||
|
|
||||||
|
def http_post(authn_request, sp_entity_id=None, relay_state=None):
|
||||||
|
response = []
|
||||||
|
response.append("<head>")
|
||||||
|
response.append("""<title>SAML 2.0 POST</title>""")
|
||||||
|
response.append("</head><body>")
|
||||||
|
#login_url = location + '?spentityid=' + "lingon.catalogix.se"
|
||||||
|
response.append(FORM_SPEC % (location, base64.b64encode(authen_req),
|
||||||
|
os.environ['REQUEST_URI']))
|
||||||
|
response.append("""<script type="text/javascript">""")
|
||||||
|
response.append(" window.onload = function ()")
|
||||||
|
response.append(" { document.forms[0].submit(); ")
|
||||||
|
response.append("""</script>""")
|
||||||
|
response.append("</body>")
|
||||||
|
|
||||||
|
return ([], response)
|
||||||
|
|
||||||
|
def http_redirect(authn_request, sp_entity_id, relay_state):
|
||||||
|
lista = ["SAMLRequest=%s" % urllib.quote_plus(
|
||||||
|
deflate_and_base64_encode(
|
||||||
|
authen_req)),
|
||||||
|
"spentityid=%s" % sp_entity_id]
|
||||||
|
if relay_state:
|
||||||
|
lista.append("RelayState=%s" % relay_state)
|
||||||
|
login_url = "?".join([location, "&".join(lista)])
|
||||||
|
headers = [('Location', login_url)]
|
||||||
|
response = []
|
||||||
|
|
||||||
|
return (headers, response)
|
||||||
|
|
||||||
|
def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
|
||||||
|
""" Returns a soap envelope containing a SAML request
|
||||||
|
as a text string.
|
||||||
|
|
||||||
|
:param thingy: The SAML thingy
|
||||||
|
:return: The SOAP envelope as a string
|
||||||
|
"""
|
||||||
|
envelope = ElementTree.Element('')
|
||||||
|
envelope.tag = '{%s}Envelope' % NAMESPACE
|
||||||
|
|
||||||
|
if header_parts:
|
||||||
|
header = ElementTree.Element('')
|
||||||
|
header.tag = '{%s}Header' % NAMESPACE
|
||||||
|
envelope.append(header)
|
||||||
|
for part in header_parts:
|
||||||
|
part.become_child_element_of(header)
|
||||||
|
|
||||||
|
body = ElementTree.Element('')
|
||||||
|
body.tag = '{%s}Body' % NAMESPACE
|
||||||
|
envelope.append(body)
|
||||||
|
|
||||||
|
thingy.become_child_element_of(body)
|
||||||
|
|
||||||
|
return ElementTree.tostring(envelope, encoding="UTF-8")
|
||||||
|
|
||||||
|
def http_soap(authn_request, sp_entity_id, relay_state):
|
||||||
|
return ({"content-type": "application/soap+xml"},
|
||||||
|
make_soap_enveloped_saml_thingy(authn_request))
|
||||||
|
|
||||||
|
def http_paos(authn_request, sp_entity_id, relay_state, extra=None):
|
||||||
|
return ({"content-type": "application/soap+xml"},
|
||||||
|
make_soap_enveloped_saml_thingy(authn_request, extra))
|
||||||
|
|
||||||
|
def parse_soap_enveloped_saml(text, body_class, header_class=None):
|
||||||
|
"""Parses a SOAP enveloped SAML thing and returns header parts and body
|
||||||
|
|
||||||
|
:param text: The SOAP object as XML
|
||||||
|
:return: header parts and body as saml.samlbase instances
|
||||||
|
"""
|
||||||
|
envelope = ElementTree.fromstring(text)
|
||||||
|
assert envelope.tag == '{%s}Envelope' % NAMESPACE
|
||||||
|
|
||||||
|
print len(envelope)
|
||||||
|
body = None
|
||||||
|
header = {}
|
||||||
|
for part in envelope:
|
||||||
|
print ">",part.tag
|
||||||
|
if part.tag == '{%s}Body' % NAMESPACE:
|
||||||
|
for sub in part:
|
||||||
|
try:
|
||||||
|
body = saml2.create_class_from_element_tree(body_class, sub)
|
||||||
|
except Exception, exc:
|
||||||
|
print exc
|
||||||
|
print body_class.c_tag
|
||||||
|
raise Exception(
|
||||||
|
"Wrong body type (%s) in SOAP envelope" % sub.tag)
|
||||||
|
elif part.tag == '{%s}Header' % NAMESPACE:
|
||||||
|
if not header_class:
|
||||||
|
raise Exception("Header where I didn't expect one")
|
||||||
|
print "--- HEADER ---"
|
||||||
|
for sub in part:
|
||||||
|
print ">>",sub.tag
|
||||||
|
for klass in header_class:
|
||||||
|
print "?{%s}%s" % (klass.c_namespace,klass.c_tag)
|
||||||
|
if sub.tag == "{%s}%s" % (klass.c_namespace,klass.c_tag):
|
||||||
|
header[sub.tag] = \
|
||||||
|
saml2.create_class_from_element_tree(klass, sub)
|
||||||
|
break
|
||||||
|
|
||||||
|
return body, header
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PACKING = {
|
||||||
|
saml2.BINDING_HTTP_REDIRECT: http_redirect,
|
||||||
|
saml2.BINDING_HTTP_POST: http_post,
|
||||||
|
}
|
||||||
|
|
||||||
|
def packager( identifier ):
|
||||||
|
try:
|
||||||
|
return PACKING[identifier]
|
||||||
|
except KeyError:
|
||||||
|
raise Exception("Unkown binding type: %s" % binding)
|
||||||
32
src/saml2/idpdisc.py
Normal file
32
src/saml2/idpdisc.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generated Mon Jul 12 22:05:35 2010 by parse_xsd.py version 0.2.
|
||||||
|
#
|
||||||
|
|
||||||
|
import saml2
|
||||||
|
from saml2 import SamlBase
|
||||||
|
from saml2 import md
|
||||||
|
|
||||||
|
NAMESPACE = "urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol"
|
||||||
|
|
||||||
|
class DiscoveryResponse(md.IndexedEndpointType):
|
||||||
|
"""The idpdisc:DiscoveryResponse element"""
|
||||||
|
c_tag = 'DiscoveryResponse'
|
||||||
|
c_namespace = NAMESPACE
|
||||||
|
|
||||||
|
def discovery_response_from_string(xml_string):
|
||||||
|
""" Create DiscoveryResponse instance from an XML string """
|
||||||
|
return saml2.create_class_from_xml_string(DiscoveryResponse, xml_string)
|
||||||
|
|
||||||
|
ELEMENT_FROM_STRING = {
|
||||||
|
DiscoveryResponse.c_tag: discovery_response_from_string,
|
||||||
|
}
|
||||||
|
|
||||||
|
ELEMENT_BY_TAG = {
|
||||||
|
'DiscoveryResponse': DiscoveryResponse,
|
||||||
|
}
|
||||||
|
|
||||||
|
def factory(tag, **kwargs):
|
||||||
|
return ELEMENT_BY_TAG[tag](**kwargs)
|
||||||
|
|
||||||
50
src/saml2/population.py
Normal file
50
src/saml2/population.py
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
from saml2.cache import Cache
|
||||||
|
|
||||||
|
class Population(object):
|
||||||
|
def __init__(self, cache=None):
|
||||||
|
if cache:
|
||||||
|
self.cache = Cache(cache)
|
||||||
|
else:
|
||||||
|
self.cache = Cache()
|
||||||
|
|
||||||
|
def add_information_about_person(self, session_info):
|
||||||
|
"""If there already are information from this source in the cache
|
||||||
|
this function will overwrite that information"""
|
||||||
|
|
||||||
|
name_id = session_info["name_id"]
|
||||||
|
issuer = session_info["issuer"]
|
||||||
|
del session_info["issuer"]
|
||||||
|
self.cache.set(name_id, issuer, session_info,
|
||||||
|
session_info["not_on_or_after"])
|
||||||
|
return name_id
|
||||||
|
|
||||||
|
def stale_sources_for_person(self, subject_id, sources=None):
|
||||||
|
if not sources: # assume that all the members has be asked
|
||||||
|
# once before, hence they are represented in the cache
|
||||||
|
sources = self.cache.entities(subject_id)
|
||||||
|
sources = [m for m in sources \
|
||||||
|
if not self.cache.active(subject_id, m)]
|
||||||
|
return sources
|
||||||
|
|
||||||
|
def issuers_of_info(self, subject_id):
|
||||||
|
return self.cache.entities(subject_id)
|
||||||
|
|
||||||
|
def get_identity(self, subject_id):
|
||||||
|
return self.cache.get_identity(subject_id)
|
||||||
|
|
||||||
|
def get_info_from(self, subject_id, entity_id):
|
||||||
|
return self.cache.get(subject_id, entity_id)
|
||||||
|
|
||||||
|
def subjects(self):
|
||||||
|
"""Returns the name id's for all the persons in the cache"""
|
||||||
|
return self.cache.subjects();
|
||||||
|
|
||||||
|
def remove_person(self, subject_id):
|
||||||
|
self.cache.delete(subject_id)
|
||||||
|
|
||||||
|
def get_entityid(self, subject_id, source_id):
|
||||||
|
try:
|
||||||
|
return self.cache.get(subject_id, source_id)["name_id"]
|
||||||
|
except (KeyError, ValueError):
|
||||||
|
return ""
|
||||||
271
src/saml2/s_utils.py
Normal file
271
src/saml2/s_utils.py
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import time
|
||||||
|
import base64
|
||||||
|
from saml2 import saml, samlp, VERSION, sigver
|
||||||
|
from saml2.time_util import instant
|
||||||
|
|
||||||
|
try:
|
||||||
|
from hashlib import md5
|
||||||
|
except ImportError:
|
||||||
|
from md5 import md5
|
||||||
|
import zlib
|
||||||
|
|
||||||
|
class VersionMismatch(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class UnknownPrincipal(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class UnsupportedBinding(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class OtherError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MissingValue(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
EXCEPTION2STATUS = {
|
||||||
|
VersionMismatch: samlp.STATUS_VERSION_MISMATCH,
|
||||||
|
UnknownPrincipal: samlp.STATUS_UNKNOWN_PRINCIPAL,
|
||||||
|
UnsupportedBinding: samlp.STATUS_UNSUPPORTED_BINDING,
|
||||||
|
OtherError: samlp.STATUS_UNKNOWN_PRINCIPAL,
|
||||||
|
MissingValue: samlp.STATUS_REQUEST_UNSUPPORTED,
|
||||||
|
}
|
||||||
|
|
||||||
|
GENERIC_DOMAINS = "aero", "asia", "biz", "cat", "com", "coop", \
|
||||||
|
"edu", "gov", "info", "int", "jobs", "mil", "mobi", "museum", \
|
||||||
|
"name", "net", "org", "pro", "tel", "travel"
|
||||||
|
|
||||||
|
def valid_email(emailaddress, domains = GENERIC_DOMAINS):
|
||||||
|
"""Checks for a syntactically valid email address."""
|
||||||
|
|
||||||
|
# Email address must be at least 6 characters in total.
|
||||||
|
# Assuming noone may have addresses of the type a@com
|
||||||
|
if len(emailaddress) < 6:
|
||||||
|
return False # Address too short.
|
||||||
|
|
||||||
|
# Split up email address into parts.
|
||||||
|
try:
|
||||||
|
localpart, domainname = emailaddress.rsplit('@', 1)
|
||||||
|
host, toplevel = domainname.rsplit('.', 1)
|
||||||
|
except ValueError:
|
||||||
|
return False # Address does not have enough parts.
|
||||||
|
|
||||||
|
# Check for Country code or Generic Domain.
|
||||||
|
if len(toplevel) != 2 and toplevel not in domains:
|
||||||
|
return False # Not a domain name.
|
||||||
|
|
||||||
|
for i in '-_.%+.':
|
||||||
|
localpart = localpart.replace(i, "")
|
||||||
|
for i in '-_.':
|
||||||
|
host = host.replace(i, "")
|
||||||
|
|
||||||
|
if localpart.isalnum() and host.isalnum():
|
||||||
|
return True # Email address is fine.
|
||||||
|
else:
|
||||||
|
return False # Email address has funny characters.
|
||||||
|
|
||||||
|
def decode_base64_and_inflate( string ):
|
||||||
|
""" base64 decodes and then inflates according to RFC1951
|
||||||
|
|
||||||
|
:param string: a deflated and encoded string
|
||||||
|
:return: the string after decoding and inflating
|
||||||
|
"""
|
||||||
|
|
||||||
|
return zlib.decompress( base64.b64decode( string ) , -15)
|
||||||
|
|
||||||
|
def deflate_and_base64_encode( string_val ):
|
||||||
|
"""
|
||||||
|
Deflates and the base64 encodes a string
|
||||||
|
|
||||||
|
:param string_val: The string to deflate and encode
|
||||||
|
:return: The deflated and encoded string
|
||||||
|
"""
|
||||||
|
return base64.b64encode( zlib.compress( string_val )[2:-4] )
|
||||||
|
|
||||||
|
def sid(seed=""):
|
||||||
|
"""The hash of the server time + seed makes an unique SID for each session.
|
||||||
|
|
||||||
|
:param seed: A seed string
|
||||||
|
:return: The hex version of the digest
|
||||||
|
"""
|
||||||
|
ident = md5()
|
||||||
|
ident.update(repr(time.time()))
|
||||||
|
if seed:
|
||||||
|
ident.update(seed)
|
||||||
|
return ident.hexdigest()
|
||||||
|
|
||||||
|
def parse_attribute_map(filenames):
|
||||||
|
"""
|
||||||
|
Expects a file with each line being composed of the oid for the attribute
|
||||||
|
exactly one space, a user friendly name of the attribute and then
|
||||||
|
the type specification of the name.
|
||||||
|
|
||||||
|
:param filename: List of filenames on mapfiles.
|
||||||
|
:return: A 2-tuple, one dictionary with the oid as keys and the friendly
|
||||||
|
names as values, the other one the other way around.
|
||||||
|
"""
|
||||||
|
forward = {}
|
||||||
|
backward = {}
|
||||||
|
for filename in filenames:
|
||||||
|
for line in open(filename).readlines():
|
||||||
|
(name, friendly_name, name_format) = line.strip().split()
|
||||||
|
forward[(name, name_format)] = friendly_name
|
||||||
|
backward[friendly_name] = (name, name_format)
|
||||||
|
|
||||||
|
return (forward, backward)
|
||||||
|
|
||||||
|
def identity_attribute(form, attribute, forward_map=None):
|
||||||
|
if form == "friendly":
|
||||||
|
if attribute.friendly_name:
|
||||||
|
return attribute.friendly_name
|
||||||
|
elif forward_map:
|
||||||
|
try:
|
||||||
|
return forward_map[(attribute.name, attribute.name_format)]
|
||||||
|
except KeyError:
|
||||||
|
return attribute.name
|
||||||
|
# default is name
|
||||||
|
return attribute.name
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def status_from_exception_factory(exception):
|
||||||
|
msg = exception.args[0]
|
||||||
|
status = samlp.Status(
|
||||||
|
status_message=samlp.StatusMessage(text=msg),
|
||||||
|
status_code=samlp.StatusCode(
|
||||||
|
value=samlp.STATUS_RESPONDER,
|
||||||
|
status_code=samlp.StatusCode(
|
||||||
|
value=EXCEPTION2STATUS[exception.__class__])
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return status
|
||||||
|
|
||||||
|
def success_status_factory():
|
||||||
|
return samlp.Status(status_code=samlp.StatusCode(
|
||||||
|
value=samlp.STATUS_SUCCESS))
|
||||||
|
|
||||||
|
def status_message_factory(message, code, fro=samlp.STATUS_RESPONDER):
|
||||||
|
return samlp.Status(
|
||||||
|
status_message=samlp.StatusMessage(text=message),
|
||||||
|
status_code=samlp.StatusCode(
|
||||||
|
value=fro,
|
||||||
|
status_code=samlp.StatusCode(value=code)))
|
||||||
|
|
||||||
|
def assertion_factory(**kwargs):
|
||||||
|
assertion = saml.Assertion(version=VERSION, id=sid(),
|
||||||
|
issue_instant=instant())
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
setattr(assertion, key, val)
|
||||||
|
return assertion
|
||||||
|
|
||||||
|
def response_factory(signature=False, encrypt=False, **kwargs):
|
||||||
|
response = samlp.Response(id=sid(), version=VERSION,
|
||||||
|
issue_instant=instant())
|
||||||
|
|
||||||
|
if signature:
|
||||||
|
response["signature"] = sigver.pre_signature_part(kwargs["id"])
|
||||||
|
if encrypt:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
setattr(response, key, val)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def _attrval(val, typ=""):
|
||||||
|
if isinstance(val, list) or isinstance(val, set):
|
||||||
|
attrval = [saml.AttributeValue(text=v) for v in val]
|
||||||
|
elif val == None:
|
||||||
|
attrval = None
|
||||||
|
else:
|
||||||
|
attrval = [saml.AttributeValue(text=val)]
|
||||||
|
|
||||||
|
if typ:
|
||||||
|
for ava in attrval:
|
||||||
|
ava.set_type(typ)
|
||||||
|
|
||||||
|
return attrval
|
||||||
|
|
||||||
|
# --- attribute profiles -----
|
||||||
|
|
||||||
|
# xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||||
|
# xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
|
||||||
|
def do_ava(val, typ=""):
|
||||||
|
if isinstance(val, basestring):
|
||||||
|
ava = saml.AttributeValue()
|
||||||
|
ava.set_text(val)
|
||||||
|
attrval = [ava]
|
||||||
|
elif isinstance(val, list):
|
||||||
|
attrval = [do_ava(v)[0] for v in val]
|
||||||
|
elif val or val == False:
|
||||||
|
ava = saml.AttributeValue()
|
||||||
|
ava.set_text(val)
|
||||||
|
attrval = [ava]
|
||||||
|
elif val == None:
|
||||||
|
attrval = None
|
||||||
|
else:
|
||||||
|
raise OtherError("strange value type on: %s" % val)
|
||||||
|
|
||||||
|
if typ:
|
||||||
|
for ava in attrval:
|
||||||
|
ava.set_type(typ)
|
||||||
|
|
||||||
|
return attrval
|
||||||
|
|
||||||
|
def do_attribute(val, typ, key):
|
||||||
|
attr = saml.Attribute()
|
||||||
|
attrval = do_ava(val, typ)
|
||||||
|
if attrval:
|
||||||
|
attr.attribute_value = attrval
|
||||||
|
|
||||||
|
if isinstance(key, basestring):
|
||||||
|
attr.name = key
|
||||||
|
elif isinstance(key, tuple): # 3-tuple or 2-tuple
|
||||||
|
try:
|
||||||
|
(name, nformat, friendly) = key
|
||||||
|
except ValueError:
|
||||||
|
(name, nformat) = key
|
||||||
|
friendly = ""
|
||||||
|
if name:
|
||||||
|
attr.name = name
|
||||||
|
if format:
|
||||||
|
attr.name_format = nformat
|
||||||
|
if friendly:
|
||||||
|
attr.friendly_name = friendly
|
||||||
|
return attr
|
||||||
|
|
||||||
|
def do_attributes(identity):
|
||||||
|
attrs = []
|
||||||
|
if not identity:
|
||||||
|
return attrs
|
||||||
|
for key, spec in identity.items():
|
||||||
|
try:
|
||||||
|
val, typ = spec
|
||||||
|
except ValueError:
|
||||||
|
val = spec
|
||||||
|
typ = ""
|
||||||
|
except TypeError:
|
||||||
|
val = ""
|
||||||
|
typ = ""
|
||||||
|
|
||||||
|
attr = do_attribute(val, typ, key)
|
||||||
|
attrs.append(attr)
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def do_attribute_statement(identity):
|
||||||
|
"""
|
||||||
|
:param identity: A dictionary with fiendly names as keys
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return saml.AttributeStatement(attribute=do_attributes(identity))
|
||||||
|
|
||||||
|
def factory(klass, **kwargs):
|
||||||
|
instance = klass()
|
||||||
|
for key, val in kwargs.items():
|
||||||
|
setattr(instance, key, val)
|
||||||
|
return instance
|
||||||
60
src/saml2/virtual_org.py
Normal file
60
src/saml2/virtual_org.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
from saml2.attribute_resolver import AttributeResolver
|
||||||
|
|
||||||
|
class VirtualOrg(object):
|
||||||
|
def __init__(self, metadata, vo_org, population, log=None, vorg_conf=None):
|
||||||
|
self.metadata = metadata
|
||||||
|
self.log = log
|
||||||
|
self.vorg_conf = vorg_conf
|
||||||
|
self.vorg = vo_org
|
||||||
|
self.population = population
|
||||||
|
|
||||||
|
def members_to_ask(self, subject_id):
|
||||||
|
# Find the member of the Virtual Organization that I haven't
|
||||||
|
# alrady spoken too
|
||||||
|
vo_members = [
|
||||||
|
member for member in self.metadata.vo_members(self.vorg)\
|
||||||
|
if member not in self.srv["idp"].keys()]
|
||||||
|
|
||||||
|
self.log and self.log.info("VO members: %s" % vo_members)
|
||||||
|
|
||||||
|
# Remove the ones I have cached data from about this subject
|
||||||
|
vo_members = [m for m in vo_members \
|
||||||
|
if not self.cache.active(subject_id, m)]
|
||||||
|
self.log and self.log.info(
|
||||||
|
"VO members (not cached): %s" % vo_members)
|
||||||
|
return vo_members
|
||||||
|
|
||||||
|
def do_aggregation(self, subject_id):
|
||||||
|
if self.log:
|
||||||
|
self.log.info("** Do VO aggregation **")
|
||||||
|
self.log.info("SubjectID: %s, VO:%s" % (subject_id, self.vorg))
|
||||||
|
|
||||||
|
vo_members = self.members_to_ask(subject_id)
|
||||||
|
|
||||||
|
if vo_members:
|
||||||
|
# Find the NameIDFormat and the SPNameQualifier
|
||||||
|
if self.vorg_conf and "name_id_format" in self.vorg_conf:
|
||||||
|
name_id_format = self.vorg_conf["name_id_format"]
|
||||||
|
sp_name_qualifier = ""
|
||||||
|
else:
|
||||||
|
sp_name_qualifier = self.vorg
|
||||||
|
name_id_format = ""
|
||||||
|
|
||||||
|
resolver = AttributeResolver(environ, self.metadata, self.conf)
|
||||||
|
# extends returns a list of session_infos
|
||||||
|
for session_info in resolver.extend(subject_id,
|
||||||
|
self.conf["entityid"], vo_members,
|
||||||
|
name_id_format=name_id_format,
|
||||||
|
sp_name_qualifier=sp_name_qualifier,
|
||||||
|
log=self.log):
|
||||||
|
_ignore = self._cache_session(session_info)
|
||||||
|
|
||||||
|
if self.log:
|
||||||
|
self.log.info(
|
||||||
|
">Issuers: %s" % self.population.issuers_of_info(subject_id))
|
||||||
|
self.log.info(
|
||||||
|
"AVA: %s" % (self.population.get_identity(subject_id),))
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
Reference in New Issue
Block a user