immunio 1.1.1 → 1.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88d0c7506de87c39b6c0c7dc765cb55da4948b64
4
- data.tar.gz: d38d7b83f8652eae78201c954215bf715fed31df
3
+ metadata.gz: 877a290ccd60b4a6e46fff24968cd223fae6ac56
4
+ data.tar.gz: 5e4c68c451a27e7de6590499dd427485d05ab577
5
5
  SHA512:
6
- metadata.gz: 98a9fddf1a26d59bd4491350613a2e016f9b4cc0697b038f96144793f33e9d01e88cafd1cf4d8ed92874e651d7af730eab7b87e73b814488cc0c17281ddae9e0
7
- data.tar.gz: 75a136f01c2ffe9bec4fda596502df66adbd2e858e25b7f8c04d5dda6653e57a2162f43601bc5e5bbe0c92d78904823443ecb9d7265a2ee9abcda74379894dc2
6
+ metadata.gz: 88c2d9d8c86bd24fa028e1c092524617f3bbc2e271f3fae53c50c8ae45f3ab6d5b1f5b8c1846be8fa7ede95441121426355b5960ed174269712a14f06883c9e6
7
+ data.tar.gz: 7a7bdc7a6cc3d85f5f226a8017061d22dda0bd9f9a6aeaae146f5f8df80b6f8d1e79b533bba2525e2ce8b245ebf52d9cb85e46d3221af0107b427114c1f421ea
data/lib/immunio.rb CHANGED
@@ -5,6 +5,7 @@ module Immunio
5
5
  require_relative "immunio/utils"
6
6
  require_relative "immunio/agent"
7
7
  require_relative "immunio/authentication"
8
+ require_relative "immunio/plugin"
8
9
 
9
10
  agent # Force load agent
10
11
  end
data/lib/immunio/agent.rb CHANGED
@@ -70,8 +70,6 @@ module Immunio
70
70
  # purposes.
71
71
  config_accessor :vm_data
72
72
 
73
- attr_reader :plugins
74
-
75
73
  def initialize
76
74
  Immunio.logger.info { "Initializing agent version #{VERSION} for process #{Process.pid}" }
77
75
 
@@ -104,8 +102,6 @@ module Immunio
104
102
  # Be sure all config attributes have a type before this call:
105
103
  load_config
106
104
 
107
- setup_plugin_registry
108
-
109
105
  Immunio::switch_to_real_logger(config.log_file, config.log_level)
110
106
 
111
107
  if !config.agent_enabled then
@@ -235,75 +231,6 @@ module Immunio
235
231
  def environment=(environment)
236
232
  @processor.environment = environment
237
233
  end
238
-
239
- def register_plugin(name, version = nil)
240
- @plugins[name] = {} unless @plugins.has_key?(name)
241
- @plugins[name]['status'] = 'loaded'
242
- @plugins[name]['version'] = version if version
243
-
244
- Immunio.logger.info do
245
- "Registering plugin '#{name}' => '#{@plugins[name]}'"
246
- end
247
- end
248
-
249
- RECOGNIZED_PLUGINS = [
250
- ## action_dispatch
251
- 'ActionDispatch::Cookies::SignedCookieJar',
252
- 'ActionDispatch::Cookies::UpgradeLegacySignedCookieJar',
253
- 'ActionDispatch::Cookies::EncryptedCookieJar',
254
- 'ActionDispatch::Cookies::UpgradeLegacyEncryptedCookieJar',
255
-
256
- ## action_view
257
- 'ActionView::Template::Handlers::Erubis',
258
- 'Haml::Compiler',
259
- 'Hash',
260
- 'ActionView::TemplateRenderer',
261
- 'ActionView::Template',
262
- 'ActionController::Caching::Fragments',
263
-
264
- ## active_record
265
- 'ActiveRecord',
266
- 'ActiveRecord::ConnectionAdapters::Mysql2Adapter',
267
- 'ActiveRecord::ConnectionAdapters::MysqlAdapter',
268
- 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter',
269
- 'ActiveRecord::ConnectionAdapters::SQLite3Adapter',
270
- 'ActiveRecord::ConnectionAdapters::SQLiteAdapter',
271
- 'ActiveRecord::Sanitization',
272
- 'Arel::Visitors::ToSql',
273
- 'ActiveRecord::ConnectionAdapters::AbstractAdapter',
274
-
275
- ## active_record_relation
276
- 'ActiveRecord::Relation',
277
- 'ActiveRecord::SpawnMethods',
278
- 'ActiveRecord::Querying',
279
- 'ActiveRecord::StatementCache',
280
- 'ActiveRecord::Associations::HasManyThroughAssociation',
281
-
282
- 'Authlogic',
283
- 'ActionController (CSRF)',
284
- 'Devise',
285
- 'Kernel (Eval)',
286
- 'Immunio::HTTPFinisher',
287
- 'Immunio::HTTPTracker',
288
-
289
- ## io
290
- 'IO',
291
- 'File',
292
- 'Kernel (Module)',
293
-
294
- 'ActionController (Redirect)',
295
- 'Warden'
296
- ].freeze
297
-
298
- private
299
-
300
- def setup_plugin_registry
301
- @plugins = {}
302
-
303
- RECOGNIZED_PLUGINS.each do |name|
304
- @plugins[name] = { 'status' => 'pending' }
305
- end
306
- end
307
234
  end
