Class: UnseenConnectionsMonitor

Inherits:
Object
  • Object
show all
Defined in:
lib/unseen_connections_monitor.rb

Defined Under Namespace

Classes: FirewallWarning

Constant Summary collapse

DEFAULTS =
{
  remember_for: 604800,
  save_interval: 3600,
  state_file: "unseen_connections.yml",
  networks: {
    production: /.*/
  }
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:) ⇒ UnseenConnectionsMonitor

Returns a new instance of UnseenConnectionsMonitor.



39
40
41
42
43
44
# File 'lib/unseen_connections_monitor.rb', line 39

def initialize(config:)
  @config = config
  @config.default_proc = proc { |h,k| h[k] = DEFAULTS[k] }
  DEFAULTS.keys.each { |k| @config[k] }
  configure_airbrake
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



37
38
39
# File 'lib/unseen_connections_monitor.rb', line 37

def config
  @config
end

Instance Method Details

#closeObject



46
47
48
49
# File 'lib/unseen_connections_monitor.rb', line 46

def close
  networks.each { |name| Airbrake.close(name) }
  save
end

#feed(datetime:, from_ip:, protocol:, to_ip:, port:) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
# File 'lib/unseen_connections_monitor.rb', line 84

def feed(datetime:,from_ip:,protocol:,to_ip:,port:)
  timestamp = Time.parse(datetime).to_i
  protocol = protocol.downcase
  key = "#{to_ip}:#{protocol}/#{port}"

  warning = notify(from: from_ip, to: to_ip, protocol: protocol, port: port) unless state.has_key?(key)
  state[key] = timestamp
  warning
ensure
  housekeeping
end

#last_saveObject



80
81
82
# File 'lib/unseen_connections_monitor.rb', line 80

def last_save
  @last_save || 0
end

#networksObject



96
97
98
# File 'lib/unseen_connections_monitor.rb', line 96

def networks
  config.fetch(:networks).keys
end

#saveObject

taken from activesupport File::atomic_write



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/unseen_connections_monitor.rb', line 52

def save
  state_file = config.fetch(:state_file)
  tempfile = Tempfile.new(File.basename(state_file), Dir.tmpdir)
  tempfile.write(state.to_yaml)
  tempfile.close
  begin
    # Get original file permissions
    old_stat = File.stat(state_file)
  rescue Errno::ENOENT
    # No old permissions, write a temp file to determine the defaults
    check_name = File.join(File.dirname(state_file), ".permissions_check.#{Thread.current.object_id}.#{Process.pid}.#{rand(1000000)}")
    File.open(check_name, "w") { }
    old_stat = File.stat(check_name)
    File.unlink(check_name)
  end
  FileUtils.mv(tempfile.path, state_file)
  File.chown(old_stat.uid, old_stat.gid, state_file)
  File.chmod(old_stat.mode, state_file)
  @last_save = Time.now.to_i
end

#stateObject



73
74
75
76
77
78
# File 'lib/unseen_connections_monitor.rb', line 73

def state
  @state ||= begin
    @last_save = Time.now.to_i
    YAML.load_file(config.fetch(:state_file)) || {} rescue {}
  end
end