inspec_tools 2.1.0 → 2.3.4

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: eee290c08f68bf8bb7894537a1871e0bdf5144266ee50932ea70af3018d5f94e
4
- data.tar.gz: 42ed4ee43680aaceb6fa12c03bfe7c29dd88a33399787b7053510716182c627e
3
+ metadata.gz: 6188a2ff394f6f733d23d032d4919e1f9e5e08267bbce30a2a4725631d5a5a13
4
+ data.tar.gz: 4b3b5fc70d53d4784ef84f881493ca361d998a254c96323e4e1e65c48e7e5630
5
5
  SHA512:
6
- metadata.gz: 43e9b4038ff40f6aee88a16fb63e536b7d3918f15b8a3f9b3fcf87688eb1a167cfd08a7f45cac6fcdd68a2cdd1b5f1ac9ab9a85a2bd42c983b9e963c0b18d96d
7
- data.tar.gz: cd750538af91a05636ad406b80f1adc83bbacfa382143d472bbced9265227f3da245a8a23dd7de0af3636c1650b1c563c6621dc48f524db1550518e7bcc55ae5
6
+ metadata.gz: e537d4749c34eaac49e4c80355250949f02d0db6020596d4c73e1f2995e384742cefc5d72a12fb7c2a159ceca406dbc723aa5d8e36ea8272967e9bd37f49da08
7
+ data.tar.gz: 5a26c4b893a8646ae1e4ae62cd380b0603f0a45b1a88a7234af5a9a8d52a2cc71561d8d0ee784a8bedbbcda7abc26d88b58f999761649bcd29c0adfc464fec78
data/README.md CHANGED
@@ -100,13 +100,15 @@ If the specified threshold is not met, an error code (1) is returned along with
100
100
 
101
101
  The compliance score are rounded down to the nearest whole number. For example a score of 77.3 would be displayed as 77.
102
102
 
103
+ Thresholds provided inline (i.e. `-i`) override thresholds provided by files (i.e. `-f`).
104
+
103
105
  ```
104
106
  USAGE: inspec_tools compliance [OPTIONS] -j <inspec-json> -i <threshold-inline>
105
107
  inspec_tools compliance [OPTIONS] -j <inspec-json> -f <threshold-file>
106
108
  FLAGS:
107
109
  -j --inspec-json <inspec-json> : path to InSpec results Json
108
110
  -i --template-inline <threshold-inline> : inline compliance threshold definition
109
- -f --template-file <threshold-file> : yaml file with compliance threshold definition
111
+ -f --threshold-file <threshold-file> : yaml file with compliance threshold definition
110
112
  Examples:
111
113
 
112
114
  inspec_tools compliance -j examples/sample_json/rhel-simp.json -i '{compliance.min: 80, failed.critical.max: 0, failed.high.max: 0}'
@@ -135,11 +137,11 @@ failed.high.max: 1
135
137
 
136
138
  #### In-Line Examples
137
139
  ```
138
- {compliance: {min: 90}, failed: {critical: {max: 0}, high: {max: 0}}}
140
+ "{compliance: {min: 90}, failed: {critical: {max: 0}, high: {max: 0}}}"
139
141
  ```
140
142
 
141
143
  ```
142
- {compliance.min: 81, failed.critical.max: 0, failed.high.max: 0}
144
+ "{compliance.min: 81, failed.critical.max: 0, failed.high.max: 0}"
143
145
  ```
144
146
 
145
147
  ## summary
@@ -185,12 +187,16 @@ Using additional flags will override the normal output and only display the outp
185
187
 
186
188
  USAGE: inspec_tools summary [OPTIONS] -j <inspec-json>
187
189
 
190
+ Thresholds provided inline (i.e. `-i`) override thresholds provided by files (i.e. `-t`).
191
+
192
+
188
193
  ```
189
194
  FLAGS:
