inspec_tools 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +15 -0
  3. data/README.md +373 -0
  4. data/Rakefile +96 -0
  5. data/exe/inspec_tools +14 -0
  6. data/lib/data/README.TXT +25 -0
  7. data/lib/data/U_CCI_List.xml +38403 -0
  8. data/lib/data/attributes.yml +23 -0
  9. data/lib/data/cci2html.xsl +136 -0
  10. data/lib/data/cis_to_nist_critical_controls +0 -0
  11. data/lib/data/cis_to_nist_mapping +0 -0
  12. data/lib/data/mapping.yml +17 -0
  13. data/lib/data/rubocop.yml +4 -0
  14. data/lib/data/stig.csv +1 -0
  15. data/lib/data/threshold.yaml +83 -0
  16. data/lib/exceptions/impact_input_error.rb +6 -0
  17. data/lib/exceptions/severity_input_error.rb +6 -0
  18. data/lib/happy_mapper_tools/benchmark.rb +161 -0
  19. data/lib/happy_mapper_tools/cci_attributes.rb +66 -0
  20. data/lib/happy_mapper_tools/stig_attributes.rb +216 -0
  21. data/lib/happy_mapper_tools/stig_checklist.rb +99 -0
  22. data/lib/inspec_tools.rb +17 -0
  23. data/lib/inspec_tools/ckl.rb +20 -0
  24. data/lib/inspec_tools/cli.rb +31 -0
  25. data/lib/inspec_tools/csv.rb +101 -0
  26. data/lib/inspec_tools/help.rb +9 -0
  27. data/lib/inspec_tools/help/compliance.md +7 -0
  28. data/lib/inspec_tools/help/csv2inspec.md +5 -0
  29. data/lib/inspec_tools/help/inspec2ckl.md +5 -0
  30. data/lib/inspec_tools/help/inspec2csv.md +5 -0
  31. data/lib/inspec_tools/help/inspec2xccdf.md +5 -0
  32. data/lib/inspec_tools/help/pdf2inspec.md +6 -0
  33. data/lib/inspec_tools/help/summary.md +5 -0
  34. data/lib/inspec_tools/help/xccdf2inspec.md +5 -0
  35. data/lib/inspec_tools/inspec.rb +331 -0
  36. data/lib/inspec_tools/pdf.rb +125 -0
  37. data/lib/inspec_tools/plugin.rb +15 -0
  38. data/lib/inspec_tools/plugin_cli.rb +275 -0
  39. data/lib/inspec_tools/summary.rb +126 -0
  40. data/lib/inspec_tools/version.rb +8 -0
  41. data/lib/inspec_tools/xccdf.rb +156 -0
  42. data/lib/inspec_tools/xlsx_tool.rb +135 -0
  43. data/lib/inspec_tools_plugin.rb +7 -0
  44. data/lib/overrides/false_class.rb +5 -0
  45. data/lib/overrides/nil_class.rb +5 -0
  46. data/lib/overrides/object.rb +5 -0
  47. data/lib/overrides/string.rb +5 -0
  48. data/lib/overrides/true_class.rb +5 -0
  49. data/lib/utilities/cis_to_nist.rb +11 -0
  50. data/lib/utilities/csv_util.rb +14 -0
  51. data/lib/utilities/extract_pdf_text.rb +20 -0
  52. data/lib/utilities/inspec_util.rb +441 -0
  53. data/lib/utilities/parser.rb +373 -0
  54. data/lib/utilities/text_cleaner.rb +69 -0
  55. metadata +359 -0
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ require 'happymapper'
4
+ require 'nokogiri'
5
+
6
+ # rubocop:disable Naming/ClassAndModuleCamelCase
7
+
8
+ module HappyMapperTools
9
+ module CCIAttributes
10
+ class Reference
11
+ include HappyMapper
12
+ tag 'reference'
13
+
14
+ attribute :creator, String, tag: 'creator'
15
+ attribute :title, String, tag: 'title'
16
+ attribute :version, String, tag: 'version'
17
+ attribute :location, String, tag: 'location'
18
+ attribute :index, String, tag: 'index'
19
+ end
20
+
21
+ class CCI_Item
22
+ include HappyMapper
23
+ tag 'cci_item'
24
+
25
+ attribute :id, String, tag: 'id'
26
+ element :status, String, tag: 'status'
27
+ element :publishdate, String, tag: 'publishdate'
28
+ element :contributor, String, tag: 'contributor'
29
+ element :definition, String, tag: 'definition'
30
+ element :type, String, tag: 'type'
31
+ has_many :references, Reference, xpath: 'xmlns:references'
32
+ end
33
+
34
+ class Metadata
35
+ include HappyMapper
36
+ tag 'metadata'
37
+
38
+ element :version, String, tag: 'version'
39
+ element :publishdate, String, tag: 'publishdate'
40
+ end
41
+
42
+ class CCI_List
43
+ include HappyMapper
44
+ tag 'cci_list'
45
+
46
+ attribute :xsi, String, tag: 'xsi', namespace: 'xmlns'
47
+ attribute :schemaLocation, String, tag: 'schemaLocation', namespace: 'xmlns'
48
+ has_one :metadata, Metadata, tag: 'metadata'
49
+ has_many :cci_items, CCI_Item, xpath: 'xmlns:cci_items'
50
+
51
+ def fetch_nists(ccis)
52
+ ccis = [ccis] unless ccis.is_a?(Array)
53
+
54
+ # some of the XCCDF files were having CCE- tags show up which
55
+ # we don't support, not sure if this is a typo on their part or
56
+ # we need to see about supporting CCE tags but ... for now
57
+ filtered_ccis = ccis.select { |f| /CCI-/.match(f) }
58
+ filtered_ccis.map do |cci|
59
+ cci_items.find { |item| item.id == cci }.references.max_by(&:version).index
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ # rubocop:enable Naming/ClassAndModuleCamelCase
@@ -0,0 +1,216 @@
1
+ # encoding: utf-8
2
+
3
+ module HappyMapperTools
4
+ module StigAttributes
5
+ require 'happymapper'
6
+ require 'nokogiri'
7
+ require 'colorize'
8
+
9
+ class ContentRef
10
+ include HappyMapper
11
+ tag 'check-content-ref'
12
+ attribute :name, String, tag: 'name'
13
+ attribute :href, String, tag: 'href'
14
+ end
15
+
16
+ class Check
17
+ include HappyMapper
18
+ tag 'check'
19
+
20
+ element :content_ref, ContentRef, tag: 'check-content-ref'
21
+ element :content, String, tag: 'check-content'
22
+ end
23
+
24
+ class Fix
25
+ include HappyMapper
26
+ tag 'fix'
27
+
28
+ attribute :id, String, tag: 'id'
29
+ end
30
+
31
+ class DescriptionDetails
32
+ include HappyMapper
33
+ tag 'Details'
34
+
35
+ element :vuln_discussion, String, tag: 'VulnDiscussion'
36
+ element :false_positives, String, tag: 'FalsePositives'
37
+ element :false_negatives, String, tag: 'FalseNegatives'
38
+ element :documentable, Boolean, tag: 'Documentable'
39
+ element :mitigations, String, tag: 'Mitigations'
40
+ element :severity_override_guidance, String, tag: 'SeverityOverrideGuidance'
41
+ element :security_override_guidance, String, tag: 'SecurityOverrideGuidance'
42
+ element :potential_impacts, String, tag: 'PotentialImpacts'
43
+ element :third_party_tools, String, tag: 'ThirdPartyTools'
44
+ element :mitigation_controls, String, tag: 'MitigationControl'
45
+ element :responsibility, String, tag: 'Responsibility'
46
+ element :ia_controls, String, tag: 'IAControls'
47
+ end
48
+
49
+ class Description
50
+ include HappyMapper
51
+ tag 'description'
52
+
53
+ content :details, DescriptionDetails
54
+
55
+ detail_tags = %i(vuln_discussion false_positives false_negatives documentable
56
+ mitigations severity_override_guidance potential_impacts
57
+ third_party_tools mitigation_controls responsibility ia_controls
58
+ security_override_guidance)
59
+
60
+ detail_tags.each do |name|
61
+ define_method name do
62
+ details.send(name)
63
+ end
64
+ end
65
+ end
66
+
67
+ class ReferenceInfo
68
+ include HappyMapper
69
+ tag 'reference'
70
+
71
+ attribute :href, String, tag: 'href'
72
+ element :dc_publisher, String, tag: 'publisher', namespace: 'dc'
73
+ element :dc_source, String, tag: 'source', namespace: 'dc'
74
+ element :dc_title, String, tag: 'title', namespace: 'dc'
75
+ element :dc_type, String, tag: 'type', namespace: 'dc'
76
+ element :dc_subject, String, tag: 'subject', namespace: 'dc'
77
+ element :dc_identifier, String, tag: 'identifier', namespace: 'dc'
78
+ end
79
+
80
+ class Rule
81
+ include HappyMapper
82
+ tag 'Rule'
83
+
84
+ attribute :id, String, tag: 'id'
85
+ attribute :severity, String, tag: 'severity'
86
+ element :version, String, tag: 'version'
87
+ element :title, String, tag: 'title'
88
+ has_one :description, Description, tag: 'description'
89
+ element :reference, ReferenceInfo, tag: 'reference'
90
+ has_many :idents, String, tag: 'ident'
91
+ element :fixtext, String, tag: 'fixtext'
92
+ has_one :fix, Fix, tag: 'fix'
93
+ has_one :check, Check, tag: 'check'
94
+ end
95
+
96
+ class Group
97
+ include HappyMapper
98
+ tag 'Group'
99
+
100
+ attribute :id, String, tag: 'id'
101
+ element :title, String, tag: 'title'
102
+ element :description, String, tag: 'description'
103
+ has_one :rule, Rule, tag: 'Rule'
104
+ end
105
+
106
+ class ReleaseDate
107
+ include HappyMapper
108
+ tag 'status'
109
+
110
+ attribute :release_date, String, tag: 'date'
111
+ end
112
+
113
+ class Notice
114
+ include HappyMapper
115
+ tag 'notice'
116
+ attribute :id, String, tag: 'id'
117
+ attribute :xml_lang, String, namespace: 'xml', tag: 'lang'
118
+ content :notice, String, tag: 'notice'
119
+ end
120
+
121
+ class Plaintext
122
+ include HappyMapper
123
+ tag 'plain-text'
124
+ attribute :id, String, tag: 'id'
125
+ content :plaintext, String
126
+ end
127
+
128
+ class Benchmark
129
+ include HappyMapper
130
+ tag 'Benchmark'
131
+
132
+ has_one :release_date, ReleaseDate, tag: 'status'
133
+ attribute :id, String, tag: 'id'
134
+ element :status, String, tag: 'status'
135
+ element :title, String, tag: 'title'
136
+ element :description, String, tag: 'description'
137
+ element :version, String, tag: 'version'
138
+ element :notice, Notice, tag: 'notice'
139
+ has_one :reference, ReferenceInfo, tag: 'reference'
140
+ element :plaintext, Plaintext, tag: 'plain-text'
141
+ has_many :group, Group, tag: 'Group'
142
+ end
143
+
144
+ class DescriptionDetailsType
145
+ class << self
146
+ def type
147
+ DescriptionDetails
148
+ end
149
+
150
+ def apply(value)
151
+ value = value.gsub('&', 'and')
152
+ DescriptionDetails.parse "<Details>#{value}</Details>"
153
+ rescue Nokogiri::XML::SyntaxError => e
154
+ if e.to_s.include?('StartTag')
155
+ report_invalid_start_tag(value, e)
156
+ else
157
+ report_disallowed_tags(value)
158
+ end
159
+ end
160
+
161
+ def apply?(value, _convert_to_type)
162
+ value.is_a?(String)
163
+ end
164
+
165
+ private
166
+
167
+ def report_invalid_start_tag(value, error)
168
+ puts error.to_s.colorize(:red)
169
+ column = error.column - '<Details>'.length - 2
170
+ puts "Error around #{value[column-10..column+10].colorize(:light_yellow)}"
171
+ exit(1)
172
+ end
173
+
174
+ def report_disallowed_tags(value)
175
+ allowed_tags = %w{VulnDiscussion FalsePositives FalseNegatives Documentable
176
+ Mitigations SeverityOverrideGuidance PotentialImpacts
177
+ PotentialImpacts ThirdPartyTools MitigationControl
178
+ Responsibility IAControl SecurityOverrideGuidance}
179
+
180
+ tags_found = value.scan(%r{(?<=<)([^\/]*?)((?= \/>)|(?=>))}).to_a
181
+
182
+ tags_found = tags_found.uniq.flatten.reject!(&:empty?)
183
+ offending_tags = tags_found - allowed_tags
184
+
185
+ if offending_tags.count > 1
186
+ puts "\n\nThe non-standard tags: #{offending_tags.to_s.colorize(:red)}" \
187
+ ' were found in: ' + "\n\n#{value}"
188
+ else
189
+ puts "\n\nThe non-standard tag: #{offending_tags.to_s.colorize(:red)}" \
190
+ ' was found in: ' + "\n\n#{value}"
191
+ end
192
+ puts "\n\nPlease:\n "
193
+ option_one = '(1) ' + '(best)'.colorize(:green) + ' Use the ' +
194
+ '`-r --replace-tags array` '.colorize(:light_yellow) +
195
+ '(case sensitive) option to replace the offending tags ' \
196
+ 'during processing of the XCCDF ' \
197
+ 'file to use the ' +
198
+ "`$#{offending_tags[0]}` " .colorize(:light_green) +
199
+ 'syntax in your InSpec profile.'
200
+ option_two = '(2) Update your XCCDF file to *not use* non-standard XCCDF ' \
201
+ 'elements within ' +
202
+ '`&lt;`,`&gt;`, `<` '.colorize(:red) +
203
+ 'or '.colorize(:default) +
204
+ '`>` '.colorize(:red) +
205
+ 'as "placeholders", and use something that doesn\'t confuse ' \
206
+ 'the XML parser, such as : ' +
207
+ "`$#{offending_tags[0]}`" .colorize(:light_green)
208
+ puts option_one
209
+ puts "\n"
210
+ puts option_two
211
+ end
212
+ end
213
+ HappyMapper::SupportedTypes.register DescriptionDetailsType
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,99 @@
1
+ # encoding: utf-8
2
+
3
+ require 'happymapper'
4
+ require 'nokogiri'
5
+
6
+ module HappyMapperTools
7
+ module StigChecklist
8
+ # see: https://github.com/dam5s/happymapper
9
+ # Class Asset maps from the 'Asset' from Checklist XML file using HappyMapper
10
+ class Asset
11
+ include HappyMapper
12
+ tag 'ASSET'
13
+ element :role, String, tag: 'ROLE'
14
+ element :type, String, tag: 'ASSET_TYPE'
15
+ element :host_name, String, tag: 'HOST_NAME'
16
+ element :host_ip, String, tag: 'HOST_IP'
17
+ element :host_mac, String, tag: 'HOST_MAC'
18
+ element :host_guid, String, tag: 'HOST_GUID'
19
+ element :host_fqdn, String, tag: 'HOST_FQDN'
20
+ element :tech_area, String, tag: 'TECH_AREA'
21
+ element :target_key, String, tag: 'TARGET_KEY'
22
+ element :web_or_database, String, tag: 'WEB_OR_DATABASE'
23
+ element :web_db_site, String, tag: 'WEB_DB_SITE'
24
+ element :web_db_instance, String, tag: 'WEB_DB_INSTANCE'
25
+ end
26
+
27
+ # Class Asset maps from the 'SI_DATA' from Checklist XML file using HappyMapper
28
+ class SiData
29
+ include HappyMapper
30
+ tag 'SI_DATA'
31
+ element :name, String, tag: 'SID_NAME'
32
+ element :data, String, tag: 'SID_DATA'
33
+ end
34
+
35
+ # Class Asset maps from the 'STIG_INFO' from Checklist XML file using HappyMapper
36
+ class StigInfo
37
+ include HappyMapper
38
+ tag 'STIG_INFO'
39
+ has_many :si_data, SiData, tag: 'SI_DATA'
40
+ end
41
+
42
+ # Class Asset maps from the 'STIG_DATA' from Checklist XML file using HappyMapper
43
+ class StigData
44
+ include HappyMapper
45
+
46
+ def initialize(attrib = nil, data = nil)
47
+ self.attrib = attrib
48
+ self.data = data
49
+ end
50
+
51
+ tag 'STIG_DATA'
52
+ has_one :attrib, String, tag: 'VULN_ATTRIBUTE'
53
+ has_one :data, String, tag: 'ATTRIBUTE_DATA'
54
+ end
55
+
56
+ # Class Asset maps from the 'VULN' from Checklist XML file using HappyMapper
57
+ class Vuln
58
+ include HappyMapper
59
+ tag 'VULN'
60
+ has_many :stig_data, StigData, tag: 'STIG_DATA'
61
+ has_one :status, String, tag: 'STATUS'
62
+ has_one :finding_details, String, tag: 'FINDING_DETAILS'
63
+ has_one :comments, String, tag: 'COMMENTS'
64
+ has_one :severity_override, String, tag: 'SEVERITY_OVERRIDE'
65
+ has_one :severity_justification, String, tag: 'SEVERITY_JUSTIFICATION'
66
+ end
67
+
68
+ # Class Asset maps from the 'iSTIG' from Checklist XML file using HappyMapper
69
+ class IStig
70
+ include HappyMapper
71
+ tag 'iSTIG'
72
+ has_one :stig_info, StigInfo, tag: 'STIG_INFO'
73
+ has_many :vuln, Vuln, tag: 'VULN'
74
+ end
75
+
76
+ # Class Asset maps from the 'STIGS' from Checklist XML file using HappyMapper
77
+ class Stigs
78
+ include HappyMapper
79
+ tag 'STIGS'
80
+ has_one :istig, IStig, tag: 'iSTIG'
81
+ end
82
+
83
+ class Checklist
84
+ include HappyMapper
85
+ tag 'CHECKLIST'
86
+ has_one :asset, Asset, tag: 'ASSET'
87
+ has_one :stig, Stigs, tag: 'STIGS'
88
+
89
+ def where(attrib, data)
90
+ stig.istig.vuln.each do |vuln|
91
+ if vuln.stig_data.any? { |element| element.attrib == attrib && element.data == data }
92
+ # TODO: Handle multiple objects that match the condition
93
+ return vuln
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.expand_path(__dir__))
2
+ require 'inspec_tools/version'
3
+ require 'rubygems'
4
+
5
+ module InspecTools
6
+ autoload :Help, 'inspec_tools/help'
7
+ autoload :Command, 'inspec_tools/command'
8
+ autoload :CLI, 'inspec_tools/cli'
9
+ autoload :XCCDF, 'inspec_tools/xccdf'
10
+ autoload :PDF, 'inspec_tools/pdf'
11
+ autoload :CSV, 'inspec_tools/csv'
12
+ autoload :CKL, 'inspec_tools/ckl'
13
+ autoload :Inspec, 'inspec_tools/inspec'
14
+ autoload :Summary, 'inspec_tools/summary'
15
+ autoload :Threshold, 'inspec_tools/threshold'
16
+ autoload :XLSXTool, 'inspec_tools/xlsx_tool'
17
+ end
@@ -0,0 +1,20 @@
1
+ module InspecTools
2
+ # Methods for converting from CKL to various formats
3
+ class CKL
4
+ def initialize(ckl)
5
+ @ckl = ckl
6
+ end
7
+
8
+ def to_csv
9
+ # TODO: to_csv
10
+ end
11
+
12
+ def to_xccdf
13
+ # TODO: to_xccdf
14
+ end
15
+
16
+ def to_inspec
17
+ # TODO: to_inspec
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'yaml'
2
+ require 'json'
3
+
4
+ require 'inspec-objects'
5
+ require 'inspec'
6
+ require_relative './plugin_cli.rb'
7
+
8
+ # This tells the ruby cli app to use the same argument parsing as the plugin
9
+ module InspecTools
10
+ CLI = InspecPlugins::InspecToolsPlugin::CliCommand
11
+ end
12
+
13
+ #=====================================================================#
14
+ # Pre-Flight Code
15
+ #=====================================================================#
16
+ help_commands = ['-h', '--help', 'help']
17
+ log_commands = ['-l', '--log-directory']
18
+ version_commands = ['-v', '--version', 'version']
19
+
20
+ #---------------------------------------------------------------------#
21
+ # Adjustments for non-required version commands
22
+ #---------------------------------------------------------------------#
23
+ unless (version_commands & ARGV).empty?
24
+ puts InspecTools::VERSION
25
+ exit 0
26
+ end
27
+
28
+ #---------------------------------------------------------------------#
29
+ # Adjustments for non-required log-directory
30
+ #---------------------------------------------------------------------#
31
+ ARGV.push("--log-directory=#{Dir.pwd}/logs") if (log_commands & ARGV).empty? && (help_commands & ARGV).empty?