def _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :return: An AuthnContext instance """ if authn_class: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl(authn_decl, authn_auth)) elif authn_decl_ref: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref(authn_decl_ref, authn_auth)) else: return factory( saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def to_(self, attrvals): """ Create a list of Attribute instances. :param attrvals: A dictionary of attributes and values :return: A list of Attribute instances """ attributes = [] for key, value in attrvals.items(): name = self._to.get(key.lower()) if name: if name == "urn:oid:1.3.6.1.4.1.5923.1.1.1.10": # special case for eduPersonTargetedID attr_value = [] for v in value: extension_element = ExtensionElement("NameID", NAMESPACE, attributes={'Format': NAMEID_FORMAT_PERSISTENT}, text=v) attrval = saml.AttributeValue(extension_elements=[extension_element]) attr_value.append(attrval) else: attr_value = do_ava(value) attributes.append(factory(saml.Attribute, name=name, name_format=self.name_format, friendly_name=key, attribute_value=attr_value)) else: attributes.append(factory(saml.Attribute, name=key, attribute_value=do_ava(value))) return attributes
def test_assertion(self): assertion = s_utils.assertion_factory( subject=factory( saml.Subject, text="_aaa", name_id=factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT) ), attribute_statement=do_attribute_statement( {("", "", "surName"): ("Jeter", ""), ("", "", "givenName"): ("Derek", "")} ), issuer=self.server._issuer(), ) assert _eq(assertion.keyswv(), ["attribute_statement", "issuer", "id", "subject", "issue_instant", "version"]) assert assertion.version == "2.0" assert assertion.issuer.text == "urn:mace:example.com:saml:roland:idp" # assert assertion.attribute_statement attribute_statement = assertion.attribute_statement assert len(attribute_statement.attribute) == 2 attr0 = attribute_statement.attribute[0] attr1 = attribute_statement.attribute[1] if attr0.attribute_value[0].text == "Derek": assert attr0.friendly_name == "givenName" assert attr1.friendly_name == "surName" assert attr1.attribute_value[0].text == "Jeter" else: assert attr1.friendly_name == "givenName" assert attr1.attribute_value[0].text == "Derek" assert attr0.friendly_name == "surName" assert attr0.attribute_value[0].text == "Jeter" # subject = assertion.subject assert _eq(subject.keyswv(), ["text", "name_id"]) assert subject.text == "_aaa" assert subject.name_id.format == saml.NAMEID_FORMAT_TRANSIENT
def test_sign_response_2(self): assertion2 = factory( saml.Assertion, version= "2.0", id= "11122", issue_instant= "2009-10-30T13:20:28Z", signature= sigver.pre_signature_part("11122", self.sec.my_cert), attribute_statement=do_attribute_statement({ ("","","surName"): ("Fox",""), ("","","givenName") :("Bear",""), }) ) response = factory(samlp.Response, assertion=assertion2, id="22233", signature=sigver.pre_signature_part("22233", self.sec.my_cert)) to_sign = [(class_name(assertion2), assertion2.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) assert s_response is not None response2 = response_from_string(s_response) sass = response2.assertion[0] assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant', 'version', 'signature', 'id']) assert sass.version == "2.0" assert sass.id == "11122" item = self.sec.check_signature(response2, class_name(response), s_response) assert isinstance(item, samlp.Response)
def test_exception_sign_verify_with_cert_from_instance(self): assertion = factory(saml.Assertion, version="2.0", id="11100", issue_instant="2009-10-30T13:20:28Z", #signature= sigver.pre_signature_part("11100", # self.sec.my_cert), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), }) ) response = factory(samlp.Response, assertion=assertion, id="22222", signature=sigver.pre_signature_part("22222", self.sec .my_cert)) to_sign = [(class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) response2 = response_from_string(s_response) # Change something that should make everything fail response2.id = "23456" raises(sigver.SignatureError, self.sec._check_signature, s_response, response2, class_name(response2))
def test_audience(): aud_restr = utils.factory(saml.AudienceRestriction, audience=utils.factory(saml.Audience, text="urn:foo:bar")) assert aud_restr.keyswv() == ["audience"] assert aud_restr.audience.text == "urn:foo:bar"
def test_authn_context(): accr = utils.factory( saml.AuthnContext, text="urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified") a = utils.factory(saml.AuthnContext, authn_context_class_ref=accr) assert a.keyswv() == ["authn_context_class_ref"]
def test_value_4(): attribute = utils.factory( saml.Attribute, attribute_value=[utils.factory(saml.AttributeValue, text="Derek")], friendly_name="givenName" ) assert _eq(attribute.keyswv(), ["friendly_name", "attribute_value", "name_format"]) assert attribute.friendly_name == "givenName" assert len(attribute.attribute_value) == 1 assert attribute.attribute_value[0].text == "Derek"
def construct(self, sp_entity_id, in_response_to, consumer_url, name_id, attrconvs, policy, issuer, authn_class=None, authn_auth=None, authn_decl=None, encrypt=None, sec_context=None): """ Construct the Assertion :param sp_entity_id: The entityid of the SP :param in_response_to: An identifier of the message, this message is a response to :param consumer_url: The intended consumer of the assertion :param name_id: An NameID instance :param attrconvs: AttributeConverters :param policy: The policy that should be adhered to when replying :param issuer: Who is issuing the statement :param authn_class: The authentication class :param authn_auth: The authentication instance :param authn_decl: :param encrypt: Whether to encrypt parts or all of the Assertion :param sec_context: The security context used when encrypting :return: An Assertion instance """ attr_statement = saml.AttributeStatement(attribute=from_local( attrconvs, self, policy.get_name_form(sp_entity_id))) if encrypt == "attributes": for attr in attr_statement.attribute: enc = sec_context.encrypt(text="%s" % attr) encd = xmlenc.encrypted_data_from_string(enc) encattr = saml.EncryptedAttribute(encrypted_data=encd) attr_statement.encrypted_attribute.append(encattr) attr_statement.attribute = [] # start using now and for some time conds = policy.conditions(sp_entity_id) return assertion_factory( issuer=issuer, attribute_statement = attr_statement, authn_statement = self._authn_statement(authn_class, authn_auth, authn_decl), conditions = conds, subject=factory( saml.Subject, name_id=name_id, subject_confirmation=factory( saml.SubjectConfirmation, method=saml.SUBJECT_CONFIRMATION_METHOD_BEARER, subject_confirmation_data=factory( saml.SubjectConfirmationData, in_response_to=in_response_to, recipient=consumer_url, not_on_or_after=policy.not_on_or_after( sp_entity_id)))), )
def authn_statement(authn_class=None, authn_auth=None, authn_decl=None, authn_decl_ref=None, authn_instant="", subject_locality="", session_not_on_or_after=None): """ Construct the AuthnStatement :param authn_class: Authentication Context Class reference :param authn_auth: Authenticating Authority :param authn_decl: Authentication Context Declaration :param authn_decl_ref: Authentication Context Declaration reference :param authn_instant: When the Authentication was performed. Assumed to be seconds since the Epoch. :param subject_locality: Specifies the DNS domain name and IP address for the system from which the assertion subject was apparently authenticated. :return: An AuthnContext instance """ if authn_instant: _instant = instant(time_stamp=authn_instant) else: _instant = instant() if authn_class: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl(authn_decl, authn_auth)) elif authn_decl_ref: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after, authn_context=_authn_context_decl_ref(authn_decl_ref, authn_auth)) else: res = factory( saml.AuthnStatement, authn_instant=_instant, session_index=sid(), session_not_on_or_after=session_not_on_or_after) if subject_locality: res.subject_locality = saml.SubjectLocality(text=subject_locality) return res
def _authn_context_decl(decl, authn_auth=None): """ Construct the authn context with a authn context declaration :param decl: The authn context declaration :param authn_auth: Authenticating Authority :return: An AuthnContext instance """ return factory(saml.AuthnContext, authn_context_decl=decl, authenticating_authority=factory( saml.AuthenticatingAuthority, text=authn_auth))
def test_authn_statement(): accr = utils.factory(saml.AuthnContextClassRef, text="urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified") ac = utils.factory(saml.AuthnContext, authn_context_class_ref=accr) ast = utils.factory( saml.AuthnStatement, authn_instant="2010-03-10T12:33:00Z", session_index="_12345", session_not_on_or_after="2010-03-11T12:00:00Z", authn_context=ac, ) assert _eq(ast.keyswv(), ["authn_instant", "session_index", "session_not_on_or_after", "authn_context"])
def _authn_context_decl_ref(self, decl_ref, authn_auth=None): """ Construct the authn context with a authn context declaration reference :param decl_ref: The authn context declaration reference :param authn_auth: Authenticating Authority :return: An AuthnContext instance """ return factory(saml.AuthnContext, authn_context_decl_ref=decl_ref, authenticating_authority=factory( saml.AuthenticatingAuthority, text=authn_auth))
def _authn_context_class_ref(self, authn_class, authn_auth=None): # authn_class: saml.AUTHN_PASSWORD cntx_class = factory(saml.AuthnContextClassRef, text=authn_class) if authn_auth: return factory( saml.AuthnContext, authn_context_class_ref=cntx_class, authenticating_authority=factory(saml.AuthenticatingAuthority, text=authn_auth), ) else: return factory(saml.AuthnContext, authn_context_class_ref=cntx_class)
def test_conditions(): conditions = utils.factory( saml.Conditions, not_before="2009-10-30T07:58:10.852Z", not_on_or_after="2009-10-30T08:03:10.852Z", audience_restriction=[utils.factory(saml.AudienceRestriction, audience=utils.factory(saml.Audience, text="urn:foo:bar"))]) assert _eq(conditions.keyswv(), ["not_before", "not_on_or_after", "audience_restriction"]) assert conditions.not_before == "2009-10-30T07:58:10.852Z" assert conditions.not_on_or_after == "2009-10-30T08:03:10.852Z" assert conditions.audience_restriction[0].audience.text == "urn:foo:bar"
def test_subject_confirmation(): s = utils.factory(saml.SubjectConfirmation, method="urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser", base_id="1234", name_id="abcd", subject_confirmation_data=utils.factory( saml.SubjectConfirmationData, in_response_to="_1234567890", recipient="http://example.com/sp/")) assert _eq(s.keyswv(), ["method", "base_id", "name_id", "subject_confirmation_data"]) assert s.method == "urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser"
def conditions(self, sp_entity_id): """ Return a saml.Condition instance :param sp_entity_id: The SP entity ID :return: A saml.Condition instance """ return factory( saml.Conditions, not_before=instant(), # How long might depend on who's getting it not_on_or_after=self.not_on_or_after(sp_entity_id), audience_restriction=[factory( saml.AudienceRestriction, audience=factory(saml.Audience, text=sp_entity_id))])
def to_format(self, attr): """ Creates an Attribute instance with name, name_format and friendly_name :param attr: The local name of the attribute :return: An Attribute instance """ try: return factory(saml.Attribute, name=self._to[attr], name_format=self.name_format, friendly_name=attr) except KeyError: return factory(saml.Attribute, name=attr)
def test_value_3(): attribute = utils.factory(saml.Attribute, attribute_value=[utils.factory( saml.AttributeValue, text="Derek")], name="urn:oid:2.5.4.42", name_format=NAME_FORMAT_URI, friendly_name="givenName") assert _eq(attribute.keyswv(), ["name", "name_format", "friendly_name", "attribute_value"]) assert attribute.name == "urn:oid:2.5.4.42" assert attribute.name_format == NAME_FORMAT_URI assert attribute.friendly_name == "givenName" assert len(attribute.attribute_value) == 1 assert attribute.attribute_value[0].text == "Derek"
def test_attribute_statement(): statement = utils.factory( saml.Statement, attribute=[ utils.factory(saml.Attribute, attribute_value=[ utils.factory( saml.AttributeValue,text="Derek")], friendly_name="givenName"), utils.factory(saml.Attribute, attribute_value=[ utils.factory( saml.AttributeValue,text="Jeter")], friendly_name="surName"), ]) assert statement.keyswv() == ["attribute"] assert len(statement.attribute) == 2
def test_attribute(): a = utils.factory(saml.Attribute, friendly_name="eduPersonScopedAffiliation", name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9", name_format="urn:oasis:names:tc:SAML:2.0:attrname-format:uri") assert _eq(a.keyswv(), ["friendly_name","name", "name_format"]) a = utils.factory(saml.Attribute, friendly_name="eduPersonScopedAffiliation", name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9", name_format="urn:oasis:names:tc:SAML:2.0:attrname-format:uri", attribute_value=[saml.AttributeValue(text="*****@*****.**")]) assert _eq(a.keyswv(), ["friendly_name","name", "name_format", "attribute_value"])
def test_xmlsec_err(): conf = config.SPConfig() conf.load_file("server_conf") md = MetadataStore([saml, samlp], None, conf) md.load("local", full_path("idp_example.xml")) conf.metadata = md conf.only_use_keys_in_metadata = False sec = sigver.security_context(conf) assertion = factory( saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part("11111", sec.my_cert, 1), attribute_statement=do_attribute_statement( {("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), }) ) try: sec.sign_statement(assertion, class_name(assertion), key_file=full_path("tes.key"), node_id=assertion.id) except (XmlsecError, SigverError) as err: # should throw an exception pass else: assert False
def test_sign_verify_with_cert_from_instance(self): response = factory(samlp.Response, assertion=self._assertion, id="22222", signature=sigver.pre_signature_part("22222", self.sec .my_cert)) to_sign = [(class_name(self._assertion), self._assertion.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) response2 = response_from_string(s_response) ci = "".join(sigver.cert_from_instance(response2)[0].split()) assert ci == self.sec.my_cert res = self.sec.verify_signature(s_response, node_name=class_name(samlp.Response())) assert res res = self.sec._check_signature(s_response, response2, class_name(response2), s_response) assert res == response2
def _authn_context_class_ref(self, authn_class, authn_auth=None): """ Construct the authn context with a authn context class reference :param authn_class: The authn context class reference :param authn_auth: Authenticating Authority :return: An AuthnContext instance """ cntx_class = factory(saml.AuthnContextClassRef, text=authn_class) if authn_auth: return factory(saml.AuthnContext, authn_context_class_ref=cntx_class, authenticating_authority=factory( saml.AuthenticatingAuthority, text=authn_auth)) else: return factory(saml.AuthnContext, authn_context_class_ref=cntx_class)
def test_response(self): response = sigver.response_factory( in_response_to="_012345", destination="https:#www.example.com", status=s_utils.success_status_factory(), assertion=s_utils.assertion_factory( subject=factory(saml.Subject, text="_aaa", name_id=saml.NAMEID_FORMAT_TRANSIENT), attribute_statement=do_attribute_statement( { ("", "", "sn"): ("Jeter", ""), ("", "", "givenName"): ("Derek", ""), } ), issuer=self.server._issuer(), ), issuer=self.server._issuer(), ) print(response.keyswv()) assert _eq(response.keyswv(), ['destination', 'assertion', 'status', 'in_response_to', 'issue_instant', 'version', 'issuer', 'id']) assert response.version == "2.0" assert response.issuer.text == "urn:mace:example.com:saml:roland:idp" assert response.destination == "https:#www.example.com" assert response.in_response_to == "_012345" # status = response.status print(status) assert status.status_code.value == samlp.STATUS_SUCCESS
def test_sign_response(self): response = factory(samlp.Response, assertion=self._assertion, id="22222", signature=sigver.pre_signature_part("22222", self.sec .my_cert)) to_sign = [(class_name(self._assertion), self._assertion.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) assert s_response is not None print(s_response) response = response_from_string(s_response) sass = response.assertion[0] print(sass) assert _eq(sass.keyswv(), ['attribute_statement', 'issue_instant', 'version', 'signature', 'id']) assert sass.version == "2.0" assert sass.id == "11111" item = self.sec.check_signature(response, class_name(response), s_response) assert isinstance(item, samlp.Response) assert item.id == "22222"
def setup_class(self): # This would be one way to initialize the security context : # # conf = config.SPConfig() # conf.load_file("server_conf") # conf.only_use_keys_in_metadata = False # # but instead, FakeConfig() is used to really only use the minimal # set of parameters needed for these test cases. Other test cases # (TestSecurityMetadata below) excersise the SPConfig() mechanism. # conf = FakeConfig() self.sec = sigver.security_context(FakeConfig()) self._assertion = factory( saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part("11111", self.sec.my_cert, 1), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), }) )
def do_subject_confirmation(policy, sp_entity_id, key_info=None, **treeargs): """ :param policy: Policy instance :param sp_entity_id: The entityid of the SP :param subject_confirmation_method: How was the subject confirmed :param address: The network address/location from which an attesting entity can present the assertion. :param key_info: Information of the key used to confirm the subject :param in_response_to: The ID of a SAML protocol message in response to which an attesting entity can present the assertion. :param recipient: A URI specifying the entity or location to which an attesting entity can present the assertion. :param not_before: A time instant before which the subject cannot be confirmed. The time value MUST be encoded in UTC. :return: """ _sc = factory(saml.SubjectConfirmation, **treeargs) _scd = _sc.subject_confirmation_data _scd.not_on_or_after = policy.not_on_or_after(sp_entity_id) if _sc.method == saml.SCM_HOLDER_OF_KEY: _scd.add_extension_element(key_info) return _sc
def do_endpoints(conf, endpoints): service = {} for endpoint, (eclass, indexed) in endpoints.items(): try: servs = [] i = 1 for args in conf[endpoint]: if isinstance(args, basestring): # Assume it's the location args = {"location": args, "binding": DEFAULT_BINDING[endpoint]} elif isinstance(args, tuple): if len(args) == 2: # (location, binding) args = {"location": args[0], "binding": args[1]} elif len(args) == 3: # (location, binding, index) args = {"location": args[0], "binding": args[1], "index": args[2]} if indexed: if "index" not in args: args["index"] = "%d" % i i += 1 else: try: int(args["index"]) except ValueError: raise else: args["index"] = str(args["index"]) servs.append(factory(eclass, **args)) service[endpoint] = servs except KeyError: pass return service
def test_sign_verify_assertion_with_cert_from_instance(self): assertion = factory(saml.Assertion, version="2.0", id="11100", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part("11100", self.sec .my_cert), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Fox", ""), ("", "", "givenName"): ("Bear", ""), }) ) to_sign = [(class_name(assertion), assertion.id)] s_assertion = sigver.signed_instance_factory(assertion, self.sec, to_sign) print(s_assertion) ass = assertion_from_string(s_assertion) ci = "".join(sigver.cert_from_instance(ass)[0].split()) assert ci == self.sec.my_cert res = self.sec.verify_signature(s_assertion, node_name=class_name(ass)) assert res res = self.sec._check_signature(s_assertion, ass, class_name(ass)) assert res
def test_value_1(): #FriendlyName="givenName" Name="urn:oid:2.5.4.42" # NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" attribute = utils.factory(saml.Attribute, name="urn:oid:2.5.4.42", name_format=NAME_FORMAT_URI) assert _eq(attribute.keyswv(), ["name", "name_format"]) assert attribute.name == "urn:oid:2.5.4.42" assert attribute.name_format == saml.NAME_FORMAT_URI
def test_attribute_statement_2(): statement = utils.factory( saml.Statement, attribute=[ utils.factory(saml.Attribute, attribute_value=[ utils.factory(saml.AttributeValue, text="Derek") ], friendly_name="givenName"), utils.factory(saml.Attribute, attribute_value=[ utils.factory(saml.AttributeValue, text="Jeter") ], friendly_name="surName"), ]) assert statement.keyswv() == ["attribute"] assert len(statement.attribute) == 2
def _authn_statement(self, authn_class=None, authn_auth=None, authn_decl=None): if authn_class: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_class_ref( authn_class, authn_auth)) elif authn_decl: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid(), authn_context=self._authn_context_decl_ref(authn_decl)) else: return factory(saml.AuthnStatement, authn_instant=instant(), session_index=sid())
def test_sign_response_2(self): assertion2 = factory( saml.Assertion, version="2.0", id="id-11122", issuer=saml.Issuer(text="the-issuer-2"), issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part("id-11122", self.sec .my_cert), attribute_statement=do_attribute_statement({ ("name:surName", "nameformat", "surName"): ("Fox", ""), ("name:givenName", "nameformat", "givenName"): ("Bear", ""), }) ) response = factory( samlp.Response, issuer=saml.Issuer(text="the-isser-2"), status=success_status_factory(), assertion=assertion2, version="2.0", issue_instant="2099-10-30T13:20:28Z", id="id-22233", signature=sigver.pre_signature_part("id-22233", self.sec.my_cert), ) to_sign = [(class_name(assertion2), assertion2.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) assert s_response is not None response2 = response_from_string(s_response) sass = response2.assertion[0] ['signature', 'attribute_statement', 'version', 'id', 'issue_instant'] ['issuer', 'attribute_statement', 'issue_instant', 'version', 'signature', 'id'] assert _eq(sass.keyswv(), ['issuer', 'attribute_statement', 'issue_instant', 'version', 'signature', 'id']) assert sass.version == "2.0" assert sass.id == "id-11122" item = self.sec.check_signature(response2, class_name(response), s_response) assert isinstance(item, samlp.Response)
def do_subject(not_on_or_after, name_id, **farg): specs = farg['subject_confirmation'] if isinstance(specs, list): res = [do_subject_confirmation(not_on_or_after, **s) for s in specs] else: res = [do_subject_confirmation(not_on_or_after, **specs)] return factory(saml.Subject, name_id=name_id, subject_confirmation=res)
def conditions(self, sp_entity_id): """ Return a saml.Condition instance :param sp_entity_id: The SP entity ID :return: A saml.Condition instance """ return factory( saml.Conditions, not_before=instant(), # How long might depend on who's getting it not_on_or_after=self.not_on_or_after(sp_entity_id), audience_restriction=[ factory( saml.AudienceRestriction, audience=[factory(saml.Audience, text=sp_entity_id)], ), ], )
def test_attribute(): a = utils.factory( saml.Attribute, friendly_name="eduPersonScopedAffiliation", name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9", name_format="urn:oasis:names:tc:SAML:2.0:attrname-format:uri") assert _eq(a.keyswv(), ["friendly_name", "name", "name_format"]) a = utils.factory( saml.Attribute, friendly_name="eduPersonScopedAffiliation", name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9", name_format="urn:oasis:names:tc:SAML:2.0:attrname-format:uri", attribute_value=[saml.AttributeValue(text="*****@*****.**")]) assert _eq(a.keyswv(), ["friendly_name", "name", "name_format", "attribute_value"])
def test_subject(): subject = utils.factory( saml.Subject, text="_aaa", name_id=saml.NameID(text=saml.NAMEID_FORMAT_TRANSIENT)) assert _eq(subject.keyswv(), ["text", "name_id"]) assert subject.text == "_aaa" assert subject.name_id.text == saml.NAMEID_FORMAT_TRANSIENT
def test_value_2(): attribute = utils.factory(saml.Attribute, name="urn:oid:2.5.4.42", name_format=NAME_FORMAT_URI, friendly_name="givenName") assert _eq(attribute.keyswv(), ["name", "name_format", "friendly_name"]) assert attribute.name == "urn:oid:2.5.4.42" assert attribute.name_format == NAME_FORMAT_URI assert attribute.friendly_name == "givenName"
def test_xbox_non_ascii_ava(): conf = config.SPConfig() conf.load_file("server_conf") md = MetadataStore([saml, samlp], None, conf) md.load("local", IDP_EXAMPLE) conf.metadata = md conf.only_use_keys_in_metadata = False sec = sigver.security_context(conf) assertion = factory(saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part( "11111", sec.my_cert, 1), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Föö", ""), ("", "", "givenName"): ("Bär", ""), })) sigass = sec.sign_statement( assertion, class_name(assertion), key_file=PRIV_KEY, node_id=assertion.id, ) _ass0 = saml.assertion_from_string(sigass) encrypted_assertion = EncryptedAssertion() encrypted_assertion.add_extension_element(_ass0) _, pre = make_temp(str(pre_encryption_part()).encode('utf-8'), decode=False) enctext = sec.crypto.encrypt( str(encrypted_assertion), conf.cert_file, pre, "des-192", '/*[local-name()="EncryptedAssertion"]/*[local-name()="Assertion"]', ) decr_text = sec.decrypt(enctext, key_file=PRIV_KEY) _seass = saml.encrypted_assertion_from_string(decr_text) assertions = [] assers = extension_elements_to_elements(_seass.extension_elements, [saml, samlp]) for ass in assers: _txt = sec.verify_signature(str(ass), PUB_KEY, node_name=class_name(assertion)) if _txt: assertions.append(ass) assert assertions print(assertions)
def test_complex_factory(): r = set_arg(Subject, 'in_response_to', '123456') subject = utils.factory(Subject, **r[0]) assert _eq(subject.keyswv(), ['subject_confirmation']) assert _eq(subject.subject_confirmation.keyswv(), ['subject_confirmation_data']) assert _eq(subject.subject_confirmation.subject_confirmation_data.keyswv(), ['in_response_to']) assert subject.subject_confirmation.subject_confirmation_data.in_response_to == '123456'
def test_xbox(): conf = config.SPConfig() conf.load_file("server_conf") md = MetadataStore([saml, samlp], None, conf) md.load("local", full_path("idp_example.xml")) conf.metadata = md conf.only_use_keys_in_metadata = False sec = sigver.security_context(conf) assertion = factory(saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part( "11111", sec.my_cert, 1), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), })) sigass = sec.sign_statement(assertion, class_name(assertion), key_file=full_path("test.key"), node_id=assertion.id) _ass0 = saml.assertion_from_string(sigass) encrypted_assertion = EncryptedAssertion() encrypted_assertion.add_extension_element(_ass0) _, pre = make_temp(str(pre_encryption_part()).encode('utf-8'), decode=False) enctext = sec.crypto.encrypt( str(encrypted_assertion), conf.cert_file, pre, "des-192", '/*[local-name()="EncryptedAssertion"]/*[local-name()="Assertion"]') decr_text = sec.decrypt(enctext) _seass = saml.encrypted_assertion_from_string(decr_text) assertions = [] assers = extension_elements_to_elements(_seass.extension_elements, [saml, samlp]) sign_cert_file = full_path("test.pem") for ass in assers: _ass = "%s" % ass #_ass = _ass.replace('xsi:nil="true" ', '') #assert sigass == _ass _txt = sec.verify_signature(_ass, sign_cert_file, node_name=class_name(assertion)) if _txt: assertions.append(ass) print(assertions)
def test_subject_confirmation_data(): s = utils.factory(saml.SubjectConfirmation, in_response_to="_12345678", not_before="2010-02-11T07:30:00Z", not_on_or_after="2010-02-11T07:35:00Z", recipient="http://example.com/sp/", address="192.168.0.10") assert _eq(s.keyswv(), ["in_response_to", "not_before", "not_on_or_after", "recipient", "address"])
def test_sign_then_encrypt_assertion2(self): # Begin with the IdPs side _sec = self.server.sec nameid_policy = samlp.NameIDPolicy( allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT) asser = Assertion({"givenName": "Derek", "surName": "Jeter"}) assertion = asser.construct( self.client.config.entityid, "_012345", "http://lingon.catalogix.se:8087/", factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT), policy=self.server.config.getattr("policy", "idp"), issuer=self.server._issuer(), attrconvs=self.server.config.attribute_converters, authn_class=INTERNETPROTOCOLPASSWORD, authn_auth="http://www.example.com/login") assertion.signature = sigver.pre_signature_part( assertion.id, _sec.my_cert, 1) sigass = _sec.sign_statement(assertion, class_name(assertion), key_file=self.client.sec.key_file, node_id=assertion.id) sigass = rm_xmltag(sigass) response = sigver.response_factory( in_response_to="_012345", destination="http://lingon.catalogix.se:8087/", status=s_utils.success_status_factory(), issuer=self.server._issuer(), encrypted_assertion=EncryptedAssertion()) xmldoc = "%s" % response # strangely enough I get different tags if I run this test separately # or as part of a bunch of tests. xmldoc = add_subelement(xmldoc, "EncryptedAssertion", sigass) enctext = _sec.crypto.encrypt_assertion(xmldoc, _sec.cert_file, pre_encryption_part()) #seresp = samlp.response_from_string(enctext) resp_str = base64.encodestring(enctext) # Now over to the client side resp = self.client.parse_authn_request_response( resp_str, BINDING_HTTP_POST, {"_012345": "http://foo.example.com/service"}) #assert resp.encrypted_assertion == [] assert resp.assertion assert resp.ava == {'givenName': ['Derek'], 'sn': ['Jeter']}
def do_subject(policy, sp_entity_id, name_id, **farg): # specs = farg['subject_confirmation'] if isinstance(specs, list): res = [do_subject_confirmation(policy, sp_entity_id, **s) for s in specs] else: res = [do_subject_confirmation(policy, sp_entity_id, **specs)] return factory(saml.Subject, name_id=name_id, subject_confirmation=res)
def to_(self, attrvals): """ Create a list of Attribute instances. :param attrvals: A dictionary of attributes and values :return: A list of Attribute instances """ attributes = [] for key, value in attrvals.items(): key = key.lower() try: attributes.append(factory(saml.Attribute, name=self._to[key], name_format=self.name_format, friendly_name=key, attribute_value=do_ava(value))) except KeyError: attributes.append(factory(saml.Attribute, name=key, attribute_value=do_ava(value))) return attributes
def test_assertion(self): assertion = s_utils.assertion_factory( subject=factory(saml.Subject, text="_aaa", name_id=factory( saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT)), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Jeter", ""), ("", "", "givenName"): ("Derek", ""), }), issuer=self.server._issuer(), ) assert _eq(assertion.keyswv(), [ 'attribute_statement', 'issuer', 'id', 'subject', 'issue_instant', 'version' ]) assert assertion.version == "2.0" assert assertion.issuer.text == "urn:mace:example.com:saml:roland:idp" # assert assertion.attribute_statement attribute_statement = assertion.attribute_statement assert len(attribute_statement.attribute) == 2 attr0 = attribute_statement.attribute[0] attr1 = attribute_statement.attribute[1] if attr0.attribute_value[0].text == "Derek": assert attr0.friendly_name == "givenName" assert attr1.friendly_name == "surName" assert attr1.attribute_value[0].text == "Jeter" else: assert attr1.friendly_name == "givenName" assert attr1.attribute_value[0].text == "Derek" assert attr0.friendly_name == "surName" assert attr0.attribute_value[0].text == "Jeter" # subject = assertion.subject assert _eq(subject.keyswv(), ["text", "name_id"]) assert subject.text == "_aaa" assert subject.name_id.format == saml.NAMEID_FORMAT_TRANSIENT
def test_sign_then_encrypt_assertion2(self): # Begin with the IdPs side _sec = self.server.sec nameid_policy = samlp.NameIDPolicy( allow_create="false", format=saml.NAMEID_FORMAT_PERSISTENT) asser = Assertion({"givenName": "Derek", "surName": "Jeter"}) assertion = asser.construct( self.client.config.entityid, "_012345", "http://lingon.catalogix.se:8087/", factory(saml.NameID, format=saml.NAMEID_FORMAT_TRANSIENT), policy=self.server.config.getattr("policy", "idp"), issuer=self.server._issuer(), attrconvs=self.server.config.attribute_converters, authn_class=INTERNETPROTOCOLPASSWORD, authn_auth="http://www.example.com/login") assertion.signature = sigver.pre_signature_part( assertion.id, _sec.my_cert, 1) sigass = _sec.sign_statement( assertion, class_name(assertion), #key_file="pki/mykey.pem", key_file="test.key", node_id=assertion.id) # Create an Assertion instance from the signed assertion _ass = saml.assertion_from_string(sigass) response = sigver.response_factory( in_response_to="_012345", destination="https://www.example.com", status=s_utils.success_status_factory(), issuer=self.server._issuer(), assertion=_ass) enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file, pre_encryption_part()) #seresp = samlp.response_from_string(enctext) resp_str = base64.encodestring(enctext) # Now over to the client side resp = self.client.parse_authn_request_response( resp_str, BINDING_HTTP_POST, {"_012345": "http://foo.example.com/service"}) #assert resp.encrypted_assertion == [] assert resp.assertion assert resp.ava == {'givenName': ['Derek'], 'sn': ['Jeter']}
def to_format(self, attr): """ Creates an Attribute instance with name, name_format and friendly_name :param attr: The local name of the attribute :return: An Attribute instance """ try: _attr = self._to[attr] except KeyError: try: _attr = self._to[attr.lower()] except: _attr = '' if _attr: return factory(saml.Attribute, name=_attr, name_format=self.name_format, friendly_name=attr) else: return factory(saml.Attribute, name=attr)
def test_sign_response_2(self): assertion2 = factory(saml.Assertion, version="2.0", id="11122", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part( "11122", self.sec.my_cert), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Räv", ""), ("", "", "givenName"): ("Björn", ""), })) response = factory(samlp.Response, assertion=assertion2, id="22233", signature=sigver.pre_signature_part( "22233", self.sec.my_cert)) to_sign = [(class_name(assertion2), assertion2.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) assert s_response is not None response2 = response_from_string(s_response) sass = response2.assertion[0] assert _eq(sass.keyswv(), [ 'attribute_statement', 'issue_instant', 'version', 'signature', 'id' ]) assert sass.version == "2.0" assert sass.id == "11122" item = self.sec.check_signature(response2, class_name(response), s_response) assert isinstance(item, samlp.Response)
def to_(self, attrvals): """ Create a list of Attribute instances. :param attrvals: A dictionary of attributes and values :return: A list of Attribute instances """ attributes = [] for key, value in attrvals.items(): name = self._to.get(key.lower()) if name: typ = self._special_cases.get(name, '') attr_value = do_ava(value, typ) attributes.append( factory(Attribute, name=name, name_format=self.name_format, attribute_value=attr_value)) else: attributes.append( factory(Attribute, name=key, attribute_value=do_ava(value))) return attributes
def to_(self, attrvals): """ Create a list of Attribute instances. :param attrvals: A dictionary of attributes and values :return: A list of Attribute instances """ attributes = [] for key, value in attrvals.items(): name = self._to.get(key.lower()) if name: if name == "urn:oid:1.3.6.1.4.1.5923.1.1.1.10": # special case for eduPersonTargetedID attr_value = [] for v in value: extension_element = ExtensionElement( "NameID", NAMESPACE, attributes={'Format': NAMEID_FORMAT_PERSISTENT}, text=v) attrval = saml.AttributeValue( extension_elements=[extension_element]) attr_value.append(attrval) else: attr_value = do_ava(value) attributes.append( factory(saml.Attribute, name=name, name_format=self.name_format, friendly_name=key, attribute_value=attr_value)) else: attributes.append( factory(saml.Attribute, name=key, attribute_value=do_ava(value))) return attributes
def test_exception_sign_verify_with_cert_from_instance(self): assertion = factory( saml.Assertion, version="2.0", id="id-11100", issuer=saml.Issuer(text="the-issuer-2"), issue_instant="2009-10-30T13:20:28Z", attribute_statement=do_attribute_statement({ ("name:surName", "nameformat", "surName"): ("Foo", ""), ("name:givenName", "nameformat", "givenName"): ("Bar", ""), }) ) response = factory( samlp.Response, issuer=saml.Issuer(text="the-isser"), status=success_status_factory(), assertion=assertion, version="2.0", issue_instant="2099-10-30T13:20:28Z", id="id-22222", signature=sigver.pre_signature_part( "id-22222", self.sec.my_cert ), ) to_sign = [(class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) response2 = response_from_string(s_response) # Change something that should make everything fail response2.id = "id-23456" with raises(sigver.SignatureError): self.sec._check_signature(s_response, response2, class_name(response2))
def to_(self, attrvals): """ Create a list of Attribute instances. :param attrvals: A dictionary of attributes and values :return: A list of Attribute instances """ attributes = [] for key, value in list(attrvals.items()): key = key.lower() attributes.append( factory(saml.Attribute, name=key, name_format=self.name_format, attribute_value=do_ava(value))) return attributes
def test_sign_verify(self): response = factory(samlp.Response, assertion=self._assertion, id="22233", signature=sigver.pre_signature_part("22233", self.sec.my_cert)) to_sign = [(class_name(self._assertion), self._assertion.id), (class_name(response), response.id)] s_response = sigver.signed_instance_factory(response, self.sec, to_sign) print s_response res = self.sec.verify_signature("%s" % s_response, node_name=class_name(samlp.Response())) print res assert res
def setup_class(self): xmlexec = get_xmlsec_binary() self.sec = sigver.SecurityContext(xmlexec, key_file=PRIV_KEY, cert_file=PUB_KEY, debug=1) self._assertion = factory(saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part( "11111", self.sec.my_cert, 1), attribute_statement=do_attribute_statement({ ("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), }))
def setup_class(self): conf = config.SPConfig() conf.load_file("server_conf") md = MetadataStore([saml, samlp], None, conf) md.load("local", full_path("metadata_cert.xml")) conf.metadata = md conf.only_use_keys_in_metadata = False self.sec = sigver.security_context(conf) assertion = factory( saml.Assertion, version="2.0", id="11111", issue_instant="2009-10-30T13:20:28Z", signature=sigver.pre_signature_part("11111", self.sec.my_cert, 1), attribute_statement=do_attribute_statement( {("", "", "surName"): ("Foo", ""), ("", "", "givenName"): ("Bar", ""), }) )
def test_multiple_signatures_response(self): response = factory(samlp.Response, assertion=self._assertion, id="22222", signature=sigver.pre_signature_part( "22222", self.sec.my_cert)) # order is important, we can't validate if the signatures are made # in the reverse order to_sign = [(self._assertion, self._assertion.id, ''), (response, response.id, '')] s_response = self.sec.multiple_signatures("%s" % response, to_sign) assert s_response is not None response = response_from_string(s_response) item = self.sec.check_signature(response, class_name(response), s_response, must=True) assert item == response assert item.id == "22222" s_assertion = item.assertion[0] assert isinstance(s_assertion, saml.Assertion) # make sure the assertion was modified when we supposedly signed it assert s_assertion != self._assertion ci = "".join(sigver.cert_from_instance(s_assertion)[0].split()) assert ci == self.sec.my_cert res = self.sec.check_signature(s_assertion, class_name(s_assertion), s_response, must=True) assert res == s_assertion assert s_assertion.id == "11111" assert s_assertion.version == "2.0" assert _eq(s_assertion.keyswv(), [ 'attribute_statement', 'issue_instant', 'version', 'signature', 'id' ])
def do_endpoints(conf, endpoints): service = {} for endpoint, (eclass, indexed) in endpoints.items(): try: servs = [] i = 1 for args in conf[endpoint]: if isinstance(args, six.string_types): # Assume it's the location args = { "location": args, "binding": DEFAULT_BINDING[endpoint] } elif isinstance(args, tuple) or isinstance(args, list): if len(args) == 2: # (location, binding) args = {"location": args[0], "binding": args[1]} elif len(args) == 3: # (location, binding, index) args = { "location": args[0], "binding": args[1], "index": args[2] } if indexed: if "index" not in args: args["index"] = "%d" % i i += 1 else: try: int(args["index"]) except ValueError: raise else: args["index"] = str(args["index"]) servs.append(factory(eclass, **args)) service[endpoint] = servs except KeyError: pass return service
def do_endpoints(conf, endpoints): service = {} for endpoint, (eclass, indexed) in endpoints.items(): try: servs = [] i = 1 for args in conf[endpoint]: if isinstance(args, basestring): # Assume it's the location args = {"location":args, "binding": DEFAULT_BINDING[endpoint]} elif isinstance(args, tuple): # (location, binding) args = {"location":args[0], "binding": args[1]} if indexed and "index" not in args: args["index"] = "%d" % i servs.append(factory(eclass, **args)) i += 1 service[endpoint] = servs except KeyError: pass return service