def choose_session_storage(self): _spec = self.config.getattr("session_storage", "idp") if not _spec: return SessionStorage() elif isinstance(_spec, basestring): if _spec.lower() == "memory": return SessionStorage() else: # Should be tuple typ, data = _spec if typ.lower() == "mongodb": return SessionStorageMDB(data) raise NotImplementedError("No such storage type implemented")
def choose_session_storage(self): _spec = self.config.getattr("session_storage", "idp") if not _spec: return SessionStorage() elif isinstance(_spec, six.string_types): if _spec.lower() == "memory": return SessionStorage() else: # Should be tuple typ, data = _spec if typ.lower() == "mongodb": from saml2.mongo_store import SessionStorageMDB return SessionStorageMDB(database=data, collection="session") raise NotImplementedError("No such storage type implemented")
def __init__(self, config_file="", config=None, _cache="", stype="idp"): Entity.__init__(self, stype, config, config_file) self.init_config(stype) self._cache = _cache self.ticket = {} self.authn = {} self.assertion = {} self.user2uid = {} self.uid2user = {} self.session_db = SessionStorage()
class Server(Entity): """ A class that does things that IdPs or AAs do """ def __init__(self, config_file="", config=None, _cache="", stype="idp"): Entity.__init__(self, stype, config, config_file) self.init_config(stype) self._cache = _cache self.ticket = {} self.authn = {} self.assertion = {} self.user2uid = {} self.uid2user = {} self.session_db = SessionStorage() def init_config(self, stype="idp"): """ Remaining init of the server configuration :param stype: The type of Server ("idp"/"aa") """ if stype == "aa": return try: # subject information is stored in a database # default database is a shelve database which is OK in some setups dbspec = self.config.getattr("subject_data", "idp") idb = None if not dbspec: pass elif isinstance(dbspec, basestring): idb = shelve.open(dbspec, writeback=True) else: # database spec is a a 2-tuple (type, address) print >> sys.stderr, "DBSPEC: %s" % (dbspec,) (typ, addr) = dbspec if typ == "shelve": idb = shelve.open(addr, writeback=True) elif typ == "memcached": idb = memcache.Client(addr) elif typ == "dict": # in-memory dictionary idb = {} elif typ == "mongodb": from mongodict import MongoDict idb = MongoDict(host='localhost', port=27017, database=addr, collection='store') if idb is not None: self.ident = IdentDB(idb) else: raise Exception("Couldn't open identity database: %s" % (dbspec,)) except AttributeError: self.ident = None def close_shelve_db(self): """Close the shelve db to prevent file system locking issues""" if self.ident: self.ident.db.close() def wants(self, sp_entity_id, index=None): """ Returns what attributes the SP requires and which are optional if any such demands are registered in the Metadata. :param sp_entity_id: The entity id of the SP :param index: which of the attribute consumer services its all about :return: 2-tuple, list of required and list of optional attributes """ return self.metadata.attribute_requirement(sp_entity_id, index) # ------------------------------------------------------------------------- def parse_authn_request(self, enc_request, binding=BINDING_HTTP_REDIRECT): """Parse a Authentication Request :param enc_request: The request in its transport format :param binding: Which binding that was used to transport the message to this entity. :return: A dictionary with keys: consumer_url - as gotten from the SPs entity_id and the metadata id - the id of the request sp_entity_id - the entity id of the SP request - The verified request """ return self._parse_request(enc_request, AuthnRequest, "single_sign_on_service", binding) def parse_attribute_query(self, xml_string, binding): """ Parse an attribute query :param xml_string: The Attribute Query as an XML string :param binding: Which binding that was used for the request :return: A query instance """ return self._parse_request(xml_string, AttributeQuery, "attribute_service", binding) def parse_authz_decision_query(self, xml_string, binding): """ Parse an attribute query :param xml_string: The Authz decision Query as an XML string :return: Query instance """ return self._parse_request(xml_string, AuthzDecisionQuery, "authz_service", binding) def parse_assertion_id_request(self, xml_string, binding): """ Parse an assertion id query :param xml_string: The AssertionIDRequest as an XML string :return: Query instance """ return self._parse_request(xml_string, AssertionIDRequest, "assertion_id_request_service", binding) def parse_authn_query(self, xml_string, binding): """ Parse an authn query :param xml_string: The AuthnQuery as an XML string :return: Query instance """ return self._parse_request(xml_string, AuthnQuery, "authn_query_service", binding) def parse_name_id_mapping_request(self, xml_string, binding): """ Parse a nameid mapping request :param xml_string: The NameIDMappingRequest as an XML string :return: Query instance """ return self._parse_request(xml_string, NameIDMappingRequest, "name_id_mapping_service", binding) # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ def _authn_response(self, in_response_to, consumer_url, sp_entity_id, identity=None, name_id=None, status=None, authn=None, authn_decl=None, issuer=None, policy=None, sign_assertion=False, sign_response=False): """ Create a response. A layer of indirection. :param in_response_to: The session identifier of the request :param consumer_url: The URL which should receive the response :param sp_entity_id: The entity identifier of the SP :param identity: A dictionary with attributes and values that are expected to be the bases for the assertion in the response. :param name_id: The identifier of the subject :param status: The status of the response :param authn: A 2-tuple denoting the authn class and the authn authority. :param authn_decl: :param issuer: The issuer of the response :param sign_assertion: Whether the assertion should be signed or not :param sign_response: Whether the response should be signed or not :return: A response instance """ to_sign = [] args = {} if identity: _issuer = self._issuer(issuer) ast = Assertion(identity) if policy is None: policy = Policy() try: ast.apply_policy(sp_entity_id, policy, self.metadata) except MissingValue, exc: return self.create_error_response(in_response_to, consumer_url, exc, sign_response) if authn: # expected to be a 2-tuple class+authority (authn_class, authn_authn) = authn assertion = ast.construct(sp_entity_id, in_response_to, consumer_url, name_id, self.config.attribute_converters, policy, issuer=_issuer, authn_class=authn_class, authn_auth=authn_authn) self.session_db.store_authn_statement(assertion.authn_statement, name_id) elif authn_decl: assertion = ast.construct(sp_entity_id, in_response_to, consumer_url, name_id, self.config.attribute_converters, policy, issuer=_issuer, authn_decl=authn_decl) self.session_db.store_authn_statement(assertion.authn_statement, name_id) else: assertion = ast.construct(sp_entity_id, in_response_to, consumer_url, name_id, self.config.attribute_converters, policy, issuer=_issuer) if sign_assertion: assertion.signature = pre_signature_part(assertion.id, self.sec.my_cert, 1) # Just the assertion or the response and the assertion ? to_sign = [(class_name(assertion), assertion.id)] # Store which assertion that has been sent to which SP about which # subject. # self.cache.set(assertion.subject.name_id.text, # sp_entity_id, {"ava": identity, "authn": authn}, # assertion.conditions.not_on_or_after) args["assertion"] = assertion self.session_db.store_assertion(assertion, to_sign) return self._response(in_response_to, consumer_url, status, issuer, sign_response, to_sign, **args)