inspec_tools 2.3.5 → 2.3.6

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: 80ef2e3696f25c1381c8ca69f7c8c0c7183c5e7d2e8ab12d2d0764afd6071f8d
4
- data.tar.gz: e34d31358000c88def3e19dcbc7b936752749cf02cc28d7c99a0cdc9875e022c
3
+ metadata.gz: 83f3edc68686aa22483f4f17080a176122ed5d3b8c41c0a1f47a68062aa04b4d
4
+ data.tar.gz: 6c140e38354f7decc791db6829bbcff2bf845d256d9860769514d62c17cf50c6
5
5
  SHA512:
6
- metadata.gz: d9a2ce7f04c865c6ba18bf8121bc20701c005b7357b5ba41fa4e33f3320ff96a82087c2b41e478e006c1ee1ce2f416b11d744f62eefad00765432915ca993fd5
7
- data.tar.gz: b1d43d8d8eb302d9121e4ffe3f51eebb4116a75d8762cd6feb14e90a89320245ac5a5758aaf8760ba2460c62550fc6f18aaa801ac5b2436320ef568b5c735267
6
+ metadata.gz: 21875ca95036a401be3eb22ef782b1d92f12869fa6cf32183a80d8dd951e9ab95196458485c3437d4be8f902d8a6def3d5da2c411d517e40020cd4b3ad013a1b
7
+ data.tar.gz: 5879c557fcf781bec5a44a637160bedd981450b071b72e8155d7046aad8adba8cefbe93f4b92f6d5be666b1d88363328e392a5fdddc271383ca6c087ccb34f8a
data/README.md CHANGED
@@ -218,6 +218,7 @@ FLAGS:
218
218
  -s --separate-files [true | false] : output the resulting controls as one or mutiple files (default: true) [optional]
219
219
  -m --metadata <metadata-json> : path to json file with additional metadata for the inspec.yml file [optional]
220
220
  -r --replace-tags <array> : A case-sensitive, space separated list to replace tags with a $ if found in a group rules description tag [optional]
221
+ -c --control-id [vulnID | ruleID] : use either legacy Vuln ID (ex. 'V-XXXXX') or Rule ID (ex. 'SV-XXXXX') as the overall Control ID (default: vulnID) [optional]
221
222
 
222
223
  example: inspec_tools xccdf2inspec -x xccdf_file.xml -a attributes.yml -o myprofile -f ruby -s false
223
224
  ```
data/exe/inspec_tools CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env -S ruby -EUTF-8
2
2
 
3
3
  # Trap ^C
4
- Signal.trap('INT') {
4
+ Signal.trap('INT') do
5
5
  puts "\nCtrl-C detected. Exiting..."
6
6
  sleep 1
7
7
  exit
8
- }
8
+ end
9
9
 
10
10
  $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
11
11
  require 'inspec_tools'
@@ -67,10 +67,11 @@ module HappyMapperTools
67
67
  content :ident, String
68
68
  def initialize(ident_str)
69
69
  @ident = ident_str
70
- if ident_str =~ /^(CCI-[0-9]{6})$/
70
+ case ident_str
71
+ when /^(CCI-[0-9]{6})$/
71
72
  # Match CCI IDs; e.g. CCI-123456
72
73
  @system = 'http://cyber.mil/cci'
73
- elsif ident_str =~ /^(S?V-[0-9]{5})$/
74
+ when /^(S?V-[0-9]{5})$/
74
75
  # Match SV- IDs; e.g. SV-12345
75
76
  # Match V- IDs; e.g. V-12345
76
77
  @system = 'http://cyber.mil/legacy'
@@ -128,7 +129,7 @@ module HappyMapperTools
128
129
  element :result, String, tag: 'result'
129
130
  # element override - Not implemented. Does not apply to Inspec execution
130
131
  has_many :ident, Ident, tag: 'ident'
131
- # Note: element metadata not implemented at this time
132
+ # NOTE: element metadata not implemented at this time
132
133
  has_many :message, MessageType, tag: 'message'
133
134
  has_many :instance, String, tag: 'instance'
134
135
  element :fix, Fix, tag: 'fix'
@@ -175,7 +176,7 @@ module HappyMapperTools
175
176
 
176
177
  class TestResult
177
178
  include HappyMapper
178
- # Note: element benchmark not implemented at this time since this is same file
179
+ # NOTE: element benchmark not implemented at this time since this is same file
179
180
  # Note: element title not implemented due to no mapping from Chef Inspec
180
181
  element :remark, String, tag: 'remark'
181
182
  has_many :organization, String, tag: 'organization'
@@ -184,14 +185,14 @@ module HappyMapperTools
184
185
  has_many :target_address, String, tag: 'target-address'
185
186
  element :target_facts, TargetFact, tag: 'target-facts'
186
187
  element :platform, CPE2idrefType, tag: 'platform'
187
- # Note: element profile not implemented since Benchmark profile is also not implemented
188
+ # NOTE: element profile not implemented since Benchmark profile is also not implemented
188
189
  has_many :rule_result, RuleResultType, tag: 'rule-result'
189
190
  has_many :score, ScoreType, tag: 'score' # One minimum
190
191
  # Note: element signature not implemented due to no mapping from Chef Inspec
191
192
  attribute :id, String, tag: 'id'
192
193
  attribute :starttime, String, tag: 'start-time'
193
194
  attribute :endtime, String, tag: 'end-time'
194
- # Note: attribute test-system not implemented at this time due to unknown CPE value for Chef Inspec
195
+ # NOTE: attribute test-system not implemented at this time due to unknown CPE value for Chef Inspec
195
196
  attribute :version, String, tag: 'version'
196
197
  end
197
198
 
@@ -3,8 +3,6 @@
3
3
  require 'happymapper'
4
4
  require 'nokogiri'
5
5
 
6
- # rubocop:disable Naming/ClassAndModuleCamelCase
7
-
8
6
  module HappyMapperTools
9
7
  module CCIAttributes
10
8
  class Reference
@@ -62,5 +60,3 @@ module HappyMapperTools
62
60
  end
63
61
  end
64
62
  end
65
-
66
- # rubocop:enable Naming/ClassAndModuleCamelCase
@@ -79,8 +79,8 @@ module HappyMapperTools
79
79
 
80
80
  class Ident
81
81
  include HappyMapper
82
- attr_accessor :legacy
83
- attr_accessor :cci
82
+ attr_accessor :legacy, :cci
83
+
84
84
  tag 'ident'
85
85
  attribute :system, String, tag: 'system'
86
86
  content :ident, String
@@ -204,7 +204,7 @@ module HappyMapperTools
204
204
  '(case sensitive) option to replace the offending tags ' \
205
205
  'during processing of the XCCDF ' \
206
206
  'file to use the ' +
207
- "`$#{offending_tags[0]}` " .colorize(:light_green) +
207
+ "`$#{offending_tags[0]}` ".colorize(:light_green) +
208
208
  'syntax in your InSpec profile.'
