chelsea 0.0.26 → 0.0.31

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/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