repsheet_visualizer 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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