190
- -j --inspec-json <inspec-json> : path to InSpec results JSON
191
- -V --verbose, --no-verbose : print verbose an debug output
192
- -f --json-full, --no-json-full : print the summary STDOUT as JSON
193
- -k --json-counts, --no-json_cou : print the reslut status to STDOUT as JSON
195
+ -j --inspec-json <inspec-json> : path to InSpec results JSON
196
+ -f --json-full, --no-json-full : print the summary STDOUT as JSON
197
+ -k --json-counts, --no-json-counts : print the result status to STDOUT as JSON
198
+ -t, --threshold-file=THRESHOLD_FILE] : path to threshold YAML file
199
+ -i, --threshold-inline=THRESHOLD_INLINE] : string of text representing threshold YAML inline
194
200
 
195
201
  Examples:
196
202
 
@@ -65,6 +65,14 @@ module HappyMapperTools
65
65
  tag 'ident'
66
66
  attribute :system, String, tag: 'system'
67
67
  content :ident, String
68
+ def initialize(ident_str)
69
+ @ident = ident_str
70
+ if ident_str =~ /^(CCI-[0-9]{6})$/
71
+ @system = 'http://cyber.mil/cci'
72
+ else
73
+ @system = 'http://cyber.mil/legacy'
74
+ end
75
+ end
68
76
  end
69
77
 
70
78
  # Class Fixtext maps from the 'fixtext' from Benchmark XML file using HappyMapper
@@ -77,6 +77,15 @@ module HappyMapperTools
77
77
  element :dc_identifier, String, tag: 'identifier', namespace: 'dc'
78
78
  end
79
79
 
80
+ class Ident
81
+ include HappyMapper
82
+ attr_accessor :legacy
83
+ attr_accessor :cci
84
+ tag 'ident'
85
+ attribute :system, String, tag: 'system'
86
+ content :ident, String
87
+ end
88
+
80
89
  class Rule
81
90
  include HappyMapper
82
91
  tag 'Rule'
@@ -87,7 +96,7 @@ module HappyMapperTools
87
96
  element :title, String, tag: 'title'
88
97
  has_one :description, Description, tag: 'description'
89
98
  element :reference, ReferenceInfo, tag: 'reference'
90
- has_many :idents, String, tag: 'ident'
99
+ has_many :idents, Ident, tag: 'ident'
91
100
  element :fixtext, String, tag: 'fixtext'
92
101
  has_one :fix, Fix, tag: 'fix'
93
102
  has_one :check, Check, tag: 'check'
@@ -21,12 +21,12 @@ module InspecTools
21
21
  @csv.shift if @mapping['skip_csv_header']
22
22
  end
23
23
 
24
- def to_inspec
24
+ def to_inspec(control_name_prefix: nil)
25
25
  @controls = []
26
26
  @profile = {}
27
27
  @cci_xml = Utils::CciXml.get_cci_list('U_CCI_List.xml')
28
28
  insert_metadata
29
- parse_controls
29
+ parse_controls(control_name_prefix)
30
30
  @profile['controls'] = @controls
31
31
  @profile['sha256'] = Digest::SHA256.hexdigest(@profile.to_s)
32
32
  @profile
@@ -66,12 +66,12 @@ module InspecTools
66
66
  cell.split("\n").first
67
67
  end
68
68
 
69
- def parse_controls
69
+ def parse_controls(prefix)
70
70
  @csv.each do |row|
71
71
  control = {}
72
- control['id'] = row[@mapping['control.id']] unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
73
- control['title'] = row[@mapping['control.title']] unless @mapping['control.title'].nil? || row[@mapping['control.title']].nil?
74
- control['desc'] = row[@mapping['control.desc']] unless @mapping['control.desc'].nil? || row[@mapping['control.desc']].nil?
72
+ control['id'] = generate_control_id(prefix, row[@mapping['control.id']]) unless @mapping['control.id'].nil? || row[@mapping['control.id']].nil?
73
+ control['title'] = row[@mapping['control.title']] unless @mapping['control.title'].nil? || row[@mapping['control.title']].nil?
74
+ control['desc'] = row[@mapping['control.desc']] unless @mapping['control.desc'].nil? || row[@mapping['control.desc']].nil?
75
75
  control['tags'] = {}