308
235
 
309
236
  AGENT_INIT_MUTEX = Mutex.new
@@ -0,0 +1,94 @@
1
+ require "msgpack"
2
+
3
+ module Immunio
4
+ # Holds the status of a plugin.
5
+ #
6
+ # A plugin can have one of four statuses:
7
+ #
8
+ # - pending: initial state, waiting to be loaded
9
+ # - loaded: successfully loaded
10
+ # - failed: error while loading
11
+ # - disabled: disabled in config, will never be loaded
12
+ #
13
+ # Each registered plugin is reported to the backend via the `EnvironmentReporter`.
14
+ class Plugin
15
+ attr_reader :status
16
+ attr_accessor :version
17
+
18
+ def initialize(name)
19
+ @name = name
20
+ @status = 'pending'
21
+ @version = nil
22
+ end
23
+
24
+ def loaded!(version)
25
+ @status = 'loaded'
26
+ @version = version
27
+ Immunio.logger.debug "Plugin #{@name} v#{version} loaded successfully"
28
+ end
29
+
30
+ def disabled!
31
+ @status = 'disabled'
32
+ Immunio.logger.debug "Plugin #{@name} is disabled"
33
+ end
34
+
35
+ def failed!(error)
36
+ @status = 'failed'
37
+ Immunio.logger.error "Plugin #{@name} failed to load: #{error}"
38
+ end
39
+
40
+ def inspect
41
+ "<#{self.class} name=#{@name.inspect} status=#{@status.inspect} version=#{@version.inspect}>"
42
+ end
43
+
44
+ def to_msgpack(packer)
45
+ packer.write_map_header 2
46
+ # `name` is provided as the key in `registered`
47
+ packer.write('status').write(@status)
48
+ packer.write('version').write(@version)
49
+ end
50
+
51
+ def self.registered
52
+ @registered ||= {}
53
+ end
54
+
55
+ # DSL to register a plugin, its status and version.
56
+ #
57
+ # A `feature` name can be passed to determine if the plugin should be enabled. If the
58
+ # plugin is disabled, the block will not run.
59
+ #
60
+ # You MUST explicitly call `plugin.loaded!` in the block to indicate that the plugin was
61
+ # loaded successfully, or else it will be kept as 'pending'.
62
+ #
63
+ # Eg.:
64
+ #
65
+ # Immunio::Plugin.load 'SomePluginName', feature: 'xss' do |plugin|
66
+ # if defined? SomePlugin
67
+ # # Your loading code here ...
68
+ # plugin.loaded! SomePluginName::VERSION
69
+ # end
70
+ # end
71
+ #
72
+ def self.load(name, options = {})
73
+ if options.key? :feature
74
+ enabled = Immunio.agent.plugin_enabled?(options[:feature])
75
+ else
76
+ enabled = true
77
+ end
78
+
79
+ plugin = registered[name] = new(name)
80
+
81
+ unless enabled # plugin is disabled
82
+ plugin.disabled!
83
+ return
84
+ end
85
+
86
+ Immunio.logger.debug "Loading plugin #{name} ..."
87
+ begin
88
+ yield plugin
89
+ rescue StandardError, LoadError => e
90
+ plugin.failed! e
91
+ end
92
+ end
93
+ end
94
+ end
@@ -29,36 +29,23 @@ module Immunio
29
29
  end
30
30
  end
31
31
 
32
- class ActionDispatch::Cookies
33
- if defined? SignedCookieJar
34
- SignedCookieJar.send :include, Immunio::CookieHooks
35
-
36
- Immunio.agent.register_plugin(
37
- 'ActionDispatch::Cookies::SignedCookieJar',
38
- ActionPack::VERSION::STRING)
39
- end
40
-
41
- if defined? UpgradeLegacySignedCookieJar
42
- UpgradeLegacySignedCookieJar.send :include, Immunio::CookieHooks
43
-
44
- Immunio.agent.register_plugin(
45
- 'ActionDispatch::Cookies::UpgradeLegacySignedCookieJar',
46
- ActionPack::VERSION::STRING)
47
- end
48
-
49
- if defined? EncryptedCookieJar
50
- EncryptedCookieJar.send :include, Immunio::CookieHooks
32
+ Immunio::Plugin.load 'ActionDispatch (Cookie)' do |plugin|
33
+ class ActionDispatch::Cookies
34
+ if defined? SignedCookieJar
35
+ SignedCookieJar.send :include, Immunio::CookieHooks
36
+ end
51
37
 
