chelsea 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +9 -0
- data/Gemfile.lock +5 -2
- data/README.md +1 -1
- data/bin/chelsea +1 -1
- data/chelsea.gemspec +0 -1
- data/lib/chelsea/gems.rb +118 -14
- data/lib/chelsea/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1633315a7f5da46a2c43414058160959b0be5202a3c7a6aa333e99f91f48a755
|
4
|
+
data.tar.gz: ac7a5f1f3c77061ccf54edf458758b621038f74ca9e272261cb0dc417cb94298
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b7eea08843bed093b27054b29da075edfc63730836421e8151e0dfd661d06f030bf7be242c8a08e11d5c4aae49434d3976f4b8a628962f44fa8e8b787979eea
|
7
|
+
data.tar.gz: c946fd43b812750e8d3ebe7b4c13914ca54e257c6b86a63d3abb1224bec4d94af027a1e4dcc7cd65940af23091b5e82d10d99e5397c1406e6d4199f2fb2f49b8
|
data/.circleci/config.yml
CHANGED
@@ -30,6 +30,15 @@ jobs:
|
|
30
30
|
bundle exec rspec --format progress \
|
31
31
|
--format RspecJunitFormatter \
|
32
32
|
--out test_results/rspec.xml
|
33
|
+
- run:
|
34
|
+
name: Build gem
|
35
|
+
command: gem build chelsea.gemspec
|
36
|
+
- run:
|
37
|
+
name: Install gem
|
38
|
+
command: gem install ./chelsea-*.gem
|
39
|
+
- run:
|
40
|
+
name: Dogfood
|
41
|
+
command: chelsea --file Gemfile.lock
|
33
42
|
- store_test_results:
|
34
43
|
path: test_results
|
35
44
|
release:
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
chelsea (0.0.
|
5
|
-
bundler (
|
4
|
+
chelsea (0.0.2)
|
5
|
+
bundler (>= 1.2.0, < 3)
|
6
6
|
pastel (~> 0.7.2)
|
7
7
|
rest-client (~> 2.0.2)
|
8
8
|
slop (~> 4.8.0)
|
@@ -43,6 +43,8 @@ GEM
|
|
43
43
|
diff-lcs (>= 1.2.0, < 2.0)
|
44
44
|
rspec-support (~> 3.9.0)
|
45
45
|
rspec-support (3.9.2)
|
46
|
+
rspec_junit_formatter (0.4.1)
|
47
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
46
48
|
slop (4.8.0)
|
47
49
|
tty-color (0.5.1)
|
48
50
|
tty-cursor (0.7.1)
|
@@ -60,6 +62,7 @@ DEPENDENCIES
|
|
60
62
|
chelsea!
|
61
63
|
rake (~> 10.0)
|
62
64
|
rspec (~> 3.0)
|
65
|
+
rspec_junit_formatter (~> 0.4.1)
|
63
66
|
|
64
67
|
BUNDLED WITH
|
65
68
|
2.0.2
|
data/README.md
CHANGED
data/bin/chelsea
CHANGED
data/chelsea.gemspec
CHANGED
@@ -35,7 +35,6 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
36
36
|
spec.require_paths = ["lib"]
|
37
37
|
|
38
|
-
|
39
38
|
spec.add_dependency "tty-font", "~> 0.5.0"
|
40
39
|
spec.add_dependency "tty-spinner", "~> 0.9.3"
|
41
40
|
spec.add_dependency "slop", "~> 4.8.0"
|
data/lib/chelsea/gems.rb
CHANGED
@@ -5,6 +5,9 @@ require 'tty-spinner'
|
|
5
5
|
require 'bundler'
|
6
6
|
require 'bundler/lockfile_parser'
|
7
7
|
require_relative 'version'
|
8
|
+
require 'rubygems'
|
9
|
+
require 'rubygems/commands/dependency_command'
|
10
|
+
require 'pstore'
|
8
11
|
|
9
12
|
module Chelsea
|
10
13
|
class Gems
|
@@ -17,6 +20,8 @@ module Chelsea
|
|
17
20
|
@coordinates = Hash.new()
|
18
21
|
@coordinates["coordinates"] = Array.new()
|
19
22
|
@server_response = Array.new()
|
23
|
+
@reverse_deps = Hash.new()
|
24
|
+
@store = PStore.new(get_db_store_location())
|
20
25
|
|
21
26
|
if not gemfile_lock_file_exists()
|
22
27
|
return
|
@@ -28,6 +33,12 @@ module Chelsea
|
|
28
33
|
)
|
29
34
|
end
|
30
35
|
|
36
|
+
def get_db_store_location()
|
37
|
+
initial_path = File.join("#{Dir.home}", ".ossindex")
|
38
|
+
Dir.mkdir(initial_path) unless File.exists? initial_path
|
39
|
+
path = File.join(initial_path, "chelsea.pstore")
|
40
|
+
end
|
41
|
+
|
31
42
|
def execute(input: $stdin, output: $stdout)
|
32
43
|
n = get_dependencies()
|
33
44
|
if n == 0
|
@@ -58,6 +69,10 @@ module Chelsea
|
|
58
69
|
spinner = TTY::Spinner.new(format, success_mark: @pastel.green('+'), hide_cursor: true)
|
59
70
|
spinner.auto_spin()
|
60
71
|
|
72
|
+
reverse = Gem::Commands::DependencyCommand.new
|
73
|
+
reverse.options[:reverse_dependencies] = true
|
74
|
+
@reverse_deps = reverse.reverse_dependencies(@lockfile.specs)
|
75
|
+
|
61
76
|
@lockfile.specs.each do |gem|
|
62
77
|
@dependencies[gem.name] = [gem.name, gem.version]
|
63
78
|
rescue StandardError => e
|
@@ -95,28 +110,36 @@ module Chelsea
|
|
95
110
|
end
|
96
111
|
end
|
97
112
|
|
98
|
-
def get_user_agent()
|
99
|
-
user_agent = "chelsea/#{Chelsea::VERSION}"
|
100
|
-
|
101
|
-
user_agent
|
102
|
-
end
|
103
|
-
|
104
113
|
def get_vulns()
|
105
114
|
require 'json'
|
106
115
|
require 'rest-client'
|
107
116
|
format = "[#{@pastel.green(':spinner')}] " + @pastel.white("Making request to OSS Index server")
|
108
117
|
spinner = TTY::Spinner.new(format, success_mark: @pastel.green('+'), hide_cursor: true)
|
109
118
|
spinner.auto_spin()
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
119
|
+
|
120
|
+
check_db_for_cached_values()
|
121
|
+
|
122
|
+
if @coordinates["coordinates"].count() > 0
|
123
|
+
chunked = Hash.new()
|
124
|
+
@coordinates["coordinates"].each_slice(128).to_a.each do |coords|
|
125
|
+
chunked["coordinates"] = coords
|
126
|
+
r = RestClient.post "https://ossindex.sonatype.org/api/v3/component-report", chunked.to_json,
|
127
|
+
{content_type: :json, accept: :json, 'User-Agent': get_user_agent()}
|
128
|
+
|
129
|
+
if r.code == 200
|
130
|
+
@server_response = @server_response.concat(JSON.parse(r.body))
|
131
|
+
save_values_to_db(JSON.parse(r.body))
|
132
|
+
spinner.success("...done.")
|
133
|
+
@server_response.count()
|
134
|
+
else
|
135
|
+
spinner.stop("...request failed.")
|
136
|
+
print_err "Error getting data from OSS Index server. Server returned non-success code #{r.code}."
|
137
|
+
0
|
138
|
+
end
|
139
|
+
end
|
140
|
+
else
|
114
141
|
spinner.success("...done.")
|
115
142
|
@server_response.count()
|
116
|
-
else
|
117
|
-
spinner.stop("...request failed.")
|
118
|
-
print_err "Error getting data from OSS Index server. Server returned non-success code #{r.code}."
|
119
|
-
0
|
120
143
|
end
|
121
144
|
rescue SocketError => e
|
122
145
|
spinner.stop("...request failed.")
|
@@ -150,17 +173,42 @@ module Chelsea
|
|
150
173
|
i += 1
|
151
174
|
package = r["coordinates"]
|
152
175
|
vulnerable = r["vulnerabilities"].length() > 0
|
176
|
+
coord = r["coordinates"].sub("pkg:gem/", "")
|
177
|
+
name = coord.split('@')[0]
|
178
|
+
version = coord.split('@')[1]
|
179
|
+
reverse_dep_coord = "#{name}-#{version}"
|
153
180
|
if vulnerable
|
154
181
|
puts @pastel.red("[#{i}/#{count}] - #{package} ") + @pastel.red.bold("Vulnerable.")
|
182
|
+
print_reverse_deps(@reverse_deps[reverse_dep_coord], name, version)
|
155
183
|
r["vulnerabilities"].each do |k, v|
|
156
184
|
puts @pastel.red.bold(" #{k}:#{v}")
|
157
185
|
end
|
158
186
|
else
|
159
187
|
puts(@pastel.white("[#{i}/#{count}] - #{package} ") + @pastel.green.bold("No vulnerabilities found!"))
|
188
|
+
print_reverse_deps(@reverse_deps[reverse_dep_coord], name, version)
|
160
189
|
end
|
161
190
|
end
|
162
191
|
end
|
163
192
|
|
193
|
+
def print_reverse_deps(reverse_deps, name, version)
|
194
|
+
reverse_deps.each do |dep|
|
195
|
+
dep.each do |gran|
|
196
|
+
if gran.class == String && !gran.include?(name)
|
197
|
+
# There is likely a fun and clever way to check @server-results, etc... and see if a dep is in there
|
198
|
+
# Right now this looks at all Ruby deps, so it might find some in your Library, but that don't belong to your project
|
199
|
+
puts "\tRequired by: " + gran
|
200
|
+
else
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def to_purl(name, version)
|
207
|
+
purl = "pkg:gem/#{name}@#{version}"
|
208
|
+
|
209
|
+
purl
|
210
|
+
end
|
211
|
+
|
164
212
|
def print_err(s)
|
165
213
|
puts @pastel.red.bold(s)
|
166
214
|
end
|
@@ -168,5 +216,61 @@ module Chelsea
|
|
168
216
|
def print_success(s)
|
169
217
|
puts @pastel.green.bold(s)
|
170
218
|
end
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
def get_user_agent()
|
223
|
+
user_agent = "chelsea/#{Chelsea::VERSION}"
|
224
|
+
|
225
|
+
user_agent
|
226
|
+
end
|
227
|
+
|
228
|
+
# This method will take an array of values, and save them to a pstore database
|
229
|
+
# and as well set a TTL of Time.now to be checked later
|
230
|
+
def save_values_to_db(values)
|
231
|
+
values.each do |val|
|
232
|
+
if get_cached_value_from_db(val["coordinates"]).nil?
|
233
|
+
new_val = val.dup
|
234
|
+
new_val["ttl"] = Time.now
|
235
|
+
@store.transaction do
|
236
|
+
@store[new_val["coordinates"]] = new_val
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Checks pstore to see if a coordinate exists, and if it does also
|
243
|
+
# checks to see if it's ttl has expired. Returns nil unless a record
|
244
|
+
# is valid in the cache (ttl has not expired) and found
|
245
|
+
def get_cached_value_from_db(coordinate)
|
246
|
+
record = @store.transaction { @store[coordinate] }
|
247
|
+
if !record.nil?
|
248
|
+
diff = (Time.now - record['ttl']) / 3600
|
249
|
+
if diff > 12
|
250
|
+
return nil
|
251
|
+
else
|
252
|
+
return record
|
253
|
+
end
|
254
|
+
else
|
255
|
+
return nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Goes through the list of @coordinates and checks pstore for them, if it finds a valid coord
|
260
|
+
# it will add it to the server response. If it does not, it will append the coord to a new hash
|
261
|
+
# and eventually set @coordinates to the new hash, so we query OSS Index on only coords not in cache
|
262
|
+
def check_db_for_cached_values()
|
263
|
+
new_coords = Hash.new
|
264
|
+
new_coords["coordinates"] = Array.new
|
265
|
+
@coordinates["coordinates"].each do |coord|
|
266
|
+
record = get_cached_value_from_db(coord)
|
267
|
+
if !record.nil?
|
268
|
+
@server_response << record
|
269
|
+
else
|
270
|
+
new_coords["coordinates"].push(coord)
|
271
|
+
end
|
272
|
+
end
|
273
|
+
@coordinates = new_coords
|
274
|
+
end
|
171
275
|
end
|
172
276
|
end
|
data/lib/chelsea/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chelsea
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Allister Beharry
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tty-font
|