76
76
  cci_number = get_cci_number(row[@mapping['control.tags']['cci']])
77
77
  nist = get_nist_reference(cci_number) unless cci_number.nil?
@@ -90,5 +90,15 @@ module InspecTools
90
90
  @controls << control
91
91
  end
92
92
  end
93
+
94
+ def generate_control_id(prefix, id)
95
+ return id if prefix.nil?
96
+
97
+ "#{prefix}-#{id}"
98
+ end
93
99
  end
94
100
  end
101
+
102
+ # rubocop:enable Metrics/AbcSize
103
+ # rubocop:enable Metrics/PerceivedComplexity
104
+ # rubocop:enable Metrics/CyclomaticComplexity
@@ -1,4 +1,3 @@
1
- require 'yaml'
2
1
  require 'json'
3
2
  require 'roo'
4
3
  require_relative '../utilities/inspec_util'
@@ -13,7 +12,6 @@ module InspecTools
13
12
  autoload :CKL, 'inspec_tools/ckl'
14
13
  autoload :Inspec, 'inspec_tools/inspec'
15
14
  autoload :Summary, 'inspec_tools/summary'
16
- autoload :Threshold, 'inspec_tools/threshold'
17
15
  autoload :XLSXTool, 'inspec_tools/xlsx_tool'
18
16
  autoload :GenerateMap, 'inspec_tools/generate_map'
19
17
  end
@@ -80,10 +78,11 @@ module InspecPlugins
80
78
  option :output, required: false, aliases: '-o', default: 'profile'
81
79
  option :format, required: false, aliases: '-f', enum: %w{ruby hash}, default: 'ruby'
82
80
  option :separate_files, required: false, type: :boolean, default: true, aliases: '-s'
81
+ option :control_name_prefix, required: false, type: :string, aliases: '-p'
83
82
  def csv2inspec
84
83
  csv = CSV.read(options[:csv], encoding: 'ISO8859-1')
85
84
  mapping = YAML.load_file(options[:mapping])
86
- profile = InspecTools::CSVTool.new(csv, mapping, options[:csv].split('/')[-1].split('.')[0], options[:verbose]).to_inspec
85
+ profile = InspecTools::CSVTool.new(csv, mapping, options[:csv].split('/')[-1].split('.')[0], options[:verbose]).to_inspec(control_name_prefix: options[:control_name_prefix])
87
86
  Utils::InspecUtil.unpack_inspec_json(options[:output], profile, options[:separate_files], options[:format])
88
87
  end
89
88
 
@@ -189,26 +188,14 @@ module InspecPlugins
189
188
  desc 'summary', 'summary parses an inspec results json to create a summary json'
190
189
  long_desc InspecTools::Help.text(:summary)
191
190
  option :inspec_json, required: true, aliases: '-j'
192
- option :verbose, type: :boolean, aliases: '-V'
193
191
  option :json_full, type: :boolean, required: false, aliases: '-f'
194
192
  option :json_counts, type: :boolean, required: false, aliases: '-k'
193
+ option :threshold_file, required: false, aliases: '-t'
194
+ option :threshold_inline, required: false, aliases: '-i'
195
195
 
196
196
  def summary
197
- summary = InspecTools::Summary.new(File.read(options[:inspec_json])).to_summary
198
-
199
- unless options.include?('json_full') || options.include?('json_counts')
200
- puts "\nOverall compliance: #{summary[:compliance]}%\n\n"
201
- summary[:status].keys.each do |category|
202
- puts category
203
- summary[:status][category].keys.each do |impact|
204
- puts "\t#{impact} : #{summary[:status][category][impact]}"
205
- end
206
- end
207
- end
208
-
209
- json_summary = summary.to_json
210
- puts json_summary if options[:json_full]
211
- puts summary[:status].to_json if options[:json_counts]
197
+ summary = InspecTools::Summary.new(options: options)
198
+ summary.output_summary
212
199
  end
