inspec_tools 2.3.5 → 2.3.6

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