52
- Immunio.agent.register_plugin(
53
- 'ActionDispatch::Cookies::EncryptedCookieJar',
54
- ActionPack::VERSION::STRING)
55
- end
38
+ if defined? UpgradeLegacySignedCookieJar
39
+ UpgradeLegacySignedCookieJar.send :include, Immunio::CookieHooks
40
+ end
56
41
 
57
- if defined? UpgradeLegacyEncryptedCookieJar
58
- UpgradeLegacyEncryptedCookieJar.send :include, Immunio::CookieHooks
42
+ if defined? EncryptedCookieJar
43
+ EncryptedCookieJar.send :include, Immunio::CookieHooks
44
+ end
59
45
 
60
- Immunio.agent.register_plugin(
61
- 'ActionDispatch::Cookies::UpgradeLegacyEncryptedCookieJar',
62
- ActionPack::VERSION::STRING)
46
+ if defined? UpgradeLegacyEncryptedCookieJar
47
+ UpgradeLegacyEncryptedCookieJar.send :include, Immunio::CookieHooks
48
+ end
63
49
  end
50
+ plugin.loaded! ActionPack::VERSION::STRING
64
51
  end
@@ -531,51 +531,33 @@ module Immunio
531
531
  end
532
532
  end
533
533
 
534
- # Add XSS hooks if enabled
535
- if Immunio::agent.plugin_enabled?("xss") then
536
- action_view_version =
537
- if ActionView.respond_to?(:version)
538
- ActionView.version.to_s
539
- else
540
- Rails.version
541
- end
534
+ # Load the plugins
542
535
 
543
- # Hook into template engines.
536
+ Immunio::Plugin.load 'Erubis', feature: 'xss' do |plugin|
544
537
  ActionView::Template::Handlers::Erubis.send :include, Immunio::ErubisHooks
538
+ plugin.loaded! Rails.version
539
+ end
545
540
 
546
- Immunio.agent.register_plugin(
547
- 'ActionView::Template::Handlers::Erubis',
548
- action_view_version)
549
-
550
- ActiveSupport.on_load(:after_initialize) do
551
- # Wait after Rails initialization to patch custom template engines.
541
+ ActiveSupport.on_load(:after_initialize) do
542
+ # Wait after Rails initialization to patch custom template engines.
543
+ Immunio::Plugin.load 'Haml', feature: 'xss' do |plugin|
552
544
  if defined? Haml::Compiler
553
545
  Haml::Compiler.send :include, Immunio::HamlHooks
554
- Immunio.agent.register_plugin('Haml::Compiler', Haml::VERSION)
546
+ plugin.loaded! Haml::VERSION
555
547
  end
556
-
557
- Hash.send :include, Immunio::ActiveSupportHooks
558
- Immunio.agent.register_plugin('Hash', RUBY_VERSION)
559
548
  end
560
549
 
561
- # Hook into rendering process of Rails.
562
- ActionView::TemplateRenderer.send :include, Immunio::TemplateRendererHooks
563
-
564
- Immunio.agent.register_plugin(
565
- 'ActionView::TemplateRenderer',
566
- action_view_version)
550
+ # Wait for ActiveSupport core ext to load
551
+ Hash.send :include, Immunio::ActiveSupportHooks
552
+ end
567
553
 
554
+ # Hook into rendering process of Rails.
555
+ Immunio::Plugin.load 'ActionView', feature: 'xss' do |plugin|
556
+ ActionView::TemplateRenderer.send :include, Immunio::TemplateRendererHooks
568
557
  ActionView::Template.send :include, Immunio::TemplateHooks
569
-
570
- Immunio.agent.register_plugin(
571
- 'ActionView::Template',
572
- action_view_version)
573
-
574
558
  ActionController::Caching::Fragments.send(
575
559
  :include,
576
560
  Immunio::FragmentCachingHooks)
577
561
 
578
- Immunio.agent.register_plugin(
579
- 'ActionController::Caching::Fragments',
580
- action_view_version)
562
+ plugin.loaded! Rails.version
581
563
  end
@@ -681,66 +681,35 @@ module Immunio
681
681
  end
682
682
  end
683
683
 
684
- Immunio.agent.register_plugin('ActiveRecord', ActiveRecord::VERSION::STRING)
685
-
686
684
  # Hook into quoting methods at the highest level possible in the ancestors chain.
687
685
  # In case the quote methods were overridden in a child class.
686
+ #
687
+ # NOTE: ActiveRecord plugin status is set in lib/immunio/rails.rb where this file is required.
688
+ #
688
689
  module ActiveRecord::ConnectionAdapters
689
690
  if defined? Mysql2Adapter
690
691
  Mysql2Adapter.send :include, Immunio::QuotingHooks