213
200
 
214
201
  desc 'compliance', 'compliance parses an inspec results json to check if the compliance level meets a specified threshold'
@@ -216,17 +203,10 @@ module InspecPlugins
216
203
  option :inspec_json, required: true, aliases: '-j'
217
204
  option :threshold_file, required: false, aliases: '-f'
218
205
  option :threshold_inline, required: false, aliases: '-i'
219
- option :verbose, type: :boolean, aliases: '-V'
220
206
 
221
207
  def compliance
222
- if options[:threshold_file].nil? && options[:threshold_inline].nil?
223
- puts 'Please provide threshold as a yaml file or inline yaml'
224
- exit(1)
225
- end
226
- threshold = YAML.load_file(options[:threshold_file]) unless options[:threshold_file].nil?
227
- threshold = YAML.safe_load(options[:threshold_inline]) unless options[:threshold_inline].nil?
228
- compliance = InspecTools::Summary.new(File.read(options[:inspec_json])).threshold(threshold)
229
- compliance ? exit(0) : exit(1)
208
+ compliance = InspecTools::Summary.new(options: options)
209
+ compliance.results_meet_threshold? ? exit(0) : exit(1)
230
210
  end
231
211
  end
232
212
  end
@@ -2,8 +2,6 @@ require 'json'
2
2
  require 'yaml'
3
3
  require_relative '../utilities/inspec_util'
4
4
 
5
- # rubocop:disable Metrics/AbcSize
6
-
7
5
  # Impact Definitions
8
6
  CRITICAL = 0.9
9
7
  HIGH = 0.7
@@ -16,48 +14,118 @@ TALLYS = %i(total critical high medium low).freeze
16
14
  THRESHOLD_TEMPLATE = File.expand_path('../data/threshold.yaml', File.dirname(__FILE__))
17
15
 
18
16
  module InspecTools
17
+ # rubocop:disable Metrics/ClassLength
19
18
  class Summary
20
- def initialize(inspec_json)
21
- @json = JSON.parse(inspec_json)
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
26
+
27
+ def initialize(**options)
28
+ options = options[:options]
29
+ @json = JSON.parse(File.read(options[:inspec_json]))
30
+ @json_full = false || options[:json_full]
31
+ @json_counts = false || options[:json_counts]
32
+ @threshold = parse_threshold(options[:threshold_inline], options[:threshold_file])
33
+ @threshold_provided = options[:threshold_inline] || options[:threshold_file]
34
+ @summary = compute_summary
22
35
  end
23
36
 
24
- def to_summary
25
- @data = Utils::InspecUtil.parse_data_for_ckl(@json)
26
- @summary = {}
27
- @data.keys.each do |control_id|
28
- current_control = @data[control_id]
29
- current_control[:compliance_status] = Utils::InspecUtil.control_status(current_control, true)
30
- current_control[:finding_details] = Utils::InspecUtil.control_finding_details(current_control, current_control[:compliance_status])
37
+ def output_summary
38
+ unless @json_full || @json_counts
39
+ puts "\nThreshold compliance: #{@threshold['compliance.min']}%"
40
+ puts "\nOverall compliance: #{@summary[:compliance]}%\n\n"
41
+ @summary[:status].keys.each do |category|
42
+ puts category
43
+ @summary[:status][category].keys.each do |impact|
44
+ puts "\t#{impact} : #{@summary[:status][category][impact]}"
45
+ end
46
+ end
31
47
  end
32
- compute_summary
33
- @summary
48
+
49
+ puts @summary.to_json if @json_full
50
+ puts @summary[:status].to_json if @json_counts
34
51
  end
35
52
 