209
209
  option_two = '(2) Update your XCCDF file to *not use* non-standard XCCDF ' \
210
210
  'elements within ' +
@@ -213,7 +213,7 @@ module HappyMapperTools
213
213
  '`>` '.colorize(:red) +
214
214
  'as "placeholders", and use something that doesn\'t confuse ' \
215
215
  'the XML parser, such as : ' +
216
- "`$#{offending_tags[0]}`" .colorize(:light_green)
216
+ "`$#{offending_tags[0]}`".colorize(:light_green)
217
217
  puts option_one
218
218
  puts "\n"
219
219
  puts option_two
@@ -3,7 +3,7 @@ require 'json'
3
3
 
4
4
  require 'inspec-objects'
5
5
  require 'inspec'
6
- require_relative './plugin_cli.rb'
6
+ require_relative './plugin_cli'
7
7
 
8
8
  # This tells the ruby cli app to use the same argument parsing as the plugin
9
9
  module InspecTools
@@ -6,10 +6,6 @@ require_relative '../utilities/inspec_util'
6
6
  require_relative '../utilities/cci_xml'
7
7
  require_relative '../utilities/mapping_validator'
8
8
 
9
- # rubocop:disable Metrics/AbcSize
10
- # rubocop:disable Metrics/PerceivedComplexity
11
- # rubocop:disable Metrics/CyclomaticComplexity
12
-
13
9
  module InspecTools
14
10
  # Methods for converting from CSV to various formats
15
11
  class CSVTool
@@ -46,8 +42,8 @@ module InspecTools
46
42
  @profile['supports'] = []
47
43
  @profile['attributes'] = []
48
44
  @profile['generator'] = {
49
- 'name': 'inspec_tools',
50
- 'version': VERSION
45
+ name: 'inspec_tools',
46
+ version: VERSION
51
47
  }
52
48
  end
53
49
 
@@ -98,7 +94,3 @@ module InspecTools
98
94
  end
99
95
  end
100
96
  end
101
-
102
- # rubocop:enable Metrics/AbcSize
103
- # rubocop:enable Metrics/PerceivedComplexity
104
- # rubocop:enable Metrics/CyclomaticComplexity
@@ -14,21 +14,21 @@ module InspecTools
14
14
 
15
15
  def default_text
16
16
  <<~YML
17
- # Setting csv_header to true will skip the csv file header
18
- skip_csv_header: true
19
- width : 80
17
+ # Setting csv_header to true will skip the csv file header
18
+ skip_csv_header: true
19
+ width : 80
20
20
 
21
21
 
22
- control.id: 0
23
- control.title: 15
24
- control.desc: 16
25
- control.tags:
26
- severity: 1
27
- rid: 8
28
- stig_id: 3
29
- cci: 2
30
- check: 12
31
- fix: 10
22
+ control.id: 0
23
+ control.title: 15
24
+ control.desc: 16
25
+ control.tags:
26
+ severity: 1
27
+ rid: 8
28
+ stig_id: 3
29
+ cci: 2
30
+ check: 12
31
+ fix: 10
32
32
  YML
33
33
  end
34
34
  end
@@ -1,9 +1,11 @@
1
- module InspecTools::Help
2
- class << self
3
- def text(namespaced_command)
4
- path = namespaced_command.to_s.tr(':', '/')
5
- path = File.expand_path("../help/#{path}.md", __FILE__)
6
- IO.read(path) if File.exist?(path)
1
+ module InspecTools
2
+ module Help
3
+ class << self
4
+ def text(namespaced_command)
5
+ path = namespaced_command.to_s.tr(':', '/')
6
+ path = File.expand_path("../help/#{path}.md", __FILE__)
7
+ IO.read(path) if File.exist?(path)
8
+ end
7
9
  end
8
10
  end
9
11
  end
@@ -13,7 +13,7 @@ require_relative '../utilities/xccdf/from_inspec'
13
13
  require_relative '../utilities/xccdf/to_xccdf'
