chelsea 0.0.26 → 0.0.31

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -14,9 +16,9 @@
14
16
  # limitations under the License.
15
17
  #
16
18
 
17
- require "bundler/gem_tasks"
18
- require "rspec/core/rake_task"
19
+ require 'bundler/gem_tasks'
20
+ require 'rspec/core/rake_task'
19
21
 
20
22
  RSpec::Core::RakeTask.new(:spec)
21
23
 
22
- task :default => :spec
24
+ task default: :spec
data/bin/chelsea CHANGED
@@ -16,7 +16,8 @@
16
16
  #
17
17
 
18
18
  # frozen_string_literal: true
19
- require_relative "../lib/chelsea"
19
+
20
+ require_relative '../lib/chelsea'
20
21
  require 'slop'
21
22
  opts =
22
23
  begin
@@ -31,13 +32,19 @@ opts =
31
32
  o.string '-iu', '--iquser', 'Specify the IQ username', default: 'admin'
32
33
  o.string '-it', '--iqpass', 'Specify the IQ auth token', default: 'admin123'
33
34
  o.string '-w', '--whitelist', 'Set path to vulnerability whitelist file'
34
- o.bool '-v', '--verbose', 'For text format, list dependencies, their reverse dependencies (what brought them in to your project), and if they are vulnerable. (default: false)', default: false
35
- o.string '-t', '--format', 'Choose what type of format you want your report in (default: text) (options: text, json, xml)', default: 'text'
35
+ o.bool '-v', '--verbose',
36
+ 'For text format, list dependencies, their reverse dependencies (what brought them in to your project), and
37
+ if they are vulnerable. (default: false)', default: false
38
+ o.string '-t', '--format',
39
+ 'Choose what type of format you want your report in (default: text) (options: text, json, xml)',
40
+ default: 'text'
36
41
  o.bool '-b', '--iq', 'Use Nexus IQ Server to audit your project'
37
- o.string '-s', '--stage', 'Specify Nexus IQ Stage (default: build) (options: develop, build, stage-release, release, operate)', default: 'build'
42
+ o.string '-s', '--stage',
43
+ 'Specify Nexus IQ Stage (default: build) (options: develop, build, stage-release, release, operate)',
44
+ default: 'build'
38
45
  o.on '--version', 'Print the version' do
39
- puts Chelsea::VERSION
40
- exit
46
+ puts Chelsea::VERSION
47
+ exit
41
48
  end
42
49
  o.on '-h', '--help', 'Show usage' do
43
50
  puts(o)
@@ -45,7 +52,7 @@ opts =
45
52
  end
46
53
  end
47
54
  rescue Slop::Error => e
48
- puts(e.message + ' (try --help)')
55
+ puts("#{e.message} (try --help)")
49
56
  exit 1
50
57
  end
51
58
  if opts.arguments.count.positive?
data/bin/console CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  #
3
5
  # Copyright 2019-Present Sonatype Inc.
4
6
  #
@@ -15,9 +17,8 @@
15
17
  # limitations under the License.
16
18
  #
17
19
 
20
+ require 'bundler/setup'
21
+ require 'chelsea'
18
22
 
19
- require "bundler/setup"
20
- require "chelsea"
21
-
22
- require "irb"
23
+ require 'irb'
23
24
  IRB.start(__FILE__)
data/chelsea.gemspec CHANGED
@@ -1,42 +1,43 @@
1
+ # frozen_string_literal: true
1
2
 