691
-
692
- Immunio.agent.register_plugin(
693
- 'ActiveRecord::ConnectionAdapters::Mysql2Adapter',
694
- ActiveRecord::VERSION::STRING)
695
692
  elsif defined? MysqlAdapter
696
693
  MysqlAdapter.send :include, Immunio::QuotingHooks
697
-
698
- Immunio.agent.register_plugin(
699
- 'ActiveRecord::ConnectionAdapters::MysqlAdapter',
700
- ActiveRecord::VERSION::STRING)
701
694
  end
702
695
 
703
696
  if defined? PostgreSQLAdapter
704
697
  PostgreSQLAdapter.send :include, Immunio::QuotingHooks
705
-
706
- Immunio.agent.register_plugin(
707
- 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter',
708
- ActiveRecord::VERSION::STRING)
709
698
  end
710
699
 
711
700
  if defined? SQLite3Adapter
712
701
  SQLite3Adapter.send :include, Immunio::QuotingHooks
713
-
714
- Immunio.agent.register_plugin(
715
- 'ActiveRecord::ConnectionAdapters::SQLite3Adapter',
716
- ActiveRecord::VERSION::STRING)
717
702
  elsif defined? SQLiteAdapter
718
703
  SQLiteAdapter.send :include, Immunio::QuotingHooks
719
-
720
- Immunio.agent.register_plugin(
721
- 'ActiveRecord::ConnectionAdapters::SQLiteAdapter',
722
- ActiveRecord::VERSION::STRING)
723
704
  end
724
705
  end
725
706
 
726
707
  module ActiveRecord::Sanitization
727
708
  ClassMethods.send :include, Immunio::SanitizeHooks
728
-
729
- Immunio.agent.register_plugin(
730
- 'ActiveRecord::Sanitization',
731
- ActiveRecord::VERSION::STRING)
732
709
  end
733
710
 
734
711
  Arel::Visitors::ToSql.send :include, Immunio::ArelToSqlHooks
735
712
 
736
- Immunio.agent.register_plugin(
737
- 'Arel::Visitors::ToSql',
738
- ActiveRecord::VERSION::STRING)
739
-
740
713
  ActiveRecord::ConnectionAdapters::AbstractAdapter.send(
741
714
  :include,
742
715
  Immunio::QueryExecutionHooks)
743
-
744
- Immunio.agent.register_plugin(
745
- 'ActiveRecord::ConnectionAdapters::AbstractAdapter',
746
- ActiveRecord::VERSION::STRING)
@@ -365,34 +365,24 @@ module Immunio
365
365
  end
366
366
  end
367
367
 
368
+ # NOTE: ActiveRecord plugin status is set in lib/immunio/rails.rb
369
+
368
370
  module ActiveRecord
369
371
  if defined? Relation
370
372
  Relation.send(
371
373
  :include,
372
374
  Immunio::RelationHooks)
373
375
 
374
- Immunio.agent.register_plugin(
375
- 'ActiveRecord::Relation',
376
- ActiveRecord::VERSION::STRING)
377
-
378
376
  if defined? SpawnMethods
379
377
  Relation.send(
380
378
  :include,
381
379
  Immunio::SpawnHooks)
382
-
383
- Immunio.agent.register_plugin(
384
- 'ActiveRecord::SpawnMethods',
385
- ActiveRecord::VERSION::STRING)
386
380
  end
387
381
 
388
382
  if defined? Querying
389
383
  Relation.send(
390
384
  :include,
391
385
  Immunio::QueryingHooks)
392
-
393
- Immunio.agent.register_plugin(
394
- 'ActiveRecord::Querying',
395
- ActiveRecord::VERSION::STRING)
396
386
  end
397
387
  end
398
388
 
@@ -400,10 +390,6 @@ module ActiveRecord
400
390
  StatementCache.send(
401
391
  :include,
402
392
  Immunio::StatementCacheHooks)
403
-
404
- Immunio.agent.register_plugin(
405
- 'ActiveRecord::StatementCache',
406
- ActiveRecord::VERSION::STRING)
407
393
  end
408
394
 
409
395
  module Associations
@@ -411,10 +397,6 @@ module ActiveRecord
411
397
  HasManyThroughAssociation.send(
412
398
  :include,
413
399
  Immunio::HasManyThroughAssociationHooks)
414
-
415
- Immunio.agent.register_plugin(
416
- 'ActiveRecord::Associations::HasManyThroughAssociation',
417
- ActiveRecord::VERSION::STRING)
418
400
  end
419
401
  end
420
402
  end
@@ -6,79 +6,79 @@ rescue LoadError # rubocop:disable Lint/HandleExceptions
6
6
  # Ignore
7
7
  end
8
8
 
