openscap_parser 0.1.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Dockerfile +15 -0
  4. data/README.md +32 -10
  5. data/Rakefile +2 -0
  6. data/lib/openscap_parser.rb +14 -35
  7. data/lib/openscap_parser/benchmark.rb +38 -0
  8. data/lib/openscap_parser/benchmarks.rb +21 -0
  9. data/lib/openscap_parser/datastream_file.rb +15 -0
  10. data/lib/openscap_parser/fix.rb +55 -0
  11. data/lib/openscap_parser/fixes.rb +21 -0
  12. data/lib/openscap_parser/oval_report.rb +24 -0
  13. data/lib/openscap_parser/profile.rb +31 -0
  14. data/lib/openscap_parser/profiles.rb +7 -12
  15. data/lib/openscap_parser/rule.rb +51 -10
  16. data/lib/openscap_parser/rule_identifier.rb +21 -0
  17. data/lib/openscap_parser/rule_reference.rb +14 -0
  18. data/lib/openscap_parser/rule_references.rb +32 -0
  19. data/lib/openscap_parser/rule_result.rb +31 -2
  20. data/lib/openscap_parser/rule_results.rb +21 -0
  21. data/lib/openscap_parser/rules.rb +9 -8
  22. data/lib/openscap_parser/selectors.rb +9 -0
  23. data/lib/openscap_parser/set_value.rb +18 -0
  24. data/lib/openscap_parser/set_values.rb +21 -0
  25. data/lib/openscap_parser/sub.rb +18 -0
  26. data/lib/openscap_parser/subs.rb +38 -0
  27. data/lib/openscap_parser/tailoring.rb +27 -0
  28. data/lib/openscap_parser/tailoring_file.rb +15 -0
  29. data/lib/openscap_parser/tailorings.rb +22 -0
  30. data/lib/openscap_parser/test_result.rb +62 -0
  31. data/lib/openscap_parser/test_result_file.rb +12 -0
  32. data/lib/openscap_parser/test_results.rb +19 -0
  33. data/lib/openscap_parser/util.rb +10 -0
  34. data/lib/openscap_parser/version.rb +1 -1
  35. data/lib/openscap_parser/xml_file.rb +13 -0
  36. data/lib/openscap_parser/xml_node.rb +36 -0
  37. data/lib/oval/definition.rb +47 -0
  38. data/lib/oval/definition_result.rb +17 -0
  39. data/lib/oval/reference.rb +21 -0
  40. data/lib/railtie.rb +15 -0
  41. data/lib/ssg.rb +5 -0
  42. data/lib/ssg/downloader.rb +94 -0
  43. data/lib/ssg/unarchiver.rb +34 -0
  44. data/lib/tasks/ssg.rake +33 -0
  45. data/openscap_parser.gemspec +13 -10
  46. metadata +94 -14
  47. data/lib/openscap_parser/xml_report.rb +0 -25
@@ -1,3 +1,3 @@
1
1
  module OpenscapParser
