paraxial 0.7.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae07951f0f8acaa36743cf6262075828235520ddc3ffb2ff7f4a29643ddd6e1d
4
- data.tar.gz: a865ff890ed5e9a802b9462e236a8efaa4b494d5b5973cf13720446c76174444
3
+ metadata.gz: 0a6510720489f0277f96eef42e60e10e7f3958ab6a3763aa3941c022c497a314
4
+ data.tar.gz: 497e56a5048f7b6cbb5d2238e5d9059a66cec676dde27d9474faaaee6a5d0fb6
5
5
  SHA512:
6
- metadata.gz: 4cfda9292ce733e777a2198b97e30443a68d8348dd822ff60f680da43af6b47aa18c2318bcf01565689ba8961bc695a71fccf31814a46092c256f52ce7893810
7
- data.tar.gz: e10ef61a321f57660a35d706cdab3b000852c68ca66c89299fe54a95daa785e008446ffa06d9ede8bca8a7ed6bd9e1a9e7c6e11ddaa78f79a8d25b5539edd48b
6
+ metadata.gz: 64182cfa8039d867bbc5e113e5f421a3e1141e833790222c52ae6191099289fbd056cef3163442c949db576d1de76402c8d5196fd05da46169e34f64de77ab71
7
+ data.tar.gz: 7fbc2ed7db3b3afb3d43a935e667d4ffc26464034c7070f8d15ba28db03c9ee5fb1fc327d56005ecefd615a39845cc8fe5f5e5aa92975186b3c9f3b615c1410b
@@ -3,19 +3,59 @@ module Paraxial
3
3
  module Checker
4
4
  @allows = { 'v4' => Patricia.new, 'v6' => Patricia.new(:AF_INET6) }
5
5
  @bans = { 'v4' => Patricia.new, 'v6' => Patricia.new(:AF_INET6) }
6
-
6
+ @buffer = Queue.new
7
+ @mutex = Mutex.new
7
8
 
8
9
  if Paraxial::Helpers.get_api_key
9
10
  @thread = Thread.new do
10
11
  loop do
11
12
  get_abr
12
13
  sleep(10)
14
+ flush_buffer
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.req_to_buff(req_hash)
20
+ @buffer << req_hash
21
+ end
22
+
23
+ def self.flush_buffer
24
+ @mutex.synchronize do
25
+ requests = []
26
+ until @buffer.empty?
27
+ requests << @buffer.pop(true) rescue nil
13
28
  end
29
+
30
+ send_async_request(requests) unless requests.empty?
14
31
  end
15
32
  end
16
33
 
34
+ def self.send_async_request(requests)
35
+ body =
36
+ {
37
+ http_requests: requests,
38
+ private_api_key: Paraxial::Helpers.get_api_key
39
+ }
40
+
41
+ # Do not send HTTP events when free tier is set to true
42
+ ft = Paraxial::FreeTier.is_free_tier
43
+ if ft
44
+ puts "[Paraxial] HTTP ingest not supported on free tier"
45
+ else
46
+ Thread.new do
47
+ uri = URI.parse(Paraxial::Helpers.get_ingest_url) # Replace with your endpoint
48
+ headers = { 'Content-Type': 'application/json' }
49
+ resp = Net::HTTP.post(uri, body.to_json, headers)
50
+ puts "ingest_url resp.code: #{resp.code}"
51
+ puts resp.body
52
+ end
53
+ end
54
+ end
55
+
56
+
17
57
  def self.get_abr
18
- uri = URI.parse(Paraxial::Helpers.get_paraxial_url + '/api/abr')
58
+ uri = URI.parse(Paraxial::Helpers.get_abr_url)
19
59
  headers = { 'Content-Type': 'application/json' }
20
60
 
21
61
  body = { api_key: Paraxial::Helpers.get_api_key }
