openscap_parser 0.1.0 → 1.0.2

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.
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: []