Merge pull request #34 from fredrikt/master

Make crypto backend configurable.
This commit is contained in:
Roland Hedberg 2013-05-07 00:01:07 -07:00
commit 3db4d1a424
26 changed files with 133 additions and 391 deletions

View File

@ -18,7 +18,6 @@ from saml2 import BINDING_HTTP_ARTIFACT
from saml2.attribute_converter import ac_factory
from saml2.assertion import Policy
from saml2.sigver import get_xmlsec_binary
from saml2.mdstore import MetadataStore
from saml2.virtual_org import VirtualOrg
@ -191,6 +190,7 @@ class Config(object):
self.domain = ""
self.name_qualifier = ""
self.entity_category = ""
self.crypto_backend = 'xmlsec1'
def setattr(self, context, attr, val):
if context == "":
@ -303,16 +303,6 @@ class Config(object):
except KeyError:
pass
if not metadata_construction:
if not self.xmlsec_binary:
self.xmlsec_binary = get_xmlsec_binary()
# verify that xmlsec is where it's supposed to be
if not os.path.exists(self.xmlsec_binary):
#if not os.access(, os.F_OK):
raise Exception(
"xmlsec binary not in '%s' !" % self.xmlsec_binary)
self.load_complex(cnf, metadata_construction=metadata_construction)
self.context = self.def_context

View File

@ -48,28 +48,33 @@ class Client(Entity):
def __init__(self, user, passwd, sp="", idp=None, metadata_file=None,
xmlsec_binary=None, verbose=0, ca_certs="",
disable_ssl_certificate_validation=True, key_file=None,
cert_file=None):
cert_file=None, config=None):
"""
:param user: user name
:param passwd: user password
:param sp: The SP URL
:param idp: The IdP PAOS endpoint
:param metadata_file: Where the metadata file is if used
:param xmlsec_binary: Where the xmlsec1 binary can be found
:param xmlsec_binary: Where the xmlsec1 binary can be found (*)
:param verbose: Chatty or not
:param ca_certs: is the path of a file containing root CA certificates
for SSL server certificate validation.
for SSL server certificate validation (*)
:param disable_ssl_certificate_validation: If
disable_ssl_certificate_validation is true, SSL cert validation
will not be performed.
will not be performed (*)
:param key_file: Private key filename (*)
:param cert_file: Certificate filename (*)
:param config: Config() instance, overrides all the parameters marked
with an asterisk (*) above
"""
config = Config()
config.disable_ssl_certificate_validation = \
disable_ssl_certificate_validation
config.key_file = key_file
config.cert_file = cert_file
config.ca_certs = ca_certs
config.xmlsec_binary = xmlsec_binary
if not config:
config = Config()
config.disable_ssl_certificate_validation = \
disable_ssl_certificate_validation
config.key_file = key_file
config.cert_file = cert_file
config.ca_certs = ca_certs
config.xmlsec_binary = xmlsec_binary
Entity.__init__(self, "sp", config)
self._idp = idp

View File