@@ -0,0 +1,34 @@
1
+ require 'net/http'
2
+ require 'json'
3
+
4
+ module Paraxial
5
+ module FreeTier
6
+ class << self
7
+ attr_reader :is_free_tier
8
+
9
+ def initialize
10
+ @is_free_tier = true
11
+ check_free_tier_status
12
+ end
13
+
14
+ private
15
+
16
+ # Kicks off an async HTTP request
17
+ def check_free_tier_status
18
+ Thread.new do
19
+ uri = URI.parse(Paraxial::Helpers.get_free_tier_url())
20
+ headers = { 'Content-Type': 'application/json' }
21
+ body = { api_key: Paraxial::Helpers.get_api_key }
22
+ r = Net::HTTP.post(uri, body.to_json, headers)
23
+ result = JSON.parse(r.body)
24
+ # Assume the API response contains a field `free_tier` (true/false)
25
+ @is_free_tier = result['free_tier']
26
+ rescue StandardError => e
27
+ # Handle any errors (network issues, parsing errors, etc.)
28
+ puts "Error fetching free tier status: #{e.message}"
29
+ @is_free_tier = true
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -12,6 +12,18 @@ module Paraxial
12
12
  get_paraxial_url + '/api/exploit'
13
13
  end
14
14
 
15
+ def self.get_free_tier_url
16
+ get_paraxial_url + '/api/free_tier'
17
+ end
18
+
19
+ def self.get_abr_url
20
+ get_paraxial_url + '/api/abr'
21
+ end
22
+
23
+ def self.get_ingest_url
24
+ get_paraxial_url + '/api/ingest'
25
+ end
26
+
15
27
  def self.get_api_key
16
28
  @paraxial_api_key ||= ENV['PARAXIAL_API_KEY']
17
29
  end
