repsheet_visualizer 0.1.0 → 0.1.1

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.
@@ -10,8 +10,11 @@ class RepsheetVisualizer < Sinatra::Base
10
10
  end
11
11
 
12
12
  helpers do
13
- def action(data)
14
- if data[:blacklist].nil? || data[:blacklist] == "false"
13
+ def action(ip, blacklist=nil)
14
+ puts ip.inspect
15
+ puts blacklist.inspect
16
+ blacklist = redis_connection.get("#{ip}:repsheet:blacklist") if blacklist.nil?
17
+ if blacklist.nil? || blacklist == "false"
15
18
  "blacklist"
16
19
  else
17
20
  "allow"
@@ -39,17 +42,31 @@ class RepsheetVisualizer < Sinatra::Base
39
42
 
40
43
  # TODO: These methods should get moved out to another place
41
44
  def summary(connection)
42
- actors = {}
45
+ suspects = {}
46
+ blacklisted = {}
47
+
43
48
  connection.keys("*:requests").map {|d| d.split(":").first}.reject {|ip| ip.empty?}.each do |actor|
44
- actors[actor] = Hash.new 0
45
- actors[actor][:repsheet] = connection.get("#{actor}:repsheet")
46
- actors[actor][:blacklist] = connection.get("#{actor}:repsheet:blacklist")
47
- actors[actor][:detected] = connection.smembers("#{actor}:detected").join(", ")
48
- connection.smembers("#{actor}:detected").each do |rule|
49
- actors[actor][:total] += connection.get("#{actor}:#{rule}:count").to_i
49
+ detected = connection.smembers("#{actor}:detected").join(", ")
50
+ blacklist = connection.get("#{actor}:repsheet:blacklist")
51
+
52
+ if !detected.empty? && blacklist != "true"
53
+ suspects[actor] = Hash.new 0
54
+ suspects[actor][:detected] = detected
55
+ connection.smembers("#{actor}:detected").each do |rule|
56
+ suspects[actor][:total] += connection.get("#{actor}:#{rule}:count").to_i
57
+ end
58
+ end
59
+
60
+ if blacklist == "true"
61
+ blacklisted[actor] = Hash.new 0
62
+ blacklisted[actor][:detected] = detected
63
+ connection.smembers("#{actor}:detected").each do |rule|
64
+ blacklisted[actor][:total] += connection.get("#{actor}:#{rule}:count").to_i
65
+ end
50
66
  end
51
67
  end
52
- actors
68
+
69
+ [suspects.sort_by{|k,v| -v[:total]}.take(10), blacklisted]
53
70
  end
54
71
 
55
72
  def breakdown(connection)
@@ -83,7 +100,7 @@ class RepsheetVisualizer < Sinatra::Base
83
100
 
84
101
  # This is the actual application
85
102
  get '/' do
86
- @data = summary(redis_connection)
103
+ @suspects, @blacklisted = summary(redis_connection)
87
104
  erb :actors
88
105
  end
89
106
 
@@ -1,8 +1,12 @@
1
1
  $(document).ready(function() {
2
- // Bring up tablesorter and sort by people who have committed the
3
- // most number of ModSecurity violations and who are not yet on
4
- // the blacklist
5
- $("#actors").tablesorter({sortList: [[2,0], [4,1]],widgets: ['zebra']});
2
+ $("#suspects").tablesorter({sortList: [[2,1]],widgets: ['zebra']});
3
+ $("#blacklisted").tablesorter({sortList: [[2,1]],widgets: ['zebra']});
4
+
5
+ $("#search-button").click(function() {
6
+ ip = $("#ip").val();
7
+ if (ip === "") return;
8
+ window.location = "activity/" + ip;
9
+ });
6
10
  });
7
11
 