2
- VERSION = "0.1.0"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'openscap_parser/xml_node'
5
+
6
+ module OpenscapParser
7
+ class XmlFile < XmlNode
8
+
9
+ def initialize(raw_xml)
10
+ parsed_xml(raw_xml)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+
5
+ module OpenscapParser
6
+ # Represents a generic Xml node with parsed_xml
7
+ class XmlNode
8
+ attr_reader :namespaces
9
+
10
+ def initialize(parsed_xml: nil)
11
+ @parsed_xml = parsed_xml
12
+ end
13
+
14
+ def parsed_xml(report_contents = '')
15
+ return @parsed_xml if @parsed_xml
16
+ @parsed_xml = ::Nokogiri::XML.parse(
17
+ report_contents, nil, nil, Nokogiri::XML::ParseOptions.new.norecover)
18
+ @namespaces = @parsed_xml.namespaces.clone
19
+ @parsed_xml.remove_namespaces!
20
+ end
21
+
22
+ def text
23
+ @parsed_xml.text
24
+ end
25
+
26
+ def xpath_node(xpath)
27
+ parsed_xml && parsed_xml.at_xpath(xpath)
28
+ end
29
+ alias :at_xpath :xpath_node
30
+
31
+ def xpath_nodes(xpath)
32
+ parsed_xml && parsed_xml.xpath(xpath) || []
33
+ end
34
+ alias :xpath :xpath_nodes
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ require "openscap_parser/xml_node"
2
+ require "oval/reference"
3
+
4
+ module Oval
5
+ class Definition < ::OpenscapParser::XmlNode
6
+ def id
7
+ @id ||= @parsed_xml['id']
8
+ end
9
+
10
+ def version
11
+ @version ||= @parsed_xml['version']
12
+ end
13
+
14
+ def klass
15
+ @klass ||= @parsed_xml['class']
16
+ end
17
+
18
+ def title
19
+ xml = @parsed_xml.at_xpath("./metadata/title")
20
+ @title ||= xml && xml.text
21
+ end
22
+
23
+ def description
24
+ xml = @parsed_xml.at_xpath("./metadata/description")
25
+ @description ||= xml && xml.text
26
+ end
27
+
28
+ def reference_nodes
29
+ @reference_nodes ||= @parsed_xml.xpath("./metadata/reference")
30
+ end
31
+
32
+ def references
33
+ @references ||= reference_nodes.map { |node| Reference.new parsed_xml: node }
34
+ end
35
+
36
+ def to_h
37
+ {
38
+ :id => id,
39
+ :version => version,
40
+ :klass => klass,
41
+ :title => title,
42
+ :description => description,
43
+ :references => references.map(&:to_h)
44
+ }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,17 @@
1
+ require 'openscap_parser/xml_node'
2
+
3
+ module Oval
4
+ class DefinitionResult < ::OpenscapParser::XmlNode
5
+ def definition_id
6
+ @definition_id ||= @parsed_xml['definition_id']
7
+ end
8
+
9
+ def result
10
+ @result ||= @parsed_xml['result']
11
+ end
12
+
13
+ def to_h
14
+ { :id => definition_id, :result => result }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ require "openscap_parser/xml_node"
2
+
3
+ module Oval
4
+ class Reference < ::OpenscapParser::XmlNode
5
+ def source
6
+ @source ||= @parsed_xml['source']
7
+ end
8
+
9
+ def ref_id
10
+ @ref_id ||= @parsed_xml['ref_id']
11
+ end
12
+
13
+ def ref_url
14
+ @ref_url ||= @parsed_xml['ref_url']
15
+ end
16
+
17
+ def to_h
18
+ { :source => source, :ref_id => ref_id, :ref_url => ref_url }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # lib/railtie.rb
2
+ require 'openscap_parser'
3
+
4
+ if defined?(Rails)
5
+ module OpenscapParser
6
+ class Railtie < Rails::Railtie
7
+ railtie_name :openscap_parser
8
+
9
+ rake_tasks do
10
+ path = File.expand_path(__dir__)
11
+ Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ require 'ssg/downloader'
2
+ require 'ssg/unarchiver'
3
+
4
+ module Ssg
5
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ module Ssg
7
+ # Downloads SCAP datastreams from the SCAP Security Guide
8
+ # https://github.com/ComplianceAsCode/content
9
+ class Downloader
10
+ RELEASES_API = 'https://api.github.com/repos'\
11
+ '/ComplianceAsCode/content/releases/'
12
+ SSG_DS_REGEX = /scap-security-guide-(\d+\.)+zip$/
13
+
14
+ def initialize(version = 'latest')
15
+ @release_uri = URI(
16
+ "#{RELEASES_API}#{'tags/' unless version[/^latest$/]}#{version}"
17
+ )
18
+ end
19
+
20
+ def self.download!(versions = [])
21
+ versions.uniq.map do |version|
22
+ [version, new(version).fetch_datastream_file]
23
+ end.to_h
24
+ end
25
+
26
+ def fetch_datastream_file
27
+ puts "Fetching #{datastream_filename}"
28
+ get_chunked(datastream_uri)
29
+
30
+ datastream_filename
31
+ end
32
+
33
+ private
34
+
35
+ def datastream_uri
36
+ @datastream_uri ||= URI(
37
+ download_urls.find { |url| url[SSG_DS_REGEX] }
38
+ )
39
+ end
40
+
41
+ def download_urls
42
+ get_json(@release_uri).dig('assets').map do |asset|
43
+ asset.dig('browser_download_url')
44
+ end
45
+ end
46
+
47
+ def fetch(request, &block)
48
+ Net::HTTP.start(
49
+ request.uri.host, request.uri.port,
50
+ use_ssl: request.uri.scheme['https']
51
+ ) do |http|
52
+ check_response(http.request(request, &block), &block)
53
+ end
54
+ end
55
+
56
+ def get(uri, &block)
57
+ fetch(Net::HTTP::Get.new(uri), &block)
58
+ end
59
+
60
+ def head(uri, &block)
61
+ fetch(Net::HTTP::Head.new(uri), &block)
62
+ end
63
+
64
+ def check_response(response, &block)
65
+ case response
66
+ when Net::HTTPSuccess
67
+ response
68
+ when Net::HTTPRedirection
69
+ get(URI(response['location']), &block)
70
+ else
71
+ response.value
72
+ end
73
+ end
74
+
75
+ def get_chunked(uri, filename: datastream_filename)
76
+ head(uri) do |response|
77
+ next unless Net::HTTPSuccess === response
78
+ open(filename, 'wb') do |file|
79
+ response.read_body do |chunk|
80
+ file.write(chunk)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def datastream_filename
87
+ datastream_uri.path.split('/').last[SSG_DS_REGEX]
88
+ end
89
+
90
+ def get_json(uri)
91
+ JSON.parse(get(uri).body)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,34 @@
1
+ module Ssg
2
+ class Unarchiver
3
+ UNZIP_CMD = ['unzip', '-o']
4
+
5
+ def initialize(ds_zip_filename, datastreams)
6
+ @ds_zip_filename = ds_zip_filename
7
+ @datastreams = datastreams
8
+ end
9
+
10
+ def self.unarchive!(ds_zip_filenames, datastreams)
11
+ ds_zip_filenames.map do |version, ds_zip_filename|
12
+ new(ds_zip_filename, [datastreams[version]].flatten).datastream_files
13
+ end
14
+ end
15
+
16
+ def datastream_files
17
+ datastream_filenames if system(
18
+ *UNZIP_CMD, @ds_zip_filename, *datastream_filenames
19
+ )
20
+ end
21
+
22
+ private
23
+
24
+ def datastream_filenames
25
+ @datastreams.map do |datastream|
26
+ "#{datastream_dir}/ssg-#{datastream}-ds.xml"
27
+ end
28
+ end
29
+
30
+ def datastream_dir
31
+ @ds_zip_filename.split('.')[0...-1].join('.')
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ desc 'Import or update SCAP datastreams from the SCAP Security Guide'
2
+ namespace :ssg do
3
+ desc 'Import or update SCAP datastreams for RHEL 6, 7, and 8'
4
+ task :sync_rhel do |task|
5
+ RHEL_SSG_VERSIONS = (
6
+ 'v0.1.28:rhel6,'\
7
+ 'v0.1.43:rhel7,'\
8
+ 'v0.1.42:rhel8'
9
+ )
10
+
11
+ ENV['DATASTREAMS'] = RHEL_SSG_VERSIONS
12
+ Rake::Task['ssg:sync'].invoke
13
+ end
14
+
15
+ desc 'Import or update SCAP datastreams, '\
16
+ 'provided as a comma separated list: '\
17
+ '`rake ssg:sync DATASTREAMS=v0.1.43:rhel7,latest:fedora`'
18
+ task :sync do |task|
19
+ DATASTREAMS = ENV.fetch('DATASTREAMS', '').split(',')
20
+ .inject({}) do |datastreams, arg|
21
+ version, datastream = arg.split(':')
22
+ datastreams[version] = (datastreams[version] || []).push(datastream)
23
+
24
+ datastreams
25
+ end
26
+
27
+ require 'ssg'
28
+
29
+ ds_zip_filenames = Ssg::Downloader.download!(DATASTREAMS.keys)
30
+ DATASTREAM_FILENAMES = Ssg::Unarchiver.
31
+ unarchive!(ds_zip_filenames, DATASTREAMS)
32
+ end
33
+ end
@@ -4,15 +4,15 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require "openscap_parser/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "openscap_parser"
7
+ spec.name = 'openscap_parser'
8
8
  spec.version = OpenscapParser::VERSION
