immunio 1.1.7 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -0
- data/lib/immunio.rb +4 -0
- data/lib/immunio/agent.rb +1 -0
- data/lib/immunio/channel.rb +64 -4
- data/lib/immunio/logger.rb +1 -1
- data/lib/immunio/processor.rb +5 -0
- data/lib/immunio/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c73cecf0da251ae6c4e8fc65c1215a84cca2a9a
|
4
|
+
data.tar.gz: cc1742b1789f90dce3c6a2ad8a698c7e4e4730da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ba46ef732b848a7bddce203578b91b801ad5c8571b5b49443c300b9f74bcbba3519ecffac8e0bd25476e2de40d7d8b8f16ae4a4bc45cf4aa93f3d26270c7291
|
7
|
+
data.tar.gz: d127335b24855d7b3cdd4725bca45b946e13d5712bc203fa972d0c79b16e719986b3d1c114bcb12df6ece8524c0af032c79f7fffd4ec46208dd03bb90d738c43
|
data/README.md
CHANGED
@@ -39,6 +39,25 @@ gem immunio', group: :production
|
|
39
39
|
|
40
40
|
You can also modify the secret and key for different environments to report to different apps, or you can disable the agent by setting `agent_enabled: false` in the configuration or `IMMUNIO_AGENT_ENABLED=0` in the environment.
|
41
41
|
|
42
|
+
|
43
|
+
### Unicorn configuration
|
44
|
+
|
45
|
+
In order for the agent to function correctly in a pre-forked environment, use the `Immunio.reset!` method.
|
46
|
+
For example, in your `config/unicorn.rb`:
|
47
|
+
|
48
|
+
```
|
49
|
+
after_fork do |server, worker|
|
50
|
+
Signal.trap 'TERM' do
|
51
|
+
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
|
52
|
+
end
|
53
|
+
|
54
|
+
defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
|
55
|
+
|
56
|
+
Immunio.reset!
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
|
42
61
|
## Handling blocked requests
|
43
62
|
|
44
63
|
By default, Immunio will return a plain text *403 Forbidden* response whenever it blocks a request for security reasons.
|
@@ -55,6 +74,7 @@ Immunio.blocked_app = -> env do
|
|
55
74
|
end
|
56
75
|
```
|
57
76
|
|
77
|
+
|
58
78
|
## Authentication API
|
59
79
|
|
60
80
|
If you're using [Devise](https://github.com/plataformatec/devise) or [Authlogic](https://github.com/binarylogic/authlogic), Immunio will automatically hook into your authentication system to protect you against attacks.
|
data/lib/immunio.rb
CHANGED
data/lib/immunio/agent.rb
CHANGED
data/lib/immunio/channel.rb
CHANGED
@@ -17,6 +17,7 @@ module Immunio
|
|
17
17
|
attr_reader :rejected_message_count
|
18
18
|
|
19
19
|
def initialize(config)
|
20
|
+
Immunio.logger.debug { "Creating channel" }
|
20
21
|
@config = config
|
21
22
|
|
22
23
|
@agent_uuid = nil
|
@@ -42,6 +43,13 @@ module Immunio
|
|
42
43
|
@started = false
|
43
44
|
@ready = false
|
44
45
|
|
46
|
+
# In the case of a forking web server like Unicorn,
|
47
|
+
# we need to remember the process id because it may
|
48
|
+
# happen that the master process starts its polling
|
49
|
+
# thread first, for example when a request is sent
|
50
|
+
# before forking the workers.
|
51
|
+
@process_id = Process.pid
|
52
|
+
|
45
53
|
@callbacks = []
|
46
54
|
|
47
55
|
# Anything looking to add to the messages sent to the server:
|
@@ -67,8 +75,18 @@ module Immunio
|
|
67
75
|
def start
|
68
76
|
return if @started
|
69
77
|
|
78
|
+
Immunio.logger.debug { "Starting channel" }
|
79
|
+
|
80
|
+
Immunio.logger.trace { "Thread count is: #{Thread.list.size}" }
|
81
|
+
Immunio.logger.trace { "Threads: #{Thread.list.map(&:object_id)}" }
|
82
|
+
Immunio.logger.trace { "@thread in thread list?: #{Thread.list.include? @thread}" }
|
83
|
+
Immunio.logger.trace { "@process_id is: #{@process_id}" }
|
84
|
+
Immunio.logger.trace { "@thread is: #{@thread.inspect}" }
|
85
|
+
|
70
86
|
@started = true
|
71
87
|
@thread = Thread.new { run }
|
88
|
+
|
89
|
+
Immunio.logger.trace { "Thread count is now: #{Thread.list.size}" }
|
72
90
|
end
|
73
91
|
|
74
92
|
# Stop and wait for the last messages to be sent.
|
@@ -86,22 +104,45 @@ module Immunio
|
|
86
104
|
end
|
87
105
|
end
|
88
106
|
|
107
|
+
def needs_reset?
|
108
|
+
@process_id != Process.pid
|
109
|
+
end
|
110
|
+
|
111
|
+
def reset
|
112
|
+
Immunio.logger.debug { "Resetting channel" }
|
113
|
+
|
114
|
+
stop
|
115
|
+
|
116
|
+
@process_id = Process.pid
|
117
|
+
@message_queue.clear
|
118
|
+
end
|
119
|
+
|
89
120
|
def send_message(message)
|
90
121
|
send_encoded_message message.to_msgpack
|
91
122
|
end
|
92
123
|
|
93
124
|
def send_encoded_message(message)
|
125
|
+
Immunio.logger.debug do
|
126
|
+
"Queueing message: (queue size: #{@message_queue.size}, max: #{@config.max_send_queue_size})"
|
127
|
+
end
|
128
|
+
|
94
129
|
if @message_queue.size > @config.max_send_queue_size
|
95
130
|
Immunio.logger.warn { "Dropping message for agent manager due to queue overflow (#{@message_queue.size} > #{@config.max_send_queue_size})" }
|
96
|
-
Immunio.logger.debug { "Dropped message: (#{message})" }
|
97
131
|
# No room for this message on the queue. Discard.
|
98
132
|
@dropped_message_count += 1
|
133
|
+
Immunio.logger.debug { "Dropped message: (#{message}, dropped count: #{@dropped_message_count})" }
|
99
134
|
return
|
100
135
|
end
|
101
136
|
|
102
|
-
Immunio.logger.debug
|
137
|
+
Immunio.logger.debug do
|
138
|
+
"Queueing message: message.size: #{message.size}, #{MessagePack.unpack(message)}"
|
139
|
+
end
|
103
140
|
|
104
141
|
@message_queue << message
|
142
|
+
|
143
|
+
Immunio.logger.debug do
|
144
|
+
"Queueing message: (queue size now: #{@message_queue.size}, max: #{@config.max_send_queue_size})"
|
145
|
+
end
|
105
146
|
end
|
106
147
|
|
107
148
|
def on_message(&block)
|
@@ -140,6 +181,7 @@ module Immunio
|
|
140
181
|
# Core method running in a thread
|
141
182
|
def run
|
142
183
|
Immunio.logger.debug { "Starting channel on thread #{Thread.current.object_id}" }
|
184
|
+
|
143
185
|
# Create an empty cert_store to prevent Faraday from using the system default OpenSSL store.
|
144
186
|
cert_store = OpenSSL::X509::Store.new
|
145
187
|
# Setup the connection for making requests to the server.
|
@@ -263,8 +305,10 @@ module Immunio
|
|
263
305
|
end
|
264
306
|
|
265
307
|
def add_to_send_buffer(message)
|
308
|
+
Immunio.logger.debug { "Adding message to send buffer (bytesize: #{message.bytesize})" }
|
266
309
|
@send_buffer_bytes += message.bytesize
|
267
310
|
@send_buffer << message
|
311
|
+
Immunio.logger.debug { "Adding message to send buffer (send buffer size: #{@send_buffer.size})" }
|
268
312
|
end
|
269
313
|
|
270
314
|
# Fill send_buffer with messages to send
|
@@ -276,8 +320,10 @@ module Immunio
|
|
276
320
|
add_to_send_buffer @next_message
|
277
321
|
else
|
278
322
|
Immunio.logger.warn { "Dropped message over max byte send size, next message size #{@next_message.bytesize}" }
|
279
|
-
Immunio.logger.debug { "Dropped next message used: #{used_bytes} over max byte: #{@next_message}" }
|
280
323
|
@dropped_message_count += 1
|
324
|
+
Immunio.logger.debug do
|
325
|
+
"Dropped next message (used: #{used_bytes} over max byte: #{@next_message}, dropped count: #{@dropped_message_count})"
|
326
|
+
end
|
281
327
|
end
|
282
328
|
@next_message = nil
|
283
329
|
end
|
@@ -285,6 +331,9 @@ module Immunio
|
|
285
331
|
# Empty the queue as much as possible.
|
286
332
|
while !@message_queue.empty?
|
287
333
|
@next_message = @message_queue.pop
|
334
|
+
|
335
|
+
Immunio.logger.debug { "Emptying message queue: (queue size: #{@message_queue.size})" }
|
336
|
+
|
288
337
|
if !send_buffer_has_room used_bytes
|
289
338
|
break
|
290
339
|
end
|
@@ -303,6 +352,9 @@ module Immunio
|
|
303
352
|
while @send_buffer.size < @config.min_report_size
|
304
353
|
# If there are no messages in the queue, this will block until one arrives.
|
305
354
|
@next_message = @message_queue.pop
|
355
|
+
|
356
|
+
Immunio.logger.debug { "Waiting for messages: (queue size: #{@message_queue.size})" }
|
357
|
+
|
306
358
|
if !send_buffer_has_room used_bytes
|
307
359
|
break
|
308
360
|
end
|
@@ -329,6 +381,8 @@ module Immunio
|
|
329
381
|
|
330
382
|
# Poll the server sending queued messages at the same time.
|
331
383
|
def poll
|
384
|
+
Immunio.logger.trace { "Polling" }
|
385
|
+
|
332
386
|
# Prep data
|
333
387
|
body = {
|
334
388
|
send_seq: @send_seq,
|
@@ -382,28 +436,35 @@ module Immunio
|
|
382
436
|
|
383
437
|
req.body = gzip(encoded_body)
|
384
438
|
|
439
|
+
Immunio.logger.debug do
|
440
|
+
"Sending request to agent manager (size: #{req.body.size})"
|
441
|
+
end
|
385
442
|
Immunio.logger.trace {"Sending request to agent manager (data: #{MessagePack.unpack(encoded_body)}, request: #{req})"}
|
386
443
|
end
|
387
444
|
|
388
445
|
if response.status >= 400 and response.status < 500 then
|
389
446
|
# 4XX response codes should NOT be retried. Discard the report.
|
390
447
|
@rejected_message_count += @send_buffer.size
|
448
|
+
Immunio.logger.debug { "Rejected message count is: #{@rejected_message_count}" }
|
391
449
|
Immunio.logger.trace { "Rejecting #{@send_buffer.size} messages" }
|
392
450
|
@send_buffer = []
|
393
451
|
@send_buffer_bytes = 0
|
394
452
|
|
453
|
+
Immunio.logger.debug {"Received response from agent manager (status: #{response.status})"}
|
395
454
|
Immunio.logger.trace {"Received response from agent manager (status: #{response.status}, raw body: #{raw_log response.body})"}
|
396
455
|
raise Error, "Bad response from Immunio server: #{response.status} #{response.body}"
|
397
456
|
end
|
398
457
|
|
399
458
|
if response.status >= 500 then
|
400
459
|
# 5XX response codes are treated like errors.
|
460
|
+
Immunio.logger.debug {"Received response from agent manager (status: #{response.status})"}
|
401
461
|
Immunio.logger.trace {"Received response from agent manager (status: #{response.status}, raw body: #{raw_log response.body})"}
|
402
462
|
raise Error, "Bad response from Immunio server: #{response.status} #{response.body}"
|
403
463
|
end
|
404
464
|
|
405
465
|
body = MessagePack.unpack(response.body)
|
406
466
|
|
467
|
+
Immunio.logger.debug {"Received response from agent manager (status: #{response.status})"}
|
407
468
|
Immunio.logger.trace {"Received response from agent manager (status: #{response.status}, body: #{body}, raw body: #{raw_log response.body})"}
|
408
469
|
|
409
470
|
# Update local data from response
|
@@ -426,7 +487,6 @@ module Immunio
|
|
426
487
|
if received_messages
|
427
488
|
received_messages.each { |message| notify message }
|
428
489
|
end
|
429
|
-
|
430
490
|
end
|
431
491
|
end
|
432
492
|
end
|
data/lib/immunio/logger.rb
CHANGED
@@ -34,7 +34,7 @@ module Immunio
|
|
34
34
|
|
35
35
|
def self.setup_logger_formatter
|
36
36
|
logger.formatter = proc do |severity, datetime, _progname, msg|
|
37
|
-
"[#{datetime}] #{severity}: #{msg}\n"
|
37
|
+
"[#{datetime}] [#{Process.pid} (#{Thread.current.object_id})]: #{severity}: #{msg}\n"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
data/lib/immunio/processor.rb
CHANGED
@@ -50,6 +50,11 @@ module Immunio
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def new_request(request)
|
53
|
+
Immunio.logger.debug { "New request: (started: #{@channel.started?})" }
|
54
|
+
|
55
|
+
# Reset channel if it was created by parent process
|
56
|
+
@channel.reset if @channel.needs_reset?
|
57
|
+
|
53
58
|
# Start channel on first request
|
54
59
|
@channel.start unless @channel.started?
|
55
60
|
|
data/lib/immunio/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: immunio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Immunio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|