nessana 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee396ef7c7de91a411465ca7cd27f2dd2ec0ae3ada00d65f2d7fd93bcf7231d1
4
- data.tar.gz: f53065e4cd980ea6ea2da9127a87bede09ceaca1a7607df7f53323b4d090aa73
3
+ metadata.gz: b385c40628994b9e7819e4a855084d81d9bf5a3c8d650e0999ec4e217ba038d6
4
+ data.tar.gz: c62f1308a920473dd891ddfa2057d2b2dabe4ae0d58b0922184ce7998ef19e65
5
5
  SHA512:
6
- metadata.gz: 68b6913aa147d06ef5e1336fd8f694f148e2f67e58cf28b1e1e3690d7761fadbcb0addcd94fa21eafd4f7bbf4bd27f8047702451e65f434d59a66141d2b604ba
7
- data.tar.gz: 0bcab82e1682510938fcaf5a69a4d3cffe2beba1af660c8417d81540dd464512dcaeaee0bf57d8e3918aba060f240a9e9c686fb190d82961ce1b9ff2cf94d808
6
+ metadata.gz: 5cb874ce7320573f4b19e0393a3d8a0af2a0851a9df0f7cebca345d3d3ffc9dfeb1cc6ae45fec6ce35ab855a75c71eb94abb22b53afeebfa55d82122ca1c4104
7
+ data.tar.gz: 9efc4f1a4f11b29db8b4b11da2800bfe5e0574219e3d0c87c8e45bfca6229d7224e190fba9e58ed23f50e1ecf0d23d3de13255dbeff3612667f72b782e2d4685
data/README.md CHANGED
@@ -11,3 +11,23 @@ $ nessana -c config.yml scan.csv
11
11
  ## Contributing
12
12
 
13
13
  See [CONTRIBUTING.md](CONTRIBUTING.md)
14
+
15
+ ## License
16
+
17
+ ```
18
+ <one line to give the program's name and a brief idea of what it does.>
19
+ Copyright (C) 2019 Kristofer Rye
20
+
21
+ This program is free software: you can redistribute it and/or modify
22
+ it under the terms of the GNU Affero General Public License as published
23
+ by the Free Software Foundation, either version 3 of the License, or
24
+ (at your option) any later version.
25
+
26
+ This program is distributed in the hope that it will be useful,
27
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
28
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29
+ GNU Affero General Public License for more details.
30
+
31
+ You should have received a copy of the GNU Affero General Public License
32
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
33
+ ```
data/bin/nessana CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'nessana/executor'
4
4
 
5
- Nessana::Executor.execute!
5
+ exit Nessana::Executor.execute!
@@ -25,7 +25,7 @@ module Nessana
25
25
  @status == other.status || false
26
26
  end
27
27
 
28
- alias eql? ==
28
+ alias :eql? :==
29
29
 
30
30
  protected
31
31
 
data/lib/nessana/dump.rb CHANGED
@@ -2,7 +2,6 @@ require 'time'
2
2
 
3
3
  require 'csv'
4
4
  require 'fastcsv'
5
- require 'tty-spinner'
6
5
 
7
6
  require 'nessana/detection'
8
7
  require 'nessana/vulnerability'
@@ -10,75 +9,32 @@ require 'nessana/vulnerability'
10
9
  module Nessana
11
10
  class Dump < Hash
12
11
  attr_reader :filters
13
- attr_reader :filename
14
12
 
15
- def initialize(filename = nil, filters = [])
16
- @filename, @filters = filename, filters
13
+ def self.read(file, filters = [])
14
+ data = read_csv(file)
17
15
 
18
- if @filename
19
- if File.readable?(@filename)
20
- spinner_options = {
21
- success_mark: "\u2713".encode('utf-8'),
22
- format: :dots_3
23
- }
24
- spinner = TTY::Spinner.new("[:spinner] Loading #{@filename}...", **spinner_options)
25
- spinner.auto_spin
16
+ self.new(data, filters)
17
+ end
26
18
 
27
- read_csv!
19
+ def initialize(vulnerabilities = {}, filters = [])
20
+ @filters = filters
28
21
 
29
- spinner.success('done!')
30
- else
31
- throw 'file not readable; sad face'
32
- end
22
+ filtered_data = vulnerabilities.select do |_, vulnerability|
23
+ !vulnerability.matches?(@filters)
33
24
  end
25
+
26
+ merge!(filtered_data)
34
27
  end
35
28
 
36
29
  def -(other)
37
- spinner_options = {
38
- success_mark: "\u2713".encode('utf-8'),
39
- format: :dots_3
40
- }
41
-
42
- spinner = TTY::Spinner.new('[:spinner] :action...', **spinner_options)
43
- spinner.update(action: 'Generating detections...')
44
-
45
30
  other_plugin_ids = other.keys