14
14
 
15
15
  module InspecTools
16
- class Inspec # rubocop:disable Metrics/ClassLength
16
+ class Inspec
17
17
  def initialize(inspec_json, metadata = {})
18
18
  @json = JSON.parse(inspec_json.gsub(/\\+u0000/, ''))
19
19
  @metadata = metadata
@@ -66,7 +66,7 @@ module InspecTools
66
66
  #
67
67
  # @param inspec_json : an inspec profile formatted as a json object
68
68
  ###
69
- def inspec_json_to_array(inspec_json) # rubocop:disable Metrics/CyclomaticComplexity
69
+ def inspec_json_to_array(inspec_json)
70
70
  data = []
71
71
  headers = {}
72
72
  inspec_json['controls'].each do |control|
@@ -158,19 +158,19 @@ module InspecTools
158
158
  vuln
159
159
  end
160
160
 
161
- def generate_asset # rubocop:disable Metrics/AbcSize
161
+ def generate_asset
162
162
  asset = HappyMapperTools::StigChecklist::Asset.new
163
- asset.role = !@metadata['role'].nil? ? @metadata['role'] : 'Workstation'
164
- asset.type = !@metadata['type'].nil? ? @metadata['type'] : 'Computing'
163
+ asset.role = @metadata['role'].nil? ? 'Workstation' : @metadata['role']
164
+ asset.type = @metadata['type'].nil? ? 'Computing' : @metadata['type']
165
165
  asset.host_name = generate_hostname
166
166
  asset.host_ip = generate_ip
167
167
  asset.host_mac = generate_mac
168
168
  asset.host_fqdn = generate_fqdn
169
- asset.tech_area = !@metadata['tech_area'].nil? ? @metadata['tech_area'] : ''
170
- asset.target_key = !@metadata['target_key'].nil? ? @metadata['target_key'] : ''
171
- asset.web_or_database = !@metadata['web_or_database'].nil? ? @metadata['web_or_database'] : '0'
172
- asset.web_db_site = !@metadata['web_db_site'].nil? ? @metadata['web_db_site'] : ''
173
- asset.web_db_instance = !@metadata['web_db_instance'].nil? ? @metadata['web_db_instance'] : ''
169
+ asset.tech_area = @metadata['tech_area'].nil? ? '' : @metadata['tech_area']
170
+ asset.target_key = @metadata['target_key'].nil? ? '' : @metadata['target_key']
171
+ asset.web_or_database = @metadata['web_or_database'].nil? ? '0' : @metadata['web_or_database']
172
+ asset.web_db_site = @metadata['web_db_site'].nil? ? '' : @metadata['web_db_site']
173
+ asset.web_db_instance = @metadata['web_db_instance'].nil? ? '' : @metadata['web_db_instance']
174
174
  asset
175
175
  end
176
176
 
@@ -6,10 +6,6 @@ require_relative '../utilities/parser'
6
6
  require_relative '../utilities/text_cleaner'
7
7
  require_relative '../utilities/cis_to_nist'
8
8
 
9
- # rubocop:disable Metrics/AbcSize
10
- # rubocop:disable Metrics/PerceivedComplexity
11
- # rubocop:disable Metrics/CyclomaticComplexity
12
-
13
9
  module InspecTools
14
10
  class PDF
15
11
  def initialize(pdf, profile_name, debug = false)
@@ -59,7 +55,7 @@ module InspecTools
59
55
  @transformed_data.each do |contr|
60
56
  nist = find_nist(contr[:cis]) unless contr[:cis] == 'No CIS Control'
61
57
  control = {}
62
- control['id'] = 'M-' + contr[:title].split(' ')[0]
58
+ control['id'] = "M-#{contr[:title].split[0]}"
63
59
  control['title'] = contr[:title]
64
60
  control['desc'] = contr[:descr]
65
61
  control['impact'] = Utils::InspecUtil.get_impact('medium')
@@ -67,7 +63,7 @@ module InspecTools
67
63
  control['tags']['severity'] = Utils::InspecUtil.get_impact_string(control['impact'])
68
64
  control['tags']['ref'] = contr[:ref] unless contr[:ref].nil?
69
65
  control['tags']['applicability'] = contr[:applicability] unless contr[:applicability].nil?
70
- control['tags']['cis_id'] = contr[:title].split(' ')[0] unless contr[:title].nil?
66
+ control['tags']['cis_id'] = contr[:title].split[0] unless contr[:title].nil?
71
67
  control['tags']['cis_control'] = [contr[:cis], @nist_mapping[0][:cis_ver]] unless contr[:cis].nil? # tag cis_control: [5, 6.1] ##6.1 is the version
72
68
  control['tags']['cis_level'] = contr[:level] unless contr[:level].nil?
73
69
  control['tags']['nist'] = nist unless nist.nil? # tag nist: [AC-3, 4] ##4 is the version
@@ -91,8 +87,8 @@ module InspecTools
91
87
  @profile['supports'] = []
92
88
  @profile['attributes'] = []
93
89
  @profile['generator'] = {
94
- 'name': 'inspec_tools',
95
- 'version': VERSION
90
+ name: 'inspec_tools',
91
+ version: VERSION
96
92
  }
97
93
  end
98
94
 
@@ -16,10 +16,9 @@ module InspecTools
16
16
  autoload :GenerateMap, 'inspec_tools/generate_map'
17
17
  end
18
18
 
19
- # rubocop:disable Style/GuardClause
20
19
  module InspecPlugins
