Class: Trackdown::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/trackdown/configuration.rb

Overview

Runtime choices for providers, MaxMind, and provider-specific source trust.

Constant Summary collapse

VALID_PROVIDERS =

Available provider types: :auto - Use one IP-corroborated CDN provider, otherwise fall back to MaxMind (recommended) :cloudflare - Only use Cloudflare headers :cloudfront - Only use Amazon CloudFront headers :maxmind - Only use MaxMind database

%i[auto cloudflare cloudfront maxmind].freeze
TRUSTED_CDN_PROVIDERS =
%i[cloudflare cloudfront].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/trackdown/configuration.rb', line 26

def initialize
  @provider = :auto # Safe default: use one verified edge candidate, otherwise MaxMind
  @maxmind_license_key = nil
  @maxmind_account_id = nil
  @database_path = defined?(Rails) ? Rails.root.join('db', 'GeoLite2-City.mmdb').to_s : 'db/GeoLite2-City.mmdb'
  @timeout = 3 # seconds
  @pool_size = 5
  @pool_timeout = 3 # seconds
  @memory_mode = MAXMIND_AVAILABLE ? MaxMind::DB::MODE_MEMORY : nil
  @reject_private_ips = true
  @trusted_cdn_path_verifiers = {}
  @warned_verifier_raised = {}
  @verifier_mutex = Mutex.new
end

Instance Attribute Details

#database_pathObject

Returns the value of attribute database_path.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def database_path
  @database_path
end

#maxmind_account_idObject

Returns the value of attribute maxmind_account_id.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def 
  @maxmind_account_id
end

#maxmind_license_keyObject

Returns the value of attribute maxmind_license_key.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def maxmind_license_key
  @maxmind_license_key
end

#memory_modeObject

Returns the value of attribute memory_mode.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def memory_mode
  @memory_mode
end

#pool_sizeObject

Returns the value of attribute pool_size.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def pool_size
  @pool_size
end

#pool_timeoutObject

Returns the value of attribute pool_timeout.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def pool_timeout
  @pool_timeout
end

#providerObject

Returns the value of attribute provider.



14
15
16
# File 'lib/trackdown/configuration.rb', line 14

def provider
  @provider
end

#reject_private_ipsObject

Returns the value of attribute reject_private_ips.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def reject_private_ips
  @reject_private_ips
end

#timeoutObject

Returns the value of attribute timeout.



15
16
17
# File 'lib/trackdown/configuration.rb', line 15

def timeout
  @timeout
end

Instance Method Details

#reject_private_ips?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/trackdown/configuration.rb', line 49

def reject_private_ips?
  @reject_private_ips
end

#request_came_through_trusted_cdn_path?(request, provider_name:) ⇒ Boolean

Did the host vouch for this request? Asked fresh every time, never cached, and a verifier that blows up means "no" — a geolocation lookup must not be able to take an application down.

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/trackdown/configuration.rb', line 110

def request_came_through_trusted_cdn_path?(request, provider_name:)
  validate_trusted_cdn_provider!(provider_name)
  verifier = trusted_cdn_path_verifier_for(provider_name)
  return false unless request && verifier

  begin
    !!verifier.call(request)
  rescue StandardError => e
    warn_verifier_raised(provider_name, e)
    false
  end
end

#trusted_cdn_path_verifier_for(provider_name) ⇒ Object



123
124
125
126
# File 'lib/trackdown/configuration.rb', line 123

def trusted_cdn_path_verifier_for(provider_name)
  validate_trusted_cdn_provider!(provider_name)
  @verifier_mutex.synchronize { @trusted_cdn_path_verifiers[provider_name] }
end

#verify_request_came_through_trusted_cdn_path_with(provider_name, verifier = nil, &block) ⇒ Object

Provider-aware lower-level form used by the two plain-English helpers above.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/trackdown/configuration.rb', line 87

def verify_request_came_through_trusted_cdn_path_with(provider_name, verifier = nil, &block)
  validate_trusted_cdn_provider!(provider_name)
  verifier ||= block

  if verifier.nil?
    raise ArgumentError, "verify_request_came_through_trusted_#{provider_name}_path_with needs a block or " \
                         'a callable saying how you know a request came through that CDN'
  end

  unless verifier.respond_to?(:call)
    raise ArgumentError, "The trusted #{provider_name} path verifier must respond to #call " \
                         "(a block, proc, lambda, or any callable object), got: #{verifier.inspect}"
  end

  @verifier_mutex.synchronize do
    @warned_verifier_raised.delete(provider_name)
    @trusted_cdn_path_verifiers[provider_name] = verifier
  end
end

#verify_request_came_through_trusted_cloudflare_path_with(verifier = nil, &block) ⇒ Object

Tell Trackdown how you know a request really came through Cloudflare, so only Cloudflare results can say source_trust: :host_verified:

expected = Rails.application.credentials.cloudflare_origin_secret.to_s
raise 'Missing Cloudflare origin secret' if expected.empty?

config.verify_request_came_through_trusted_cloudflare_path_with do |request|
supplied = request.env['HTTP_X_ORIGIN_SECRET'].to_s
!supplied.empty? && ActiveSupport::SecurityUtils.secure_compare(supplied, expected)
end

The non-empty checks are essential: secure_compare('', '') is true. Rails: https://api.rubyonrails.org/classes/ActiveSupport/SecurityUtils.html#method-c-secure_compare

Trackdown never infers trust from headers. Anyone who can reach an unprotected origin can set them. Verify each CDN independently so a trusted CloudFront path can never vouch for forwarded, viewer-supplied CF-* headers: https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/ https://developers.cloudflare.com/fundamentals/concepts/cloudflare-ip-addresses/#block-other-ip-addresses-recommended https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/add-origin-custom-headers.html https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-overview.html https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-and-cloudfront

Trackdown reports this trust state; it does not act on it. Deciding what an unverified location may be used for is your application's call.



78
79
80
# File 'lib/trackdown/configuration.rb', line 78

def verify_request_came_through_trusted_cloudflare_path_with(verifier = nil, &block)
  verify_request_came_through_trusted_cdn_path_with(:cloudflare, verifier, &block)
end

#verify_request_came_through_trusted_cloudfront_path_with(verifier = nil, &block) ⇒ Object



82
83
84
# File 'lib/trackdown/configuration.rb', line 82

def verify_request_came_through_trusted_cloudfront_path_with(verifier = nil, &block)
  verify_request_came_through_trusted_cdn_path_with(:cloudfront, verifier, &block)
end