46
31
  self_plugin_ids = keys
47
32
 
48
- spinner.update(action: 'Finding L detections')
49
-
50
- other_detection_pairs = other.map do |plugin_id, vulnerability|
51
- spinner.update(action: "Finding L detections (#{plugin_id})")
52
- spinner.auto_spin
53
-
54
- vulnerability.detections.map do |detection|
55
- { plugin_id => detection }
56
- end
57
- end
58
-
59
- other_detections = Set.new(other_detection_pairs.flatten)
60
-
61
- spinner.update(action: 'Finding R detections')
62
-
63
- detection_pairs = map do |plugin_id, vulnerability|
64
- spinner.update(action: "Finding R detections (#{plugin_id})")
65
- spinner.auto_spin
66
-
67
- vulnerability.detections.map do |detection|
68
- { plugin_id => detection }
69
- end
70
- end
71
-
72
- self_detections = Set.new(detection_pairs.flatten)
73
-
74
- spinner.update(action: 'Joining detection sets')
75
- spinner.auto_spin
33
+ other_detections = other.detection_pairs
34
+ self_detections = detection_pairs
76
35
 
77
36
  detections = Set.new([other_detections, self_detections]).flatten
78
37
 
79
- spinner.update(action: 'Processing detections')
80
- spinner.auto_spin
81
-
82
38
  detections.each do |detection_entry|
83
39
  in_self = self_detections.include? detection_entry
84
40
  in_other = other_detections.include? detection_entry
@@ -96,8 +52,6 @@ module Nessana
96
52
  end
97
53
  end
98
54
 
99
- spinner.success('done!')
100
-
101
55
  added_plugin_ids = self_plugin_ids - other_plugin_ids
102
56
  deleted_plugin_ids = other_plugin_ids - self_plugin_ids
103
57
  all_plugin_ids = other_plugin_ids + added_plugin_ids
@@ -127,19 +81,19 @@ module Nessana
127
81
  all_vulnerabilities
128
82
  end
129
83
 
130
- def read_csv!
131
- data = read_csv(filename)
132
-
133
- filtered_data = data.select do |_, vulnerability|
134
- !vulnerability.matches?(@filters)
84
+ def detection_pairs
85
+ pairs = map do |plugin_id, vulnerability|
86
+ vulnerability.detections.map do |detection|
87
+ { plugin_id => detection }
88
+ end
135
89
  end
136
90
 
137
- merge!(filtered_data)
91
+ Set.new(pairs.flatten)
138
92
  end
139
93
 
140
94
  protected
141
95
 
142
- def read_csv(filename)
96
+ def self.read_csv(filename)
143
97
  dump_data = {}
144
98
 
145
99
  first_row = true
@@ -1,7 +1,6 @@
1
1
  require 'optparse'
2
2
  require 'pp'
3
- require 'ruby-prof'
4
- require 'ruby-prof-flamegraph'
3
+ require 'tty-spinner'
5
4
 
6
5
  require 'nessana/executor/execution_configuration'
7
6
  require 'nessana/filter'
@@ -16,26 +15,55 @@ module Nessana
16
15
  def self.execute!(argv = ARGV)
17
16
  parse!(*argv)
18
17
 
19
- RubyProf.start if !!@configuration['performance']
18
+ return @configuration unless @configuration.is_a?(Nessana::Executor::ExecutionConfiguration)
19
+
20
+ return @configuration['__exit-code__'] if @configuration['__stop__']
20
21
 
21
22
  unless @configuration['old_filename']
22
- $stderr.puts 'No old dump filename given; will assume no prior knowledge.'
23
+ warn 'No old dump filename given; assuming you want this.'
23
24
  end
24
25
 
25
26
  unless @configuration['new_filename']
26
- puts 'No new dump filename given; cannot do anything.'
27
- return
27
+ warn 'No new dump filename given; cannot do anything.'
28
+ return 1
28
29
  end
29
30
 
30
31
  filters = @configuration['filters'].map do |filter_hash|
31
32
  Filter.new(filter_hash)
32
33
  end
33
34
 