21
20
  module InspecToolsPlugin
22
- class CliCommand < Inspec.plugin(2, :cli_command) # rubocop:disable Metrics/ClassLength
21
+ class CliCommand < Inspec.plugin(2, :cli_command)
23
22
  POSSIBLE_LOG_LEVELS = %w{debug info warn error fatal}.freeze
24
23
 
25
24
  class_option :log_directory, type: :string, aliases: :l, desc: 'Provide log location'
@@ -36,8 +35,9 @@ module InspecPlugins
36
35
  option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
37
36
  option :replace_tags, type: :array, required: false, aliases: '-r'
38
37
  option :metadata, required: false, aliases: '-m'
38
+ option :control_id, required: false, enum: %w{ruleID vulnID}, aliases: '-c', default: 'vulnID'
39
39
  def xccdf2inspec
40
- xccdf = InspecTools::XCCDF.new(File.read(options[:xccdf]), options[:replace_tags])
40
+ xccdf = InspecTools::XCCDF.new(File.read(options[:xccdf]), options[:control_id] == 'vulnID', options[:replace_tags])
41
41
  profile = xccdf.to_inspec
42
42
 
43
43
  if !options[:metadata].nil?
@@ -240,5 +240,3 @@ if help_commands.any? { |cmd| ARGV.include? cmd }
240
240
  end
241
241
  end
242
242
  end
243
-
244
- # rubocop:enable Style/GuardClause
@@ -14,15 +14,8 @@ TALLYS = %i(total critical high medium low).freeze
14
14
  THRESHOLD_TEMPLATE = File.expand_path('../data/threshold.yaml', File.dirname(__FILE__))
15
15
 
16
16
  module InspecTools
17
- # rubocop:disable Metrics/ClassLength
18
17
  class Summary
19
- attr_reader :json
20
- attr_reader :json_full
21
- attr_reader :json_counts
22
- attr_reader :threshold_file
23
- attr_reader :threshold_inline
24
- attr_reader :summary
25
- attr_reader :threshold
18
+ attr_reader :json, :json_full, :json_counts, :threshold_file, :threshold_inline, :summary, :threshold
26
19
 
27
20
  def initialize(**options)
28
21
  options = options[:options]
@@ -154,5 +147,4 @@ module InspecTools
154
147
  summary[:status][:error][:total])).floor
155
148
  end
156
149
  end
157
- # rubocop:enable Metrics/ClassLength
158
150
  end
@@ -6,19 +6,15 @@ require 'digest'
6
6
  require 'json'
7
7
 
8
8
  module InspecTools
9
- # rubocop:disable Metrics/ClassLength
10
- # rubocop:disable Metrics/AbcSize
11
- # rubocop:disable Metrics/PerceivedComplexity
12
- # rubocop:disable Metrics/CyclomaticComplexity
13
- # rubocop:disable Metrics/BlockLength
14
9
  class XCCDF
15
- def initialize(xccdf, replace_tags = nil)
10
+ def initialize(xccdf, use_vuln_id, replace_tags = nil)
16
11
  @xccdf = xccdf
17
12
  @xccdf = replace_tags_in_xccdf(replace_tags, @xccdf) unless replace_tags.nil?
18
13
  cci_list_path = File.join(File.dirname(__FILE__), '../data/U_CCI_List.xml')
19
14
  @cci_items = HappyMapperTools::CCIAttributes::CCI_List.parse(File.read(cci_list_path))
20
15
  register_after_parse_callbacks
21
16
  @benchmark = HappyMapperTools::StigAttributes::Benchmark.parse(@xccdf)
17
+ @use_vuln_id = use_vuln_id
22
18
  end
23
19
 
24
20
  def to_ckl
@@ -42,7 +38,7 @@ module InspecTools
42
38
  # extracts non-InSpec attributes
43
39
  ###
44
40
  # TODO there may be more attributes we want to extract, see data/attributes.yml for example
45
- def to_attributes # rubocop:disable Metrics/AbcSize
41
+ def to_attributes
46
42
  @attribute = {}
47
43
 
48
44
  @attribute['benchmark.title'] = @benchmark.title
@@ -116,8 +112,8 @@ module InspecTools
116
112
  @profile['supports'] = []
117
113
  @profile['attributes'] = []
118
114
  @profile['generator'] = {
119
- 'name': 'inspec_tools',
120
- 'version': VERSION
115
+ name: 'inspec_tools',
116
+ version: VERSION
121
117
  }
122
118
  @profile['plaintext'] = @benchmark.plaintext.plaintext
123
119
  @profile['status'] = "#{@benchmark.status} on #{@benchmark.release_date.release_date}"
@@ -129,7 +125,7 @@ module InspecTools
129
125
  def insert_controls
130
126
  @benchmark.group.each do |group|
131
127
  control = {}
132
- control['id'] = group.id
128
+ control['id'] = @use_vuln_id ? group.id : group.rule.id.split('r').first
133
129
  control['title'] = group.rule.title
134
130
  control['desc'] = group.rule.description.vuln_discussion.split('Satisfies: ')[0]
135
131
  control['impact'] = Utils::InspecUtil.get_impact(group.rule.severity)
@@ -141,8 +137,9 @@ module InspecTools
141
137
  control['tags']['rid'] = group.rule.id
142
138
  control['tags']['stig_id'] = group.rule.version
143
139
  control['tags']['fix_id'] = group.rule.fix.id