9
- spec.authors = ["Daniel Lobato Garcia"]
10
- spec.email = ["me@daniellobato.me"]
9
+ spec.authors = ['Daniel Lobato Garcia', 'Andrew Kofink']
10
+ spec.email = ['me@daniellobato.me', 'ajkofink@gmail.com']
11
11
 
12
- spec.summary = %q{Parse OpenSCAP reports}
13
- # spec.description = %q{TODO: Write a longer description or delete this line.}
14
- # spec.homepage = "TODO: Put your gem's website or public repo URL here."
15
- spec.license = "MIT"
12
+ spec.summary = %q{Parse OpenSCAP content}
13
+ spec.description = %q{This gem is a Ruby interface into SCAP content. It can parse SCAP datastream files (i.e. ssg-rhel7-ds.xml), scan result files output by oscap eval, and tailoring files.}
14
+ spec.homepage = 'https://github.com/OpenSCAP/openscap_parser'
15
+ spec.license = 'MIT'
16
16
 
17
17
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
18
  # to allow pushing to a single host or delete this section to allow pushing to any host.
@@ -32,13 +32,16 @@ Gem::Specification.new do |spec|
32
32
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
33
33
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
34
  end
35
- spec.bindir = "exe"
36
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.bindir = "bin"
36
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ["lib"]
38
38
 