2
- lib = File.expand_path("../lib", __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "chelsea/version"
5
+ require 'chelsea/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "chelsea"
8
- spec.license = "Apache-2.0"
8
+ spec.name = 'chelsea'
9
+ spec.license = 'Apache-2.0'
9
10
  spec.version = Chelsea::VERSION
10
- spec.authors = ["Allister Beharry"]
11
- spec.email = ["allister.beharry@gmail.com"]
11
+ spec.authors = ['Allister Beharry']
12
+ spec.email = ['allister.beharry@gmail.com']
13
+ spec.required_ruby_version = '>= 2.6.6'
12
14
 
13
- spec.summary = "Audit Ruby package dependencies for security vulnerabilities."
14
- spec.homepage = "https://github.com/sonatype-nexus-community/chelsea"
15
-
16
- spec.metadata["homepage_uri"] = spec.homepage
17
- spec.metadata["source_code_uri"] = "https://github.com/sonatype-nexus-community/chelsea"
18
- spec.metadata["changelog_uri"] = "https://github.com/sonatype-nexus-community/chelsea/CHANGELOG"
15
+ spec.summary = 'Audit Ruby package dependencies for security vulnerabilities.'
16
+ spec.homepage = 'https://github.com/sonatype-nexus-community/chelsea'
19
17
 
20
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = 'https://github.com/sonatype-nexus-community/chelsea'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/sonatype-nexus-community/chelsea/CHANGELOG'
21
+
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
23
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
24
  end
23
- spec.bindir = "bin"
25
+ spec.bindir = 'bin'
24
26
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
- spec.require_paths = ["lib"]
27
+ spec.require_paths = ['lib']
26
28
 
27
- spec.add_dependency "tty-font", "~> 0.5.0"
28
- spec.add_dependency "tty-spinner", "~> 0.9.3"
29
- spec.add_dependency "slop", "~> 4.8.1"
30
- spec.add_dependency "pastel", "~> 0.7.2"
31
- spec.add_dependency "rest-client", "~> 2.0.2"
32
- spec.add_dependency "bundler", ">= 1.2.0", "< 3"
33
- spec.add_dependency "ox", "~> 2.13.2"
34
- spec.add_dependency "tty-table", "~> 0.11.0"
29
+ spec.add_dependency 'bundler', '>= 1.2.0', '< 3'
30
+ spec.add_dependency 'ox', '~> 2.13.2'
31
+ spec.add_dependency 'pastel', '~> 0.7.2'
32
+ spec.add_dependency 'rest-client', '~> 2.0.2'
33
+ spec.add_dependency 'slop', '~> 4.8.1'
34
+ spec.add_dependency 'tty-font', '~> 0.5.0'
35
+ spec.add_dependency 'tty-spinner', '~> 0.9.3'
36
+ spec.add_dependency 'tty-table', '~> 0.11.0'
35
37
 
36
- spec.add_development_dependency "rake", "~> 12.3"
37
- spec.add_development_dependency "rspec", "~> 3.0"
38
- spec.add_development_dependency "rspec_junit_formatter", "~> 0.4.1"
39
- spec.add_development_dependency "webmock", "~> 3.8.3"
40
- spec.add_development_dependency "byebug", "~> 11.1.2"
41
- spec.add_development_dependency 'pry'
38
+ spec.add_development_dependency 'byebug', '~> 11.1.2'
39
+ spec.add_development_dependency 'rake', '~> 12.3'
40
+ spec.add_development_dependency 'rspec', '~> 3.0'
41
+ spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
42
+ spec.add_development_dependency 'webmock', '~> 3.8.3'
42
43
  end
data/lib/chelsea/bom.rb CHANGED
@@ -40,7 +40,7 @@ module Chelsea
40
40
  end
41
41
 
42
42
  def random_urn_uuid
43
- 'urn:uuid:' + SecureRandom.uuid
43
+ "urn:uuid:#{SecureRandom.uuid}"
44
44
  end
45
45
 
46
46
  private
@@ -87,8 +87,8 @@ module Chelsea
87
87
  component
88
88
  end
89
89
 
90
- def _show_logo
91
- logo = %Q(
90
+ def _show_logo # rubocop:disable Metrics/MethodLength
91
+ logo = %(
92
92
  -o/
93
93
  -+hNmNN-
94
94
  .:+osyhddddyso/-``ody+- .NN.
data/lib/chelsea/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -26,7 +28,7 @@ require_relative 'config'
26
28
  module Chelsea
27
29
  ##
28
30
  # This class provides an interface to the oss index, gems and deps
29
- class CLI
31
+ class CLI # rubocop:disable Metrics/ClassLength
30
32
  def initialize(opts)
31
33
  @opts = opts
32
34
  @pastel = Pastel.new
@@ -34,22 +36,28 @@ module Chelsea
34
36
  _show_logo # Move to formatter
35
37
  end
36
38
 
37
- def process!
39
+ # rubocop:disable Metrics/CyclomaticComplexity
40
+ def process! # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/PerceivedComplexity
38
41
  if @opts.config?
39
42
  _set_config # move to init
40
43
  elsif @opts.clear?
41
44
  require_relative 'db'
42
- Chelsea::DB.new().clear_cache
43
- puts "OSS Index cache cleared"
45
+ Chelsea::DB.new.clear_cache
46
+ puts 'OSS Index cache cleared'
44
47
  elsif @opts.file? && @opts.iq?
45
48
  dependencies = _process_file_iq
46
49
  _submit_sbom(dependencies)
50
+ elsif !@opts.file? && @opts.iq?
51
+ abort 'Missing the --file argument. It is required with the --iq argument.'
47
52
  elsif @opts.file?
48
53
  _process_file
49
54
  elsif @opts.help? # quit on opts.help earlier
50
55
  puts _cli_flags # this doesn't exist
56
+ else
57
+ abort 'Missing arguments! Chelsea did nothing. Try providing the --file <Gemfile.lock> argument.'
51
58
  end
52
59
  end
60
+ # rubocop:enable Metrics/CyclomaticComplexity
53
61
 
54
62
  def self.version
55
63
  Chelsea::VERSION
@@ -57,7 +65,7 @@ module Chelsea
57
65
 
58
66
  private
59
67
 
60
- def _submit_sbom(gems)
68
+ def _submit_sbom(gems) # rubocop:disable Metrics/MethodLength
61
69
  iq = Chelsea::IQClient.new(
62
70
  options: {
63
71
  public_application_id: @opts[:application],
@@ -70,10 +78,29 @@ module Chelsea
70
78
  bom = Chelsea::Bom.new(gems.deps.dependencies).collect
71
79
 
72
80
  status_url = iq.post_sbom(bom)
73
-
81
+
74
82
  return unless status_url
75
83
 
76
- iq.poll_status(status_url)
84
+ msg, color, exit_code = iq.poll_status(status_url)
85
+ show_status(msg, color)
86
+ # this may not be very ruby-esque, but `return exit_code` and `exit_code` didn't result in the desired exit status
87
+ exit exit_code
88
+ end
89
+
90
+ def show_status(msg, color)
91
+ case color
92
+ when Chelsea::IQClient::COLOR_FAILURE
93
+ puts @pastel.red.bold(msg)
94
+ when Chelsea::IQClient::COLOR_WARNING
95
+ # want yellow, but that doesn't print
96
+ # puts @pastel.color.bold(msg, color)
97
+ puts @pastel.blue.blue(msg)
98
+ when Chelsea::IQClient::COLOR_NONE
99
+ # want yellow, but that doesn't print
100
+ puts @pastel.green.bold(msg)
101
+ else
102
+ puts @pastel.bold(msg)
103
+ end
77
104
  end
78
105
 
79
106
  def _process_file
@@ -108,7 +135,7 @@ module Chelsea
108
135
 
109
136
  def _flags_set?
110
137
  # I'm still unsure what this is trying to express
111
- valid_flags = _flags.collect {|arg| @opts[arg] }.compact
138
+ valid_flags = _flags.collect { |arg| @opts[arg] }.compact
112
139
  valid_flags.count > 1
113
140
  end
114
141
 
@@ -120,7 +147,7 @@ module Chelsea
120
147
  def _show_logo
121
148
  font = TTY::Font.new(:doom)
122
149
  puts @pastel.green(font.write('Chelsea'))
123
- puts @pastel.green('Version: ' + CLI.version)
150
+ puts @pastel.green("Version: #{CLI.version}")
124
151
  end
125
152
 
126
153
  def _load_config
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -17,6 +19,7 @@
17
19
  require 'yaml'
18
20
  require_relative 'oss_index'
19
21
 
22
+ # Saved credentials
20
23
  module Chelsea
21
24
  @oss_index_config_location = File.join(Dir.home.to_s, '.ossindex')
22
25
  @oss_index_config_filename = '.oss-index-config'
@@ -43,10 +46,8 @@ module Chelsea
43
46
  @client
44
47
  end
45
48
 
46
- def self.oss_index_config
47
- if !File.exist? File.join(@oss_index_config_location, @oss_index_config_filename)
48
- { oss_index_user_name: '', oss_index_user_token: '' }
49
- else
49
+ def self.oss_index_config # rubocop:disable Metrics/MethodLength
50
+ if File.exist? File.join(@oss_index_config_location, @oss_index_config_filename)
50
51
  conf_hash = YAML.safe_load(
51
52
  File.read(
52
53
  File.join(@oss_index_config_location, @oss_index_config_filename)
@@ -56,6 +57,8 @@ module Chelsea
56
57
  oss_index_user_name: conf_hash['Username'],
57
58
  oss_index_user_token: conf_hash['Token']
58
59
  }
60
+ else
61
+ { oss_index_user_name: '', oss_index_user_token: '' }
59
62
  end
60
63
  end
61
64
 
@@ -71,20 +74,18 @@ module Chelsea
71
74
  config = {}
72
75
 
73
76
  puts 'What username do you want to authenticate as (ex: your email address)? '
74
- config['Username'] = STDIN.gets.chomp
77
+ config['Username'] = $stdin.gets.chomp
75
78
 
76
79
  puts 'What token do you want to use? '
77
- config['Token'] = STDIN.gets.chomp
80
+ config['Token'] = $stdin.gets.chomp
78
81
 
79
82
  _write_oss_index_config_file(config)
80
83
  end
81
84
 
82
85
  def self._write_oss_index_config_file(config)
83
- unless File.exist? @oss_index_config_location
84
- Dir.mkdir(@oss_index_config_location)
85
- end
86
- File.open(File.join(@oss_index_config_location, @oss_index_config_filename), "w") do |file|
86
+ Dir.mkdir(@oss_index_config_location) unless File.exist? @oss_index_config_location
87
+ File.open(File.join(@oss_index_config_location, @oss_index_config_filename), 'w') do |file|
87
88
  file.write config.to_yaml
88
89
  end
89
90
  end
90
- end
91
+ end
data/lib/chelsea/db.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -17,6 +19,7 @@
17
19
  require 'pstore'
18
20
 
19
21
  module Chelsea
22
+ # OSS Index data cache
20
23
  class DB
21
24
  def initialize
22
25
  @store = PStore.new(_get_db_store_location)
@@ -45,7 +48,7 @@ module Chelsea
45
48
  end
46
49
  end
47
50
 
48
- def _get_db_store_location()
51
+ def _get_db_store_location
49
52
  initial_path = File.join(Dir.home.to_s, '.ossindex')
50
53
  Dir.mkdir(initial_path) unless File.exist? initial_path
51
54
  File.join(initial_path, 'chelsea.pstore')
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -15,8 +17,9 @@
15
17
  #
16
18
 
17
19
  module Chelsea
20
+ # Project dependency exception
18
21
  class DependencyException < StandardError
19
- def initialize(msg="This is a custom exception", exception_type="custom")
22
+ def initialize(msg = 'This is a custom exception', exception_type = 'custom')
20
23
  @exception_type = exception_type
21
24
  super(msg)
22
25
  end
data/lib/chelsea/deps.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -22,6 +24,7 @@ require 'json'
22
24
  require 'rest-client'
23
25
 
24
26
  module Chelsea
27
+ # Project dependencies
25
28
  class Deps
26
29
  def initialize(path:, verbose: false)
27
30
  @verbose = verbose
@@ -47,7 +50,7 @@ module Chelsea
47
50
 
48
51
  # Collects all reverse dependencies in reverse_dependencies instance var
49
52
  # this rescue block honks
50
- def reverse_dependencies
53
+ def reverse_dependencies # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
51
54
  reverse = Gem::Commands::DependencyCommand.new
52
55
  reverse.options[:reverse_dependencies] = true
53
56
  # We want to filter the reverses dependencies by specs in lockfile
@@ -68,7 +71,7 @@ module Chelsea
68
71
  # in dependencies_versions and coordinates instance vars
69
72
  def coordinates
70
73
  dependencies.each_with_object({ 'coordinates' => [] }) do |(name, v), coords|
71
- coords['coordinates'] << self.class.to_purl(name, v[1]);
74
+ coords['coordinates'] << self.class.to_purl(name, v[1])
72
75
  end
73
76
  end
74
77
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -20,7 +22,7 @@ require_relative 'text'
20
22
 
21
23
  # Factory for formatting dependencies
22
24
  class FormatterFactory
23
- def get_formatter(format: 'text', verbose:)
25
+ def get_formatter(verbose:, format: 'text')
24
26
  case format
25
27
  when 'text'
26
28
  Chelsea::TextFormatter.new verbose: verbose
@@ -28,7 +30,7 @@ class FormatterFactory
28
30
  Chelsea::JsonFormatter.new verbose: verbose
29
31
  when 'xml'
30
32
  Chelsea::XMLFormatter.new verbose: verbose
31
- else
33
+ else # rubocop:disable Lint/DuplicateBranch
32
34
  Chelsea::TextFormatter.new verbose: verbose
33
35
  end
34
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2019-Present Sonatype Inc.
3
5
  #
@@ -14,15 +16,17 @@
14
16
  # limitations under the License.
15
17
  #
16
18
 
19
+ # Base formatter class
17
20
  class Formatter
18
- def initialize
19
- @pastel = Pastel.new
20
- end
21
- def get_results
22
- raise 'must implement get_results method in subclass'
23
- end
24
-
25
- def do_print
26
- raise 'must implement do_print method in subclass'
27
- end
28
- end
21
+ def initialize
22
+ @pastel = Pastel.new
23
+ end
24
+
25
+ def fetch_results
26
+ raise 'must implement get_results method in subclass'
27
+ end
28
+
29
+ def do_print
30
+ raise 'must implement do_print method in subclass'
31
+ end
32
+ end