144
- control['tags']['cci'] = group.rule.idents.select { |i| i.cci }.map { |i| i.ident }
145
- control['tags']['legacy'] = group.rule.idents.select { |i| i.legacy}.map { |i| i.ident }
140
+ control['tags']['cci'] = group.rule.idents.select(&:cci).map(&:ident)
141
+ legacy_tags = group.rule.idents.select(&:legacy)
142
+ control['tags']['legacy'] = legacy_tags.map(&:ident) unless legacy_tags.empty?
146
143
  control['tags']['nist'] = @cci_items.fetch_nists(control['tags']['cci'])
147
144
  control['tags']['false_negatives'] = group.rule.description.false_negatives if group.rule.description.false_negatives != ''
148
145
  control['tags']['false_positives'] = group.rule.description.false_positives if group.rule.description.false_positives != ''
@@ -8,10 +8,6 @@ require_relative '../utilities/inspec_util'
8
8
  require_relative '../utilities/cis_to_nist'
9
9
  require_relative '../utilities/mapping_validator'
10
10
 
11
- # rubocop:disable Metrics/AbcSize
12
- # rubocop:disable Metrics/PerceivedComplexity
13
- # rubocop:disable Metrics/CyclomaticComplexity
14
-
15
11
  module InspecTools
16
12
  # Methods for converting from XLS to various formats
17
13
  class XLSXTool
@@ -58,8 +54,8 @@ module InspecTools
58
54
  @profile['supports'] = []
59
55
  @profile['attributes'] = []
60
56
  @profile['generator'] = {
61
- 'name': 'inspec_tools',
62
- 'version': ::InspecTools::VERSION
57
+ name: 'inspec_tools',
58
+ version: ::InspecTools::VERSION
63
59
  }
64
60
  end
65
61
 
@@ -73,7 +69,7 @@ module InspecTools
73
69
  tag_pos = @mapping['control.tags']
74
70
  control = {}
75
71
  control['tags'] = {}
76
- control['id'] = control_prefix + '-' + row[@mapping['control.id']].formatted_value unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
72
+ control['id'] = "#{control_prefix}-#{row[@mapping['control.id']].formatted_value}" unless cell_empty?(@mapping['control.id']) || cell_empty?(row[@mapping['control.id']])
77
73
  control['title'] = row[@mapping['control.title']].formatted_value unless cell_empty?(@mapping['control.title']) || cell_empty?(row[@mapping['control.title']])
78
74
  control['desc'] = ''
79
75
  control['desc'] = row[@mapping['control.desc']].formatted_value unless cell_empty?(row[@mapping['control.desc']])
@@ -107,7 +103,8 @@ module InspecTools
107
103
  end
108
104
 
109
105
  def apply_cis_and_nist_controls(control, cis_tags)
110
- control['tags']['cis_controls'], control['tags']['nist'] = [], []
106
+ control['tags']['cis_controls'] = []
107
+ control['tags']['nist'] = []
111
108
 
112
109
  if cis_tags[:sub_section].nil? || cis_tags[:sub_section].blank?
113
110
  control['tags']['cis_controls'] << cis_tags[:section]
@@ -130,7 +127,3 @@ module InspecTools
130
127
  end
131
128
  end
132
129
  end
133
-
134
- # rubocop:enable Metrics/AbcSize
135
- # rubocop:enable Metrics/PerceivedComplexity
136
- # rubocop:enable Metrics/CyclomaticComplexity
@@ -1,5 +1,5 @@
1
1
  class String
2
2
  def blank?
3
- self.strip.empty?
3
+ strip.empty?
4
4
  end
5
5
  end
@@ -14,7 +14,7 @@ require 'overrides/string'
14
14
  require 'rubocop'
15
15
 
16
16
  module Utils
17
- class InspecUtil # rubocop:disable Metrics/ClassLength
17
+ class InspecUtil
18
18
  WIDTH = 80
19
19
  IMPACT_SCORES = {
20
20
  'none' => 0.0,
@@ -24,7 +24,7 @@ module Utils
24
24
  'critical' => 0.9
25
25
  }.freeze
26
26
 