@ -1,271 +0,0 @@
import logging
import os
import sys
from subprocess import Popen
from subprocess import PIPE
from tempfile import NamedTemporaryFile
from saml2.sigver import make_temp
from saml2.sigver import parse_xmlsec_output
from saml2.sigver import XmlsecError
from saml2 import saml
__author__ = 'rohe0002'
import xmlenc as enc
logger = logging.getLogger(__name__)
#<EncryptedData
# xmlns="http://www.w3.org/2001/04/xmlenc#"
# Type="http://www.w3.org/2001/04/xmlenc#Element">
# <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
# <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
# <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
# <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
# <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
# <KeyName/>
# </KeyInfo>
# <CipherData>
# <CipherValue/>
# </CipherData>
# </EncryptedKey>
# </KeyInfo>
# <CipherData>
# <CipherValue/>
# </CipherData>
#</EncryptedData>
class DecryptionError(Exception):
pass
ID_ATTR = "ID"
#NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:Assertion"
ENC_DATA = "urn:oasis:names:tc:SAML:2.0:assertion:EncryptedData"
ENC_KEY_CLASS = "EncryptedKey"
RSA_15 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"
AES128_CBC="http://www.w3.org/2001/04/xmlenc#aes128-cbc"
TRIPLE_DES = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
LOG_LINE = 60*"="+"\n%s\n"+60*"-"+"\n%s"+60*"="
LOG_LINE_2 = 60*"="+"\n%s\n%s\n"+60*"-"+"\n%s"+60*"="
# registered xmlsec transforms
TRANSFORMS = ["base64","enveloped-signature","c14n","c14n-with-comments",
"c14n11","c14n11-with-comments","exc-c14n",
"exc-c14n-with-comments","xpath","xpath2","xpointer","xslt",
"aes128-cbc","aes192-cbc","aes256-cbc","kw-aes128","kw-aes192",
"kw-aes256","tripledes-cbc","kw-tripledes","dsa-sha1","hmac-md5",
"hmac-ripemd160","hmac-sha1","hmac-sha224","hmac-sha256",
"hmac-sha384","hmac-sha512","md5","ripemd160","rsa-md5",
"rsa-ripemd160","rsa-sha1","rsa-sha224","rsa-sha256","rsa-sha384",
"rsa-sha512","rsa-1_5","rsa-oaep-mgf1p","sha1","sha224","sha256",
"sha384","sha512"]
ALGORITHM = {
"tripledes-cbc": TRIPLE_DES,
"aes128-cbc": AES128_CBC,
"rsa-1_5": RSA_15,
"rsa-oaep-mgf1p": RSA_OAEP
}
def template(ident=None, session_key="tripledes-cbc"):
"""
If an assertion is to be signed the signature part has to be preset
with which algorithms to be used, this function returns such a
preset part.
:param ident: The identifier of the assertion, so you know which assertion
was signed
:return: A preset signature part
"""
cipher_data = enc.CipherData(cipher_value=enc.CipherValue())
encryption_method = enc.EncryptionMethod(algorithm=ALGORITHM[session_key])
#key_info = ds.KeyInfo(key_name=ds.KeyName())
encrypted_data = enc.EncryptedData(
type = "http://www.w3.org/2001/04/xmlenc#Element",
encryption_method=encryption_method,
#key_info=key_info,
cipher_data=cipher_data)
if ident:
encrypted_data.id = "%s" % ident
return encrypted_data
# xmlsec decrypt --privkey-pem userkey.pem doc-encrypted.xml
def decrypt_message(enctext, xmlsec_binary, key_file=None,
key_file_type="privkey-pem", cafile=None,
epath=None, id_attr="",
node_name="", node_id=None, debug=False):
""" Decrypts an encrypted part of a XML document.
:param enctext: XML document containing an encrypted part
:param xmlsec_binary: The xmlsec1 binaries to be used
:param key_file: The key used to decrypt the message
:param key_file_type: The key file type
:param node_name: The SAML class of the root node in the message
:param node_id: The identifier of the root node if any
:param id_attr: Should normally be one of "id", "Id" or "ID"
:param debug: To debug or not
:return: The decrypted document if all was OK otherwise will raise an
exception.
"""
if not id_attr:
id_attr = ID_ATTR
_, fil = make_temp(enctext, decode=False)
com_list = [xmlsec_binary, "--decrypt",
"--%s" % key_file_type, key_file]
if key_file_type in ["privkey-pem", "privkey-der", "pkcs8-pem",
"pkcs8-der"]:
if isinstance(cafile, basestring):
com_list.append(cafile)
else:
com_list.extend(cafile)
if id_attr:
com_list.extend(["--id-attr:%s" % id_attr, node_name])
elif epath:
xpath = create_xpath(epath)
com_list.extend(['--node-xpath', xpath])
# if debug:
# com_list.append("--store-signatures")
if node_id:
com_list.extend(["--node-id", node_id])
com_list.append(fil)
if debug:
try:
print " ".join(com_list)
except TypeError:
print "key_file_type", key_file_type
print "key_file", key_file
print "node_name", node_name
print "fil", fil
raise
print "%s: %s" % (key_file, os.access(key_file, os.F_OK))
print "%s: %s" % (fil, os.access(fil, os.F_OK))
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
p_out = pof.stdout.read()
try:
p_err = pof.stderr.read()
if debug:
print p_err
verified = parse_xmlsec_output(p_err)
except XmlsecError, exc:
logger(LOG_LINE % (p_out, exc))
raise DecryptionError("%s" % (exc,))
return verified
# Whole document
#xmlsec1 encrypt --pubkey-pem ServerKeys/pubkey.pem --session-key des-192
# --xml-data ClientRequest.xml
# --output ClientEncrypted.xml EncryptionTemplate.xml
# single value
#/opt/local/bin/xmlsec1 encrypt --pubkey-cert-pem pubkey.pem
# --session-key des-192 --xml-data pre_saml2_response.xml
# --node-xpath '/*[local-name()="Response"]/*[local-name()="Assertion"]/*[local-name()="Subject"]/*[local-name()="EncryptedID"]/text()'
# encryption_template.xml > enc.out
def create_xpath(path):
"""
:param path: list of element names
"""
return "/*".join(['[local-name()="%s"]' % e for e in path]) + "/text()"
def encrypt_using_xmlsec(xmlsec, data, template, epath=None, key=None,
key_file=None, key_file_type="pubkey-pem",
session_key=None):
"""encrypting a value using xmlsec.
:param xmlsec: Path to the xmlsec1 binary
:param data: A XML document from which the value should be picked.
:param template: The encyption part template
:param epath: Which value to encrypt, if not the whole document
should be encrypted.
:param key: The key to be used for the encrypting, either this or
:param key_file: The file where the key can be found
:param key_file_type: pubkey-pem, pubkey-der, pubkey-cert-pem,
pubkey-cert-der, privkey-der, privkey-pem, ...
:param session_key: Key algorithm
:return: The signed statement
"""
if not key_file and key:
_, key_file = make_temp("%s" % key, ".pem")
ntf = NamedTemporaryFile()
xpath = create_xpath(epath)
com_list = [xmlsec, "encrypt",
"--output", ntf.name,
"--xml-data", data,
'--node-xpath', xpath,
key_file_type, key_file
]
if session_key:
com_list.extend(["--session-key", session_key])
_, fil = make_temp("%s" % template, decode=False)
com_list.append(fil)
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
p_out = pof.stdout.read()
p_err = pof.stderr.read()
# this doesn't work if --store-signatures are used
if p_out == "":
ntf.seek(0)
encrypted_statement = ntf.read()
if not encrypted_statement:
logger.error(p_err)
raise Exception("Encryption failed")
else:
return encrypted_statement
else:
logger.error(LOG_LINE % (p_out, p_err))
raise Exception("Encryption failed")
def encrypt_id(response, xmlsec, key_file, key_file_type, identifier,
session_key, node_id=""):
"""
:param response: The response as a Response class instance
:param xmlsec: Where the xmlsec1 binaries reside
:param key_file: Which key file to use
:param key_file_type: The type of key file
:param identifier: The subject identifier
:param session_key: The type of key used to encrypt
:return: statement with the subject identifier encrypted
"""
if not response.assertion[0].subject.encrypted_id:
response.assertion[0].subject.encrypted_id = saml.EncryptedID(
identifier)
statement = encrypt_using_xmlsec(xmlsec, "%s" % response,
template=template(ident=node_id,
session_key=session_key),
epath=["Response","Assertion","Subject","NameID"],
key_file=key_file,
key_file_type=key_file_type,
session_key=session_key)
return statement

