Module: Verikloak::BFF::ProxyTrust
- Defined in:
- lib/verikloak/bff/proxy_trust.rb
Overview
Determines whether the selected peer (via XFF/REMOTE_ADDR) is a trusted proxy.
Class Method Summary collapse
-
.extract_peer_ip(env, strategy) ⇒ String?
Select the peer IP from X-Forwarded-For according to strategy or fall back to REMOTE_ADDR.
-
.ip_or_nil(str) ⇒ IPAddr?
Parse string to IPAddr or nil on failure.
-
.resolve_peer(env, preference, strategy) ⇒ String?
Resolve the peer value based on preference and strategy.
-
.rule_trusts?(rule, remote, remote_ip, env) ⇒ Boolean
Check whether a single rule trusts the selected remote.
-
.selected_peer(env, preference, strategy) ⇒ String?
Return the selected peer IP according to preference and strategy.
-
.trusted?(env, trusted, strategy = :rightmost, preference: :remote_then_xff) ⇒ Boolean
Determine if the immediate peer (based on REMOTE_ADDR / X-Forwarded-For) is trusted.
-
.trusted_remote?(remote, trusted, env) ⇒ Boolean
Determine whether a remote peer appears in the trusted list.
Class Method Details
.extract_peer_ip(env, strategy) ⇒ String?
Select the peer IP from X-Forwarded-For according to strategy or fall back to REMOTE_ADDR.
37 38 39 40 41 42 43 44 45 46 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 37 def extract_peer_ip(env, strategy) mode = strategy.to_s.to_sym xff = env['HTTP_X_FORWARDED_FOR'] if xff && !xff.strip.empty? parts = xff.split(',').map(&:strip) ip = mode == :leftmost ? parts.first : parts.last return ip end env['REMOTE_ADDR'] end |
.ip_or_nil(str) ⇒ IPAddr?
Parse string to IPAddr or nil on failure. IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1) are normalised to native IPv4 so that CIDR checks against plain IPv4 ranges succeed.
64 65 66 67 68 69 70 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 64 def ip_or_nil(str) addr = IPAddr.new(str) addr = addr.native if addr.respond_to?(:native) addr rescue StandardError nil end |
.resolve_peer(env, preference, strategy) ⇒ String?
Resolve the peer value based on preference and strategy.
Only :xff_only selects the peer from X-Forwarded-For first. Every other
value — the :remote_then_xff default, nil, or an unrecognized/typo'd
preference — falls back to the safe REMOTE_ADDR-first path so a
misconfiguration can never switch the trust decision onto the
client-controlled X-Forwarded-For header.
118 119 120 121 122 123 124 125 126 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 118 def resolve_peer(env, preference, strategy) return extract_peer_ip(env, strategy) if preference.to_s.to_sym == :xff_only remote = (env['REMOTE_ADDR'] || '').to_s.strip return remote unless remote.empty? # Fall back to X-Forwarded-For when REMOTE_ADDR is empty extract_peer_ip(env, strategy) end |
.rule_trusts?(rule, remote, remote_ip, env) ⇒ Boolean
Check whether a single rule trusts the selected remote. A rule that raises (e.g. an invalid CIDR string or a failing Proc) is treated as non-matching so that one bad rule cannot disable the rest of the allowlist.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 82 def rule_trusts?(rule, remote, remote_ip, env) case rule when String if rule.include?('/') # CIDR cidr = IPAddr.new(rule) remote_ip ? cidr.include?(remote_ip) : false else remote == rule end when Regexp remote =~ rule when Proc rule.call(remote, env) else false end rescue StandardError => e # Isolate a single failing rule without disabling the rest of the # allowlist, but surface it under $DEBUG so a broken Proc/CIDR rule is # observable instead of silently denying trust. warn("[verikloak-bff] trusted_proxies rule raised and was skipped: #{e.class}: #{e.}") if $DEBUG false end |
.selected_peer(env, preference, strategy) ⇒ String?
Return the selected peer IP according to preference and strategy.
54 55 56 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 54 def selected_peer(env, preference, strategy) resolve_peer(env, preference, strategy) end |
.trusted?(env, trusted, strategy = :rightmost, preference: :remote_then_xff) ⇒ Boolean
Determine if the immediate peer (based on REMOTE_ADDR / X-Forwarded-For) is trusted. strategy :rightmost (typical when proxy appends client IP to the right)
27 28 29 30 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 27 def trusted?(env, trusted, strategy = :rightmost, preference: :remote_then_xff) remote = resolve_peer(env, preference, strategy) trusted_remote?(remote, trusted, env) end |
.trusted_remote?(remote, trusted, env) ⇒ Boolean
Determine whether a remote peer appears in the trusted list.
134 135 136 137 138 139 140 141 142 |
# File 'lib/verikloak/bff/proxy_trust.rb', line 134 def trusted_remote?(remote, trusted, env) return false if trusted.nil? || trusted.empty? return false unless remote remote_ip = ip_or_nil(remote) trusted.any? { |rule| rule_trusts?(rule, remote, remote_ip, env) } rescue StandardError false end |