openscap_parser 0.1.2 → 1.0.0
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 +4 -4
- data/Dockerfile +15 -0
- data/README.md +32 -10
- data/Rakefile +2 -0
- data/lib/openscap_parser/benchmark.rb +38 -0
- data/lib/openscap_parser/benchmarks.rb +21 -0
- data/lib/openscap_parser/datastream_file.rb +15 -0
- data/lib/openscap_parser/profile.rb +31 -2
- data/lib/openscap_parser/profiles.rb +7 -12
- data/lib/openscap_parser/rule.rb +33 -19
- data/lib/openscap_parser/rule_identifier.rb +14 -0
- data/lib/openscap_parser/rule_reference.rb +14 -0
- data/lib/openscap_parser/rule_references.rb +32 -0
- data/lib/openscap_parser/rule_result.rb +21 -2
- data/lib/openscap_parser/rule_results.rb +21 -0
- data/lib/openscap_parser/rules.rb +9 -8
- data/lib/openscap_parser/tailoring.rb +27 -0
- data/lib/openscap_parser/tailoring_file.rb +13 -0
- data/lib/openscap_parser/tailorings.rb +22 -0
- data/lib/openscap_parser/test_result.rb +60 -0
- data/lib/openscap_parser/test_result_file.rb +9 -0
- data/lib/openscap_parser/test_results.rb +19 -0
- data/lib/openscap_parser/util.rb +10 -0
- data/lib/openscap_parser/version.rb +1 -1
- data/lib/openscap_parser/xml_file.rb +6 -4
- data/lib/openscap_parser/xml_node.rb +32 -0
- data/lib/openscap_parser.rb +13 -36
- data/lib/railtie.rb +15 -0
- data/lib/ssg/downloader.rb +94 -0
- data/lib/ssg/unarchiver.rb +34 -0
- data/lib/ssg.rb +5 -0
- data/lib/tasks/ssg.rake +33 -0
- data/openscap_parser.gemspec +13 -10
- metadata +81 -15
- data/lib/openscap_parser/ds.rb +0 -27
- data/lib/openscap_parser/xml_report.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bbc310b2adc402a398f0b9e8524199a91c06e0b74c2f2757a9fdae292c645c5
|
4
|
+
data.tar.gz: 1d8314602c86e916aff3b19b09d88a858892635beaee738bd79177bf38434abb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2d316e18f0d82b9597b24b306dbae8615a044648102c085170005d1eaa9737263c11ec6a3c4e8af4e355cc59a9e57f78f560fe46f11c0e2cabfd134220153d7
|
7
|
+
data.tar.gz: 59f11993820161a4ece0d23df623ea3412cfb90d1895a5dd7a11fd1fa519e8eb3afbd0812c9a4a78ba1d254c74bcb58578f849ec773ace989ca91b07cffa4fab
|
data/Dockerfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# docker build . -t openscap_parser # build the container image
|
2
|
+
# docker run -itv $PWD:/app:z openscap_parser rake # run tests
|
3
|
+
# docker run -itv $PWD:/app:z openscap_parser pry --gem # console
|
4
|
+
|
5
|
+
FROM ruby:2.5
|
6
|
+
|
7
|
+
RUN gem update bundler
|
8
|
+
|
9
|
+
WORKDIR /app
|
10
|
+
|
11
|
+
COPY . ./
|
12
|
+
|
13
|
+
RUN bundle -j4
|
14
|
+
|
15
|
+
CMD bash
|
data/README.md
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/openscap_parser`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
4
|
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
6
|
-
|
7
5
|
## Installation
|
8
6
|
|
9
7
|
Add this line to your application's Gemfile:
|
@@ -24,16 +22,30 @@ Or install it yourself as:
|
|
24
22
|
|
25
23
|
ARF/XCCDF report goes IN - Ruby hash goes OUT
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
```rb
|
26
|
+
parser = OpenscapParser::Base.new(File.read('rhel7-xccdf_org.ssgproject.content_profile_standard.xml'))
|
27
|
+
parser.host # "rhel7-insights-client.virbr0.akofink-laptop"
|
28
|
+
parser.start_time # <DateTime: 2019-08-08T17:25:50+00:00 ((2458704j,62750s,0n),+0s,2299161j)>
|
29
|
+
parser.end_time # <DateTime: 2019-08-08T17:26:45+00:00 ((2458704j,62805s,0n),+0s,2299161j)>
|
30
|
+
parser.score # 80.833328
|
31
|
+
parser.profiles # {"xccdf_org.ssgproject.content_profile_standard"=>"Standard System Security Profile for Red Hat Enterprise Linux 7"}
|
32
|
+
parser.rules # [#<OpenscapParser::Rule:0x00005576e752db7 ... >, ...]
|
33
|
+
parser.rule_results # [#<OpenscapParser::RuleResult:0x00005576e8022f60 @id="xccdf_org.ssgproject.content_rule_package_rsh_removed", @result="notselected">, ...]
|
34
|
+
|
35
|
+
# and more!
|
36
|
+
```
|
37
|
+
|
38
|
+
### Fetching SCAP Security Guide Content
|
34
39
|
|
35
|
-
|
40
|
+
This gem includes a rake task to sync content from the [ComplianceAsCode project](https://github.com/ComplianceAsCode/content). The following examples show how to download and exract datastream files from the released versions:
|
41
|
+
|
42
|
+
```sh
|
43
|
+
rake ssg:sync DATASTREAMS=latest:fedora # fetch and extract the latest fedora datastream
|
44
|
+
rake ssg:sync DATASTREAMS=v0.1.45:fedora,v0.1.45:firefox # fetch and extract tag v0.1.45 for fedora and firefox datastreams
|
45
|
+
rake ssg:sync_rhel # fetch and extract the latest released versions of the RHEL 6, 7, and 8 datastreams
|
46
|
+
```
|
36
47
|
|
48
|
+
An SSG version will be downloaded only once, even if it is specified multiple times for multiple datastreams.
|
37
49
|
|
38
50
|
## Development
|
39
51
|
|
@@ -41,6 +53,16 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
41
53
|
|
42
54
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
43
55
|
|
56
|
+
### With Docker
|
57
|
+
|
58
|
+
A Dockerfile is provided to allow a containerized development environment:
|
59
|
+
|
60
|
+
```
|
61
|
+
docker build . -t openscap_parser # build the container image
|
62
|
+
docker run -itv $PWD:/app:z openscap_parser rake # run tests
|
63
|
+
docker run -itv $PWD:/app:z openscap_parser pry --gem # console
|
64
|
+
```
|
65
|
+
|
44
66
|
## Contributing
|
45
67
|
|
46
68
|
Bug reports and pull requests are welcome on GitHub at https://github.com/elobato/openscap_parser. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/Rakefile
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/util'
|
4
|
+
require 'openscap_parser/xml_file'
|
5
|
+
require 'openscap_parser/rules'
|
6
|
+
require 'openscap_parser/profiles'
|
7
|
+
require 'openscap_parser/rule_references'
|
8
|
+
|
9
|
+
# Mimics openscap-ruby Benchmark interface
|
10
|
+
module OpenscapParser
|
11
|
+
class Benchmark < XmlNode
|
12
|
+
include OpenscapParser::Util
|
13
|
+
include OpenscapParser::Rules
|
14
|
+
include OpenscapParser::RuleReferences
|
15
|
+
include OpenscapParser::Profiles
|
16
|
+
|
17
|
+
def id
|
18
|
+
@id ||= @parsed_xml['id']
|
19
|
+
end
|
20
|
+
|
21
|
+
def title
|
22
|
+
@title ||= @parsed_xml.xpath('title') &&
|
23
|
+
@parsed_xml.xpath('title').text
|
24
|
+
end
|
25
|
+
|
26
|
+
def description
|
27
|
+
@description ||= newline_to_whitespace(
|
28
|
+
@parsed_xml.xpath('description') &&
|
29
|
+
@parsed_xml.xpath('description').text || ''
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def version
|
34
|
+
@version ||= @parsed_xml.xpath('version') &&
|
35
|
+
@parsed_xml.xpath('version').text
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/benchmark'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
# Methods related to saving profiles and finding which hosts
|
7
|
+
# they belong to
|
8
|
+
module Benchmarks
|
9
|
+
def self.included(base)
|
10
|
+
base.class_eval do
|
11
|
+
def benchmark
|
12
|
+
@benchmark ||= OpenscapParser::Benchmark.new(parsed_xml: benchmark_node)
|
13
|
+
end
|
14
|
+
|
15
|
+
def benchmark_node(xpath = ".//Benchmark")
|
16
|
+
xpath_node(xpath)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'openscap_parser/xml_file'
|
3
|
+
require 'openscap_parser/benchmarks'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
# A class to represent a datastream (-ds.xml) XmlFile
|
7
|
+
class DatastreamFile < XmlFile
|
8
|
+
include OpenscapParser::Benchmarks
|
9
|
+
|
10
|
+
def valid?
|
11
|
+
return true if @parsed_xml.root.name == 'data-stream-collection' && namespaces.keys.include?('xmlns:ds')
|
12
|
+
false
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,6 +1,35 @@
|
|
1
1
|
module OpenscapParser
|
2
|
-
class Profile
|
3
|
-
|
2
|
+
class Profile < XmlNode
|
3
|
+
def id
|
4
|
+
@id ||= @parsed_xml['id']
|
5
|
+
end
|
6
|
+
|
7
|
+
def extends_profile_id
|
8
|
+
@extends ||= @parsed_xml['extends']
|
9
|
+
end
|
10
|
+
|
11
|
+
def title
|
12
|
+
@title ||= @parsed_xml.at_css('title') &&
|
13
|
+
@parsed_xml.at_css('title').text
|
14
|
+
end
|
15
|
+
alias :name :title
|
16
|
+
|
17
|
+
def description
|
18
|
+
@description ||= @parsed_xml.at_css('description') &&
|
19
|
+
@parsed_xml.at_css('description').text
|
20
|
+
end
|
21
|
+
|
22
|
+
def selected_rule_ids
|
23
|
+
@selected_rule_ids ||= @parsed_xml.xpath("select[@selected='true']/@idref") &&
|
24
|
+
@parsed_xml.xpath("select[@selected='true']/@idref").map(&:text)
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_values
|
28
|
+
@set_values ||= @parsed_xml.xpath("set-value") &&
|
29
|
+
@parsed_xml.xpath("set-value").map do |set_value|
|
30
|
+
[set_value['idref'], set_value.text]
|
31
|
+
end.to_h
|
32
|
+
end
|
4
33
|
|
5
34
|
def to_h
|
6
35
|
{ :id => id, :title => title, :description => description }
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'openscap_parser/profile'
|
4
|
+
|
3
5
|
module OpenscapParser
|
4
6
|
# Methods related to saving profiles and finding which hosts
|
5
7
|
# they belong to
|
@@ -7,20 +9,13 @@ module OpenscapParser
|
|
7
9
|
def self.included(base)
|
8
10
|
base.class_eval do
|
9
11
|
def profiles
|
10
|
-
@profiles ||=
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def profile_node
|
18
|
-
@report_xml.at_xpath(".//Profile\
|
19
|
-
[contains('#{test_result_node['id']}', @id)]")
|
12
|
+
@profiles ||= profile_nodes.map do |profile_node|
|
13
|
+
OpenscapParser::Profile.new(parsed_xml: profile_node)
|
14
|
+
end
|
20
15
|
end
|
21
16
|
|
22
|
-
def
|
23
|
-
|
17
|
+
def profile_nodes(xpath = ".//Profile")
|
18
|
+
xpath_nodes(xpath)
|
24
19
|
end
|
25
20
|
end
|
26
21
|
end
|
data/lib/openscap_parser/rule.rb
CHANGED
@@ -1,44 +1,58 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'openscap_parser/rule_identifier'
|
4
|
+
require 'openscap_parser/rule_references'
|
5
|
+
require 'openscap_parser/xml_file'
|
6
|
+
|
3
7
|
# Mimics openscap-ruby Rule interface
|
4
8
|
module OpenscapParser
|
5
|
-
class Rule
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
+
class Rule < XmlNode
|
10
|
+
include OpenscapParser::Util
|
11
|
+
include OpenscapParser::RuleReferences
|
9
12
|
|
10
13
|
def id
|
11
|
-
@id ||=
|
14
|
+
@id ||= parsed_xml['id']
|
15
|
+
end
|
16
|
+
|
17
|
+
def selected
|
18
|
+
@selected ||= parsed_xml['selected']
|
12
19
|
end
|
13
20
|
|
14
21
|
def severity
|
15
|
-
@severity ||=
|
22
|
+
@severity ||= parsed_xml['severity']
|
16
23
|
end
|
17
24
|
|
18
25
|
def title
|
19
|
-
@title ||=
|
26
|
+
@title ||= parsed_xml.at_css('title') &&
|
27
|
+
parsed_xml.at_css('title').text
|
20
28
|
end
|
21
29
|
|
22
30
|
def description
|
23
|
-
@description ||=
|
31
|
+
@description ||= newline_to_whitespace(
|
32
|
+
parsed_xml.at_css('description') &&
|
33
|
+
parsed_xml.at_css('description').text || ''
|
34
|
+
)
|
24
35
|
end
|
25
36
|
|
26
37
|
def rationale
|
27
|
-
@rationale ||=
|
38
|
+
@rationale ||= newline_to_whitespace(
|
39
|
+
parsed_xml.at_css('rationale') &&
|
40
|
+
parsed_xml.at_css('rationale').text || ''
|
41
|
+
)
|
28
42
|
end
|
29
43
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
44
|
+
alias :rule_reference_nodes_old :rule_reference_nodes
|
45
|
+
def rule_reference_nodes(xpath = "reference")
|
46
|
+
rule_reference_nodes_old(xpath)
|
34
47
|
end
|
35
48
|
|
36
|
-
def
|
37
|
-
@identifier ||=
|
38
|
-
|
39
|
-
|
40
|
-
|
49
|
+
def rule_identifier
|
50
|
+
@identifier ||= RuleIdentifier.new(parsed_xml: identifier_node)
|
51
|
+
end
|
52
|
+
alias :identifier :rule_identifier
|
53
|
+
|
54
|
+
def identifier_node
|
55
|
+
@identifier_node ||= parsed_xml.at_xpath('ident')
|
41
56
|
end
|
42
57
|
end
|
43
58
|
end
|
44
|
-
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RuleIdentifier interface as an object
|
4
|
+
module OpenscapParser
|
5
|
+
class RuleIdentifier < XmlNode
|
6
|
+
def label
|
7
|
+
@label ||= @parsed_xml && @parsed_xml.text
|
8
|
+
end
|
9
|
+
|
10
|
+
def system
|
11
|
+
@system ||= @parsed_xml && @parsed_xml['system']
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# RuleReference interface as an object
|
4
|
+
module OpenscapParser
|
5
|
+
class RuleReference < XmlNode
|
6
|
+
def href
|
7
|
+
@href ||= @parsed_xml && @parsed_xml['href']
|
8
|
+
end
|
9
|
+
|
10
|
+
def label
|
11
|
+
@label ||= @parsed_xml && @parsed_xml.text
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/xml_file'
|
4
|
+
require 'openscap_parser/rule_reference'
|
5
|
+
|
6
|
+
module OpenscapParser
|
7
|
+
# Methods related to finding and saving rule references
|
8
|
+
module RuleReferences
|
9
|
+
def self.included(base)
|
10
|
+
base.class_eval do
|
11
|
+
def rule_reference_strings
|
12
|
+
@rule_reference_strings ||= rule_references.map do |rr|
|
13
|
+
"#{rr.label}#{rr.href}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def rule_references
|
18
|
+
@rule_references ||= rule_reference_nodes.map do |node|
|
19
|
+
OpenscapParser::RuleReference.new(parsed_xml: node)
|
20
|
+
end.uniq do |reference|
|
21
|
+
[reference.label, reference.href]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
alias :references :rule_references
|
25
|
+
|
26
|
+
def rule_reference_nodes(xpath = ".//Rule/reference")
|
27
|
+
xpath_nodes(xpath)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,8 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module OpenscapParser
|
4
|
-
class RuleResult
|
5
|
-
|
4
|
+
class RuleResult < XmlNode
|
5
|
+
def id
|
6
|
+
@id ||= parsed_xml['idref']
|
7
|
+
end
|
8
|
+
|
9
|
+
def time
|
10
|
+
@time ||= parsed_xml['time']
|
11
|
+
end
|
12
|
+
|
13
|
+
def severity
|
14
|
+
@severity ||= parsed_xml['severity']
|
15
|
+
end
|
16
|
+
|
17
|
+
def weight
|
18
|
+
@weight ||= parsed_xml['weight']
|
19
|
+
end
|
20
|
+
|
21
|
+
def result
|
22
|
+
@result ||= parsed_xml.at_xpath('result') &&
|
23
|
+
parsed_xml.at_xpath('result').text || ''
|
24
|
+
end
|
6
25
|
end
|
7
26
|
end
|
8
27
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/rule_result'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
module RuleResults
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
def rule_result_nodes
|
10
|
+
@rule_result_nodes ||= parsed_xml.xpath('rule-result')
|
11
|
+
end
|
12
|
+
|
13
|
+
def rule_results
|
14
|
+
rule_result_nodes.map do |node|
|
15
|
+
RuleResult.new(parsed_xml: node)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,21 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'openscap_parser/rule'
|
4
|
+
|
3
5
|
module OpenscapParser
|
4
6
|
# Methods related to parsing rules
|
5
7
|
module Rules
|
6
8
|
def self.included(base)
|
7
9
|
base.class_eval do
|
8
|
-
def rule_ids
|
9
|
-
test_result_node.xpath('.//rule-result/@idref').map(&:value)
|
10
|
-
end
|
11
|
-
|
12
10
|
def rule_objects
|
13
|
-
|
14
|
-
|
15
|
-
@rule_objects ||= @report_xml.search('Rule').map do |rule|
|
16
|
-
Rule.new(rule_xml: rule)
|
11
|
+
@rule_objects ||= rule_nodes.map do |rule_node|
|
12
|
+
Rule.new(parsed_xml: rule_node)
|
17
13
|
end
|
18
14
|
end
|
15
|
+
alias :rules :rule_objects
|
16
|
+
|
17
|
+
def rule_nodes(xpath = ".//Rule")
|
18
|
+
xpath_nodes(xpath)
|
19
|
+
end
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Mimics openscap-ruby Rule interface
|
4
|
+
module OpenscapParser
|
5
|
+
class Tailoring < XmlNode
|
6
|
+
include OpenscapParser::Profiles
|
7
|
+
|
8
|
+
def id
|
9
|
+
@id ||= @parsed_xml['id']
|
10
|
+
end
|
11
|
+
|
12
|
+
def benchmark
|
13
|
+
@benchmark ||= @parsed_xml.at_xpath('benchmark/@href') &&
|
14
|
+
@parsed_xml.at_xpath('benchmark/@href').text
|
15
|
+
end
|
16
|
+
|
17
|
+
def version
|
18
|
+
@version ||= @parsed_xml.at_xpath('version') &&
|
19
|
+
@parsed_xml.at_xpath('version').text
|
20
|
+
end
|
21
|
+
|
22
|
+
def version_time
|
23
|
+
@version_time ||= @parsed_xml.at_xpath('version/@time') &&
|
24
|
+
@parsed_xml.at_xpath('version/@time').text
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenscapParser
|
4
|
+
# A class to represent a tailoring XmlFile
|
5
|
+
class TailoringFile < XmlFile
|
6
|
+
include OpenscapParser::Tailorings
|
7
|
+
|
8
|
+
def valid?
|
9
|
+
return true if @parsed_xml.root.name == 'Tailoring' && namespaces.keys.include?('xmlns:xccdf')
|
10
|
+
false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/tailoring'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
# Methods related to parsing Xccdf Tailoring types
|
7
|
+
module Tailorings
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
def tailoring
|
11
|
+
@tailoring ||= OpenscapParser::Tailoring.new(
|
12
|
+
parsed_xml: tailoring_node
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def tailoring_node(xpath = ".//Tailoring")
|
17
|
+
xpath_node(xpath)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/rule_results'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
class TestResult < XmlNode
|
7
|
+
include OpenscapParser::RuleResults
|
8
|
+
|
9
|
+
def target
|
10
|
+
@target ||= parsed_xml.at_xpath('target') &&
|
11
|
+
parsed_xml.at_xpath('target').text || ''
|
12
|
+
end
|
13
|
+
alias :host :target
|
14
|
+
|
15
|
+
def target_fact_nodes
|
16
|
+
@target_fact_nodes ||= parsed_xml.xpath('target-facts/fact')
|
17
|
+
end
|
18
|
+
|
19
|
+
def platform_nodes
|
20
|
+
@platform_nodes ||= parsed_xml.xpath('platform')
|
21
|
+
end
|
22
|
+
|
23
|
+
def title
|
24
|
+
@title ||= parsed_xml.at_xpath('title') &&
|
25
|
+
parsed_xml.at_xpath('title').text || ''
|
26
|
+
end
|
27
|
+
|
28
|
+
def identity
|
29
|
+
@identity ||= parsed_xml.at_xpath('identity') &&
|
30
|
+
parsed_xml.at_xpath('identity').text || ''
|
31
|
+
end
|
32
|
+
|
33
|
+
def profile_id
|
34
|
+
@profile_id ||= parsed_xml.at_xpath('profile') &&
|
35
|
+
parsed_xml.at_xpath('profile')['idref'] || ''
|
36
|
+
end
|
37
|
+
|
38
|
+
def benchmark_id
|
39
|
+
@benchmark_id ||= parsed_xml.at_xpath('benchmark') &&
|
40
|
+
parsed_xml.at_xpath('benchmark')['id'] || ''
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_value_nodes
|
44
|
+
@set_value_nodes ||= parsed_xml.xpath('set-value')
|
45
|
+
end
|
46
|
+
|
47
|
+
def score
|
48
|
+
@score ||= parsed_xml.at_xpath('score') &&
|
49
|
+
parsed_xml.at_xpath('score').text.to_f
|
50
|
+
end
|
51
|
+
|
52
|
+
def start_time
|
53
|
+
@start_time ||= DateTime.parse(parsed_xml['start-time'])
|
54
|
+
end
|
55
|
+
|
56
|
+
def end_time
|
57
|
+
@end_time ||= DateTime.parse(parsed_xml['end-time'])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/test_result'
|
4
|
+
|
5
|
+
module OpenscapParser
|
6
|
+
module TestResults
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
def test_result
|
10
|
+
TestResult.new(parsed_xml: test_result_node)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_result_node
|
14
|
+
@test_result_node ||= xpath_node('.//TestResult')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'nokogiri'
|
4
|
+
require 'openscap_parser/xml_node'
|
3
5
|
|
4
6
|
module OpenscapParser
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
class XmlFile < XmlNode
|
8
|
+
|
9
|
+
def initialize(raw_xml)
|
10
|
+
parsed_xml(raw_xml)
|
9
11
|
end
|
10
12
|
end
|
11
13
|
end
|
@@ -0,0 +1,32 @@
|
|
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 xpath_node(xpath)
|
23
|
+
parsed_xml && parsed_xml.at_xpath(xpath)
|
24
|
+
end
|
25
|
+
alias :at_xpath :xpath_node
|
26
|
+
|
27
|
+
def xpath_nodes(xpath)
|
28
|
+
parsed_xml && parsed_xml.xpath(xpath) || []
|
29
|
+
end
|
30
|
+
alias :xpath :xpath_nodes
|
31
|
+
end
|
32
|
+
end
|
data/lib/openscap_parser.rb
CHANGED
@@ -1,45 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'openscap_parser/version'
|
4
|
+
require 'openscap_parser/util'
|
5
|
+
require 'openscap_parser/benchmarks'
|
6
|
+
require 'openscap_parser/test_results'
|
2
7
|
require 'openscap_parser/profiles'
|
3
|
-
require 'openscap_parser/rule'
|
4
|
-
require 'openscap_parser/rule_result'
|
5
8
|
require 'openscap_parser/rules'
|
6
|
-
require 'openscap_parser/
|
7
|
-
require 'openscap_parser/
|
8
|
-
|
9
|
+
require 'openscap_parser/rule_results'
|
10
|
+
require 'openscap_parser/tailorings'
|
11
|
+
|
12
|
+
require 'openscap_parser/xml_file'
|
13
|
+
require 'openscap_parser/datastream_file'
|
14
|
+
require 'openscap_parser/test_result_file'
|
15
|
+
require 'openscap_parser/tailoring_file'
|
9
16
|
|
10
17
|
require 'date'
|
18
|
+
require 'railtie' if defined?(Rails)
|
11
19
|
|
12
20
|
module OpenscapParser
|
13
21
|
class Error < StandardError; end
|
14
|
-
|
15
|
-
class Base
|
16
|
-
include OpenscapParser::XMLReport
|
17
|
-
include OpenscapParser::Profiles
|
18
|
-
include OpenscapParser::Rules
|
19
|
-
|
20
|
-
def initialize(report)
|
21
|
-
report_xml(report)
|
22
|
-
end
|
23
|
-
|
24
|
-
def score
|
25
|
-
test_result_node.search('score').text.to_f
|
26
|
-
end
|
27
|
-
|
28
|
-
def start_time
|
29
|
-
@start_time ||= DateTime.parse(test_result_node['start-time'])
|
30
|
-
end
|
31
|
-
|
32
|
-
def end_time
|
33
|
-
@end_time ||= DateTime.parse(test_result_node['end-time'])
|
34
|
-
end
|
35
|
-
|
36
|
-
def rule_results
|
37
|
-
@rule_results ||= test_result_node.search('rule-result').map do |rr|
|
38
|
-
rule_result_oscap = RuleResult.new
|
39
|
-
rule_result_oscap.id = rr.attributes['idref'].value
|
40
|
-
rule_result_oscap.result = rr.search('result').first.text
|
41
|
-
rule_result_oscap
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
22
|
end
|
data/lib/railtie.rb
ADDED
@@ -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,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
|
data/lib/ssg.rb
ADDED
data/lib/tasks/ssg.rake
ADDED
@@ -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
|
data/openscap_parser.gemspec
CHANGED
@@ -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 =
|
7
|
+
spec.name = 'openscap_parser'
|
8
8
|
spec.version = OpenscapParser::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
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
|
13
|
-
|
14
|
-
|
15
|
-
spec.license =
|
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/dLobatog/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 = "
|
36
|
-
spec.executables = spec.files.grep(%r{^
|
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
|
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.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Lobato Garcia
|
8
|
+
- Andrew Kofink
|
8
9
|
autorequire:
|
9
|
-
bindir:
|
10
|
+
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2019-
|
12
|
+
date: 2019-10-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: '
|
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: '
|
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
|
-
|
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
|
-
|
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,17 +146,35 @@ files:
|
|
97
146
|
- bin/console
|
98
147
|
- bin/setup
|
99
148
|
- lib/openscap_parser.rb
|
100
|
-
- lib/openscap_parser/
|
149
|
+
- lib/openscap_parser/benchmark.rb
|
150
|
+
- lib/openscap_parser/benchmarks.rb
|
151
|
+
- lib/openscap_parser/datastream_file.rb
|
101
152
|
- lib/openscap_parser/profile.rb
|
102
153
|
- lib/openscap_parser/profiles.rb
|
103
154
|
- lib/openscap_parser/rule.rb
|
155
|
+
- lib/openscap_parser/rule_identifier.rb
|
156
|
+
- lib/openscap_parser/rule_reference.rb
|
157
|
+
- lib/openscap_parser/rule_references.rb
|
104
158
|
- lib/openscap_parser/rule_result.rb
|
159
|
+
- lib/openscap_parser/rule_results.rb
|
105
160
|
- lib/openscap_parser/rules.rb
|
161
|
+
- lib/openscap_parser/tailoring.rb
|
162
|
+
- lib/openscap_parser/tailoring_file.rb
|
163
|
+
- lib/openscap_parser/tailorings.rb
|
164
|
+
- lib/openscap_parser/test_result.rb
|
165
|
+
- lib/openscap_parser/test_result_file.rb
|
166
|
+
- lib/openscap_parser/test_results.rb
|
167
|
+
- lib/openscap_parser/util.rb
|
106
168
|
- lib/openscap_parser/version.rb
|
107
169
|
- lib/openscap_parser/xml_file.rb
|
108
|
-
- lib/openscap_parser/
|
170
|
+
- lib/openscap_parser/xml_node.rb
|
171
|
+
- lib/railtie.rb
|
172
|
+
- lib/ssg.rb
|
173
|
+
- lib/ssg/downloader.rb
|
174
|
+
- lib/ssg/unarchiver.rb
|
175
|
+
- lib/tasks/ssg.rake
|
109
176
|
- openscap_parser.gemspec
|
110
|
-
homepage:
|
177
|
+
homepage: https://github.com/dLobatog/openscap_parser
|
111
178
|
licenses:
|
112
179
|
- MIT
|
113
180
|
metadata: {}
|
@@ -126,9 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
193
|
- !ruby/object:Gem::Version
|
127
194
|
version: '0'
|
128
195
|
requirements: []
|
129
|
-
|
130
|
-
rubygems_version: 2.7.6
|
196
|
+
rubygems_version: 3.0.6
|
131
197
|
signing_key:
|
132
198
|
specification_version: 4
|
133
|
-
summary: Parse OpenSCAP
|
199
|
+
summary: Parse OpenSCAP content
|
134
200
|
test_files: []
|
data/lib/openscap_parser/ds.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'openscap_parser/xml_file'
|
3
|
-
|
4
|
-
module OpenscapParser
|
5
|
-
class Ds
|
6
|
-
include OpenscapParser::XmlFile
|
7
|
-
|
8
|
-
def initialize(report)
|
9
|
-
report_xml report
|
10
|
-
end
|
11
|
-
|
12
|
-
def profiles
|
13
|
-
@profiles ||= profile_nodes
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def profile_nodes
|
19
|
-
@report_xml.xpath(".//Profile").map do |node|
|
20
|
-
id = node.attribute('id')&.value
|
21
|
-
title = node.at_xpath('./title')&.text
|
22
|
-
description = node.at_xpath('./description')&.text
|
23
|
-
{ :id => id, :title => title, :description => description }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'nokogiri'
|
3
|
-
require 'openscap_parser/xml_file'
|
4
|
-
|
5
|
-
module OpenscapParser
|
6
|
-
# Methods related with parsing directly the XML from the Report
|
7
|
-
# as opposed to using the OpenSCAP APIs
|
8
|
-
module XMLReport
|
9
|
-
def self.included(base)
|
10
|
-
base.class_eval do
|
11
|
-
include OpenscapParser::XmlFile
|
12
|
-
|
13
|
-
def host
|
14
|
-
@report_xml.search('target').text
|
15
|
-
end
|
16
|
-
|
17
|
-
def description
|
18
|
-
@report_xml.search('description').first.text
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|