27
- def self.parse_data_for_ckl(json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
27
+ def self.parse_data_for_ckl(json)
28
28
  data = {}
29
29
 
30
30
  # Parse for inspec profile results json
@@ -88,7 +88,7 @@ module Utils
88
88
  hash.each_with_object({}) do |(k, v), ret|
89
89
  key = recursive_key + k.to_s
90
90
  if v.is_a? Hash
91
- ret.merge! to_dotted_hash(v, key + '.')
91
+ ret.merge! to_dotted_hash(v, "#{key}.")
92
92
  else
93
93
  ret[key] = v
94
94
  end
@@ -165,15 +165,16 @@ module Utils
165
165
  end
166
166
 
167
167
  private_class_method def self.string_to_impact(severity, use_cvss_terms)
168
- if %r{none|na|n/a|not[_|(\s*)]?applicable}i.match?(severity)
168
+ case severity
169
+ when %r{none|na|n/a|not[_|(\s*)]?applicable}i
169
170
  impact = 0.0 # Informative
170
- elsif /low|cat(egory)?\s*(iii|3)/i.match?(severity)
171
+ when /low|cat(egory)?\s*(iii|3)/i
171
172
  impact = 0.3 # Low Impact
172
- elsif /med(ium)?|cat(egory)?\s*(ii|2)/i.match?(severity)
173
+ when /med(ium)?|cat(egory)?\s*(ii|2)/i
173
174
  impact = 0.5 # Medium Impact
174
- elsif /high|cat(egory)?\s*(i|1)/i.match?(severity)
175
+ when /high|cat(egory)?\s*(i|1)/i
175
176
  impact = 0.7 # High Impact
176
- elsif /crit(ical)?|severe/i.match?(severity)
177
+ when /crit(ical)?|severe/i
177
178
  impact = 1.0 # Critical Controls
178
179
  else
179
180
  raise SeverityInputError, "'#{severity}' is not a valid severity value. It should be a Float between 0.0 and " \
@@ -218,7 +219,7 @@ module Utils
218
219
  WordWrap.ww(str.to_s, width)
219
220
  end
220
221
 
221
- private_class_method def self.generate_controls(inspec_json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
222
+ private_class_method def self.generate_controls(inspec_json)
222
223
  controls = []
223
224
  inspec_json['controls'].each do |json_control|
224
225
  control = ::Inspec::Object::Control.new
@@ -246,7 +247,7 @@ module Utils
246
247
  control.add_tag(::Inspec::Object::Tag.new('stig_id', json_control['tags']['stig_id']))
247
248
  control.add_tag(::Inspec::Object::Tag.new('fix_id', json_control['tags']['fix_id']))
248
249
  control.add_tag(::Inspec::Object::Tag.new('cci', json_control['tags']['cci']))
249
- control.add_tag(::Inspec::Object::Tag.new('legacy', json_control['tags']['legacy']))
250
+ control.add_tag(::Inspec::Object::Tag.new('legacy', json_control['tags']['legacy'])) unless json_control['tags']['legacy'].blank?
250
251
  control.add_tag(::Inspec::Object::Tag.new('nist', json_control['tags']['nist']))
251
252
  control.add_tag(::Inspec::Object::Tag.new('cis_level', json_control['tags']['cis_level'])) unless json_control['tags']['cis_level'].blank?
252
253
  control.add_tag(::Inspec::Object::Tag.new('cis_controls', json_control['tags']['cis_controls'])) unless json_control['tags']['cis_controls'].blank?
@@ -326,7 +327,7 @@ module Utils
326
327
  myfile.puts readme_contents
327
328
  end
328
329
 
329
- private_class_method def self.unpack_profile(directory, controls, separated, output_format) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
330
+ private_class_method def self.unpack_profile(directory, controls, separated, output_format)
330
331
  FileUtils.rm_rf(directory) if Dir.exist?(directory)
331
332
  Dir.mkdir directory unless Dir.exist?(directory)
332
333
  Dir.mkdir "#{directory}/controls" unless Dir.exist?("#{directory}/controls")
@@ -337,7 +338,7 @@ module Utils
337
338
  file_name = control.id.to_s
338
339
  myfile = File.new("#{directory}/controls/#{file_name}.rb", 'w')
339
340
  myfile.puts "# encoding: UTF-8\n\n"
340
- myfile.puts wrap(control.to_ruby, WIDTH) + "\n"
341
+ myfile.puts "#{wrap(control.to_ruby, WIDTH)}\n"
341
342
  myfile.close
342
343
  end
343
344
  else
@@ -353,7 +354,7 @@ module Utils
353
354
  if output_format == 'ruby'
354
355
  controls.each do |control|
355
356
  myfile.puts "# encoding: UTF-8\n\n"
356
- myfile.puts wrap(control.to_ruby.gsub('"', "\'"), WIDTH) + "\n"
357
+ myfile.puts "#{wrap(control.to_ruby.gsub('"', "\'"), WIDTH)}\n"
357
358
  end
358
359
  else
359
360
  controls.each do |control|
@@ -4,7 +4,6 @@ require 'parslet'
4
4
  require 'parslet/convenience'
5
5
  require 'pp'
6
6
 
7
- # rubocop:disable Metrics/ClassLength
8
7
  module Util
9
8
  class ControlParser < Parslet::Parser
10
9
  root :controls
@@ -345,8 +344,8 @@ module Util
345
344
 
346
345
  def parse(clean_text)
347
346
  @parser.parse(clean_text)
348
- rescue Parslet::ParseFailed => error
349
- puts error.parse_failure_cause.ascii_tree
347
+ rescue Parslet::ParseFailed => e
348
+ puts e.parse_failure_cause.ascii_tree
350
349
  end
351
350
 
352
351
  def convert_str(value)
@@ -359,13 +358,13 @@ module Util
359
358
  references = ctrl[:ref].split("\n")
360
359
  references.each do |ref|
361
360
  match = ref.scan(/(?<=#)\d+\.\d+/).map(&:inspect).join(',').delete('"').tr(',', ' ')
362
- ctrl[:cis] = match.split(' ') unless match.empty?
361
+ ctrl[:cis] = match.split unless match.empty?
363
362
  end
364
363
  ctrl[:cis] = 'No CIS Control' unless ctrl[:cis]
365
364
  elsif !ctrl[:cis] && !ctrl[:ref]
366
365
  ctrl[:cis] = 'No CIS Control'
367
366
  elsif ctrl[:cis] && ctrl[:ref]
368
- ctrl[:cis] = ctrl[:cis].scan(/^\d+[\.\d+]*/)
367
+ ctrl[:cis] = ctrl[:cis].scan(/^\d+[.\d+]*/)
369
368
  end
370
369
  end
371
370
  end
@@ -15,36 +15,31 @@ module Util
15
15
  clean_special = remove_special(clean_whitespace)
16
16
  clean_no_space = remove_extra_space(clean_special)
17
17
  clean_pagenum = remove_pagenum(clean_no_space)
18
- clean_data = separate_controls(clean_pagenum)
19
- clean_data
18
+ separate_controls(clean_pagenum)
20
19
  end
21
20
 
22
21
  # Removes everything before and after the controls
23
22
  def isolate_controls_data(extracted_data)
24
23
  extracted_data = extracted_data.gsub(/\| P a g e+/, "| P a g e\n")
25
- extracted_data = extracted_data.split("\n").map{ |line| line.strip}.reject { |e| e.to_s.empty? }.join("\n")
24
+ extracted_data = extracted_data.split("\n").map(&:strip).reject { |e| e.to_s.empty? }.join("\n")
26
25
  extracted_data = extracted_data.gsub('???', '')
27
- controls_data = /^1\.1\s*[^\)]*?(?=\)$)(.*\n)*?(?=\s*Appendix:)/.match(extracted_data).to_s
28
- controls_data
26
+ /^1\.1\s*[^)]*?(?=\)$)(.*\n)*?(?=\s*Appendix:)/.match(extracted_data).to_s
29
27
  end
