immunio 1.1.7 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|