View File

@ -72,7 +72,7 @@ def signed(item):
return False
def get_xmlsec_binary(paths=None):
def _get_xmlsec_binary(paths=None):
"""
Tries to find the xmlsec1 binary.
@ -107,18 +107,17 @@ def get_xmlsec_binary(paths=None):
raise Exception("Can't find %s" % bin_name)
def _get_xmlsec_cryptobackend(path=None, search_paths=None, debug=False):
"""
Initialize a CryptoBackendXmlSec1 crypto backend.
def get_xmlsec_cryptobackend(path=None, search_paths=None, debug=False):
This function is now internal to this module.
"""
if path is None:
path=get_xmlsec_binary(paths=search_paths)
path=_get_xmlsec_binary(paths=search_paths)
return CryptoBackendXmlSec1(path, debug=debug)
try:
XMLSEC_BINARY = get_xmlsec_binary()
except Exception:
XMLSEC_BINARY = ""
ID_ATTR = "ID"
NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:Assertion"
ENC_NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:EncryptedAssertion"
@ -145,14 +144,6 @@ class DecryptError(Exception):
# --------------------------------------------------------------------------
def xmlsec_version(execname):
com_list = [execname, "--version"]
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
try:
return pof.stdout.read().split(" ")[1]
except Exception:
return ""
def _make_vals(val, klass, seccont, klass_inst=None, prop=None, part=False,
base64encode=False, elements_to_sign=None):
@ -601,6 +592,9 @@ class CryptoBackend():
def __init__(self, debug=False):
self.debug = debug
def version(self):
raise NotImplementedError()
def encrypt(self, text, recv_key, template, key_type):
raise NotImplementedError()
@ -629,6 +623,14 @@ class CryptoBackendXmlSec1(CryptoBackend):
assert(isinstance(xmlsec_binary, basestring))
self.xmlsec = xmlsec_binary
def version(self):
com_list = [self.xmlsec, "--version"]
pof = Popen(com_list, stderr=PIPE, stdout=PIPE)
try:
return pof.stdout.read().split(" ")[1]
except Exception:
return ""
def encrypt(self, text, recv_key, template, key_type):
logger.info("Encryption input len: %d" % len(text))
_, fil = make_temp("%s" % text, decode=False)
@ -782,6 +784,11 @@ class CryptoBackendXMLSecurity(CryptoBackend):
CryptoBackend.__init__(self)
self.debug = debug
def version():
# XXX if XMLSecurity.__init__ included a __version__, that would be
# better than static 0.0 here.
return "XMLSecurity 0.0"
def sign_statement(self, statement, _class_name, key_file, _nodeid,
_id_attr):
"""
@ -842,10 +849,22 @@ def security_context(conf, debug=None):
if _only_md is None:
_only_md = False
crypto = get_xmlsec_cryptobackend(conf.xmlsec_binary, debug=debug)
# Uncomment this to enable the new and somewhat untested pyXMLSecurity
# crypto backend.
#crypto = CryptoBackendXMLSecurity(debug=debug)
if conf.crypto_backend == 'xmlsec1':
xmlsec_binary = conf.xmlsec_binary
if not xmlsec_binary:
xmlsec_binary = _get_xmlsec_binary()
# verify that xmlsec is where it's supposed to be
if not os.path.exists(xmlsec_binary):
#if not os.access(, os.F_OK):
raise Exception(
"xmlsec binary not in '%s' !" % xmlsec_binary)
crypto = _get_xmlsec_cryptobackend(xmlsec_binary, debug=debug)
elif conf.crypto_backend == 'XMLSecurity':
# new and somewhat untested pyXMLSecurity crypto backend.
crypto = CryptoBackendXMLSecurity(debug=debug)
else:
raise Exception('Unknown crypto_backend %s' % (
repr(conf.crypto_backend)))
return SecurityContext(crypto, conf.key_file,
cert_file=conf.cert_file, metadata=metadata,

View File

@ -2,7 +2,7 @@
from saml2 import BINDING_SOAP, BINDING_HTTP_REDIRECT, NAME_FORMAT_URI
BASE = "http://localhost:8089/"
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG={
@ -27,7 +27,7 @@ CONFIG={
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
#"xmlsec_binary" : xmlsec_path,
#"xmlsec_binary" : None,
"metadata": {
"local": [full_path("metadata.xml"), full_path("vo_metadata.xml")],
},

View File

@ -1,6 +1,6 @@
from saml2.extension.idpdisc import BINDING_DISCO
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://localhost:8088"
@ -17,7 +17,7 @@ CONFIG = {
},
},
"debug" : 1,
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("servera.xml")],
},