36
- def threshold(threshold = nil)
37
- @summary = to_summary
38
- @threshold = Utils::InspecUtil.to_dotted_hash(YAML.load_file(THRESHOLD_TEMPLATE))
39
- parse_threshold(Utils::InspecUtil.to_dotted_hash(threshold))
40
- threshold_compliance
53
+ def results_meet_threshold?
54
+ raise 'Please provide threshold as a yaml file or inline yaml' unless @threshold_provided
55
+
56
+ compliance = true
57
+ failure = []
58
+ failure << check_max_compliance(@threshold['compliance.max'], @summary[:compliance], '', 'compliance')
59
+ failure << check_min_compliance(@threshold['compliance.min'], @summary[:compliance], '', 'compliance')
60
+
61
+ BUCKETS.each do |bucket|
62
+ TALLYS.each do |tally|
63
+ failure << check_min_compliance(@threshold["#{bucket}.#{tally}.min"], @summary[:status][bucket][tally], bucket, tally)
64
+ failure << check_max_compliance(@threshold["#{bucket}.#{tally}.max"], @summary[:status][bucket][tally], bucket, tally)
65
+ end
66
+ end
67
+
68
+ failure.reject!(&:nil?)
69
+ compliance = false if failure.length.positive?
70
+ output(compliance, failure)
71
+ compliance
41
72
  end
42
73
 
43
74
  private
44
75
 
76
+ def check_min_compliance(min, data, bucket, tally)
77
+ expected_to_string(bucket, tally, 'min', min, data) if min != -1 and data < min
78
+ end
79
+
80
+ def check_max_compliance(max, data, bucket, tally)
81
+ expected_to_string(bucket, tally, 'max', max, data) if max != -1 and data > max
82
+ end
83
+
84
+ def output(passed_threshold, what_failed)
85
+ if passed_threshold
86
+ puts "Overall compliance threshold of #{@threshold['compliance.min']}\% met. Current compliance at #{@summary[:compliance]}\%"
87
+ else
88
+ puts 'Compliance threshold was not met: '
89
+ puts what_failed.join("\n")
90
+ end
91
+ end
92
+
93
+ def expected_to_string(bucket, tally, maxmin, value, got)
94
+ return "Expected #{bucket}.#{tally}.#{maxmin}:#{value} got:#{got}" unless bucket.empty? || bucket.nil?
95
+
96
+ "Expected #{tally}.#{maxmin}:#{value}\% got:#{got}\%"
97
+ end
98
+
99
+ def parse_threshold(threshold_inline, threshold_file)
100
+ threshold = Utils::InspecUtil.to_dotted_hash(YAML.load_file(THRESHOLD_TEMPLATE))
101
+ threshold.merge!(Utils::InspecUtil.to_dotted_hash(YAML.load_file(threshold_file))) if threshold_file
102
+ threshold.merge!(Utils::InspecUtil.to_dotted_hash(YAML.safe_load(threshold_inline))) if threshold_inline
103
+ threshold
104
+ end
105
+
45
106
  def compute_summary