8
12
  function angle(d) {
@@ -10,19 +10,20 @@
10
10
  <link href="<%= @mount %>css/bootstrap.css" rel="stylesheet">
11
11
  <style>
12
12
  body {
13
- padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
13
+ padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
14
14
  }
15
15
  </style>
16
16
  <link href="<%= @mount %>css/bootstrap-responsive.css" rel="stylesheet">
17
-
17
+
18
18
  <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
19
19
  <!--[if lt IE 9]>
20
- <script src="<%= @mount %>javascripts/html5shiv.js"></script>
21
- <![endif]-->
20
+ <script src="<%= @mount %>javascripts/html5shiv.js"></script>
21
+ <![endif]-->
22
22
 
23
23
  <link rel="shortcut icon" href="/<%= @mount %>/images/favicon.ico">
24
24
 
25
- <script src="<%= @mount %>javascripts/d3.v3.min.js" type="text/javascript"></script>
25
+ <script src="<%= @mount %>javascripts/jquery-latest.js" type="text/javascript"></script>
26
+ <script src="<%= @mount %>javascripts/jquery.tablesorter.min.js" type="text/javascript"></script>
26
27
  <script src="<%= @mount %>javascripts/application.js" type="text/javascript"></script>
27
28
  </head>
28
29
 
@@ -31,24 +32,35 @@
31
32
  <div class="navbar-inner">
32
33
  <div class="container">
33
34
  <a class="brand" href="<%= @mount %>">Repsheet</a>
34
- <div class="nav-collapse collapse">
35
- <ul class="nav">
36
- <li><a href="<%= @mount %>">Actors</a></li>
37
- <li><a href="<%= @mount %>breakdown">Breakdown</a></li>
38
- <li><a href="<%= @mount %>worldview">Worldview</a></li>
39
- </ul>
40
- </div>
35
+ <div class="nav-collapse collapse">
36
+ <ul class="nav">
37
+ <li><a href="<%= @mount %>">Actors</a></li>
38
+ <li><a href="<%= @mount %>breakdown">Breakdown</a></li>
39
+ <li><a href="<%= @mount %>worldview">Worldview</a></li>
40
+ </ul>
41
+ </div>
41
42
  </div>
42
43
  </div>
43
44
  </div>
44
45
 
45
46
  <div class="container">
46
47
  <h2>Activity for <%= @ip %></h2>
47
- <div><a href="<%= @mount %>">Back</a></div>
48
+ <form method="post" action="<%= @mount %>action" class="button_to">
49
+ <div>
50
+ <input value="<%= action(@ip) %>" type="submit" />
51
+ <input type="hidden" name="ip" value="<%= @ip %>"/>
52
+ <input type="hidden" name="action" value="<%= action(@ip) %>"/>
53
+ </div>
54
+ </form>
55
+
56
+ <div>
57
+ <a href="<%= @mount %>">Back</a>
58
+ </div>
59
+
48
60
  <ul>
49
- <% @data.each do |action| %>
50
- <li><%= action %></li>
51
- <% end %>
61
+ <% @data.each do |action| %>
62
+ <li><%= action %></li>
63
+ <% end %>
52
64
  </ul>
53
65
  </div>
54
66
  </body>
@@ -15,9 +15,45 @@
15
15
  padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
16
16
  }
17
17
 
18
+ #search {
19
+ padding-bottom: 20px;
20
+ }
21
+
18
22
  .actors {
19
23
  border-color: #FFF;
20
24
  }
25
+
26
+ #suspects-wrapper {
27
+ float: left;
28
+ }
29
+
30
+ #suspects-table-wrapper {
31
+ overflow: auto;
32
+ max-height: 800px;
33
+
34
+ }
35
+
36
+ #suspects {
37
+ width: 550px;
38
+ }
39
+
40
+ #blacklisted-wrapper {
41
+ float: right;
42
+ }
43
+
44
+ #blacklisted-table-wrapper {
45
+ overflow: auto;
46
+ max-height: 570px;
47
+ }
48
+
49
+ #blacklisted {
50
+ width: 550px;
51
+ }
52
+
53
+ .clearfix {
54
+ display: inline-block;
55
+ clear: both;
56
+ }
21
57
  </style>
22
58
 
23
59
  <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
@@ -49,40 +85,85 @@
49
85
  </div>
50
86
 
51
87
  <div class="container">