9
- if defined? Authlogic
10
- module Immunio
11
- module Authlogic
12
- module SessionHooks
13
- def self.included(klass)
14
- klass.class_eval do
15
- include InstanceMethods
16
- after_create :immunio_login
17
- validate :immunio_check_failed_login
18
- before_destroy :immunio_logout
19
- after_persisting :immunio_set_user
9
+ Immunio::Plugin.load 'Authlogic' do |plugin|
10
+ if defined? Authlogic
11
+ module Immunio
12
+ module Authlogic
13
+ module SessionHooks
14
+ def self.included(klass)
15
+ klass.class_eval do
16
+ include InstanceMethods
17
+ after_create :immunio_login
18
+ validate :immunio_check_failed_login
19
+ before_destroy :immunio_logout
20
+ after_persisting :immunio_set_user
21
+ end
20
22
  end
21
- end
22
-
23
- module InstanceMethods
24
- private
25
- def opts
26
- info = {plugin: "authlogic"}
27
23
 
28
- if defined?(:record) && record
29
- # record is set when already logged in, e.g. you are now logging out
30
- info[:user_record] = record
31
- elsif defined?(:attempted_record) && attempted_record
32
- # attempted_record is set when attempting to log in and the user record has been fetched
33
- info[:user_record] = attempted_record
34
- end
24
+ module InstanceMethods
25
+ private
26
+ def opts
27
+ info = {plugin: "authlogic"}
35
28
 
36
- # credentials are set when the user attempts to log in
37
- if defined?(:credentials) && defined?(:login_field)
38
- login = credentials[login_field.to_sym]
39
- info[:username] = login if login
40
- end
29
+ if defined?(:record) && record
30
+ # record is set when already logged in, e.g. you are now logging out
31
+ info[:user_record] = record
32
+ elsif defined?(:attempted_record) && attempted_record
33
+ # attempted_record is set when attempting to log in and the user record has been fetched
34
+ info[:user_record] = attempted_record
35
+ end
41
36
 
42
- info
43
- end
37
+ # credentials are set when the user attempts to log in
38
+ if defined?(:credentials) && defined?(:login_field)
39
+ login = credentials[login_field.to_sym]
40
+ info[:username] = login if login
41
+ end
44
42
 
45
- def immunio_login
46
- Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
47
- Immunio.logger.debug {"Authlogic instrumentation fired for login with opts #{opts}"}
48
- Immunio.login opts
43
+ info
49
44
  end
50
- end
51
45
 
52
- def immunio_check_failed_login
53
- if errors.any?
46
+ def immunio_login
54
47
  Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
55
- Immunio.logger.debug { "Authlogic instrumentation fired for before_failure with opts #{opts}" }
56
- Immunio.failed_login opts
48
+ Immunio.logger.debug {"Authlogic instrumentation fired for login with opts #{opts}"}
49
+ Immunio.login opts
57
50
  end
58
51
  end
59
- end
60
52
 
61
- def immunio_logout
62
- Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
63
- Immunio.logger.debug { "Authlogic instrumentation fired for logout with opts #{opts}" }
64
- Immunio.logout opts
53
+ def immunio_check_failed_login
54
+ if errors.any?
55
+ Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
56
+ Immunio.logger.debug { "Authlogic instrumentation fired for before_failure with opts #{opts}" }
57
+ Immunio.failed_login opts
58
+ end
59
+ end
65
60
  end
66
- end
67
61
 
68
- def immunio_set_user
69
- Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
70
- Immunio.logger.debug { "Authlogic instrumentation fired for after_set_user with opts #{opts}" }
71
- Immunio.set_user opts
62
+ def immunio_logout
63
+ Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
64
+ Immunio.logger.debug { "Authlogic instrumentation fired for logout with opts #{opts}" }
65
+ Immunio.logout opts
66
+ end
72
67
  end
73
- end
68
+
69
+ def immunio_set_user
70
+ Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
71
+ Immunio.logger.debug { "Authlogic instrumentation fired for after_set_user with opts #{opts}" }
72
+ Immunio.set_user opts
73
+ end
74
+ end
75
+ end
74
76
  end
75
77
  end
76
78
  end
77
- end
78
79
 
79
- Authlogic::Session::Base.send :include, Immunio::Authlogic::SessionHooks
80
+ Authlogic::Session::Base.send :include, Immunio::Authlogic::SessionHooks
80
81
 
81
- Immunio.agent.register_plugin(
82
- 'Authlogic',
83
- Gem.loaded_specs['authlogic'].version.to_s)
84
- end
82
+ plugin.loaded! Gem.loaded_specs['authlogic'].version.to_s
83
+ end
84
+ end
@@ -23,8 +23,7 @@ module Immunio
23
23
  end
24
24
  end
25
25
 