@@ -4,9 +4,9 @@ unless Rails.env.test? || File.basename($0) == 'rake' || defined?(Rails::Generat
4
4
  alias_method :original_load, :load
5
5
 
6
6
  def load(source, proc = nil)
7
- exg = Paraxial.configuration.exploit_guard
7
+ exg = Paraxial.configuration&.exploit_guard || nil
8
8
  if [:monitor, :block].include?(exg)
9
- if source.is_a?(String) && source.match?(/ActionView|Net::BufferedIO|ERB|ActiveSupport/)
9
+ if source.is_a?(String) && source.match?(/ActionView|Net::BufferedIO|ERB/)
10
10
  puts "[Paraxial] Exploit Guard triggered, malicious input to Marshal.load"
11
11
  puts source
12
12
 
@@ -3,6 +3,7 @@ require 'paraxial'
3
3
  require 'rpatricia'
4
4
  require_relative '../helpers'
5
5
  require_relative '../checker'
6
+ require_relative '../free_tier'
6
7
 
7
8
  Bundler.setup
8
9
 
@@ -20,6 +21,7 @@ unless Rails.env.test? || File.basename($0) == 'rake' || defined?(Rails::Generat
20
21
  puts '[Paraxial] API key detected, agent starting'
21
22
 
22
23
  Paraxial.check_exploit_guard
24
+ Paraxial::FreeTier.initialize
23
25
 
24
26
  deps_and_licenses = []
25
27
  Bundler.load.specs.each do |spec|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Paraxial
4
- VERSION = '0.7.0'
4
+ VERSION = '0.9.0'
5
5
  end
data/lib/paraxial.rb CHANGED
@@ -44,7 +44,66 @@ module Paraxial
44
44
  utc_time.strftime('%Y-%m-%d %H:%M:%S.%6N') + 'Z'
45
45
  end
46
46
 
47
+ def self.record(request, status)
48
+ return if Paraxial::Helpers.get_api_key.nil?
49
+
50
+ req_hash =
51
+ {
52
+ ip_address: request.remote_ip,
53
+ http_method: request.request_method,
54
+ path: request.path,
55
+ user_agent: request.user_agent,
56
+ allowed: !request.env['paraxial.deny'],
57
+ status_code: status,
58
+ inserted_at: get_timestamp,
59
+ cloud_ip: request.env['paraxial.cloud_ip'],
60
+ host: request.host
61
+ }
62
+ puts req_hash
63
+ Paraxial::Checker.req_to_buff(req_hash)
64
+ end
65
+
66
+ # routes = ['/login', '/users/:id']
67
+ def self.block_cloud_ip(request, routes)
68
+ return if Paraxial::Helpers.get_api_key.nil?
69
+
70
+ ip = request.remote_ip
71
+ cloud_provider = get_cloud_provider(ip)
72
+
73
+ if cloud_provider
74
+ request.env['paraxial.cloud_ip'] = cloud_provider
75
+ else
76
+ request.env['paraxial.cloud_ip'] = nil
77
+ end
78
+
79
+ route_patterns = routes.map do |route|
80
+ Regexp.new("^" + route.gsub(/:\w+/, '\d+') + "$")
81
+ end
82
+
83
+ match = route_patterns.any? { |pattern| pattern.match?(request.path) }
84
+
85
+ if match and cloud_provider
86
+ request.env['paraxial.deny'] = true
87
+ end
88
+ end
89
+
90
+ def self.req_allowed?(request)
91
+ return if Paraxial::Helpers.get_api_key.nil?
92
+
93
+ if request.env['paraxial.deny'] == true
94
+ false
95
+ elsif Paraxial::Checker.allow_ip?(request.remote_ip) == true
96
+ request.env['paraxial.deny'] = false
97
+ true
98
+ else
99
+ request.env['paraxial.deny'] = true
100
+ false
101
+ end
102
+ end
103
+
47
104
  def self.cloud_ip?(ip)
105
+ return if Paraxial::Helpers.get_api_key.nil?
106
+
48
107
  if ip.include?('.')
49
108
  !!PARAXIAL_IPV4.search_best(ip)
50
109
  else
@@ -52,11 +111,25 @@ module Paraxial
52
111
  end
53
112
  end
54
113
 
114
+ def self.get_cloud_provider(ip)
115
+ return if Paraxial::Helpers.get_api_key.nil?
116
+
117
+ if ip.include?('.')
118
+ PARAXIAL_IPV4.search_best(ip)&.data
119
+ else
120
+ PARAXIAL_IPV6.search_best(ip)&.data
121
+ end
122
+ end
123
+
55
124
  def self.ban_ip(ip)
125
+ return if Paraxial::Helpers.get_api_key.nil?
126
+
56
127
  Paraxial::Checker.ban_ip(ip)
57
128
  end
58
129
 
59
130
  def self.allow_ip?(ip)
131
+ return if Paraxial::Helpers.get_api_key.nil?
132
+
60
133
  Paraxial::Checker.allow_ip?(ip)
61
134
  end
62
135
 
@@ -83,7 +156,7 @@ module Paraxial
83
156
 
84
157
  def self.check_exploit_guard
85
158
  if configuration.nil?
86
- puts "[Paraxial] Exploit Guard, no config exists, will not run"
159
+ puts "[Paraxial] Exploit Guard, no configuration exists, will not run"
87
160
  return
88
161
  end
89
162
 
@@ -95,7 +168,7 @@ module Paraxial
95
168
  when nil
96
169
  puts "[Paraxial] Exploit Guard, not configured, will not run"
97
170
  else
98
- puts "[Paraxial] Exploit Guard, bad value"
171
+ puts "[Paraxial] Exploit Guard, bad configuration value: #{configuration.exploit_guard}, will not run"
99
172
  end
100
173
  end
101
174
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paraxial
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Lubas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-13 00:00:00.000000000 Z
11
+ date: 2024-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -97,6 +97,7 @@ files:
97
97
  - lib/paraxial/checker.rb
98
98
  - lib/paraxial/cli.rb
99
99
  - lib/paraxial/engine.rb
100
+ - lib/paraxial/free_tier.rb
100
101
  - lib/paraxial/helpers.rb
101
102
  - lib/paraxial/initializers/marshal_patch.rb
102
103
  - lib/paraxial/initializers/startup.rb