diff --git a/.gitignore b/.gitignore index 02d5cce..a0d5e6a 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,23 @@ example/idp2/modules/root.mako.py example/idp3/idp_conf_test.py update + +src/saml2/entity_category/swamid2.py + +example/idp2/IdpTestConf.py + +example/idp2/create_idp_conf.json + +example/idp2/create_idp_conf.py + +example/idp2/idpSaml2test.xml + +example/idp2/idp_conf.template + +example/idp2/idp_conf_saml2test.py + +example/sp/sp.xml + +example/idp2/idp_conf_local.py + +example/sp/sp_conf_local.py diff --git a/example/idp2/idp.py b/example/idp2/idp.py index 028d6ef..0d6ecbe 100755 --- a/example/idp2/idp.py +++ b/example/idp2/idp.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +import argparse import base64 import re @@ -8,6 +9,8 @@ from hashlib import sha1 from urlparse import parse_qs from Cookie import SimpleCookie +import subprocess +import os from saml2 import server from saml2 import BINDING_HTTP_ARTIFACT @@ -31,6 +34,7 @@ from saml2.httputil import Unauthorized from saml2.httputil import BadRequest from saml2.httputil import ServiceError from saml2.ident import Unknown +from saml2.metadata import create_metadata_string from saml2.s_utils import rndstr, exception_trace from saml2.s_utils import UnknownPrincipal from saml2.s_utils import UnsupportedBinding @@ -431,7 +435,8 @@ def do_authentication(environ, start_response, authn_context, key, # ----------------------------------------------------------------------------- -PASSWD = {"roland": "dianakra", +PASSWD = {"haho0032": "qwerty", + "roland": "dianakra", "babs": "howes", "upper": "crust"} @@ -809,6 +814,21 @@ NON_AUTHN_URLS = [ # ---------------------------------------------------------------------------- +def metadata(environ, start_response): + try: + path = args.path + if path is None or len(path) == 0: + path = os.path.dirname(os.path.abspath( __file__ )) + if path[-1] != "/": + path += "/" + metadata = create_metadata_string(path+args.config, IDP.config, + args.valid, args.cert, args.keyfile, + args.id, args.name, args.sign) + start_response('200 OK', [('Content-Type', "text/xml")]) + return metadata + except Exception as ex: + logger.error("An error occured while creating metadata:" + ex.message) + return not_found(environ, start_response) def application(environ, start_response): """ @@ -826,6 +846,10 @@ def application(environ, start_response): """ path = environ.get('PATH_INFO', '').lstrip('/') + + if path == "metadata": + return metadata(environ, start_response) + kaka = environ.get("HTTP_COOKIE", None) logger.info(" PATH: %s" % path) @@ -882,6 +906,21 @@ if __name__ == '__main__': from idp_user import EXTRA from wsgiref.simple_server import make_server + parser = argparse.ArgumentParser() + parser.add_argument('-p', dest='path', help='Path to configuration file.') + parser.add_argument('-v', dest='valid', + help="How long, in days, the metadata is valid from the time of creation") + parser.add_argument('-c', dest='cert', help='certificate') + parser.add_argument('-i', dest='id', + help="The ID of the entities descriptor") + parser.add_argument('-k', dest='keyfile', + help="A file with a key to sign the metadata with") + parser.add_argument('-n', dest='name') + parser.add_argument('-s', dest='sign', action='store_true', + help="sign the metadata") + parser.add_argument(dest="config") + args = parser.parse_args() + PORT = 8088 AUTHN_BROKER = AuthnBroker() @@ -891,7 +930,7 @@ if __name__ == '__main__': AUTHN_BROKER.add(authn_context_class_ref(UNSPECIFIED), "", 0, "http://%s" % socket.gethostname()) - IDP = server.Server(sys.argv[1], cache=Cache()) + IDP = server.Server(args.config, cache=Cache()) IDP.ticket = {} SRV = make_server('', PORT, application) diff --git a/example/idp2/idp_user.py b/example/idp2/idp_user.py index ee2f68b..aa60c7d 100644 --- a/example/idp2/idp_user.py +++ b/example/idp2/idp_user.py @@ -1,4 +1,21 @@ USERS = { + "haho0032": { + "sn": "Hoerberg", + "givenName": "Hans", + "eduPersonScopedAffiliation": "staff@example.com", + "eduPersonPrincipalName": "haho@example.com", + "uid": "haho", + "eduPersonTargetedID": "one!for!all", + "c": "SE", + "o": "Example Co.", + "ou": "IT", + "initials": "P", + "schacHomeOrganization": "example.com", + "email": "hans@example.com", + "displayName": "Hans Hoerberg", + "labeledURL": "http://www.example.com/haho My homepage", + "norEduPersonNIN": "SE199012315555" + }, "roland": { "sn": "Hedberg", "givenName": "Roland", @@ -10,7 +27,7 @@ USERS = { "o": "Example Co.", "ou": "IT", "initials": "P", - "schacHomeOrganization": "example.com", + #"schacHomeOrganization": "example.com", "email": "roland@example.com", "displayName": "P. Roland Hedberg", "labeledURL": "http://www.example.com/rohe My homepage", diff --git a/example/sp/sp.py b/example/sp/sp.py index a00d626..b0a3c61 100755 --- a/example/sp/sp.py +++ b/example/sp/sp.py @@ -1,18 +1,27 @@ #!/usr/bin/env python from Cookie import SimpleCookie import logging +import os +from sp_conf import CONFIG import re +import subprocess from urlparse import parse_qs +import argparse from saml2 import BINDING_HTTP_REDIRECT, time_util from saml2.httputil import Response from saml2.httputil import Unauthorized from saml2.httputil import NotFound from saml2.httputil import Redirect #from saml2.httputil import ServiceError +from saml2.metadata import create_metadata_string +from saml2.metadata import entities_descriptor +from saml2.config import Config +from saml2.sigver import security_context logger = logging.getLogger("saml2.SP") +args = None # ----------------------------------------------------------------------------- @@ -193,6 +202,21 @@ urls = [ # ---------------------------------------------------------------------------- +def metadata(environ, start_response): + try: + path = args.path + if path is None or len(path) == 0: + path = os.path.dirname(os.path.abspath( __file__ )) + if path[-1] != "/": + path += "/" + metadata = create_metadata_string(path+"sp_conf.py", None, + args.valid, args.cert, args.keyfile, + args.id, args.name, args.sign) + start_response('200 OK', [('Content-Type', "text/xml")]) + return metadata + except Exception as ex: + logger.error("An error occured while creating metadata:" + ex.message) + return not_found(environ, start_response) def application(environ, start_response): """ @@ -211,6 +235,9 @@ def application(environ, start_response): path = environ.get('PATH_INFO', '').lstrip('/') logger.info(" PATH: %s" % path) + if path == "metadata": + return metadata(environ, start_response) + user = environ.get("REMOTE_USER", "") if not user: user = environ.get("repoze.who.identity", "") @@ -243,7 +270,23 @@ app_with_auth = make_middleware_with_config(application, {"here": "."}, # ---------------------------------------------------------------------------- PORT = 8087 + if __name__ == '__main__': + #make_metadata arguments + parser = argparse.ArgumentParser() + parser.add_argument('-p', dest='path', help='Path to configuration file.') + parser.add_argument('-v', dest='valid', default="4", + help="How long, in days, the metadata is valid from the time of creation") + parser.add_argument('-c', dest='cert', help='certificate') + parser.add_argument('-i', dest='id', + help="The ID of the entities descriptor in the metadata") + parser.add_argument('-k', dest='keyfile', + help="A file with a key to sign the metadata with") + parser.add_argument('-n', dest='name') + parser.add_argument('-s', dest='sign', action='store_true', + help="sign the metadata") + args = parser.parse_args() + from wsgiref.simple_server import make_server srv = make_server('', PORT, app_with_auth) print "SP listening on port: %s" % PORT diff --git a/src/saml2/metadata.py b/src/saml2/metadata.py index 28f5c8a..b477ef0 100644 --- a/src/saml2/metadata.py +++ b/src/saml2/metadata.py @@ -1,4 +1,7 @@ #!/usr/bin/env python +from saml2.sigver import security_context +from saml2.config import Config +from saml2.validate import valid_instance from saml2.time_util import in_a_while from saml2.extension import mdui, idpdisc, shibmd, mdattr from saml2.saml import NAME_FORMAT_URI, AttributeValue, Attribute @@ -10,7 +13,8 @@ from saml2 import BINDING_SOAP from saml2 import samlp from saml2 import class_name import xmldsig as ds - +import sys +import os from saml2.sigver import pre_signature_part from saml2.s_utils import factory @@ -41,6 +45,45 @@ ORG_ATTR_TRANSL = { "organization_url": ("url", md.OrganizationURL) } +def create_metadata_string(configfile, config, valid, cert, keyfile, id, name, sign): + valid_for = 0 + nspair = {"xs": "http://www.w3.org/2001/XMLSchema"} + paths = [".", "/opt/local/bin"] + + if valid: + valid_for = int(valid) #Hours + + + eds = [] + if config is not None: + eds.append(entity_descriptor(config)) + else: + if configfile.endswith(".py"): + configfile = configfile[:-3] + config = Config().load_file(configfile, metadata_construction=True) + eds.append(entity_descriptor(config)) + + conf = Config() + conf.key_file = keyfile + conf.cert_file = cert + conf.debug = 1 + conf.xmlsec_binary = config.xmlsec_binary + secc = security_context(conf) + + if id: + desc = entities_descriptor(eds, valid_for, name, id, + sign, secc) + valid_instance(desc) + return desc.to_string(nspair) + else: + for eid in eds: + if sign: + desc = sign_entity_descriptor(eid, id, secc) + else: + desc = eid + valid_instance(desc) + return desc.to_string(nspair) + def _localized_name(val, klass): """If no language is defined 'en' is the default"""