52
- <table id="actors" class="tablesorter actors">
53
- <thead>
54
- <tr>
55
- <th>IP</th>
56
- <th>Repsheet?</th>
57
- <th>Blacklist?</th>
58
- <th>Triggered Rules</th>
59
- <th>Offenses</th>
60
- <th>Activity</th>
61
- <th>Action</th>
62
- </tr>
63
- </thead>
64
- <tbody>
65
- <% @data.each do |actor,details| %>
66
- <tr>
67
- <td><%= actor %></td>
68
- <td><%= details[:repsheet] %></td>
69
- <td><%= details[:blacklist] %></td>
70
- <td><%= details[:detected] %></td>
71
- <td><%= details[:total] %></td>
72
- <td><a href="<%= @mount %>activity/<%= actor %>">Click to see activity</a>
73
- <td>
74
- <form method="post" action="<%= @mount %>action" class="button_to">
75
- <div>
76
- <input value="<%= action(details) %>" type="submit" />
77
- <input type="hidden" name="ip" value="<%= actor %>"/>
78
- <input type="hidden" name="action" value="<%= action(details) %>"/>
79
- </div>
80
- </form>
81
- </td>
82
- </tr>
83
- <% end %>
84
- </tbody>
85
- </table>
88
+ <div id="search">
89
+ <label-for="ip"><b>Find Activity For an IP</b> </label>
90
+ <input name="ip" id="ip" type="text-field"/>
91
+ <input type="submit" id="search-button" value="Search"/>
92
+ </div>
93
+
94
+ <div id="suspects-wrapper">
95
+ <h2>Top 10 Suspect Actors</h2>
96
+ <div id="suspects-table-wrapper">
97
+ <table id="suspects" class="tablesorter actors">
98
+ <thead>
99
+ <tr>
100
+ <th>IP</th>
101
+ <th>Triggered Rules</th>
102
+ <th>Offenses</th>
103
+ <th>Activity</th>
104
+ <th>Action</th>
105
+ </tr>
106
+ </thead>
107
+ <tbody>
108
+ <% @suspects.each do |actor,details| %>
109
+ <tr>
110
+ <td><%= actor %></td>
111
+ <td><%= details[:detected] %></td>
112
+ <td><%= details[:total] %></td>
113
+ <td width=100><a href="<%= @mount %>activity/<%= actor %>">Click to see activity</a>
114
+ <td width=90>
115
+ <form method="post" action="<%= @mount %>action" class="button_to">
116
+ <div>
117
+ <input value="<%= action(actor) %>" type="submit" />
118
+ <input type="hidden" name="ip" value="<%= actor %>"/>
119
+ <input type="hidden" name="action" value="<%= action(actor) %>"/>
120
+ </div>
121
+ </form>
122
+ </td>
123
+ </tr>
124
+ <% end %>
125
+ </tbody>
126
+ </table>
127
+ </div>
128
+ </div>
129
+
130
+ <div class="clearfix"></div>
131
+
132
+ <div id="blacklisted-wrapper">
133
+ <h2>Blacklisted Actors</h2>
134
+ <div id="blacklisted-table-wrapper">
135
+ <table id="blacklisted" class="tablesorter actors">
136
+ <thead>
137
+ <tr>
138
+ <th>IP</th>
139
+ <th>Triggered Rules</th>
140
+ <th>Offenses</th>
141
+ <th>Activity</th>
142
+ <th>Action</th>
143
+ </tr>
144
+ </thead>
145
+ <tbody>
146
+ <% @blacklisted.each do |actor,details| %>
147
+ <tr>
148
+ <td><%= actor %></td>
149
+ <td><%= details[:detected] %></td>
150
+ <td><%= details[:total] %></td>
151
+ <td width=100><a href="<%= @mount %>activity/<%= actor %>">Click to see activity</a>
152
+ <td width=70>
153
+ <form method="post" action="<%= @mount %>action" class="button_to">
154
+ <div>
155
+ <input value="<%= action(actor, details[:blacklist]) %>" type="submit" />
156
+ <input type="hidden" name="ip" value="<%= actor %>"/>
157
+ <input type="hidden" name="action" value="<%= action(actor, details[:blacklist]) %>"/>
158
+ </div>
159
+ </form>
160
+ </td>
161
+ </tr>
162
+ <% end %>
163
+ </tbody>
164
+ </table>
165
+ </div>
166
+ </div>
86
167
  </div>
87
168
  </body>
88
169
  </html>
@@ -1,3 +1,3 @@
1
1
  module RepsheetVisualizer
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/script/fill ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'redis'
4
+
5
+ r = Redis.new
6
+ r.flushdb
7
+
8
+ 255.times do |i|
9
+ r.set("1.1.1.#{i}:950001:count", rand(1000))
10
+ r.lpush("1.1.1.#{i}:requests", "request")
11
+ r.sadd("1.1.1.#{i}:detected", "950001")
12
+ if i > 220
13
+ r.set("1.1.1.#{i}:repsheet:blacklist", "true")
14
+ end
15
+ end
16
+
17
+ 255.times do |i|
18
+ r.lpush("2.2.2.#{i}:requests", "request")
19
+ end
20
+
21
+
22
+ 20.times do |i|
23
+ r.sadd("1.1.1.1:detected", "9900#{i + 10}")
24
+ r.set("1.1.1.1:9900#{i + 10}:count", 1000)
25
+ end
26
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repsheet_visualizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-11 00:00:00.000000000 Z
12
+ date: 2013-06-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: geoip
@@ -161,6 +161,7 @@ files:
161
161
  - lib/repsheet_visualizer/application/views/worldview.erb
162
162
  - lib/repsheet_visualizer/version.rb
163
163
  - repsheet_visualizer.gemspec
164
+ - script/fill
164
165
  homepage: https://github.com/Repsheet/visualizer
165
166
  licenses:
166
167
  - MIT