View File

@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://localhost:8088"
@ -85,7 +85,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("servera.xml"),
full_path("vo_metadata.xml")],

View File

@ -2,7 +2,7 @@ from saml2 import BINDING_SOAP, BINDING_HTTP_REDIRECT, BINDING_HTTP_POST
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://localhost:8088"
@ -41,7 +41,7 @@ CONFIG = {
"debug": 1,
"key_file": full_path("test.key"),
"cert_file": full_path("test.pem"),
"xmlsec_binary": xmlsec_path,
"xmlsec_binary": None,
"metadata": {
"local": [full_path("metadata_sp_1.xml"),
full_path("vo_metadata.xml")],

View File

@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://localhost:8088"
@ -86,7 +86,7 @@ CONFIG = {
"debug": 1,
"key_file": full_path("test.key"),
"cert_file": full_path("test.pem"),
"xmlsec_binary": xmlsec_path,
"xmlsec_binary": None,
"metadata": {
"local": [full_path("servera.xml"),
full_path("vo_metadata.xml")],

View File

@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://localhost:8089"
@ -86,7 +86,7 @@ CONFIG = {
"debug": 1,
"key_file": full_path("test.key"),
"cert_file": full_path("test.pem"),
"xmlsec_binary": xmlsec_path,
"xmlsec_binary": None,
"metadata": {
"local": [full_path("servera.xml"),
full_path("vo_metadata.xml")],

View File

@ -2,7 +2,7 @@ from saml2 import BINDING_HTTP_REDIRECT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:idp",
@ -32,7 +32,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("sp_slo_redirect.xml")],
},

View File

@ -36,7 +36,7 @@ CONFIG={
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
#"xmlsec_binary" : xmlsec_path,
#"xmlsec_binary" : None,
"metadata": {
"local": [full_path("metadata.xml"), full_path("vo_metadata.xml")],
},

View File

@ -6,7 +6,7 @@ from saml2.saml import NAME_FORMAT_URI
BASE = "http://localhost:8088/"
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:idp",
@ -49,7 +49,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("metadata.xml"), full_path("vo_metadata.xml")],
},

View File

@ -12,15 +12,3 @@ def dotname(module):
return 'tests.' + module
else:
return module
try:
from saml2.sigver import get_xmlsec_binary
except ImportError:
get_xmlsec_binary = None
if get_xmlsec_binary:
xmlsec_path = get_xmlsec_binary(["/opt/local/bin"])
else:
xmlsec_path = '/usr/bin/xmlsec1'

View File

@ -3,7 +3,7 @@ from saml2.saml import NAME_FORMAT_URI
BASE = "http://localhost:8089/"
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:idpr",
@ -36,7 +36,7 @@ CONFIG = {
},
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("sp_0.metadata")],
},

View File

@ -1,4 +1,4 @@
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:sp",
@ -18,7 +18,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp_soap.xml"), full_path("vo_metadata.xml")],
},

