def testToElement(self): """ Tests the to_etree method of the OneLogin_Saml2_XML """ xml = '<test>test1</test>' elem = etree.fromstring(xml) xml_expected = etree.tostring(elem) res = OneLogin_Saml2_XML.to_etree(xml) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8')) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) res = OneLogin_Saml2_XML.to_etree(elem) self.assertIs(res, elem) with self.assertRaises(ValueError) as context: OneLogin_Saml2_XML.to_etree(1) exception = context.exception self.assertIn("unsupported type", str(exception))
def testToElement(self): """ Tests the to_etree method of the OneLogin_Saml2_XML """ xml = '<test>test1</test>' elem = etree.fromstring(xml) xml_expected = etree.tostring(elem) res = OneLogin_Saml2_XML.to_etree(xml) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) res = OneLogin_Saml2_XML.to_etree(xml.encode('utf8')) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) self.assertIsInstance(res, etree._Element) self.assertEqual(xml_expected, etree.tostring(res)) res = OneLogin_Saml2_XML.to_etree(elem) self.assertIs(res, elem) self.assertRaisesRegexp(ValueError, 'unsupported type', OneLogin_Saml2_XML.to_etree, 1)
def AddSign(xml, key, cert, debug=False, sign_algorithm=OneLogin_Saml2_Constants.RSA_SHA1, digest_algorithm=OneLogin_Saml2_Constants.SHA1, addKeyValue=False): """ Adds signature key and senders certificate to an element (Message or Assertion). :param xml: The element we should sign :type: string | Document :param key: The private key :type: string :param cert: The public :type: string :param debug: Activate the xmlsec debug :type: bool :param sign_algorithm: Signature algorithm method :type sign_algorithm: string :param digest_algorithm: Digest algorithm method :type digest_algorithm: string :returns: Signed XML :rtype: string """ if xml is None or xml == '': raise Exception('Empty string supplied as input') elem = OneLogin_Saml2_XML.to_etree(xml) xmlsec.enable_debug_trace(debug) xmlsec.tree.add_ids(elem, ["ID"]) # Sign the metadata with our private key. sign_algorithm_transform_map = { OneLogin_Saml2_Constants.DSA_SHA1: xmlsec.Transform.DSA_SHA1, OneLogin_Saml2_Constants.RSA_SHA1: xmlsec.Transform.RSA_SHA1, OneLogin_Saml2_Constants.RSA_SHA256: xmlsec.Transform.RSA_SHA256, OneLogin_Saml2_Constants.RSA_SHA384: xmlsec.Transform.RSA_SHA384, OneLogin_Saml2_Constants.RSA_SHA512: xmlsec.Transform.RSA_SHA512 } sign_algorithm_transform = sign_algorithm_transform_map.get( sign_algorithm, xmlsec.Transform.RSA_SHA1) signature = xmlsec.template.create(elem, xmlsec.Transform.EXCL_C14N, sign_algorithm_transform, ns='ds') issuer = OneLogin_Saml2_XML.query(elem, '//saml:Issuer') if len(issuer) > 0: issuer = issuer[0] issuer.addnext(signature) else: elem.insert(0, signature) elem_id = elem.get('ID', None) if elem_id: elem_id = '#' + elem_id #else: # elem_id = "" digest_algorithm_transform_map = { OneLogin_Saml2_Constants.SHA1: xmlsec.Transform.SHA1, OneLogin_Saml2_Constants.SHA256: xmlsec.Transform.SHA256, OneLogin_Saml2_Constants.SHA384: xmlsec.Transform.SHA384, OneLogin_Saml2_Constants.SHA512: xmlsec.Transform.SHA512 } digest_algorithm_transform = digest_algorithm_transform_map.get( digest_algorithm, xmlsec.Transform.SHA1) ref = xmlsec.template.add_reference(signature, digest_algorithm_transform, uri=elem_id) xmlsec.template.add_transform(ref, xmlsec.Transform.ENVELOPED) xmlsec.template.add_transform(ref, xmlsec.Transform.EXCL_C14N) key_info = xmlsec.template.ensure_key_info(signature) if addKeyValue: xmlsec.template.add_key_value(key_info) xmlsec.template.add_x509_data(key_info) dsig_ctx = xmlsec.SignatureContext() sign_key = xmlsec.Key.from_memory(key, xmlsec.KeyFormat.PEM, None) sign_key.load_cert_from_memory(cert, xmlsec.KeyFormat.PEM) dsig_ctx.key = sign_key dsig_ctx.sign(signature) return OneLogin_Saml2_XML.to_string(elem)
def validate_metadata_sign(xml, cert=None, fingerprint=None, fingerprintalg='sha1', validatecert=False, debug=False): """ Validates a signature of a EntityDescriptor. :param xml: The element we should validate :type: string | Document :param cert: The public cert :type: string :param fingerprint: The fingerprint of the public cert :type: string :param fingerprintalg: The algorithm used to build the fingerprint :type: string :param validatecert: If true, will verify the signature and if the cert is valid. :type: bool :param debug: Activate the xmlsec debug :type: bool :param raise_exceptions: Whether to return false on failure or raise an exception :type raise_exceptions: Boolean """ if xml is None or xml == '': raise Exception('Empty string supplied as input') elem = OneLogin_Saml2_XML.to_etree(xml) xmlsec.enable_debug_trace(debug) xmlsec.tree.add_ids(elem, ["ID"]) signature_nodes = OneLogin_Saml2_XML.query( elem, '/md:EntitiesDescriptor/ds:Signature') if len(signature_nodes) == 0: signature_nodes += OneLogin_Saml2_XML.query( elem, '/md:EntityDescriptor/ds:Signature') if len(signature_nodes) == 0: signature_nodes += OneLogin_Saml2_XML.query( elem, '/md:EntityDescriptor/md:SPSSODescriptor/ds:Signature') signature_nodes += OneLogin_Saml2_XML.query( elem, '/md:EntityDescriptor/md:IDPSSODescriptor/ds:Signature') if len(signature_nodes) > 0: for signature_node in signature_nodes: # Raises expection if invalid Saml2_Utils.validate_node_sign(signature_node, elem, cert, fingerprint, fingerprintalg, validatecert, debug, raise_exceptions=True) return True else: raise Exception( 'Could not validate metadata signature: No signature nodes found.' )