32
32
from saml2 .s_utils import UnknownSystemEntity
33
33
from saml2 .sigver import split_len
34
34
from saml2 .validate import valid_instance
35
- from saml2 .time_util import valid
35
+ from saml2 .time_util import valid , instant , add_duration , before , str_to_time
36
36
from saml2 .validate import NotValid
37
37
from saml2 .sigver import security_context
38
38
from saml2 .extension .mdattr import NAMESPACE as NS_MDATTR
@@ -821,7 +821,7 @@ def sha1_entity_transform(entity_id):
821
821
hashlib .sha1 (entity_id .encode ("utf-8" )).hexdigest ())
822
822
823
823
def __init__ (self , url = None , security = None , cert = None ,
824
- entity_transform = None , ** kwargs ):
824
+ entity_transform = None , freshness_period = None , ** kwargs ):
825
825
"""
826
826
:params url: mdx service url
827
827
:params security: SecurityContext()
@@ -831,6 +831,8 @@ def __init__(self, url=None, security=None, cert=None,
831
831
hash) the entity id. It is applied to the entity id before it is
832
832
concatenated with the request URL sent to the MDX server. Defaults to
833
833
sha1 transformation.
834
+ :params freshness_period: a duration in the format described at
835
+ https://www.w3.org/TR/xmlschema-2/#duration
834
836
"""
835
837
super (MetaDataMDX , self ).__init__ (None , ** kwargs )
836
838
if not url :
@@ -845,6 +847,9 @@ def __init__(self, url=None, security=None, cert=None,
845
847
846
848
self .cert = cert
847
849
self .security = security
850
+ self .freshness_period = freshness_period
851
+ if freshness_period :
852
+ self .expiration_date = {}
848
853
849
854
# We assume that the MDQ server will return a single entity
850
855
# described by a single <EntityDescriptor> element. The protocol
@@ -859,21 +864,37 @@ def load(self, *args, **kwargs):
859
864
# Do nothing
860
865
pass
861
866
867
+ def fetch_metadata (self , item ):
868
+ mdx_url = "%s/entities/%s" % (self .url , self .entity_transform (item ))
869
+ response = requests .get (mdx_url , headers = {
870
+ 'Accept' : SAML_METADATA_CONTENT_TYPE })
871
+ if response .status_code == 200 :
872
+ _txt = response .content
873
+ if self .parse_and_check_signature (_txt ):
874
+ if self .freshness_period :
875
+ curr_time = str_to_time (instant ())
876
+ self .expiration_date [item ] = add_duration (
877
+ curr_time , self .freshness_period )
878
+ return self .entity [item ]
879
+ else :
880
+ logger .info ("Response status: %s" , response .status_code )
881
+ raise KeyError
882
+
883
+ def _is_fresh (self , item ):
884
+ return self .freshness_period and before (self .expiration_date [item ])
885
+
862
886
def __getitem__ (self , item ):
863
- try :
864
- return self .entity [item ]
865
- except KeyError :
866
- mdx_url = "%s/entities/%s" % (self .url , self .entity_transform (item ))
867
- response = requests .get (mdx_url , headers = {
868
- 'Accept' : SAML_METADATA_CONTENT_TYPE })
869
- if response .status_code == 200 :
870
- _txt = response .content
871
-
872
- if self .parse_and_check_signature (_txt ):
873
- return self .entity [item ]
887
+ if item in self .entity :
888
+ if self ._is_fresh (item ):
889
+ entity = self .entity [item ]
874
890
else :
875
- logger .info ("Response status: %s" , response .status_code )
876
- raise KeyError
891
+ logger .info ("Metadata for {} have expired, refreshing "
892
+ "metadata" .format (item ))
893
+ self .entity .pop (item , None )
894
+ entity = self .fetch_metadata (item )
895
+ else :
896
+ entity = self .fetch_metadata (item )
897
+ return entity
877
898
878
899
def single_sign_on_service (self , entity_id , binding = None , typ = "idpsso" ):
879
900
if binding is None :
@@ -960,9 +981,11 @@ def load(self, *args, **kwargs):
960
981
key = kwargs ['url' ]
961
982
url = kwargs ['url' ]
962
983
cert = kwargs .get ('cert' )
984
+ freshness_period = kwargs .get ('freshness_period' , None )
963
985
security = self .security
964
986
entity_transform = kwargs .get ('entity_transform' , None )
965
- _md = MetaDataMDX (url , security , cert , entity_transform )
987
+ _md = MetaDataMDX (url , security , cert , entity_transform ,
988
+ freshness_period = freshness_period )
966
989
else :
967
990
key = args [1 ]
968
991
url = args [1 ]
0 commit comments