View File

@ -1,4 +1,4 @@
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:sp",
@ -18,7 +18,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp_aa.xml"), full_path("vo_metadata.xml")],
},

View File

@ -1,4 +1,4 @@
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG={
"entityid" : "urn:mace:example.com:saml:roland:sp",
@ -19,7 +19,7 @@ CONFIG={
"key_file": full_path("test.key"),
"cert_file": full_path("test.pem"),
"ca_certs": full_path("cacerts.txt"),
"xmlsec_binary": xmlsec_path,
"xmlsec_binary": None,
"metadata": {
"local": [full_path("idp.xml"), full_path("vo_metadata.xml")],
},

View File

@ -20,7 +20,7 @@ CONFIG={
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
#"xmlsec_binary" : xmlsec_path,
#"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp.xml"), full_path("vo_metadata.xml")],
},

View File

@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT
from saml2.saml import NAMEID_FORMAT_TRANSIENT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from pathutils import full_path, xmlsec_path
from pathutils import full_path
BASE = "http://lingon.catalogix.se:8087"
@ -49,7 +49,7 @@ CONFIG = {
"key_file": full_path("test.key"),
"cert_file": full_path("test.pem"),
"ca_certs": full_path("cacerts.txt"),
"xmlsec_binary": xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp_all.xml"), full_path("vo_metadata.xml")],
},

View File

@ -1,4 +1,4 @@
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
@ -18,7 +18,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp.xml"), full_path("vo_metadata.xml")],
},

View File

@ -1,4 +1,4 @@
from pathutils import full_path, xmlsec_path
from pathutils import full_path
CONFIG = {
"entityid" : "urn:mace:example.com:saml:roland:sp",
@ -17,7 +17,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp_2.xml")],
},

View File

@ -2,7 +2,7 @@ from saml2 import BINDING_HTTP_REDIRECT
from saml2.saml import NAMEID_FORMAT_PERSISTENT
from saml2.saml import NAME_FORMAT_URI
from pathutils import full_path, xmlsec_path
from pathutils import full_path
HOME = "http://lingon.catalogix.se:8087/"
CONFIG = {
@ -26,7 +26,7 @@ CONFIG = {
"debug" : 1,
"key_file" : full_path("test.key"),
"cert_file" : full_path("test.pem"),
"xmlsec_binary" : xmlsec_path,
"xmlsec_binary" : None,
"metadata": {
"local": [full_path("idp_slo_redirect.xml")],
},

View File

@ -11,7 +11,6 @@ from saml2 import time_util
from saml2 import saml, samlp
from saml2 import config
from saml2.s_utils import factory, do_attribute_statement
from saml2.sigver import xmlsec_version, get_xmlsec_cryptobackend, get_xmlsec_binary
from py.test import raises
@ -84,12 +83,33 @@ def test_cert_from_instance_ssp():
print str(decoder.decode(der)).replace('.', "\n.")
assert decoder.decode(der)
class FakeConfig():
"""
Configuration parameters for signature validation test cases.
"""
xmlsec_binary = None
crypto_backend = 'xmlsec1'
only_use_keys_in_metadata = False
metadata = None
cert_file = PUB_KEY
key_file = PRIV_KEY
debug = False
class TestSecurity():
def setup_class(self):
crypto = get_xmlsec_cryptobackend()
self.sec = sigver.SecurityContext(crypto, key_file=PRIV_KEY,
cert_file=PUB_KEY, debug=1)
# 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,
@ -122,8 +142,7 @@ class TestSecurity():
def test_sign_assertion(self):
ass = self._assertion
print ass
sign_ass = self.sec.sign_assertion_using_xmlsec("%s" % ass,
node_id=ass.id)
sign_ass = self.sec.sign_assertion("%s" % ass, node_id=ass.id)
#print sign_ass
sass = saml.assertion_from_string(sign_ass)
#print sass
@ -133,7 +152,7 @@ class TestSecurity():
assert sass.id == "11111"
assert time_util.str_to_time(sass.issue_instant)
print xmlsec_version(get_xmlsec_binary())
print "Crypto version : %s" % (self.sec.crypto.version())
item = self.sec.check_signature(sass, class_name(sass), sign_ass)
@ -153,7 +172,7 @@ class TestSecurity():
assert sass.id == "11111"
assert time_util.str_to_time(sass.issue_instant)
print xmlsec_version(get_xmlsec_binary())
print "Crypto version : %s" % (self.sec.crypto.version())
item = self.sec.check_signature(sass, class_name(sass),
sign_ass, must=True)
@ -366,9 +385,9 @@ class TestSecurityMetadata():
md = MetadataStore([saml, samlp], None, conf)
md.load("local", full_path("metadata_cert.xml"))
crypto = get_xmlsec_cryptobackend()
self.sec = sigver.SecurityContext(crypto, key_file=PRIV_KEY,
cert_file=PUB_KEY, debug=1, metadata=md)
conf.metadata = md
conf.only_use_keys_in_metadata = False
self.sec = sigver.security_context(conf)
self._assertion = factory( saml.Assertion,
version="2.0",
@ -384,8 +403,7 @@ class TestSecurityMetadata():
def test_sign_assertion(self):
ass = self._assertion
print ass
sign_ass = self.sec.sign_assertion_using_xmlsec("%s" % ass,
node_id=ass.id)
sign_ass = self.sec.sign_assertion("%s" % ass, node_id=ass.id)
#print sign_ass
sass = saml.assertion_from_string(sign_ass)
#print sass
@ -395,7 +413,7 @@ class TestSecurityMetadata():
assert sass.id == "11111"
assert time_util.str_to_time(sass.issue_instant)
print xmlsec_version(get_xmlsec_binary())
print "Crypto version : %s" % (self.sec.crypto.version())
item = self.sec.check_signature(sass, class_name(sass), sign_ass)

View File

@ -14,7 +14,7 @@ from saml2 import create_class_from_xml_string
from saml2.profile import ecp as ecp_prof
from saml2.client import Saml2Client
from pathutils import dotname, full_path, xmlsec_path
from pathutils import dotname, full_path
__author__ = 'rolandh'
@ -38,8 +38,7 @@ class DummyResponse(object):
def test_complete_flow():
client = ecp_client.Client("user", "password",
metadata_file=full_path("idp_all.xml"),
xmlsec_binary=xmlsec_path)
metadata_file=full_path("idp_all.xml"))
sp = Saml2Client(config_file=dotname("servera_conf"))
idp = Server(config_file=dotname("idp_all_conf"))

View File

@ -1,14 +1,12 @@
#!/usr/bin/env python
import argparse
import os
import os
import sys
from saml2.metadata import entity_descriptor
from saml2.metadata import entities_descriptor
from saml2.metadata import sign_entity_descriptor
from saml2.sigver import SecurityContext, CryptoBackendXmlSec1
from saml2.sigver import get_xmlsec_cryptobackend
from saml2.sigver import get_xmlsec_binary
from saml2.sigver import security_context
from saml2.validate import valid_instance
from saml2.config import Config
@ -46,10 +44,7 @@ paths = [".", "/opt/local/bin"]
if args.valid:
# translate into hours
valid_for = int(args.valid) * 24
if args.xmlsec:
xmlsec = args.xmlsec
else:
xmlsec = get_xmlsec_binary(paths)
eds = []
for filespec in args.config:
@ -61,13 +56,12 @@ for filespec in args.config:
cnf = Config().load_file(fil, metadata_construction=True)
eds.append(entity_descriptor(cnf))
if not xmlsec:
crypto = get_xmlsec_cryptobackend()
else:
crypto = CryptoBackendXmlSec1(xmlsec)
secc = SecurityContext(crypto, key_file=args.keyfile, cert_file=args.cert,
debug=1)
conf = Config()
conf.key_file = args.keyfile
conf.cert_file = args.cert
conf.debug = 1
conf.xmlsec_binary = args.xmlsec
secc = security_context(conf)
if args.id:
desc = entities_descriptor(eds, valid_for, args.name, args.id,