Class: CloudflareAccessGate::JwksCache

Inherits:
Object
  • Object
show all
Defined in:
lib/cloudflare_access_gate/jwks_cache.rb

Overview

Fetches and caches the Cloudflare Access team's JWKS (public signing keys).

#fetch returns a usable key set or nil; nil means the caller must deny the request. Three behaviors matter for a gate that has to stay both closed and available:

  • TTL — a good key set is served from memory for CACHE_TTL seconds.
  • Error backoff — fetches happen under a mutex, so without a cooldown every request during a JWKS outage would queue behind its own (up to 6s) HTTP timeout, hanging the dashboard. After a failure, Cloudflare isn't contacted again for ERROR_BACKOFF seconds.
  • Staleness grace — if a refresh fails, the last known-good key set is reused for up to stale_grace seconds past the TTL. Access signing keys rotate on the order of weeks, so a few minutes of staleness is a far smaller risk than locking every operator out during a transient failure. Pass stale_grace: 0 for strict behavior.

Constant Summary collapse

CACHE_TTL =

seconds a successfully fetched JWKS is served as fresh

600
ERROR_BACKOFF =

seconds to wait after a failed fetch before retrying

30
DEFAULT_STALE_GRACE =

seconds a stale JWKS may be reused past the TTL

300
HTTP_OPEN_TIMEOUT =

seconds

3
HTTP_READ_TIMEOUT =

seconds

3
MONOTONIC_CLOCK =
-> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }

Instance Method Summary collapse

Constructor Details

#initialize(certs_url:, logger:, stale_grace: DEFAULT_STALE_GRACE, clock: MONOTONIC_CLOCK) ⇒ JwksCache

Returns a new instance of JwksCache.



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/cloudflare_access_gate/jwks_cache.rb', line 33

def initialize(certs_url:, logger:, stale_grace: DEFAULT_STALE_GRACE, clock: MONOTONIC_CLOCK)
  @certs_url = certs_url
  @logger = logger
  @stale_grace = stale_grace
  @clock = clock

  @jwks = nil
  @fetched_at = nil
  @failed_at = nil
  @mutex = Mutex.new
end

Instance Method Details

#fetchObject

Returns the JWKS to verify against, or nil if none can be obtained.



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/cloudflare_access_gate/jwks_cache.rb', line 46

def fetch
  @mutex.synchronize do
    return @jwks if fresh?
    return stale if backing_off?

    jwks = request
    return remember(jwks) if jwks

    @failed_at = now
    stale
  end
end