Class: Immunio::Agent

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::Configurable
Defined in:
lib/immunio/agent.rb

Instance Method Summary collapse

Constructor Details

#initializeAgent

Returns a new instance of Agent.



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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/immunio/agent.rb', line 82

def initialize
  Immunio.logger.info { "Initializing agent version #{VERSION} for process #{Process.pid}" }

  config.key = config.secret = "-default-"
  config.hello_url = "https://agent.immun.io/"
  config.log_file = "log/immunio.log"
  config.log_level = "info"
  config.log_timings = false
  config.log_context_data = false
  config.http_timeout = 30 # seconds
  config.max_send_queue_size = 500 # messages
  config.max_report_interval = 10 # seconds
  config.min_report_size = 25 # messages
  config.max_report_size = 50 # messages
  config.max_report_bytes = 1500000 # Just shy of 1.5 megs
  config.initial_delay_ms = 100  # milliseconds
  config.max_delay_ms = 10 * 60 * 1000  # milliseconds
  config.dev_mode = false
  config.debug_mode = false
  config.ready_timeout = 0
  # Default list of active plugins
  config.plugins_active = DEFAULT_PLUGINS.to_set
  # Default to empty lists for enabled and disabled
  config.plugins_enabled = []
  config.plugins_disabled = []
  config.code_protection_plugins_enabled = false
  config.agent_enabled = true
  config.safe_script_tag_contexts = []
  config.vm_data = {}

  # Be sure all config attributes have a type before this call:
  load_config

  Immunio::switch_to_real_logger(config.log_file, config.log_level)

  if !config.agent_enabled then
    Immunio.logger.info { "Agent disabled in config" }
    return
  end

  @vmfactory = VMFactory.new(config[:key], config.secret, config.dev_mode,
                             config.debug_mode)

  @channel = Channel.new(config)
  @channel.on_sending do
    @vmfactory.current_state
  end

  # Link things together. The vmfactory needs to know about updates
  # to the code and data, and the channel needs to know when everything
  # is up to date.
  have_code = config.dev_mode
  have_data = false
  @channel.on_message do |message|
    case message[:type]
      when "engine.vm.code.update"
        # Don't update code in dev_mode
        unless config.dev_mode
          @vmfactory.update_code message[:version], message[:code]
          have_code = true
          if have_data
            @channel.set_ready
          end
        end
      when "engine.vm.data.update"
        @vmfactory.update_data message[:version], message[:data]
        have_data = true
        if have_code
          @channel.set_ready
        end
    end
  end

  @processor = Processor.new(@channel, @vmfactory, config)
  @process_id = Process.pid
end

Instance Method Details

#environment=(environment) ⇒ Object



246
247
248
# File 'lib/immunio/agent.rb', line 246

def environment=(environment)
  @processor.environment = environment
end

#finish_request(*args) ⇒ Object



234
235
236
# File 'lib/immunio/agent.rb', line 234

def finish_request(*args)
  @processor.finish_request(*args)
end

#load_configObject



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/immunio/agent.rb', line 159

def load_config
  Immunio.logger.debug { "Default configuration: #{config}" }

  # Try loading file from some standard locations. First match is used.
  locations = []
  locations << Rails.root.join("config", CONFIG_FILENAME) if defined?(Rails.root) && Rails.root
  locations << File.join("config", CONFIG_FILENAME)

  locations.each do |location|
    begin
      config.update load_config_at_location(location)
      Immunio.logger.debug { "Configuration after loading from file: #{config}" }
      break
    rescue SystemCallError => e
      Immunio.logger.error { "Failed to open config: #{e}" }
    rescue => e
      Immunio.logger.error { "Bad immunio configuration file: #{e.inspect}" }
    end
  end

  # Load private config from env vars.
  # Set the type of the same as set in initialize
  config.keys.each do |key|
    if ENV["IMMUNIO_#{key.upcase}"] then
      new_value = ENV["IMMUNIO_#{key.upcase}"]
      case config[key]
      when String
        config[key] = new_value
      when Fixnum
        config[key] = Integer(new_value)
      when TrueClass, FalseClass
        config[key] = !(new_value =~ (/^(true|t|yes|y|1)$/i)).nil?
      when Array
        config[key] = new_value.split(/[\s,]+/)
      when Set
        config[key] = new_value.split(/[\s,]+/).to_set
      else
        raise ArgumentError, "Unknown ENV conversion for #{config[key].class}"
      end
    end
  end

  Immunio.logger.debug { "Configuration after evaluating env vars: #{config}" }

  # Remove any requested plugins, then add any requested plugins.
  config.plugins_active.subtract(config.plugins_disabled)
  config.plugins_active.merge(config.plugins_enabled)
  Immunio.logger.info { "Active plugins: #{config.plugins_active.to_a}" }
end

#load_config_at_location(location) ⇒ Object

Loads the configuration file. Raises:

- Errno::ENOENT if it doesn't exist;
- NoMethodError if the config is invalid, `YAML.load_file` will return
  a `String`, and `symbolize_keys` will be called on it.


214
215
216
217
218
219
# File 'lib/immunio/agent.rb', line 214

def load_config_at_location(location)
  Immunio.logger.debug { "Trying to find config file at #{location}" }
  realpath = File.realpath(location) # Raises exception if file doesn't exist
  Immunio.logger.debug { "Found config file at #{realpath}" }
  YAML.load_file(realpath).symbolize_keys
end

#new_request(*args) ⇒ Object



230
231
232
# File 'lib/immunio/agent.rb', line 230

def new_request(*args)
  @processor.new_request(*args)
end

#plugin_enabled?(plugin) ⇒ Boolean

Returns:

  • (Boolean)


221
222
223
224
225
226
227
228
# File 'lib/immunio/agent.rb', line 221

def plugin_enabled?(plugin)
  if CODE_PROTECTION_PLUGINS.include?(plugin)
    return false unless config.code_protection_plugins_enabled
  end

  # Check if the specified `plugin` is enabled based on the Agent config.
  config.plugins_active.member?(plugin)
end

#run_hook(*args) ⇒ Object



238
239
240
# File 'lib/immunio/agent.rb', line 238

def run_hook(*args)
  @processor.run_hook(*args) if defined? @processor
end

#run_hook!(*args) ⇒ Object



242
243
244
# File 'lib/immunio/agent.rb', line 242

def run_hook!(*args)
  @processor.run_hook!(*args) if defined? @processor
end