39
- spec.add_dependency 'nokogiri'
39
+ spec.add_dependency "nokogiri", "~> 1.6"
40
40
  spec.add_development_dependency "bundler", "~> 2.0"
41
41
  spec.add_development_dependency "rake", "~> 10.0"
42
42
  spec.add_development_dependency "minitest", "~> 5.0"
43
+ spec.add_development_dependency "mocha", "~> 1.0"
43
44
  spec.add_development_dependency "shoulda-context"
45
+ spec.add_development_dependency "pry"
46
+ spec.add_development_dependency "pry-byebug"
44
47
  end
metadata CHANGED
@@ -1,29 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openscap_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Lobato Garcia
8
+ - Andrew Kofink
8
9
  autorequire:
9
- bindir: exe
10
+ bindir: bin
10
11
  cert_chain: []
11
- date: 2019-06-05 00:00:00.000000000 Z
12
+ date: 2020-12-15 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: nokogiri
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ">="
18
+ - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '0'
20
+ version: '1.6'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ">="
25
+ - - "~>"
25
26
  - !ruby/object:Gem::Version
26
- version: '0'
27
+ version: '1.6'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: bundler
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +67,20 @@ dependencies:
66
67
  - - "~>"
67
68
  - !ruby/object:Gem::Version
68
69
  version: '5.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: mocha
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '1.0'
69
84
  - !ruby/object:Gem::Dependency
70
85
  name: shoulda-context
71
86
  requirement: !ruby/object:Gem::Requirement
@@ -80,16 +95,50 @@ dependencies:
80
95
  - - ">="