30
28
 
31
29
  # Removes all pagenumbers between the controls
32
30
  def remove_pagenum(extracted_data)
33
31
  clean_pagenum = extracted_data.gsub(/(\d{1,3}\|Page|\d{1,3} \| P a g e)/, '').to_s
34
- clean_pagenum = clean_pagenum.gsub(/(\d{1,3} \| Page)/, '').to_s
35
- clean_pagenum
32
+ clean_pagenum.gsub(/(\d{1,3} \| Page)/, '').to_s
36
33
  end
37
34
 
38
35
  # Removes section headers for each control
39
36
  def remove_section_header(extracted_data)
40
- clean_section_header = extracted_data.gsub(/(?<!•)\s\n\d{1}\s.*(?:.*\n)*?(?=\d\.\d)/, "\n\n").to_s
41
- clean_section_header
37
+ extracted_data.gsub(/(?<!•)\s\n\d{1}\s.*(?:.*\n)*?(?=\d\.\d)/, "\n\n").to_s
42
38
  end
43
39
 
44
40
  # removes newlines between a control
45
41
  def remove_newline_in_controls(extracted_data)
46
- clean_whitespace = extracted_data.gsub(/\s\n.*?(?!d\.)/, "\n").to_s
47
- clean_whitespace
42
+ extracted_data.gsub(/\s\n.*?(?!d\.)/, "\n").to_s
48
43
  end
49
44
 
50
45
  # adds whitespace between different controls
@@ -53,8 +48,8 @@ module Util
53
48
  end
54
49
 
55
50
  def remove_special(extracted_data)
