44import logging
55import os
66import time
7+ from datetime import datetime
78from functools import cmp_to_key
89
910import requests
@@ -156,6 +157,7 @@ def __init__(
156157 keys = None ,
157158 source = "" ,
158159 cache_time = 300 ,
160+ error_holddown = 0 ,
159161 fileformat = "jwks" ,
160162 keytype = "RSA" ,
161163 keyusage = None ,
@@ -188,6 +190,7 @@ def __init__(
188190 self .remote = False
189191 self .local = False
190192 self .cache_time = cache_time
193+ self .error_holddown = error_holddown
191194 self .time_out = 0
192195 self .etag = ""
193196 self .source = None
@@ -198,6 +201,7 @@ def __init__(
198201 self .last_updated = 0
199202 self .last_remote = None # HTTP Date of last remote update
200203 self .last_local = None # UNIX timestamp of last local update
204+ self .last_error = None # UNIX timestamp of last error
201205
202206 if httpc :
203207 self .httpc = httpc
@@ -365,6 +369,16 @@ def do_remote(self):
365369 # if self.verify_ssl is not None:
366370 # self.httpc_params["verify"] = self.verify_ssl
367371
372+ if self .last_error :
373+ t = self .last_error + self .error_holddown
374+ if time .time () < t :
375+ LOGGER .warning (
376+ "Not reading remote JWKS from %s (in error holddown until %s)" ,
377+ self .source ,
378+ datetime .fromtimestamp (t ),
379+ )
380+ return False
381+
368382 LOGGER .info ("Reading remote JWKS from %s" , self .source )
369383 try :
370384 LOGGER .debug ("KeyBundle fetch keys from: %s" , self .source )
@@ -390,6 +404,7 @@ def do_remote(self):
390404 self .do_keys (self .imp_jwks ["keys" ])
391405 except KeyError :
392406 LOGGER .error ("No 'keys' keyword in JWKS" )
407+ self .last_error = time .time ()
393408 raise UpdateFailed (MALFORMED .format (self .source ))
394409
395410 if hasattr (_http_resp , "headers" ):
@@ -402,12 +417,13 @@ def do_remote(self):
402417
403418 else :
404419 LOGGER .warning (
405- "HTTP status %d reading remote JWKS from %s" ,
406- _http_resp .status_code ,
407- self .source ,
420+ "HTTP status %d reading remote JWKS from %s" , _http_resp .status_code , self .source ,
408421 )
422+ self .last_error = time .time ()
409423 raise UpdateFailed (REMOTE_FAILED .format (self .source , _http_resp .status_code ))
424+
410425 self .last_updated = time .time ()
426+ self .last_error = None
411427 return True
412428
413429 def _parse_remote_response (self , response ):
0 commit comments