gems-status 0.8.0 → 0.9.0
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.
- data/lib/gems-status/gems_composite_command.rb +1 -2
- data/lib/gems-status/gems_status_metadata.rb +1 -1
- data/lib/gems-status/not_a_security_alert_checker.rb +76 -5
- data/lib/gems-status/scm_check_messages.rb +1 -5
- data/lib/gems-status/utils.rb +9 -1
- data/lib/gems-status/view_results.rb +48 -21
- metadata +4 -4
@@ -39,9 +39,9 @@ class GemsCompositeCommand < GemsCommand
|
|
39
39
|
@checkers.each do |check_object|
|
40
40
|
Utils::log_debug "checking #{check_object.class.name}"
|
41
41
|
@results[@target].sort.each do |k, gems|
|
42
|
-
@checker_results[k] = "" unless @checker_results[k]
|
43
42
|
gems.each do |gem|
|
44
43
|
if !check_object.check?(gem)
|
44
|
+
@checker_results[k] = "" unless @checker_results[k]
|
45
45
|
@checker_results[gem.name] << "
|
46
46
|
<br/>#{gem.name} #{gem.version} #{gem.origin}: <br/>
|
47
47
|
#{check_object.description} "
|
@@ -103,7 +103,6 @@ class GemsCompositeCommand < GemsCommand
|
|
103
103
|
comments = nil
|
104
104
|
end
|
105
105
|
ViewResults::print_results(k, @results, @target, checker_results, comments)
|
106
|
-
@checker_results.delete(k)
|
107
106
|
@comments.delete(k)
|
108
107
|
end
|
109
108
|
ViewResults::print_tail(@checker_results, @comments)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "gmail"
|
1
2
|
require "json"
|
2
3
|
require "open-uri"
|
3
4
|
|
@@ -9,24 +10,93 @@ require "gems-status/scm_security_messages"
|
|
9
10
|
|
10
11
|
class NotASecurityAlertChecker < GemChecker
|
11
12
|
def initialize(conf)
|
12
|
-
Utils::check_parameters('NotASecurityAlertChecker', conf, ["fixed", "source_repos"])
|
13
|
+
Utils::check_parameters('NotASecurityAlertChecker', conf, ["fixed", "source_repos", "email_username", "email_password", "mailing_lists", "email_to"])
|
13
14
|
@fixed = conf["fixed"]
|
14
15
|
@source_repos = conf["source_repos"]
|
15
16
|
@security_messages = {}
|
17
|
+
@email_username = conf["email_username"]
|
18
|
+
@email_password = conf["email_password"]
|
19
|
+
@mailing_lists = conf["mailing_lists"]
|
20
|
+
@email_to = conf["email_to"]
|
21
|
+
@emails = {}
|
22
|
+
download_emails
|
16
23
|
end
|
17
24
|
|
18
|
-
def
|
19
|
-
|
25
|
+
def download_emails
|
26
|
+
#TODO: only download new emails and keep the old ones in a database
|
27
|
+
#puts "Security email alerts from #{mailing_list} #{gmail.inbox.count(:unread, :to => mailing_list}"
|
28
|
+
Gmail.new(@email_username, @email_password) do |gmail|
|
29
|
+
@mailing_lists.each do |mailing_list|
|
30
|
+
@emails[mailing_list] = []
|
31
|
+
Utils::log_debug "Security email alerts from #{mailing_list} #{gmail.inbox.count( :to => mailing_list)}"
|
32
|
+
#TODO: only read new emails
|
33
|
+
#gmail.inbox.emails(:unread, :to => "rubyonrails-security@googlegroups.com").each do |email|
|
34
|
+
gmail.inbox.emails(:to => mailing_list).each do |email|
|
35
|
+
Utils::log_debug "Read #{email.subject}"
|
36
|
+
@emails[mailing_list] << email
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def send_emails(gem)
|
43
|
+
return if @security_messages.length == 0
|
44
|
+
#gems.origin == gems.gems_url if we are looking to an upstream gem,
|
45
|
+
#for example in rubygems.org. We only care about our application gems.
|
46
|
+
return if gem.origin == gem.gems_url
|
47
|
+
mssg = ""
|
48
|
+
mssg = "#{gem.name} #{gem.version} : #{gem.origin} \n"
|
49
|
+
@security_messages.each do |k,v|
|
50
|
+
mssg = mssg + "\n #{v}"
|
51
|
+
end
|
52
|
+
email_receiver = @email_to
|
53
|
+
Gmail.new(@email_username, @email_password) do |gmail|
|
54
|
+
gmail.deliver do
|
55
|
+
to email_receiver
|
56
|
+
subject "[gems-status] security alerts for #{gem.name}"
|
57
|
+
text_part do
|
58
|
+
body mssg
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
Utils::log_debug "Email sent to #{@email_to} "
|
63
|
+
Utils::log_debug "with body #{mssg} "
|
64
|
+
end
|
65
|
+
|
66
|
+
def look_in_scm(gem)
|
20
67
|
version = gem.version
|
21
68
|
source_repo = source_repo(gem)
|
22
69
|
if ! source_repo
|
23
70
|
Utils::log_error gem.name, "Not source URL for #{gem.name}"
|
24
|
-
|
25
|
-
return false
|
71
|
+
return
|
26
72
|
end
|
27
73
|
Utils::log_debug "Source URL for #{gem.name} #{source_repo}"
|
28
74
|
look_for_security_messages(gem.name, source_repo)
|
29
75
|
filter_security_messages_already_fixed(gem.version)
|
76
|
+
end
|
77
|
+
|
78
|
+
def look_in_emails(gem)
|
79
|
+
@emails.each do |listname, emails|
|
80
|
+
emails.each do |email|
|
81
|
+
if listname.include?(gem.name)
|
82
|
+
@security_messages[Utils::next_key(gem.name)] = email.subject
|
83
|
+
Utils::log_debug "looking for security emails: listname matches gem #{gem.name}: #{listname}"
|
84
|
+
next
|
85
|
+
end
|
86
|
+
if email.subject.include?(gem.name)
|
87
|
+
@security_messages[Utils::next_key(gem.name)] = email.subject
|
88
|
+
Utils::log_debug "looking for security emails: subject matches gem #{gem.name}: #{email.subject}"
|
89
|
+
next
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def check?(gem)
|
96
|
+
@security_messages = {}
|
97
|
+
look_in_scm(gem)
|
98
|
+
look_in_emails(gem)
|
99
|
+
send_emails(gem)
|
30
100
|
return @security_messages.length == 0
|
31
101
|
end
|
32
102
|
|
@@ -42,6 +112,7 @@ class NotASecurityAlertChecker < GemChecker
|
|
42
112
|
private
|
43
113
|
|
44
114
|
def filter_security_messages_already_fixed(version)
|
115
|
+
#TODO: let's use a database instead of having the info in yaml file
|
45
116
|
@security_messages.delete_if do |k,v|
|
46
117
|
@fixed[k] && Gem::Version.new(@fixed[k]) <= version
|
47
118
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
class ScmCheckMessages
|
2
2
|
MAX_RETRIES = 3
|
3
|
-
@@keys = {}
|
4
3
|
|
5
4
|
def check_messages(name, source_repo, message_checker, counter = 0)
|
6
5
|
begin
|
@@ -33,10 +32,7 @@ private
|
|
33
32
|
end
|
34
33
|
|
35
34
|
def next_key(name)
|
36
|
-
|
37
|
-
key = name + @@keys[name].to_s
|
38
|
-
@@keys[name] = @@keys[name] + 1
|
39
|
-
return key
|
35
|
+
return Utils::next_key(name)
|
40
36
|
end
|
41
37
|
|
42
38
|
def message(commit)
|
data/lib/gems-status/utils.rb
CHANGED
@@ -5,11 +5,19 @@ class Utils
|
|
5
5
|
attr_accessor :errors
|
6
6
|
@@errors = {}
|
7
7
|
@@md5_sums = {}
|
8
|
+
@@keys = {}
|
8
9
|
|
9
10
|
def Utils.errors
|
10
11
|
return @@errors
|
11
12
|
end
|
12
|
-
|
13
|
+
|
14
|
+
def Utils.next_key(name)
|
15
|
+
@@keys[name] = 0 unless @@keys[name]
|
16
|
+
key = name + @@keys[name].to_s
|
17
|
+
@@keys[name] = @@keys[name] + 1
|
18
|
+
return key
|
19
|
+
end
|
20
|
+
|
13
21
|
def Utils.check_parameters(classname, conf, parameters)
|
14
22
|
if !conf['classname'] then
|
15
23
|
raise "trying to initialize #{classname} when parameter classname does not exists"
|
@@ -3,9 +3,9 @@ require 'gems-status/gems_status_metadata'
|
|
3
3
|
require 'gems-status/utils'
|
4
4
|
|
5
5
|
class ViewResults
|
6
|
-
@@patched =
|
7
|
-
@@outdated =
|
8
|
-
@@up_to_date =
|
6
|
+
@@patched = []
|
7
|
+
@@outdated = []
|
8
|
+
@@up_to_date = []
|
9
9
|
|
10
10
|
def ViewResults.print_description(ids)
|
11
11
|
puts "
|
@@ -47,18 +47,20 @@ class ViewResults
|
|
47
47
|
<p> At the end there are the errors, checks and comments that do not apply to any of the gems. Look them carefully.
|
48
48
|
</p>
|
49
49
|
<p>
|
50
|
+
There is a summary at the end.
|
51
|
+
</p>
|
50
52
|
You should run gems-status periodically until the lists of errors, patched, outdated and checks are gone.
|
51
53
|
</p>
|
52
54
|
"
|
53
55
|
end
|
54
56
|
|
55
|
-
def ViewResults.update_summary(
|
56
|
-
if
|
57
|
-
@@patched
|
58
|
-
elsif
|
59
|
-
@@outdated
|
57
|
+
def ViewResults.update_summary(gem_name, status)
|
58
|
+
if status == "alert"
|
59
|
+
@@patched << gem_name
|
60
|
+
elsif status == "warning"
|
61
|
+
@@outdated << gem_name
|
60
62
|
else
|
61
|
-
@@up_to_date
|
63
|
+
@@up_to_date << gem_name
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
@@ -116,9 +118,9 @@ class ViewResults
|
|
116
118
|
md5 = gem.md5
|
117
119
|
end
|
118
120
|
end
|
119
|
-
puts "<tr><td width='50%'><span class='#{name_color}'
|
121
|
+
puts "<tr><td width='50%'><span class='#{name_color}'><a name=\"#{k}\" />#{k}</span></td><td width='10%'>version</td><td width='40%'>md5</td></tr>"
|
120
122
|
puts html_string
|
121
|
-
update_summary(name_color)
|
123
|
+
update_summary(k, name_color)
|
122
124
|
puts "</table>"
|
123
125
|
puts "</p>"
|
124
126
|
if checker_results
|
@@ -145,7 +147,7 @@ class ViewResults
|
|
145
147
|
<style>
|
146
148
|
body
|
147
149
|
{
|
148
|
-
font-size:
|
150
|
+
font-size: 90%;
|
149
151
|
}
|
150
152
|
h1
|
151
153
|
{
|
@@ -155,7 +157,8 @@ class ViewResults
|
|
155
157
|
h2
|
156
158
|
{
|
157
159
|
font-size: 100%;
|
158
|
-
font-
|
160
|
+
font-style: italic;
|
161
|
+
font-weight: normal;
|
159
162
|
}
|
160
163
|
.gem_name
|
161
164
|
{
|
@@ -186,19 +189,19 @@ class ViewResults
|
|
186
189
|
.errors
|
187
190
|
{
|
188
191
|
color: #ff0000;
|
189
|
-
font-size:
|
192
|
+
font-size: 100%;
|
190
193
|
font-style: italic;
|
191
194
|
}
|
192
195
|
.check
|
193
196
|
{
|
194
197
|
color: #a0a0a0;
|
195
|
-
font-size:
|
198
|
+
font-size: 100%;
|
196
199
|
font-style: italic;
|
197
200
|
}
|
198
201
|
.comment
|
199
202
|
{
|
200
203
|
color: #a0a0a0;
|
201
|
-
font-size:
|
204
|
+
font-size: 100%;
|
202
205
|
font-style: italic;
|
203
206
|
}
|
204
207
|
.table_results
|
@@ -210,24 +213,48 @@ class ViewResults
|
|
210
213
|
<body>"
|
211
214
|
end
|
212
215
|
|
213
|
-
def ViewResults.print_hash(desc, data, style)
|
216
|
+
def ViewResults.print_hash(desc, data, style, anchor = false)
|
214
217
|
return if !data or data.length == 0
|
215
218
|
puts "<p>"
|
216
219
|
puts "<h2>#{desc}: #{data.length}</h2>"
|
217
|
-
data.each
|
220
|
+
data.each do |k,v|
|
221
|
+
if anchor
|
222
|
+
puts "<a href=\"\##{k}\"><span class='#{style}'>#{k}</span></a>"
|
223
|
+
else
|
224
|
+
puts "<span class='#{style}'>#{k}</span>"
|
225
|
+
end
|
226
|
+
puts "<span class='#{style}'> #{v}</span><br/>"
|
227
|
+
|
228
|
+
end
|
218
229
|
puts "</p>"
|
219
230
|
end
|
220
231
|
|
221
232
|
def ViewResults.print_summary
|
222
|
-
puts "<
|
223
|
-
puts "patched/errored
|
233
|
+
puts "<a name='summary'/><h1>Summary</h1>"
|
234
|
+
puts "<p><h2>patched/errored</h2>"
|
235
|
+
puts "<ul>"
|
236
|
+
@@patched.each do |p|
|
237
|
+
puts "<li><a href=\"\##{p}\">#{p}</a>"
|
238
|
+
end
|
239
|
+
puts "</ul></p>"
|
240
|
+
puts "<p><h2>outdated #{@@outdated.length}</h2>"
|
241
|
+
@@outdated.each do |p|
|
242
|
+
puts "<li><a href=\"\##{p}\">#{p}</a>"
|
243
|
+
end
|
244
|
+
puts "</ul></p>"
|
245
|
+
puts "<p> <h2>up-to-date #{@@up_to_date.length}</h2>"
|
246
|
+
@@up_to_date.each do |p|
|
247
|
+
puts "<li><a href=\"\##{p}\">#{p}</a>"
|
248
|
+
end
|
249
|
+
puts "</ul></p>"
|
224
250
|
end
|
225
251
|
|
226
252
|
def ViewResults.print_tail(checker_results, comments)
|
227
|
-
|
253
|
+
puts "<h1>Others</h1>"
|
228
254
|
self.print_hash("comments", comments, "comment")
|
229
255
|
self.print_hash("errors", Utils::errors, "errors")
|
230
256
|
self.print_summary
|
257
|
+
self.print_hash("checks", checker_results, "summary", true)
|
231
258
|
date = Time.now.strftime('%a %b %d %H:%M:%S %Z %Y')
|
232
259
|
puts "<p class='footer'>run by <a href=\"https://github.com/jordimassaguerpla/gems-status\">gems-status</a> - #{date} - version: #{GemsStatusMetadata::VERSION}</p>
|
233
260
|
</body>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gems-status
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 9
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jordi Massaguer Pla
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-27 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: xml-simple
|