56
- extracted_data = extracted_data.gsub(/[]/, '')
57
- extracted_data.gsub(/[•]/, '')
51
+ extracted_data = extracted_data.gsub(//, '')
52
+ extracted_data.gsub(/•/, '')
58
53
  end
59
54
 
60
55
  def remove_extra_space(extracted_data)
@@ -4,7 +4,7 @@ module Utils
4
4
  DATA_NOT_FOUND_MESSAGE = 'N/A'.freeze
5
5
 
6
6
  # Convert raw Inspec result json into format acceptable for XCCDF transformation.
7
- def parse_data_for_xccdf(json) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
7
+ def parse_data_for_xccdf(json)
8
8
  data = {}
9
9
 
10
10
  controls = []
@@ -29,7 +29,7 @@ module Utils
29
29
  c_data[c_id]['gid'] = control['tags']['gid'] || control['id']
30
30
  c_data[c_id]['gtitle'] = control['tags']['gtitle'] if control['tags']['gtitle'] # Optional attribute
31
31
  c_data[c_id]['gdescription'] = control['tags']['gdescription'] if control['tags']['gdescription'] # Optional attribute
32
- c_data[c_id]['rid'] = control['tags']['rid'] || 'r_' + c_data[c_id]['gid']
32
+ c_data[c_id]['rid'] = control['tags']['rid'] || "r_#{c_data[c_id]['gid']}"
33
33
  c_data[c_id]['rversion'] = control['tags']['rversion'] if control['tags']['rversion'] # Optional attribute
34
34
  c_data[c_id]['rweight'] = control['tags']['rweight'] if control['tags']['rweight'] # Optional attribute where N/A is not schema compliant
35
35
  c_data[c_id]['stig_id'] = control['tags']['stig_id'] || DATA_NOT_FOUND_MESSAGE
@@ -2,7 +2,7 @@ require_relative 'xccdf_score'
2
2
 
3
3
  module Utils
4
4
  # Data conversions for Inspec output into XCCDF format.
5
- class ToXCCDF # rubocop:disable Metrics/ClassLength
5
+ class ToXCCDF
6
6
  # @param attribute [Hash] XCCDF supplemental attributes
7
7
  # @param data [Hash] Converted Inspec output data
8
8
  def initialize(attribute, data)
@@ -53,7 +53,7 @@ module Utils
53
53
  end
54
54
 
55
55
  # Translate join of Inspec results and input attributes to XCCDF Groups
56
- def build_groups # rubocop:disable Metrics/AbcSize
56
+ def build_groups
57
57
  group_array = []
58
58
  @data['controls'].each do |control|
59
59
  group = HappyMapperTools::Benchmark::Group.new
@@ -67,7 +67,7 @@ module Utils
67
67
  group.rule.weight = control['rweight']
68
68
  group.rule.version = control['rversion']
69
69
  group.rule.title = control['title'].tr("\n", ' ') if control['title']
70
- group.rule.description = "<VulnDiscussion>#{control['desc'].tr("\n", ' ')}</VulnDiscussion><FalsePositives></FalsePositives><FalseNegatives></FalseNegatives><Documentable>false</Documentable><Mitigations></Mitigations><SeverityOverrideGuidance></SeverityOverrideGuidance><PotentialImpacts></PotentialImpacts><ThirdPartyTools></ThirdPartyTools><MitigationControl></MitigationControl><Responsibility></Responsibility><IAControls></IAControls>"
70
+ group.rule.description = "<VulnDiscussion>#{control['desc']}</VulnDiscussion><FalsePositives></FalsePositives><FalseNegatives></FalseNegatives><Documentable>false</Documentable><Mitigations></Mitigations><SeverityOverrideGuidance></SeverityOverrideGuidance><PotentialImpacts></PotentialImpacts><ThirdPartyTools></ThirdPartyTools><MitigationControl></MitigationControl><Responsibility></Responsibility><IAControls></IAControls>"
71
71
 
72
72
  if ['reference.dc.publisher', 'reference.dc.title', 'reference.dc.subject', 'reference.dc.type', 'reference.dc.identifier'].any? { |a| @attribute.key?(a) }
73
73
  group.rule.reference = build_rule_reference
@@ -127,7 +127,7 @@ module Utils
127
127
 
128
128
  # Each rule identifier is a different element
129
129
  idents.map do |identifier|
130
- ident = HappyMapperTools::Benchmark::Ident.new identifier
130
+ HappyMapperTools::Benchmark::Ident.new identifier
131
131
  end
132
132
  end
133
133
 
@@ -182,7 +182,7 @@ module Utils
182
182
 
183
183
  # Build out the TestResult given all the control and result data.
184
184
  def populate_results(test_result)
185
- # Note: id is not an XCCDF 1.2 compliant identifier and will need to be updated when that support is added.
185
+ # NOTE: id is not an XCCDF 1.2 compliant identifier and will need to be updated when that support is added.
186
186
  test_result.id = 'result_1'
187
187
  test_result.starttime = run_start_time
188
188
  test_result.endtime = run_end_time
@@ -237,7 +237,7 @@ module Utils
237
237
  end
238
238
 
239
239
  # Combines rule results with the same result into a single rule result.
240
- def combine_results(rule_results) # rubocop:disable Metrics/AbcSize
240
+ def combine_results(rule_results)
241
241
  return rule_results.first if rule_results.size == 1
242
242
 
243
243
  # Can combine, result, idents (duplicate, take first instance), instance - combine into an array removing duplicates
@@ -328,7 +328,7 @@ module Utils
328
328
  # @param one [String] A rule-result status
329
329
  # @param two [String] A rule-result status
330
330
  # @return The result of the AND operation.
331
- def xccdf_and_result(one, two) # rubocop:disable Metrics/CyclomaticComplexity
331
+ def xccdf_and_result(one, two)
332
332
  # From XCCDF specification truth table
333
333
  # P = pass
334
334
  # F = fail
@@ -361,7 +361,7 @@ module Utils
361
361
 
362
362
  message = HappyMapperTools::Benchmark::MessageType.new
363
363
  # Including the code of the check and the resulting message if there is one.
364
- message.message = "#{result['code_desc'] ? result['code_desc'] + "\n\n" : ''}#{result['message'] || result['skip_message']}"
364
+ message.message = "#{result['code_desc'] ? "#{result['code_desc']}\n\n" : ''}#{result['message'] || result['skip_message']}"
365
365
  message.severity = result_message_severity(xccdf_status)
366
366
  message
367
367
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.5
4
+ version: 2.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Thew
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: exe
13
13
  cert_chain: []
14
- date: 2021-05-03 00:00:00.000000000 Z
14
+ date: 2021-05-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: colorize
@@ -149,16 +149,16 @@ dependencies:
149
149
  name: rubocop
150
150
  requirement: !ruby/object:Gem::Requirement
151
151
  requirements:
152
- - - ">="
152
+ - - "~>"
153
153
  - !ruby/object:Gem::Version
154
- version: '0'
154
+ version: '1.11'
155
155
  type: :runtime
156
156
  prerelease: false
157
157
  version_requirements: !ruby/object:Gem::Requirement
158
158
  requirements:
159
- - - ">="
159
+ - - "~>"
160
160
  - !ruby/object:Gem::Version
161
- version: '0'
161
+ version: '1.11'
162
162
  - !ruby/object:Gem::Dependency
163
163
  name: word_wrap
164
164
  requirement: !ruby/object:Gem::Requirement
@@ -257,6 +257,20 @@ dependencies:
257
257
  - - ">="
258
258
  - !ruby/object:Gem::Version
259
259
  version: '0'
260
+ - !ruby/object:Gem::Dependency
261
+ name: rubocop-minitest
262
+ requirement: !ruby/object:Gem::Requirement
263
+ requirements:
264
+ - - "~>"
265
+ - !ruby/object:Gem::Version
266
+ version: 0.12.1
267
+ type: :development
268
+ prerelease: false
269
+ version_requirements: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - "~>"
272
+ - !ruby/object:Gem::Version
273
+ version: 0.12.1
260
274
  - !ruby/object:Gem::Dependency
261
275
  name: simplecov
262
276
  requirement: !ruby/object:Gem::Requirement