46
- @summary[:buckets] = {}
47
- @summary[:buckets][:failed] = select_by_status(@data, 'Open')
48
- @summary[:buckets][:passed] = select_by_status(@data, 'NotAFinding')
49
- @summary[:buckets][:no_impact] = select_by_status(@data, 'Not_Applicable')
50
- @summary[:buckets][:skipped] = select_by_status(@data, 'Not_Reviewed')
51
- @summary[:buckets][:error] = select_by_status(@data, 'Profile_Error')
52
-
53
- @summary[:status] = {}
54
- @summary[:status][:failed] = tally_by_impact(@summary[:buckets][:failed])
55
- @summary[:status][:passed] = tally_by_impact(@summary[:buckets][:passed])
56
- @summary[:status][:no_impact] = tally_by_impact(@summary[:buckets][:no_impact])
57
- @summary[:status][:skipped] = tally_by_impact(@summary[:buckets][:skipped])
58
- @summary[:status][:error] = tally_by_impact(@summary[:buckets][:error])
59
-
60
- @summary[:compliance] = compute_compliance
107
+ data = Utils::InspecUtil.parse_data_for_ckl(@json)
108
+
109
+ data.keys.each do |control_id|
110
+ current_control = data[control_id]
111
+ current_control[:compliance_status] = Utils::InspecUtil.control_status(current_control, true)
112
+ current_control[:finding_details] = Utils::InspecUtil.control_finding_details(current_control, current_control[:compliance_status])
113
+ end
114
+
115
+ summary = {}
116
+ summary[:buckets] = {}
117
+ summary[:buckets][:failed] = select_by_status(data, 'Open')
118
+ summary[:buckets][:passed] = select_by_status(data, 'NotAFinding')
119
+ summary[:buckets][:no_impact] = select_by_status(data, 'Not_Applicable')
120
+ summary[:buckets][:skipped] = select_by_status(data, 'Not_Reviewed')
121
+ summary[:buckets][:error] = select_by_status(data, 'Profile_Error')
122
+
123
+ summary[:status] = {}
124
+ %i(failed passed no_impact skipped error).each do |key|
125
+ summary[:status][key] = tally_by_impact(summary[:buckets][key])
126
+ end
127
+ summary[:compliance] = compute_compliance(summary)
128
+ summary
61
129
  end
62
130
 
63
131
  def select_by_impact(controls, impact)
@@ -78,49 +146,13 @@ module InspecTools
78
146
  tally
79
147
  end
80
148
 
81
- def compute_compliance
82
- (@summary[:status][:passed][:total]*100.0/
83
- (@summary[:status][:passed][:total]+
84
- @summary[:status][:failed][:total]+
85
- @summary[:status][:skipped][:total]+
86
- @summary[:status][:error][:total])).floor
87
- end
88
-
89
- def threshold_compliance
90
- compliance = true
91
- failure = []
92
- max = @threshold['compliance.max']
93
- min = @threshold['compliance.min']
94
- if max != -1 and @summary[:compliance] > max
95
- compliance = false
96
- failure << "Expected compliance.max:#{max} got:#{@summary[:compliance]}"
97
- end
98
- if min != -1 and @summary[:compliance] < min
99
- compliance = false
100
- failure << "Expected compliance.min:#{min} got:#{@summary[:compliance]}"
101
- end
102
- status = @summary[:status]
103
- BUCKETS.each do |bucket|
104
- TALLYS.each do |tally|
105
- max = @threshold["#{bucket}.#{tally}.max"]
106
- min = @threshold["#{bucket}.#{tally}.min"]
107
- if max != -1 and status[bucket][tally] > max
108
- compliance = false
109
- failure << "Expected #{bucket}.#{tally}.max:#{max} got:#{status[bucket][tally]}"
110
- end
111
- if min != -1 and status[bucket][tally] < min
112
- compliance = false
113
- failure << "Expected #{bucket}.#{tally}.min:#{min} got:#{status[bucket][tally]}"
114
- end
115
- end
116
- end
117
- puts failure.join("\n") unless compliance
118
- puts 'Compliance threshold met' if compliance
119
- compliance
120
- end
121
-
122
- def parse_threshold(new_threshold)
123
- @threshold.merge!(new_threshold)
149
+ def compute_compliance(summary)
150
+ (summary[:status][:passed][:total]*100.0/
151
+ (summary[:status][:passed][:total]+
152
+ summary[:status][:failed][:total]+
153
+ summary[:status][:skipped][:total]+
154
+ summary[:status][:error][:total])).floor
124
155
  end
125
156
  end
157
+ # rubocop:enable Metrics/ClassLength
126
158
  end
@@ -17,7 +17,7 @@ module InspecTools
17
17
  @xccdf = replace_tags_in_xccdf(replace_tags, @xccdf) unless replace_tags.nil?
18
18
  cci_list_path = File.join(File.dirname(__FILE__), '../data/U_CCI_List.xml')