26
- ActionController::Base.send :include, Immunio::CsrfHook
27
-
28
- Immunio.agent.register_plugin(
29
- 'ActionController (CSRF)',
30
- ActionPack::VERSION::STRING)
26
+ Immunio::Plugin.load 'ActionController (CSRF)' do |plugin|
27
+ ActionController::Base.send :include, Immunio::CsrfHook
28
+ plugin.loaded! ActionPack::VERSION::STRING
29
+ end
@@ -6,38 +6,40 @@ rescue LoadError # rubocop:disable Lint/HandleExceptions
6
6
  # Ignore
7
7
  end
8
8
 
9
- if defined? Devise
10
- module Immunio
11
- # Hook into password recovery feature to trigger the `framework_password_reset` hook.
12
- module DeviseRecoverableHooks
13
- extend ActiveSupport::Concern
14
-
15
- included do
16
- Immunio::Utils.alias_method_chain self, :send_reset_password_instructions, :immunio
17
- end
9
+ Immunio::Plugin.load 'Devise' do |plugin|
10
+ if defined? Devise
11
+ module Immunio
12
+ # Hook into password recovery feature to trigger the `framework_password_reset` hook.
13
+ module DeviseRecoverableHooks
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ Immunio::Utils.alias_method_chain self, :send_reset_password_instructions, :immunio
18
+ end
18
19
 
19
- def send_reset_password_instructions_with_immunio(attributes={})
20
- Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
21
- Immunio.logger.debug { "Devise instrumentation fired for send_reset_password_instructions" }
20
+ def send_reset_password_instructions_with_immunio(attributes={})
21
+ Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
22
+ Immunio.logger.debug { "Devise instrumentation fired for send_reset_password_instructions" }
22
23
 
23
- recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
24
+ recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
24
25
 
25
- if recoverable.persisted? # Found
26
- Immunio.password_reset user_record: recoverable, plugin: 'devise'
27
- else
28
- Immunio.failed_password_reset email: recoverable.email, plugin: 'devise'
29
- end
26
+ if recoverable.persisted? # Found
27
+ Immunio.password_reset user_record: recoverable, plugin: 'devise'
28
+ else
29
+ Immunio.failed_password_reset email: recoverable.email, plugin: 'devise'
30
+ end
30
31
 
31
- Request.pause "plugin", "#{Module.nesting[0]}::#{__method__}" do
32
- send_reset_password_instructions_without_immunio(attributes)
32
+ Request.pause "plugin", "#{Module.nesting[0]}::#{__method__}" do
33
+ send_reset_password_instructions_without_immunio(attributes)
34
+ end
33
35
  end
34
36
  end
35
37
  end
36
38
  end
37
- end
38
39
 
39
- Devise::Models::Recoverable::ClassMethods.send :include, Immunio::DeviseRecoverableHooks
40
+ Devise::Models::Recoverable::ClassMethods.send :include, Immunio::DeviseRecoverableHooks
40
41
 
41
- require 'devise/version'
42
- Immunio.agent.register_plugin('Devise', Devise::VERSION)
43
- end
42
+ require 'devise/version'
43
+ plugin.loaded! Devise::VERSION
44
+ end
45
+ end
@@ -56,6 +56,10 @@ module Immunio
56
56
  Addrinfo.getaddrinfo(hostname, nil).first.ip_address rescue SocketError
57
57
  end
58
58
 
59
+ def plugins
60
+ Immunio::Plugin.registered
61
+ end
62
+
59
63
  def report
60
64
  @reported = true
61
65
 
@@ -76,7 +80,7 @@ module Immunio
76
80
  hostname_ip: hostname_ip,
77
81
  ips: ips
78
82
  },
79
- plugins: Immunio.agent.plugins
83
+ plugins: plugins
80
84
  }
81
85
 
82
86
  Immunio.agent.environment = info
@@ -37,9 +37,8 @@ module Immunio
37
37
  end
38
38
  end
39
39
 
40
- if Immunio::agent.plugin_enabled?("eval") then
40
+ Immunio::Plugin.load 'Kernel (Eval)', feature: 'eval' do |plugin|
41
41
  Kernel.send :include, Immunio::KernelEvalHook
42
42
  Kernel.extend Immunio::KernelEvalHook
43
- Immunio.logger.debug { "Eval: All hooks installed." }
44
- Immunio.agent.register_plugin('Kernel (Eval)', RUBY_VERSION)
43
+ plugin.loaded! RUBY_VERSION
45
44
  end
@@ -4,7 +4,6 @@ module Immunio
4
4
  # Rack middleware running at the very end of the stack to finish HTTP requests.
5
5
  class HTTPFinisher
6
6
  def initialize(app)
7
- Immunio.agent.register_plugin(self.class.name)
8
7
  @app = app
9
8
  end
10
9
 
@@ -5,7 +5,6 @@ module Immunio
5
5
  # Rack middleware tracking HTTP requests and responses and triggers the proper hooks.
6
6
  class HTTPTracker
7
7
  def initialize(app)