34
- old_dump = @configuration['old_filename'] ? Dump.new(@configuration['old_filename'], filters) : Dump.new
35
- new_dump = Dump.new(@configuration['new_filename'], filters)
35
+ spinner_options = {
36
+ success_mark: "\u2713".encode('utf-8'),
37
+ format: :dots_3
38
+ }
39
+
40
+ old_dump = nil
41
+
42
+ if @configuration['old_filename']
43
+ spinner = TTY::Spinner.new("[:spinner] Loading #{@configuration['old_filename']}...", **spinner_options)
44
+ spinner.auto_spin
45
+
46
+ old_dump = Dump.read(@configuration['old_filename'], filters)
47
+
48
+ spinner.success('done!')
49
+ else
50
+ old_dump = Dump.new
51
+ end
52
+
53
+ spinner = TTY::Spinner.new("[:spinner] Loading #{@configuration['old_filename']}...", **spinner_options)
54
+ spinner.auto_spin
55
+
56
+ new_dump = Dump.read(@configuration['new_filename'], filters)
57
+
58
+ spinner.success('done!')
59
+
60
+ spinner = TTY::Spinner.new('[:spinner] Comparing dumps...', **spinner_options)
61
+ spinner.auto_spin
36
62
 
37
63
  diff = new_dump - old_dump
38
64
 
65
+ spinner.success('done!')
66
+
39
67
  diff.sort do |vulnerability_a, vulnerability_b|
40
68
  vulnerability_a.plugin_id.to_i <=> vulnerability_b.plugin_id.to_i
41
69
  end.sort do |vulnerability_a, vulnerability_b|
@@ -52,12 +80,7 @@ DISCOVERIES"
52
80
  puts "\n" * 2
53
81
  end
54
82
 
55
- if !!@configuration['performance']
56
- result = RubyProf.stop
57
- printer = RubyProf::FlameGraphPrinter.new(result)
58
- io = open(@configuration['performance'], 'wb')
59
- printer.print(io, {})
60
- end
83
+ 0
61
84
  end
62
85
 
63
86
  def self.parse(*argv)
@@ -68,10 +91,8 @@ DISCOVERIES"
68
91
 
69
92
  if argv.count == 0
70
93
  puts parser
71
- exit 1
94
+ return 1
72
95
  end
73
-
74
- parser.parse(*argv)
75
96
  end
76
97
 
77
98
  remaining_arguments = option_parser.order!(argv)
@@ -95,6 +116,5 @@ DISCOVERIES"
95
116
  def self.parse!(*argv)
96
117
  @configuration = parse(*argv)
97
118
  end
98
-
99
119
  end
100
120
  end
@@ -3,6 +3,8 @@ require 'mime-types'
3
3
  require 'nessana/version'
4
4
 
5
5
  module Nessana::Executor
6
+ # TODO: Replace __stop__ and __exit-code__ with exits again, and
7
+ # use a rescue SystemExit => e instead.
6
8
  class ExecutionConfiguration < ::Hash
7
9
  def initialize
8
10
  self['verbosity'] = 'info'
@@ -25,14 +27,10 @@ module Nessana::Executor
25
27
  add_usage_option(parser)
26
28
  add_verbosity_option(parser)
27
29
 
28
- parser.on_tail('-h', '--help', 'Show this message') do
29
- puts parser
30
- exit
31
- end
32
-
33
- parser.on_tail('--version', 'Show version') do
30
+ parser.on_tail('-V', '--version', 'Show version') do
34
31
  puts Nessana::VERSION
35
- exit
32
+ self['__stop__'] = true
33
+ self['__exit-code__'] = 0
36
34
  end
37
35
  end
38
36
 
@@ -52,7 +50,8 @@ module Nessana::Executor
52
50
  def add_usage_option(parser)
53
51
  parser.on('-h', '--help', 'Print usage summary.') do
54
52
  puts parser
55
- exit 0
53
+ self['__stop__'] = true
54
+ self['__exit-code__'] = 0
56
55
  end
57
56
  end
58
57
 
@@ -1,3 +1,3 @@
1
1
  module Nessana
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nessana
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristofer Rye <kristofer.rye@gmail.com>
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-22 00:00:00.000000000 Z
11
+ date: 2019-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fastcsv
@@ -136,34 +136,6 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0.57'
139
- - !ruby/object:Gem::Dependency
140
- name: ruby-prof
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 0.17.0
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: 0.17.0
153
- - !ruby/object:Gem::Dependency
154
- name: ruby-prof-flamegraph
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - "~>"
158
- - !ruby/object:Gem::Version
159
- version: 0.3.0
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: 0.3.0
167
139
  - !ruby/object:Gem::Dependency
168
140
  name: simplecov
169
141
  requirement: !ruby/object:Gem::Requirement
@@ -199,7 +171,7 @@ files:
199
171
  - lib/nessana/vulnerability.rb
200
172
  homepage: https://github.com/rye/nessana
201
173
  licenses:
202
- - MIT
174
+ - AGPL-3.0-only
203
175
  metadata: {}
204
176
  post_install_message:
205
177
  rdoc_options: []