81
96
  - !ruby/object:Gem::Version
82
97
  version: '0'
83
- description:
98
+ - !ruby/object:Gem::Dependency
99
+ name: pry
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: pry-byebug
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ description: This gem is a Ruby interface into SCAP content. It can parse SCAP datastream
127
+ files (i.e. ssg-rhel7-ds.xml), scan result files output by oscap eval, and tailoring
128
+ files.
84
129
  email:
85
130
  - me@daniellobato.me
86
- executables: []
131
+ - ajkofink@gmail.com
132
+ executables:
133
+ - console
134
+ - setup
87
135
  extensions: []
88
136
  extra_rdoc_files: []
89
137
  files:
90
138
  - ".gitignore"
91
139
  - ".travis.yml"
92
140
  - CODE_OF_CONDUCT.md
141
+ - Dockerfile
93
142
  - Gemfile
94
143
  - LICENSE.txt
95
144
  - README.md
@@ -97,14 +146,46 @@ files:
97
146
  - bin/console
98
147
  - bin/setup
99
148
  - lib/openscap_parser.rb
149
+ - lib/openscap_parser/benchmark.rb
150
+ - lib/openscap_parser/benchmarks.rb
151
+ - lib/openscap_parser/datastream_file.rb
152
+ - lib/openscap_parser/fix.rb
153
+ - lib/openscap_parser/fixes.rb
154
+ - lib/openscap_parser/oval_report.rb
155
+ - lib/openscap_parser/profile.rb
100
156
  - lib/openscap_parser/profiles.rb
101
157
  - lib/openscap_parser/rule.rb
158
+ - lib/openscap_parser/rule_identifier.rb
159
+ - lib/openscap_parser/rule_reference.rb
160
+ - lib/openscap_parser/rule_references.rb
102
161
  - lib/openscap_parser/rule_result.rb
162
+ - lib/openscap_parser/rule_results.rb
103
163
  - lib/openscap_parser/rules.rb
164
+ - lib/openscap_parser/selectors.rb
165
+ - lib/openscap_parser/set_value.rb
166
+ - lib/openscap_parser/set_values.rb
167
+ - lib/openscap_parser/sub.rb
168
+ - lib/openscap_parser/subs.rb
169
+ - lib/openscap_parser/tailoring.rb
170
+ - lib/openscap_parser/tailoring_file.rb
171
+ - lib/openscap_parser/tailorings.rb
172
+ - lib/openscap_parser/test_result.rb
173
+ - lib/openscap_parser/test_result_file.rb
174
+ - lib/openscap_parser/test_results.rb
175
+ - lib/openscap_parser/util.rb
104
176
  - lib/openscap_parser/version.rb
105
- - lib/openscap_parser/xml_report.rb
177
+ - lib/openscap_parser/xml_file.rb
178
+ - lib/openscap_parser/xml_node.rb
179
+ - lib/oval/definition.rb
180
+ - lib/oval/definition_result.rb
181
+ - lib/oval/reference.rb
182
+ - lib/railtie.rb
183
+ - lib/ssg.rb
184
+ - lib/ssg/downloader.rb
185
+ - lib/ssg/unarchiver.rb
186
+ - lib/tasks/ssg.rake
106
187
  - openscap_parser.gemspec
107
- homepage:
188
+ homepage: https://github.com/OpenSCAP/openscap_parser
108
189
  licenses:
109
190
  - MIT
110
191
  metadata: {}
@@ -123,9 +204,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
204
  - !ruby/object:Gem::Version
124
205
  version: '0'
125
206
  requirements: []
126
- rubyforge_project:
127
- rubygems_version: 2.7.6
207
+ rubygems_version: 3.1.4
128
208
  signing_key:
129
209
  specification_version: 4
130
- summary: Parse OpenSCAP reports
210
+ summary: Parse OpenSCAP content
131
211
  test_files: []