8
- Immunio.agent.register_plugin(self.class.name)
9
8
  @app = app
10
9
  end
11
10
 
@@ -100,19 +100,16 @@ module Immunio
100
100
  end
101
101
 
102
102
  # Add FileIO hooks if enabled
103
- if Immunio.agent.plugin_enabled?("file_io")
103
+ Immunio::Plugin.load 'IO', feature: 'file_io' do |plugin|
104
104
  IO.extend Immunio::IOClassHooks
105
105
  File.extend Immunio::FileClassHooks
106
- Immunio.logger.debug { "IO: All hooks installed." }
107
- Immunio.agent.register_plugin('IO', RUBY_VERSION)
108
- Immunio.agent.register_plugin('File', RUBY_VERSION)
106
+ plugin.loaded! RUBY_VERSION
109
107
  end
110
108
 
111
109
  # Add Kernel hooks if enabled
112
- if Immunio.agent.plugin_enabled?("shell_command")
110
+ Immunio::Plugin.load 'Kernel (shell_command)', feature: 'shell_command' do |plugin|
113
111
  # Both are necessary to hook calling both Kernel.open() and open() etc.
114
112
  Kernel.send :include, Immunio::KernelModuleHooks
115
113
  Kernel.extend Immunio::KernelModuleHooks
116
- Immunio.logger.debug { "Shell: All hooks installed." }
117
- Immunio.agent.register_plugin('Kernel (Module)', RUBY_VERSION)
114
+ plugin.loaded! RUBY_VERSION
118
115
  end
@@ -36,11 +36,8 @@ module Immunio
36
36
  end
37
37
  end
38
38
 
39
- if Immunio::agent.plugin_enabled?("redirect") then
39
+ Immunio::Plugin.load 'ActionController (Redirect)', feature: 'redirect' do |plugin|
40
40
  ActionController::Base.send :include, Immunio::RedirectHook
41
- Immunio.logger.debug { "Redirect: All hooks installed." }
42
41
 
43
- Immunio.agent.register_plugin(
44
- 'ActionController (Redirect)',
45
- ActionPack::VERSION::STRING)
42
+ plugin.loaded! ActionPack::VERSION::STRING
46
43
  end
@@ -6,67 +6,69 @@ rescue LoadError # rubocop:disable Lint/HandleExceptions
6
6
  # Ignore
7
7
  end
8
8
 
9
- if defined?(Warden::Manager)
10
- class Warden::Manager
11
- after_authentication do |user|
12
- Immunio::Request.time "plugin", "Warden::Manager.after_authentication" do
13
- Immunio.logger.debug { "Warden instrumentation fired for after_authentication" }
14
- Immunio.login user_record: user, plugin: "warden"
9
+ Immunio::Plugin.load 'Warden' do |plugin|
10
+ if defined?(Warden::Manager)
11
+ class Warden::Manager
12
+ after_authentication do |user|
13
+ Immunio::Request.time "plugin", "Warden::Manager.after_authentication" do
14
+ Immunio.logger.debug { "Warden instrumentation fired for after_authentication" }
15
+ Immunio.login user_record: user, plugin: "warden"
16
+ end
15
17
  end
16
- end
17
18
 
18
- before_failure do |env|
19
- Immunio::Request.time "plugin", "Warden::Manager.before_failure" do
20
- info = {plugin: "warden"}
19
+ before_failure do |env|
20
+ Immunio::Request.time "plugin", "Warden::Manager.before_failure" do
21
+ info = {plugin: "warden"}
21
22
 
22
- # Devise uses these specific form fields for authentication by default
23
- user_found = false
24
- [:username, :email].each do |attr|
25
- value = env.fetch("rack.request.form_hash", {}).fetch("user", {})[attr.to_s]
26
- if value
27
- info[attr] = value
28
- user_found = true
23
+ # Devise uses these specific form fields for authentication by default
24
+ user_found = false
25
+ [:username, :email].each do |attr|
26
+ value = env.fetch("rack.request.form_hash", {}).fetch("user", {})[attr.to_s]
27
+ if value
28
+ info[attr] = value
29
+ user_found = true
30
+ end
29
31
  end
30
- end
31
32
 
32
- # before_failure is called under many circumstances, but unfortunately
33
- # there's no easy way to tell why. If we can't figure out who the
34
- # attempted user was, don't report it as a failed login.
35
- if user_found
36
- Immunio.logger.debug { "Warden instrumentation fired for before_failure" }
37
- Immunio.failed_login info
38
- else
39
- Immunio.logger.debug { "Failed to find user info for Warden failure, ignoring instead of reporting as failed login" }
33
+ # before_failure is called under many circumstances, but unfortunately
34
+ # there's no easy way to tell why. If we can't figure out who the
35
+ # attempted user was, don't report it as a failed login.
36
+ if user_found
37
+ Immunio.logger.debug { "Warden instrumentation fired for before_failure" }
38
+ Immunio.failed_login info
39
+ else
40
+ Immunio.logger.debug { "Failed to find user info for Warden failure, ignoring instead of reporting as failed login" }
41
+ end
40
42
  end