19
19
  @cci_items = HappyMapperTools::CCIAttributes::CCI_List.parse(File.read(cci_list_path))
20
- # @cci_items = HappyMapperTools::CCIAttributes::CCI_List.parse(File.read('./data/U_CCI_List.xml'))
20
+ register_after_parse_callbacks
21
21
  @benchmark = HappyMapperTools::StigAttributes::Benchmark.parse(@xccdf)
22
22
  end
23
23
 
@@ -89,6 +89,14 @@ module InspecTools
89
89
 
90
90
  private
91
91
 
92
+ def register_after_parse_callbacks
93
+ # Determine if the parsed Ident is refrencing a legacy ID number.
94
+ HappyMapperTools::StigAttributes::Ident.after_parse do |object|
95
+ object.cci = object.system.eql?('http://cyber.mil/cci')
96
+ object.legacy = !object.cci
97
+ end
98
+ end
99
+
92
100
  def replace_tags_in_xccdf(replace_tags, xccdf_xml)
93
101
  replace_tags.each do |tag|
94
102
  xccdf_xml = xccdf_xml.gsub(/(&lt;|<)#{tag}(&gt;|>)/, "$#{tag}")
@@ -133,8 +141,9 @@ module InspecTools
133
141
  control['tags']['rid'] = group.rule.id
134
142
  control['tags']['stig_id'] = group.rule.version
135
143
  control['tags']['fix_id'] = group.rule.fix.id
136
- control['tags']['cci'] = group.rule.idents
137
- control['tags']['nist'] = @cci_items.fetch_nists(group.rule.idents)
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 }
146
+ control['tags']['nist'] = @cci_items.fetch_nists(control['tags']['cci'])
138
147
  control['tags']['false_negatives'] = group.rule.description.false_negatives if group.rule.description.false_negatives != ''
139
148
  control['tags']['false_positives'] = group.rule.description.false_positives if group.rule.description.false_positives != ''
140
149
  control['tags']['documentable'] = group.rule.description.documentable if group.rule.description.documentable != ''
@@ -48,8 +48,8 @@ module Utils
48
48
  end
49
49
 
50
50
  if control['descriptions'].respond_to?(:find)
51
- data[c_id][:check_content] = control['descriptions'].find { |c| c['label'] == 'fix' }&.dig('data')
52
- data[c_id][:fix_text] = control['descriptions'].find { |c| c['label'] == 'check' }&.dig('data')
51
+ data[c_id][:check_content] = control['descriptions'].find { |c| c['label'] == 'check' }&.dig('data')
52
+ data[c_id][:fix_text] = control['descriptions'].find { |c| c['label'] == 'fix' }&.dig('data')
53
53
  end
54
54
 
55
55
  data[c_id][:impact] = control['impact'].to_s unless control['impact'].nil?
@@ -99,12 +99,12 @@ module Utils
99
99
  status_list = control[:status].uniq
100
100
  if control[:impact].to_f.zero?
101
101
  'Not_Applicable'
102
+ elsif (status_list.include?('error') || status_list.empty?) && for_summary
103
+ 'Profile_Error'
102
104
  elsif status_list.include?('failed')
103
105
  'Open'
104
106
  elsif status_list.include?('passed')
105
107
  'NotAFinding'
106
- elsif status_list.include?('error') && for_summary
107
- 'Profile_Error'
108
108
  else
109
109
  # profile skipped or profile error
110
110
  'Not_Reviewed'
@@ -246,6 +246,7 @@ module Utils
246
246
  control.add_tag(::Inspec::Object::Tag.new('stig_id', json_control['tags']['stig_id']))
247
247
  control.add_tag(::Inspec::Object::Tag.new('fix_id', json_control['tags']['fix_id']))
248
248
  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']))
249
250
  control.add_tag(::Inspec::Object::Tag.new('nist', json_control['tags']['nist']))
