Class: QueryGuard::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/query_guard/config.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize ⇒ Config

Returns a new instance of Config.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/query_guard/config.rb', line 60

def initialize
  # User-facing configuration - simplified for new users
  @migrations_directory     = "db/migrate"
  @enabled_environments     = %i[development test]

  # Query monitoring thresholds
  @max_queries_per_request  = 100
  @max_duration_ms_per_query = 100.0
  @block_select_star        = false
  @raise_on_violation       = false
  @ignored_sql              = [/^PRAGMA /i, /^BEGIN/i, /^COMMIT/i]
  @log_prefix               = "[QueryGuard]"

  # Analyzer registry and control
  @disabled_analyzers       = []
  @analyzer_registry        = Analyzers::Registry.new
  @analyze_query_risks      = true
  @use_explain_plans        = false
  @explain_enricher         = nil

  # Analyzer severity levels
  @slow_query_severity      = :warn
  @query_count_severity     = :warn
  @select_star_severity     = :warn
  @migration_risk_severity  = :error

  # --- Security defaults (safe, low noise) ---
  @enable_security          = true
  @detect_sql_injection     = true
  @sql_injection_patterns   = [
    /(\bor\b|\band\b)\s+\d+\s*=\s*\d+/i,   # OR 1=1
    /\bunion\s+select\b/i,
    /--|\/\*|\*\//,                         # comment tokens
    /;\s*(drop|alter|truncate)\b/i,
    /\b(pg_sleep|sleep)\s*\(/i,
    /\binformation_schema\b/i
  ]

  @detect_unusual_query_pattern = true
  @max_queries_per_minute_per_actor = 300
  @max_unique_query_fingerprints_per_minute_per_actor = 80

  @detect_data_exfiltration = true
  @max_response_bytes_per_request = 2_000_000 # ~2MB
  @exfiltration_path_regex = %r{/(export|download|reports|dump)\b}i

  @detect_mass_assignment   = true
  @sensitive_param_keys     = %w[
    admin is_admin role roles permissions permission account_id user_id
    plan_id price amount balance credit debit status state
  ]

  @actor_resolver = lambda do |env|
    env["query_guard.actor"] ||
      env["action_dispatch.remote_ip"]&.to_s ||
      env["REMOTE_ADDR"]&.to_s ||
      "unknown"
  end

  @store = nil # will default to QueryGuard::Store.new

  @export_mode              = :async
  @export_queries           = :all
  @max_query_events_per_req = 200
  @origin_app               = nil

  # Budget system
  @budget = Budget.new

  # Uploader configuration (SaaS ingestion, future feature)
  @uploader_type            = 'no-op'
  @api_base_url             = nil
  @project_key              = nil
  @api_token                = nil

  # Register default analyzers
  @analyzer_registry.register(:slow_query, Analyzers::SlowQueryAnalyzer.new)
  @analyzer_registry.register(:query_count, Analyzers::QueryCountAnalyzer.new)
  @analyzer_registry.register(:select_star, Analyzers::SelectStarAnalyzer.new)
  @analyzer_registry.register(:query_risk, Analyzers::QueryRiskAnalyzer.new)
end

Instance Attribute Details

#actor_resolver ⇒ Object

Actor resolver for rate limiting (ip/user/token)



52
53
54
# File 'lib/query_guard/config.rb', line 52

def actor_resolver
  @actor_resolver
end

#analyze_query_risks ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def analyze_query_risks
  @analyze_query_risks
end

#analyzer_registry ⇒ Object (readonly)

Returns the value of attribute analyzer_registry.



33
34
35
# File 'lib/query_guard/config.rb', line 33

def analyzer_registry
  @analyzer_registry
end

#api_base_url ⇒ Object

Uploader configuration (SaaS ingestion, future feature)



31
32
33
# File 'lib/query_guard/config.rb', line 31

def api_base_url
  @api_base_url
end

#api_token ⇒ Object

Uploader configuration (SaaS ingestion, future feature)



31
32
33
# File 'lib/query_guard/config.rb', line 31

def api_token
  @api_token
end

#block_select_star ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def block_select_star
  @block_select_star
end

#budget ⇒ Object (readonly)

Budget system



58
59
60
# File 'lib/query_guard/config.rb', line 58

def budget
  @budget
end

#detect_data_exfiltration ⇒ Object

Returns the value of attribute detect_data_exfiltration.



44
45
46
# File 'lib/query_guard/config.rb', line 44

def detect_data_exfiltration
  @detect_data_exfiltration
end

#detect_mass_assignment ⇒ Object

Returns the value of attribute detect_mass_assignment.



48
49
50
# File 'lib/query_guard/config.rb', line 48

def detect_mass_assignment
  @detect_mass_assignment
end

#detect_sql_injection ⇒ Object

Returns the value of attribute detect_sql_injection.



37
38
39
# File 'lib/query_guard/config.rb', line 37

def detect_sql_injection
  @detect_sql_injection
end

#detect_unusual_query_pattern ⇒ Object

Returns the value of attribute detect_unusual_query_pattern.



40
41
42
# File 'lib/query_guard/config.rb', line 40

def detect_unusual_query_pattern
  @detect_unusual_query_pattern
end

#disabled_analyzers ⇒ Object

Analyzer control



16
17
18
# File 'lib/query_guard/config.rb', line 16

def disabled_analyzers
  @disabled_analyzers
end

#enable_security ⇒ Object

--- Security features ---



36
37
38
# File 'lib/query_guard/config.rb', line 36

def enable_security
  @enable_security
end

#enabled_environments ⇒ Object

User-facing configuration



13
14
15
# File 'lib/query_guard/config.rb', line 13

def enabled_environments
  @enabled_environments
end

#exfiltration_path_regex ⇒ Object

Returns the value of attribute exfiltration_path_regex.



46
47
48
# File 'lib/query_guard/config.rb', line 46

def exfiltration_path_regex
  @exfiltration_path_regex
end

#explain_enricher ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def explain_enricher
  @explain_enricher
end

#ignored_sql ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def ignored_sql
  @ignored_sql
end

#max_duration_ms_per_query ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def max_duration_ms_per_query
  @max_duration_ms_per_query
end

#max_queries_per_minute_per_actor ⇒ Object

Returns the value of attribute max_queries_per_minute_per_actor.



41
42
43
# File 'lib/query_guard/config.rb', line 41

def max_queries_per_minute_per_actor
  @max_queries_per_minute_per_actor
end

#max_queries_per_request ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def max_queries_per_request
  @max_queries_per_request
end

#max_response_bytes_per_request ⇒ Object

Returns the value of attribute max_response_bytes_per_request.



45
46
47
# File 'lib/query_guard/config.rb', line 45

def max_response_bytes_per_request
  @max_response_bytes_per_request
end

#max_unique_query_fingerprints_per_minute_per_actor ⇒ Object

Returns the value of attribute max_unique_query_fingerprints_per_minute_per_actor.



42
43
44
# File 'lib/query_guard/config.rb', line 42

def max_unique_query_fingerprints_per_minute_per_actor
  @max_unique_query_fingerprints_per_minute_per_actor
end

#migration_risk_severity ⇒ Object

Severity levels for analyzers



19
20
21
# File 'lib/query_guard/config.rb', line 19

def migration_risk_severity
  @migration_risk_severity
end

#migrations_directory ⇒ Object

User-facing configuration



13
14
15
# File 'lib/query_guard/config.rb', line 13

def migrations_directory
  @migrations_directory
end

#project_key ⇒ Object

Uploader configuration (SaaS ingestion, future feature)



31
32
33
# File 'lib/query_guard/config.rb', line 31

def project_key
  @project_key
end

#query_count_severity ⇒ Object

Severity levels for analyzers



19
20
21
# File 'lib/query_guard/config.rb', line 19

def query_count_severity
  @query_count_severity
end

#raise_on_violation ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def raise_on_violation
  @raise_on_violation
end

#select_star_severity ⇒ Object

Severity levels for analyzers



19
20
21
# File 'lib/query_guard/config.rb', line 19

def select_star_severity
  @select_star_severity
end

#sensitive_param_keys ⇒ Object

Returns the value of attribute sensitive_param_keys.



49
50
51
# File 'lib/query_guard/config.rb', line 49

def sensitive_param_keys
  @sensitive_param_keys
end

#slow_query_severity ⇒ Object

Severity levels for analyzers



19
20
21
# File 'lib/query_guard/config.rb', line 19

def slow_query_severity
  @slow_query_severity
end

#sql_injection_patterns ⇒ Object

Returns the value of attribute sql_injection_patterns.



38
39
40
# File 'lib/query_guard/config.rb', line 38

def sql_injection_patterns
  @sql_injection_patterns
end

#store ⇒ Object

Storage for rolling counters (defaults to in-memory)



55
56
57
# File 'lib/query_guard/config.rb', line 55

def store
  @store
end

#uploader_type ⇒ Object

Uploader configuration (SaaS ingestion, future feature)



31
32
33
# File 'lib/query_guard/config.rb', line 31

def uploader_type
  @uploader_type
end

#use_explain_plans ⇒ Object

Query monitoring (optional, defaults disabled)



23
24
25
# File 'lib/query_guard/config.rb', line 23

def use_explain_plans
  @use_explain_plans
end

Instance Method Details

#disable_analyzer(name) ⇒ Object

Disable a specific analyzer by name



147
148
149
150
# File 'lib/query_guard/config.rb', line 147

def disable_analyzer(name)
  analyzer_sym = name.to_sym
  @disabled_analyzers << analyzer_sym unless @disabled_analyzers.include?(analyzer_sym)
end

#enable_analyzer(name) ⇒ Object

Enable a previously disabled analyzer



153
154
155
# File 'lib/query_guard/config.rb', line 153

def enable_analyzer(name)
  @disabled_analyzers.delete(name.to_sym)
end

#enabled?(env) ⇒ Boolean

Returns:

  • (Boolean)


142
143
144
# File 'lib/query_guard/config.rb', line 142

def enabled?(env)
  @enabled_environments.map(&:to_sym).include?(env.to_sym)
end

#register_analyzer(name, analyzer) ⇒ Object

Register a custom analyzer



158
159
160
# File 'lib/query_guard/config.rb', line 158

def register_analyzer(name, analyzer)
  @analyzer_registry.register(name, analyzer)
end