1
1
#!/usr/bin/env python
2
2
from __future__ import print_function
3
- import logging
4
- import re
3
+
5
4
import argparse
5
+ import importlib
6
+ import logging
6
7
import os
8
+ import re
9
+ import sys
7
10
8
- from six .moves .http_cookies import SimpleCookie
9
11
import six
10
-
11
- from saml2 .extension .pefim import SPCertEnc
12
- from saml2 .metadata import create_metadata_string
13
- import service_conf
14
-
12
+ from six .moves .http_cookies import SimpleCookie
15
13
from six .moves .urllib .parse import parse_qs
16
- import sys
17
14
15
+ import saml2 .xmldsig as ds
16
+ from saml2 import BINDING_HTTP_ARTIFACT
17
+ from saml2 import BINDING_HTTP_POST
18
18
from saml2 import BINDING_HTTP_REDIRECT , element_to_extension_element
19
19
from saml2 import BINDING_SOAP
20
- from saml2 import time_util
21
20
from saml2 import ecp
22
- from saml2 import BINDING_HTTP_ARTIFACT
23
- from saml2 import BINDING_HTTP_POST
21
+ from saml2 import time_util
24
22
from saml2 .client import Saml2Client
25
23
from saml2 .ecp_client import PAOS_HEADER_INFO
26
- from saml2 .httputil import geturl , make_cookie , parse_cookie
27
- from saml2 .httputil import get_post
28
- from saml2 .httputil import Response
24
+ from saml2 .extension .pefim import SPCertEnc
29
25
from saml2 .httputil import BadRequest
30
- from saml2 .httputil import ServiceError
31
- from saml2 .httputil import SeeOther
32
- from saml2 .httputil import Unauthorized
33
26
from saml2 .httputil import NotFound
34
- from saml2 .httputil import Redirect
35
27
from saml2 .httputil import NotImplemented
28
+ from saml2 .httputil import Redirect
29
+ from saml2 .httputil import Response
30
+ from saml2 .httputil import SeeOther
31
+ from saml2 .httputil import ServiceError
32
+ from saml2 .httputil import Unauthorized
33
+ from saml2 .httputil import get_post
34
+ from saml2 .httputil import geturl , make_cookie , parse_cookie
35
+ from saml2 .metadata import create_metadata_string
36
36
from saml2 .response import StatusError
37
37
from saml2 .response import VerificationError
38
38
from saml2 .s_utils import UnknownPrincipal
39
- from saml2 .s_utils import decode_base64_and_inflate
40
39
from saml2 .s_utils import UnsupportedBinding
41
- from saml2 .s_utils import sid
40
+ from saml2 .s_utils import decode_base64_and_inflate
42
41
from saml2 .s_utils import rndstr
43
- #from srtest import exception_trace
42
+ from saml2 .s_utils import sid
43
+ from saml2 .saml import NAMEID_FORMAT_PERSISTENT
44
44
from saml2 .samlp import Extensions
45
- from saml2 import xmldsig as ds
46
- import saml2 .xmldsig as ds
47
45
48
46
logger = logging .getLogger ("" )
49
47
hdlr = logging .FileHandler ('spx.log' )
54
52
logger .addHandler (hdlr )
55
53
logger .setLevel (logging .INFO )
56
54
57
-
58
55
SP = None
59
56
SEED = ""
60
57
POLICY = None
@@ -139,7 +136,7 @@ class ECPResponse(object):
139
136
def __init__ (self , content ):
140
137
self .content = content
141
138
142
- #noinspection PyUnusedLocal
139
+ # noinspection PyUnusedLocal
143
140
def __call__ (self , environ , start_response ):
144
141
start_response ('%s %s' % (self .code , self .title ),
145
142
[('Content-Type' , "text/xml" )])
@@ -351,7 +348,7 @@ def do(self, response, binding, relay_state="", mtype="response"):
351
348
:param response: The SAML response, transport encoded
352
349
:param binding: Which binding the query came in over
353
350
"""
354
- #tmp_outstanding_queries = dict(self.outstanding_queries)
351
+ # tmp_outstanding_queries = dict(self.outstanding_queries)
355
352
if not response :
356
353
logger .info ("Missing Response" )
357
354
resp = Unauthorized ('Unknown user' )
@@ -405,6 +402,7 @@ def verify_attributes(self, ava):
405
402
406
403
return res
407
404
405
+
408
406
# -----------------------------------------------------------------------------
409
407
# REQUESTERS
410
408
# -----------------------------------------------------------------------------
@@ -554,7 +552,7 @@ def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""):
554
552
"single_sign_on_service" , self .bindings , "idpsso" ,
555
553
entity_id = entity_id )
556
554
logger .debug ("binding: %s, destination: %s" , _binding ,
557
- destination )
555
+ destination )
558
556
# Binding here is the response binding that is which binding the
559
557
# IDP should use to return the response.
560
558
acs = _cli .config .getattr ("endpoints" , "sp" )[
@@ -565,19 +563,20 @@ def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=""):
565
563
extensions = None
566
564
cert = None
567
565
if _cli .config .generate_cert_func is not None :
568
- cert_str , req_key_str = _cli .config .generate_cert_func ()
569
- cert = {
570
- "cert" : cert_str ,
571
- "key" : req_key_str
572
- }
573
- spcertenc = SPCertEnc (x509_data = ds .X509Data (
574
- x509_certificate = ds .X509Certificate (text = cert_str )))
575
- extensions = Extensions (extension_elements = [
576
- element_to_extension_element (spcertenc )])
566
+ cert_str , req_key_str = _cli .config .generate_cert_func ()
567
+ cert = {
568
+ "cert" : cert_str ,
569
+ "key" : req_key_str
570
+ }
571
+ spcertenc = SPCertEnc (x509_data = ds .X509Data (
572
+ x509_certificate = ds .X509Certificate (text = cert_str )))
573
+ extensions = Extensions (extension_elements = [
574
+ element_to_extension_element (spcertenc )])
577
575
578
576
req_id , req = _cli .create_authn_request (destination ,
579
577
binding = return_binding ,
580
- extensions = extensions )
578
+ extensions = extensions ,
579
+ nameid_format = NAMEID_FORMAT_PERSISTENT )
581
580
_rstate = rndstr ()
582
581
self .cache .relay_state [_rstate ] = came_from
583
582
ht_args = _cli .apply_binding (_binding , "%s" % req , destination ,
@@ -636,7 +635,7 @@ def do(self, message, binding, relay_state="", mtype="response"):
636
635
try :
637
636
txt = decode_base64_and_inflate (message )
638
637
is_logout_request = 'LogoutRequest' in txt .split ('>' , 1 )[0 ]
639
- except : # TODO: parse the XML correctly
638
+ except : # TODO: parse the XML correctly
640
639
is_logout_request = False
641
640
642
641
if is_logout_request :
@@ -646,10 +645,11 @@ def do(self, message, binding, relay_state="", mtype="response"):
646
645
647
646
return finish_logout (self .environ , self .start_response )
648
647
648
+
649
649
# ----------------------------------------------------------------------------
650
650
651
651
652
- #noinspection PyUnusedLocal
652
+ # noinspection PyUnusedLocal
653
653
def not_found (environ , start_response ):
654
654
"""Called if no URL matches."""
655
655
resp = NotFound ('Not Found' )
@@ -659,7 +659,7 @@ def not_found(environ, start_response):
659
659
# ----------------------------------------------------------------------------
660
660
661
661
662
- #noinspection PyUnusedLocal
662
+ # noinspection PyUnusedLocal
663
663
def main (environ , start_response , sp ):
664
664
user = CACHE .get_user (environ )
665
665
@@ -687,10 +687,11 @@ def disco(environ, start_response, _sp):
687
687
resp .headers .append (kaka )
688
688
return resp (environ , start_response )
689
689
690
+
690
691
# ----------------------------------------------------------------------------
691
692
692
693
693
- #noinspection PyUnusedLocal
694
+ # noinspection PyUnusedLocal
694
695
def logout (environ , start_response , sp ):
695
696
user = CACHE .get_user (environ )
696
697
@@ -737,10 +738,11 @@ def finish_logout(environ, start_response):
737
738
cookie = CACHE .delete_cookie (environ )
738
739
739
740
resp = Response ('You are now logged out of this service' , headers = [
740
- cookie ,
741
+ cookie ,
741
742
])
742
743
return resp (environ , start_response )
743
744
745
+
744
746
# ----------------------------------------------------------------------------
745
747
746
748
# map urls to functions
@@ -768,16 +770,17 @@ def add_urls():
768
770
urls .append (("%s/redirect$" % base , (SLO , "redirect" , SP )))
769
771
urls .append (("%s/redirect/(.*)$" % base , (SLO , "redirect" , SP )))
770
772
773
+
771
774
# ----------------------------------------------------------------------------
772
775
773
776
def metadata (environ , start_response ):
774
777
try :
775
778
path = _args .path
776
779
if path is None or len (path ) == 0 :
777
- path = os .path .dirname (os .path .abspath ( __file__ ))
780
+ path = os .path .dirname (os .path .abspath (__file__ ))
778
781
if path [- 1 ] != "/" :
779
782
path += "/"
780
- metadata = create_metadata_string (path + "sp_conf.py" , None ,
783
+ metadata = create_metadata_string (path + "sp_conf.py" , None ,
781
784
_args .valid , _args .cert , _args .keyfile ,
782
785
_args .id , _args .name , _args .sign )
783
786
start_response ('200 OK' , [('Content-Type' , "text/xml" )])
@@ -786,6 +789,7 @@ def metadata(environ, start_response):
786
789
logger .error ("An error occured while creating metadata: %s" , ex .message )
787
790
return not_found (environ , start_response )
788
791
792
+
789
793
def application (environ , start_response ):
790
794
"""
791
795
The main WSGI application. Dispatch the current request to
@@ -824,23 +828,12 @@ def application(environ, start_response):
824
828
resp = BadRequest ("%s" % err )
825
829
return resp (environ , start_response )
826
830
except Exception as err :
827
- #_err = exception_trace("RUN", err)
828
- #logging.error(exception_trace("RUN", _err))
831
+ # _err = exception_trace("RUN", err)
832
+ # logging.error(exception_trace("RUN", _err))
829
833
print (err , file = sys .stderr )
830
834
resp = ServiceError ("%s" % err )
831
835
return resp (environ , start_response )
832
836
833
- # ----------------------------------------------------------------------------
834
-
835
- HOST = service_conf .HOST
836
- PORT = service_conf .PORT
837
- # ------- HTTPS -------
838
- # These should point to relevant files
839
- SERVER_CERT = service_conf .SERVER_CERT
840
- SERVER_KEY = service_conf .SERVER_KEY
841
- # This is of course the certificate chain for the CA that signed
842
- # your cert and all the way up to the top
843
- CERT_CHAIN = service_conf .CERT_CHAIN
844
837
845
838
if __name__ == '__main__' :
846
839
from cherrypy import wsgiserver
@@ -866,7 +859,8 @@ def application(environ, start_response):
866
859
_parser .add_argument ('-n' , dest = 'name' )
867
860
_parser .add_argument ('-S' , dest = 'sign' , action = 'store_true' ,
868
861
help = "sign the metadata" )
869
-
862
+ _parser .add_argument ('-C' , dest = 'service_conf_module' ,
863
+ help = "service config module" )
870
864
871
865
ARGS = {}
872
866
_args = _parser .parse_args ()
@@ -882,6 +876,21 @@ def application(environ, start_response):
882
876
else :
883
877
SEED = "SnabbtInspel"
884
878
879
+ if _args .service_conf_module :
880
+ service_conf = importlib .import_module (_args .service_conf_module )
881
+ else :
882
+ import service_conf
883
+
884
+ HOST = service_conf .HOST
885
+ PORT = service_conf .PORT
886
+ # ------- HTTPS -------
887
+ # These should point to relevant files
888
+ SERVER_CERT = service_conf .SERVER_CERT
889
+ SERVER_KEY = service_conf .SERVER_KEY
890
+ # This is of course the certificate chain for the CA that signed
891
+ # your cert and all the way up to the top
892
+ CERT_CHAIN = service_conf .CERT_CHAIN
893
+
885
894
SP = Saml2Client (config_file = "%s" % CNFBASE )
886
895
887
896
POLICY = service_conf .POLICY
@@ -904,6 +913,7 @@ def application(environ, start_response):
904
913
_https = ""
905
914
if service_conf .HTTPS :
906
915
from cherrypy .wsgiserver import ssl_pyopenssl
916
+
907
917
SRV .ssl_adapter = ssl_pyopenssl .pyOpenSSLAdapter (SERVER_CERT ,
908
918
SERVER_KEY , CERT_CHAIN )
909
919
_https = " using SSL/TLS"
0 commit comments