250
251
  control.add_tag(::Inspec::Object::Tag.new('cis_level', json_control['tags']['cis_level'])) unless json_control['tags']['cis_level'].blank?
251
252
  control.add_tag(::Inspec::Object::Tag.new('cis_controls', json_control['tags']['cis_controls'])) unless json_control['tags']['cis_controls'].blank?
@@ -34,6 +34,7 @@ module Utils
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
36
36
  c_data[c_id]['cci'] = control['tags']['cci'] if control['tags']['cci'] # Optional attribute
37
+ c_data[c_id]['legacy'] = control['tags']['legacy'] if control['tags']['legacy'] # Optional attribute
37
38
  c_data[c_id]['nist'] = control['tags']['nist'] || ['unmapped']
38
39
  c_data[c_id]['check'] = control['tags']['check'] || DATA_NOT_FOUND_MESSAGE
39
40
  c_data[c_id]['checkref'] = control['tags']['checkref'] || DATA_NOT_FOUND_MESSAGE
@@ -74,6 +74,7 @@ module Utils
74
74
  end
75
75
 
76
76
  group.rule.ident = build_rule_idents(control['cci']) if control['cci']
77
+ group.rule.ident += build_rule_idents(control['legacy']) if control['legacy']
77
78
 
78
79
  group.rule.fixtext = HappyMapperTools::Benchmark::Fixtext.new
79
80
  group.rule.fixtext.fixref = control['fix_id']
@@ -126,10 +127,7 @@ module Utils
126
127
 
127
128
  # Each rule identifier is a different element
128
129
  idents.map do |identifier|
129
- ident = HappyMapperTools::Benchmark::Ident.new
130
- ident.system = 'https://public.cyber.mil/stigs/cci/'
131
- ident.ident = identifier
132
- ident
130
+ ident = HappyMapperTools::Benchmark::Ident.new identifier
133
131
  end
134
132
  end
135
133
 
@@ -227,6 +225,7 @@ module Utils
227
225
  rule_result.instance = result['code_desc']
228
226
 
229
227
  rule_result.ident = build_rule_idents(control['cci']) if control['cci']
228
+ rule_result.ident += build_rule_idents(control['legacy']) if control['legacy']
230
229
 
231
230
  # Fix information is only necessary when there are failed tests
232
231
  rule_result.fix = build_rule_fix(control['fix_id']) if control['fix_id'] && result_status == 'fail'
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.1.0
4
+ version: 2.3.4
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: 2020-08-11 00:00:00.000000000 Z
14
+ date: 2021-04-16 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: colorize
@@ -201,20 +201,6 @@ dependencies:
201
201
  - - ">="
202
202
  - !ruby/object:Gem::Version
203
203
  version: '0'
204
- - !ruby/object:Gem::Dependency
205
- name: codeclimate-test-reporter
206
- requirement: !ruby/object:Gem::Requirement
207
- requirements:
208
- - - ">="
209
- - !ruby/object:Gem::Version
210
- version: '0'
211
- type: :development
212
- prerelease: false
213
- version_requirements: !ruby/object:Gem::Requirement
214
- requirements:
215
- - - ">="
216
- - !ruby/object:Gem::Version
217
- version: '0'
218
204
  - !ruby/object:Gem::Dependency
219
205
  name: minitest
220
206
  requirement: !ruby/object:Gem::Requirement
@@ -363,7 +349,7 @@ require_paths:
363
349
  - lib
364
350
  required_ruby_version: !ruby/object:Gem::Requirement
365
351
  requirements:
366
- - - "~>"
352
+ - - ">="
367
353
  - !ruby/object:Gem::Version
368
354
  version: '2.5'
369
355
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -372,7 +358,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
372
358
  - !ruby/object:Gem::Version
373
359
  version: '0'
374
360
  requirements: []
375
- rubygems_version: 3.1.2
361
+ rubygems_version: 3.2.15
376
362
  signing_key:
377
363
  specification_version: 4
378
364
  summary: Converter utils for Inspec