41
43
  end
42
- end
43
44
 
44
- after_set_user do |user|
45
- Immunio::Request.time "plugin", "Warden::Manager.after_set_user" do
46
- Immunio.logger.debug { "Warden instrumentation fired for after_set_user" }
47
- Immunio.set_user user_record: user, plugin: "warden"
45
+ after_set_user do |user|
46
+ Immunio::Request.time "plugin", "Warden::Manager.after_set_user" do
47
+ Immunio.logger.debug { "Warden instrumentation fired for after_set_user" }
48
+ Immunio.set_user user_record: user, plugin: "warden"
49
+ end
48
50
  end
49
- end
50
51
 
51
- before_logout do |user|
52
- Immunio::Request.time "plugin", "Warden::Manager.before_logout" do
53
- Immunio.logger.debug { "Warden instrumentation fired for before_logout" }
54
- Immunio.logout user_record: user, plugin: "warden"
52
+ before_logout do |user|
53
+ Immunio::Request.time "plugin", "Warden::Manager.before_logout" do
54
+ Immunio.logger.debug { "Warden instrumentation fired for before_logout" }
55
+ Immunio.logout user_record: user, plugin: "warden"
56
+ end
55
57
  end
56
- end
57
58
 
58
- # Force lookup of user info for all requests.
59
- def call_with_immunio(env)
60
- call_without_immunio(env)
61
- ensure
62
- Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
63
- env['warden'].user if env['warden']
59
+ # Force lookup of user info for all requests.
60
+ def call_with_immunio(env)
61
+ call_without_immunio(env)
62
+ ensure
63
+ Immunio::Request.time "plugin", "#{Module.nesting[0]}::#{__method__}" do
64
+ env['warden'].user if env['warden']
65
+ end
64
66
  end
67
+ alias :call_without_immunio :call
68
+ alias :call :call_with_immunio
65
69
  end
66
- alias :call_without_immunio :call
67
- alias :call :call_with_immunio
68
- end
69
70
 
70
- require 'warden/version'
71
- Immunio.agent.register_plugin('Warden', Warden::VERSION)
72
- end
71
+ require 'warden/version'
72
+ plugin.loaded! Warden::VERSION
73
+ end
74
+ end
data/lib/immunio/rails.rb CHANGED
@@ -7,17 +7,21 @@ require_relative "plugins/warden"
7
7
 
8
8
  module Immunio
9
9
  class Engine < ::Rails::Engine
10
- config.app_middleware.insert 0, HTTPFinisher
11
- config.app_middleware.insert_before ActionDispatch::ShowExceptions, HTTPTracker
12
- config.app_middleware.insert_after ActionDispatch::DebugExceptions, ExceptionHandler
13
- config.app_middleware.use EnvironmentReporter
10
+ Immunio::Plugin.load 'Middlewares' do |plugin|
11
+ config.app_middleware.insert 0, HTTPFinisher
12
+ config.app_middleware.insert_before ActionDispatch::ShowExceptions, HTTPTracker
13
+ config.app_middleware.insert_after ActionDispatch::DebugExceptions, ExceptionHandler
14
+ config.app_middleware.use EnvironmentReporter
15
+ plugin.loaded! Rails.version
16
+ end
14
17
 
15
18
  config.action_dispatch.rescue_responses.merge!('Immunio::RequestBlocked' => :forbidden)
16
19
 
17
- if Immunio::agent.plugin_enabled?("sqli") then
20
+ Immunio::Plugin.load 'ActionRecord', feature: 'sqli' do |plugin|
18
21
  initializer "immunio.active_record", after: "active_record.initialize_database" do
19
22
  ActiveSupport.on_load(:active_record) do
20
23
  require_relative "plugins/active_record"
24
+ plugin.loaded! ActiveRecord::VERSION::STRING
21
25
  end
22
26
  end
23
27
  end
@@ -1,5 +1,5 @@
1
1
  module Immunio
2
2
  AGENT_TYPE = "agent-ruby"
3
- VERSION = "1.1.1"
3
+ VERSION = "1.1.2"
4
4
  VM_VERSION = "2.2.0"
5
5
  end
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.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Immunio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-07 00:00:00.000000000 Z
11
+ date: 2016-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -138,6 +138,7 @@ files:
138
138
  - lib/immunio/errors.rb
139
139
  - lib/immunio/immunio_ca.crt
140
140
  - lib/immunio/logger.rb
141
+ - lib/immunio/plugin.rb
141
142
  - lib/immunio/plugins/action_dispatch.rb
142
143
  - lib/immunio/plugins/action_view.rb
143
144
  - lib/immunio/plugins/active_record.rb