smart_proxy_openscap 0.7.5 → 0.8.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/Gemfile +1 -0
- data/lib/smart_proxy_openscap/arf_parser.rb +74 -17
- data/lib/smart_proxy_openscap/content_parser.rb +19 -25
- data/lib/smart_proxy_openscap/openscap_api.rb +5 -12
- data/lib/smart_proxy_openscap/openscap_exception.rb +1 -0
- data/lib/smart_proxy_openscap/profiles_parser.rb +22 -23
- data/lib/smart_proxy_openscap/spool_forwarder.rb +1 -1
- data/lib/smart_proxy_openscap/version.rb +1 -1
- data/smart_proxy_openscap.gemspec +3 -0
- data/test/scap_content_parser_api_test.rb +1 -1
- data/test/script_class_test.rb +0 -58
- metadata +18 -9
- data/bin/smart-proxy-arf-json +0 -7
- data/bin/smart-proxy-scap-profiles +0 -7
- data/bin/smart-proxy-scap-validation +0 -7
- data/lib/smart_proxy_openscap/arf_json.rb +0 -114
- data/lib/smart_proxy_openscap/scap_profiles.rb +0 -52
- data/lib/smart_proxy_openscap/scap_validation.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 385df2070cb04d103c5a01adaafe76ad62e2e11d45b0f9dd8cf9b8ee85a398b8
|
4
|
+
data.tar.gz: e715e8f29c68228523b9960a9940941a911cc6d917d9e422e745994c0976f7b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 544dfb94c425239d852f31d4e32a840b4fc3bc1891cde91d78b24ca43ae8d17220e79dcd1eba96e1f8a147d368795b3f9da8062eac92c62a3a01608d4d0ce3d2
|
7
|
+
data.tar.gz: ad70eb12bc8f21f208de39af555efb0646fa2e56bd1e20bb193d4fae70be78d56b1862047de183322e63c12bd9a04edc86e4304f5c31257a9c431da59c701a26
|
data/Gemfile
CHANGED
@@ -1,38 +1,95 @@
|
|
1
|
-
require '
|
1
|
+
require 'openscap_parser/test_result_file'
|
2
|
+
require 'smart_proxy_openscap/openscap_exception'
|
2
3
|
|
3
4
|
module Proxy
|
4
5
|
module OpenSCAP
|
5
|
-
class ArfParser
|
6
|
+
class ArfParser
|
7
|
+
include Proxy::Log
|
6
8
|
|
7
9
|
def initialize(cname, policy_id, date)
|
8
10
|
@cname = cname
|
9
11
|
@policy_id = policy_id
|
10
12
|
@date = date
|
11
|
-
@script_name = 'smart-proxy-arf-json'
|
12
13
|
end
|
13
14
|
|
14
15
|
def as_json(arf_data)
|
15
|
-
|
16
|
-
|
16
|
+
begin
|
17
|
+
file = Tempfile.new
|
18
|
+
file.write(arf_data)
|
19
|
+
file.rewind
|
20
|
+
decompressed = `bunzip2 -dc #{file.path}`
|
21
|
+
rescue => e
|
22
|
+
logger.error e
|
23
|
+
raise Proxy::OpenSCAP::ReportDecompressError, "Failed to decompress received report bzip, cause: #{e.message}"
|
24
|
+
ensure
|
25
|
+
file.close
|
26
|
+
file.unlink
|
27
|
+
end
|
28
|
+
arf_file = ::OpenscapParser::TestResultFile.new(decompressed)
|
29
|
+
rules = arf_file.benchmark.rules.reduce({}) do |memo, rule|
|
30
|
+
memo[rule.id] = rule
|
31
|
+
memo
|
32
|
+
end
|
17
33
|
|
18
|
-
|
19
|
-
|
34
|
+
arf_digest = Digest::SHA256.hexdigest(arf_data)
|
35
|
+
report = parse_results(rules, arf_file.test_result, arf_digest)
|
36
|
+
report[:openscap_proxy_name] = Proxy::OpenSCAP::Plugin.settings.registered_proxy_name
|
37
|
+
report[:openscap_proxy_url] = Proxy::OpenSCAP::Plugin.settings.registered_proxy_url
|
38
|
+
report.to_json
|
20
39
|
end
|
21
40
|
|
22
|
-
|
23
|
-
|
41
|
+
private
|
42
|
+
|
43
|
+
def parse_results(rules, test_result, arf_digest)
|
44
|
+
results = test_result.rule_results
|
45
|
+
set_values = test_result.set_values
|
46
|
+
report = {}
|
47
|
+
report[:logs] = []
|
48
|
+
passed = 0
|
49
|
+
failed = 0
|
50
|
+
othered = 0
|
51
|
+
results.each do |result|
|
52
|
+
next if result.result == 'notapplicable' || result.result == 'notselected'
|
53
|
+
# get rules and their results
|
54
|
+
rule_data = rules[result.id]
|
55
|
+
report[:logs] << populate_result_data(result.id, result.result, rule_data, set_values)
|
56
|
+
# create metrics for the results
|
57
|
+
case result.result
|
58
|
+
when 'pass', 'fixed'
|
59
|
+
passed += 1
|
60
|
+
when 'fail'
|
61
|
+
failed += 1
|
62
|
+
else
|
63
|
+
othered += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
report[:digest] = arf_digest
|
67
|
+
report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
|
68
|
+
report[:score] = test_result.score
|
69
|
+
report
|
24
70
|
end
|
25
71
|
|
26
|
-
def
|
27
|
-
|
72
|
+
def populate_result_data(result_id, rule_result, rule_data, set_values)
|
73
|
+
log = {}
|
74
|
+
log[:source] = result_id
|
75
|
+
log[:result] = rule_result
|
76
|
+
log[:title] = rule_data.title
|
77
|
+
log[:description] = rule_data.description
|
78
|
+
log[:rationale] = rule_data.rationale
|
79
|
+
log[:references] = rule_data.references.map { |ref| { :href => ref.href, :title => ref.label }}
|
80
|
+
log[:fixes] = populate_fixes rule_data.fixes, set_values
|
81
|
+
log[:severity] = rule_data.severity
|
82
|
+
log
|
28
83
|
end
|
29
84
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
85
|
+
def populate_fixes(fixes, set_values)
|
86
|
+
fixes.map do |fix|
|
87
|
+
{
|
88
|
+
:id => fix.id,
|
89
|
+
:system => fix.system,
|
90
|
+
:full_text => fix.full_text(set_values)
|
91
|
+
}
|
92
|
+
end
|
36
93
|
end
|
37
94
|
end
|
38
95
|
end
|
@@ -1,30 +1,24 @@
|
|
1
|
-
require '
|
1
|
+
require 'openscap_parser/datastream_file'
|
2
|
+
require 'openscap_parser/tailoring_file'
|
2
3
|
|
3
4
|
module Proxy::OpenSCAP
|
4
|
-
class ContentParser
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def failure_message
|
23
|
-
"Failure when running script which validates scap files"
|
24
|
-
end
|
25
|
-
|
26
|
-
def command(in_file, out_file)
|
27
|
-
"#{script_location} #{in_file.path} #{out_file.path} #{@type}"
|
5
|
+
class ContentParser
|
6
|
+
def validate(file_type, scap_file)
|
7
|
+
msg = 'Invalid SCAP file type'
|
8
|
+
errors = []
|
9
|
+
file = nil
|
10
|
+
begin
|
11
|
+
case file_type
|
12
|
+
when 'scap_content'
|
13
|
+
file = ::OpenscapParser::DatastreamFile.new(scap_file)
|
14
|
+
when 'tailoring_file'
|
15
|
+
file = ::OpenscapParser::TailoringFile.new(scap_file)
|
16
|
+
end
|
17
|
+
errors << msg unless file.valid?
|
18
|
+
rescue Nokogiri::XML::SyntaxError => e
|
19
|
+
errors << msg
|
20
|
+
end
|
21
|
+
{ errors: errors }
|
28
22
|
end
|
29
23
|
end
|
30
24
|
end
|
@@ -25,13 +25,6 @@ module Proxy::OpenSCAP
|
|
25
25
|
include ::Proxy::Log
|
26
26
|
helpers ::Proxy::Helpers
|
27
27
|
authorize_with_ssl_client
|
28
|
-
CLIENT_PATHS = Regexp.compile(%r{^(/arf/\d+|/policies/\d+/content/|/policies/\d+/tailoring/)})
|
29
|
-
|
30
|
-
# authorize via trusted hosts but let client paths in without such authorization
|
31
|
-
before do
|
32
|
-
pass if request.path_info =~ CLIENT_PATHS
|
33
|
-
do_authorize_with_trusted_hosts
|
34
|
-
end
|
35
28
|
|
36
29
|
post "/arf/:policy" do
|
37
30
|
# first let's verify client's certificate
|
@@ -52,7 +45,7 @@ module Proxy::OpenSCAP
|
|
52
45
|
logger.error "Failed to save Report in reports directory (#{Proxy::OpenSCAP::Plugin.settings.reportsdir}). Failed with: #{e.message}.
|
53
46
|
Saving file in #{Proxy::OpenSCAP::Plugin.settings.failed_dir}. Please copy manually to #{Proxy::OpenSCAP::Plugin.settings.reportsdir}"
|
54
47
|
{ :result => 'Storage failure on proxy, see proxy logs for details' }.to_json
|
55
|
-
rescue
|
48
|
+
rescue Nokogiri::XML::SyntaxError => e
|
56
49
|
error = "Failed to parse Arf Report, moving to #{Proxy::OpenSCAP::Plugin.settings.corrupted_dir}"
|
57
50
|
logger.error error
|
58
51
|
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.corrupted_dir, cn, policy, date).store_corrupted(request.body.string)
|
@@ -65,7 +58,7 @@ module Proxy::OpenSCAP
|
|
65
58
|
{ :result => msg }.to_json
|
66
59
|
rescue Proxy::OpenSCAP::StoreSpoolError => e
|
67
60
|
log_halt 500, e.message
|
68
|
-
rescue Proxy::OpenSCAP::ReportUploadError => e
|
61
|
+
rescue Proxy::OpenSCAP::ReportUploadError, Proxy::OpenSCAP::ReportDecompressError => e
|
69
62
|
{ :result => e.message }.to_json
|
70
63
|
end
|
71
64
|
end
|
@@ -133,7 +126,7 @@ module Proxy::OpenSCAP
|
|
133
126
|
|
134
127
|
post "/scap_content/policies" do
|
135
128
|
begin
|
136
|
-
Proxy::OpenSCAP::ProfilesParser.new('scap_content'
|
129
|
+
Proxy::OpenSCAP::ProfilesParser.new.profiles('scap_content', request.body.string)
|
137
130
|
rescue *HTTP_ERRORS => e
|
138
131
|
log_halt 500, e.message
|
139
132
|
rescue StandardError => e
|
@@ -143,7 +136,7 @@ module Proxy::OpenSCAP
|
|
143
136
|
|
144
137
|
post "/tailoring_file/profiles" do
|
145
138
|
begin
|
146
|
-
Proxy::OpenSCAP::ProfilesParser.new('tailoring_file'
|
139
|
+
Proxy::OpenSCAP::ProfilesParser.new.profiles('tailoring_file', request.body.string)
|
147
140
|
rescue *HTTP_ERRORS => e
|
148
141
|
log_halt 500, e.message
|
149
142
|
rescue StandardError => e
|
@@ -183,7 +176,7 @@ module Proxy::OpenSCAP
|
|
183
176
|
|
184
177
|
def validate_scap_file(params)
|
185
178
|
begin
|
186
|
-
Proxy::OpenSCAP::ContentParser.new(params[:type]
|
179
|
+
Proxy::OpenSCAP::ContentParser.new.validate(params[:type], request.body.string).to_json
|
187
180
|
rescue *HTTP_ERRORS => e
|
188
181
|
log_halt 500, e.message
|
189
182
|
rescue StandardError => e
|
@@ -1,31 +1,30 @@
|
|
1
|
-
require '
|
1
|
+
require 'openscap_parser/datastream_file'
|
2
|
+
require 'openscap_parser/tailoring_file'
|
2
3
|
|
3
4
|
module Proxy
|
4
5
|
module OpenSCAP
|
5
|
-
class ProfilesParser
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
6
|
+
class ProfilesParser
|
7
|
+
def profiles(file_type, scap_file)
|
8
|
+
profiles = []
|
9
|
+
error_msg = 'Failed to parse profiles'
|
10
|
+
begin
|
11
|
+
case file_type
|
12
|
+
when 'scap_content'
|
13
|
+
profiles = ::OpenscapParser::DatastreamFile.new(scap_file).benchmark.profiles
|
14
|
+
when 'tailoring_file'
|
15
|
+
profiles = ::OpenscapParser::TailoringFile.new(scap_file).tailoring.profiles
|
16
|
+
else
|
17
|
+
raise OpenSCAPException, "Unknown file type, expected 'scap_content' or 'tailoring_file'"
|
18
|
+
end
|
19
|
+
rescue Nokogiri::XML::SyntaxError
|
20
|
+
raise OpenSCAPException, error_msg
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
"Failure when running script which extracts profiles from scap file"
|
25
|
-
end
|
23
|
+
raise OpenSCAPException, error_msg if profiles.empty?
|
26
24
|
|
27
|
-
|
28
|
-
|
25
|
+
result = profiles.reduce({}) do |memo, profile|
|
26
|
+
memo.tap { |acc| acc[profile.id] = profile.title }
|
27
|
+
end.to_json
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
@@ -55,7 +55,7 @@ module Proxy::OpenSCAP
|
|
55
55
|
post_to_foreman = ForemanForwarder.new.post_arf_report(cname, policy_id, date, data, @loaded_settings.timeout)
|
56
56
|
Proxy::OpenSCAP::StorageFS.new(@loaded_settings.reportsdir, cname, post_to_foreman['id'], date).store_archive(data)
|
57
57
|
File.delete arf_file_path
|
58
|
-
rescue Proxy::OpenSCAP::
|
58
|
+
rescue Nokogiri::XML::SyntaxError, Proxy::OpenSCAP::ReportDecompressError => e
|
59
59
|
logger.error "Failed to parse Arf Report at #{arf_file_path}, moving to #{@loaded_settings.corrupted_dir}"
|
60
60
|
|
61
61
|
Proxy::OpenSCAP::StorageFS.new(@loaded_settings.corrupted_dir, cname, policy_id, date).
|
@@ -14,10 +14,13 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
s.files = `git ls-files`.split("\n") - ['.gitignore']
|
16
16
|
s.executables = ['smart-proxy-openscap-send']
|
17
|
+
s.requirements = 'bzip2'
|
17
18
|
|
18
19
|
s.add_development_dependency('rake')
|
19
20
|
s.add_development_dependency('rack-test')
|
20
21
|
s.add_development_dependency('mocha')
|
21
22
|
s.add_development_dependency('webmock')
|
22
23
|
s.add_dependency 'openscap', '~> 0.4.7'
|
24
|
+
|
25
|
+
s.add_dependency 'openscap_parser', '~> 1.0.1'
|
23
26
|
end
|
@@ -37,7 +37,7 @@ class ScapContentParserApiTest < Test::Unit::TestCase
|
|
37
37
|
|
38
38
|
def test_invalid_scap_content_policies
|
39
39
|
post '/scap_content/policies', '<xml>blah</xml>', 'CONTENT_TYPE' => 'text/xml'
|
40
|
-
assert(last_response.body.include?('
|
40
|
+
assert(last_response.body.include?('Failed to parse profiles'))
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_scap_content_validator
|
data/test/script_class_test.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'smart_proxy_openscap/arf_html'
|
3
|
-
require 'smart_proxy_openscap/arf_json'
|
4
3
|
require 'smart_proxy_openscap/policy_guide'
|
5
|
-
require 'smart_proxy_openscap/scap_profiles'
|
6
|
-
require 'smart_proxy_openscap/arf_json'
|
7
|
-
require 'smart_proxy_openscap/scap_validation'
|
8
4
|
|
9
5
|
class ScriptClassTest < Test::Unit::TestCase
|
10
6
|
def test_arf_generate_html
|
@@ -15,17 +11,6 @@ class ScriptClassTest < Test::Unit::TestCase
|
|
15
11
|
end
|
16
12
|
end
|
17
13
|
|
18
|
-
def test_arf_as_json
|
19
|
-
carry_out do |tmp|
|
20
|
-
Proxy::OpenSCAP::ArfJson.new.as_json("#{Dir.getwd}/test/data/arf_report", tmp.path, 'my-proxy', 'http://test-proxy.org')
|
21
|
-
json = read_json tmp
|
22
|
-
refute_empty json['logs']
|
23
|
-
refute_empty json['metrics']
|
24
|
-
refute_empty json['openscap_proxy_name']
|
25
|
-
refute_empty json['openscap_proxy_url']
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
14
|
def test_policy_guide
|
30
15
|
carry_out do |tmp|
|
31
16
|
profile = "xccdf_org.ssgproject.content_profile_rht-ccp"
|
@@ -35,49 +20,6 @@ class ScriptClassTest < Test::Unit::TestCase
|
|
35
20
|
end
|
36
21
|
end
|
37
22
|
|
38
|
-
def test_scap_file_profiles
|
39
|
-
carry_out do |tmp|
|
40
|
-
Proxy::OpenSCAP::ScapProfiles.new.profiles("#{Dir.getwd}/test/data/ssg-rhel7-ds.xml", tmp.path, 'scap_content')
|
41
|
-
profiles = read_json tmp
|
42
|
-
refute_empty profiles
|
43
|
-
assert profiles["xccdf_org.ssgproject.content_profile_standard"]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_tailoring_file_profiles
|
48
|
-
carry_out do |tmp|
|
49
|
-
Proxy::OpenSCAP::ScapProfiles.new.profiles("#{Dir.getwd}/test/data/tailoring.xml", tmp.path, 'tailoring_file')
|
50
|
-
profiles = read_json tmp
|
51
|
-
refute_empty profiles
|
52
|
-
assert profiles["xccdf_org.ssgproject.content_profile_stig-firefox-upstream_customized"]
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def test_arf_json
|
57
|
-
carry_out do |tmp|
|
58
|
-
Proxy::OpenSCAP::ArfJson.new.as_json("#{Dir.getwd}/test/data/arf_report", tmp.path, 'my-proxy', 'http://test-proxy.org')
|
59
|
-
json = read_json tmp
|
60
|
-
refute_empty json['logs']
|
61
|
-
refute_empty json['metrics']
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_scap_content_validation
|
66
|
-
carry_out do |tmp|
|
67
|
-
Proxy::OpenSCAP::ScapValidation.new.validate("#{Dir.getwd}/test/data/ssg-rhel7-ds.xml", tmp.path, 'scap_content')
|
68
|
-
res = read_json tmp
|
69
|
-
assert_empty res['errors']
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_tailoring_file_validation
|
74
|
-
carry_out do |tmp|
|
75
|
-
Proxy::OpenSCAP::ScapValidation.new.validate("#{Dir.getwd}/test/data/tailoring.xml", tmp.path, 'tailoring_file')
|
76
|
-
res = read_json tmp
|
77
|
-
assert_empty res['errors']
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
23
|
private
|
82
24
|
|
83
25
|
def carry_out
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_openscap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Šimon Lukašík
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-
|
13
|
+
date: 2021-03-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -82,6 +82,20 @@ dependencies:
|
|
82
82
|
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: 0.4.7
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: openscap_parser
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 1.0.1
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 1.0.1
|
85
99
|
description: |-
|
86
100
|
A plug-in to the Foreman's smart-proxy which receives
|
87
101
|
bzip2ed ARF files and forwards them to the Foreman.
|
@@ -99,18 +113,14 @@ files:
|
|
99
113
|
- README.md
|
100
114
|
- Rakefile
|
101
115
|
- bin/smart-proxy-arf-html
|
102
|
-
- bin/smart-proxy-arf-json
|
103
116
|
- bin/smart-proxy-openscap-send
|
104
117
|
- bin/smart-proxy-openscap-send-inner
|
105
118
|
- bin/smart-proxy-policy-guide
|
106
|
-
- bin/smart-proxy-scap-profiles
|
107
|
-
- bin/smart-proxy-scap-validation
|
108
119
|
- bundler.d/openscap.rb
|
109
120
|
- extra/rubygem-smart_proxy_openscap.spec
|
110
121
|
- extra/smart-proxy-openscap-send.cron
|
111
122
|
- lib/smart_proxy_openscap.rb
|
112
123
|
- lib/smart_proxy_openscap/arf_html.rb
|
113
|
-
- lib/smart_proxy_openscap/arf_json.rb
|
114
124
|
- lib/smart_proxy_openscap/arf_parser.rb
|
115
125
|
- lib/smart_proxy_openscap/content_parser.rb
|
116
126
|
- lib/smart_proxy_openscap/fetch_file.rb
|
@@ -127,8 +137,6 @@ files:
|
|
127
137
|
- lib/smart_proxy_openscap/policy_guide.rb
|
128
138
|
- lib/smart_proxy_openscap/policy_parser.rb
|
129
139
|
- lib/smart_proxy_openscap/profiles_parser.rb
|
130
|
-
- lib/smart_proxy_openscap/scap_profiles.rb
|
131
|
-
- lib/smart_proxy_openscap/scap_validation.rb
|
132
140
|
- lib/smart_proxy_openscap/shell_wrapper.rb
|
133
141
|
- lib/smart_proxy_openscap/spool_forwarder.rb
|
134
142
|
- lib/smart_proxy_openscap/storage.rb
|
@@ -172,7 +180,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
172
180
|
- - ">="
|
173
181
|
- !ruby/object:Gem::Version
|
174
182
|
version: '0'
|
175
|
-
requirements:
|
183
|
+
requirements:
|
184
|
+
- bzip2
|
176
185
|
rubygems_version: 3.1.2
|
177
186
|
signing_key:
|
178
187
|
specification_version: 4
|
data/bin/smart-proxy-arf-json
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
require 'openscap'
|
3
|
-
require 'openscap/ds/arf'
|
4
|
-
require 'openscap/xccdf/testresult'
|
5
|
-
require 'openscap/xccdf/ruleresult'
|
6
|
-
require 'openscap/xccdf/rule'
|
7
|
-
require 'openscap/xccdf/fix'
|
8
|
-
require 'openscap/xccdf/benchmark'
|
9
|
-
require 'json'
|
10
|
-
require 'digest'
|
11
|
-
|
12
|
-
module Proxy
|
13
|
-
module OpenSCAP
|
14
|
-
class ArfJson
|
15
|
-
def as_json(file_in, file_out, proxy_name, proxy_url)
|
16
|
-
::OpenSCAP.oscap_init
|
17
|
-
arf_digest = Digest::SHA256.hexdigest(File.read(file_in))
|
18
|
-
|
19
|
-
arf = ::OpenSCAP::DS::Arf.new(file_in)
|
20
|
-
test_result = arf.test_result
|
21
|
-
|
22
|
-
results = test_result.rr
|
23
|
-
sds = arf.report_request
|
24
|
-
bench_source = sds.select_checklist!
|
25
|
-
benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
26
|
-
items = benchmark.items
|
27
|
-
|
28
|
-
report = parse_results(items, results, arf_digest)
|
29
|
-
report[:openscap_proxy_name] = proxy_name
|
30
|
-
report[:openscap_proxy_url] = proxy_url
|
31
|
-
|
32
|
-
File.write file_out, report.to_json
|
33
|
-
ensure
|
34
|
-
cleanup test_result, benchmark, sds, arf
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def parse_results(items, results, arf_digest)
|
40
|
-
report = {}
|
41
|
-
report[:logs] = []
|
42
|
-
passed = 0
|
43
|
-
failed = 0
|
44
|
-
othered = 0
|
45
|
-
results.each do |rr_id, result|
|
46
|
-
next if result.result == 'notapplicable' || result.result == 'notselected'
|
47
|
-
# get rules and their results
|
48
|
-
rule_data = items[rr_id]
|
49
|
-
report[:logs] << populate_result_data(rr_id, result.result, rule_data)
|
50
|
-
# create metrics for the results
|
51
|
-
case result.result
|
52
|
-
when 'pass', 'fixed'
|
53
|
-
passed += 1
|
54
|
-
when 'fail'
|
55
|
-
failed += 1
|
56
|
-
else
|
57
|
-
othered += 1
|
58
|
-
end
|
59
|
-
end
|
60
|
-
report[:digest] = arf_digest
|
61
|
-
report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
|
62
|
-
report
|
63
|
-
end
|
64
|
-
|
65
|
-
def populate_result_data(result_id, rule_result, rule_data)
|
66
|
-
log = {}
|
67
|
-
log[:source] = ascii8bit_to_utf8(result_id)
|
68
|
-
log[:result] = ascii8bit_to_utf8(rule_result)
|
69
|
-
log[:title] = ascii8bit_to_utf8(rule_data.title)
|
70
|
-
log[:description] = ascii8bit_to_utf8(rule_data.description)
|
71
|
-
log[:rationale] = ascii8bit_to_utf8(rule_data.rationale)
|
72
|
-
log[:references] = hash_a8b(rule_data.references.map(&:to_hash))
|
73
|
-
log[:fixes] = hash_a8b(rule_data.fixes.map(&:to_hash))
|
74
|
-
log[:severity] = ascii8bit_to_utf8(rule_data.severity)
|
75
|
-
log
|
76
|
-
end
|
77
|
-
|
78
|
-
def cleanup(*args)
|
79
|
-
args.compact.map(&:destroy)
|
80
|
-
::OpenSCAP.oscap_cleanup
|
81
|
-
end
|
82
|
-
|
83
|
-
# Unfortunately openscap in ruby 1.9.3 outputs data in Ascii-8bit.
|
84
|
-
# We transform it to UTF-8 for easier json integration.
|
85
|
-
|
86
|
-
# :invalid ::
|
87
|
-
# If the value is invalid, #encode replaces invalid byte sequences in
|
88
|
-
# +str+ with the replacement character. The default is to raise the
|
89
|
-
# Encoding::InvalidByteSequenceError exception
|
90
|
-
# :undef ::
|
91
|
-
# If the value is undefined, #encode replaces characters which are
|
92
|
-
# undefined in the destination encoding with the replacement character.
|
93
|
-
# The default is to raise the Encoding::UndefinedConversionError.
|
94
|
-
# :replace ::
|
95
|
-
# Sets the replacement string to the given value. The default replacement
|
96
|
-
# string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
|
97
|
-
def ascii8bit_to_utf8(string)
|
98
|
-
return ascii8bit_to_utf8_legacy(string) if RUBY_VERSION.start_with? '1.8'
|
99
|
-
string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
|
100
|
-
end
|
101
|
-
|
102
|
-
# String#encode appeared first in 1.9, so we need a workaround for 1.8
|
103
|
-
def ascii8bit_to_utf8_legacy(string)
|
104
|
-
Iconv.conv('UTF-8//IGNORE', 'UTF-8', string.to_s)
|
105
|
-
end
|
106
|
-
|
107
|
-
def hash_a8b(ary)
|
108
|
-
ary.map do |hash|
|
109
|
-
Hash[hash.map { |key, value| [ascii8bit_to_utf8(key), ascii8bit_to_utf8(value)] }]
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'openscap'
|
2
|
-
require 'openscap/ds/sds'
|
3
|
-
require 'openscap/source'
|
4
|
-
require 'openscap/xccdf/benchmark'
|
5
|
-
require 'openscap/xccdf/tailoring'
|
6
|
-
require 'json'
|
7
|
-
|
8
|
-
module Proxy
|
9
|
-
module OpenSCAP
|
10
|
-
class ScapProfiles
|
11
|
-
def profiles(in_file, out_file, type)
|
12
|
-
::OpenSCAP.oscap_init
|
13
|
-
source = ::OpenSCAP::Source.new(in_file)
|
14
|
-
json = type == 'scap_content' ? scap_content_profiles(source) : tailoring_profiles(source)
|
15
|
-
File.write out_file, json
|
16
|
-
ensure
|
17
|
-
source.destroy if source
|
18
|
-
::OpenSCAP.oscap_cleanup
|
19
|
-
end
|
20
|
-
|
21
|
-
def scap_content_profiles(source)
|
22
|
-
bench = benchmark_profiles source
|
23
|
-
profiles = collect_profiles bench
|
24
|
-
profiles.to_json
|
25
|
-
ensure
|
26
|
-
bench.destroy if bench
|
27
|
-
end
|
28
|
-
|
29
|
-
def tailoring_profiles(source)
|
30
|
-
tailoring = ::OpenSCAP::Xccdf::Tailoring.new(source, nil)
|
31
|
-
profiles = collect_profiles tailoring
|
32
|
-
profiles.to_json
|
33
|
-
ensure
|
34
|
-
tailoring.destroy if tailoring
|
35
|
-
end
|
36
|
-
|
37
|
-
def collect_profiles(profile_source)
|
38
|
-
profile_source.profiles.inject({}) do |memo, (key, profile)|
|
39
|
-
memo.tap { |hash| hash[key] = profile.title.strip }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def benchmark_profiles(source)
|
44
|
-
sds = ::OpenSCAP::DS::Sds.new(source)
|
45
|
-
bench_source = sds.select_checklist!
|
46
|
-
::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
47
|
-
ensure
|
48
|
-
sds.destroy if sds
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'openscap'
|
3
|
-
require 'openscap/source'
|
4
|
-
|
5
|
-
module Proxy
|
6
|
-
module OpenSCAP
|
7
|
-
class ScapValidation
|
8
|
-
def allowed_types
|
9
|
-
{
|
10
|
-
'tailoring_file' => 'XCCDF Tailoring',
|
11
|
-
'scap_content' => 'SCAP Source Datastream'
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def validate(in_file, out_file, type)
|
16
|
-
errors = []
|
17
|
-
::OpenSCAP.oscap_init
|
18
|
-
source = ::OpenSCAP::Source.new(in_file)
|
19
|
-
if source.type != allowed_types[type]
|
20
|
-
errors << "Uploaded file is #{source.type}, unexpected file type"
|
21
|
-
end
|
22
|
-
|
23
|
-
begin
|
24
|
-
source.validate!
|
25
|
-
rescue ::OpenSCAP::OpenSCAPError
|
26
|
-
errors << "Invalid SCAP file type"
|
27
|
-
end
|
28
|
-
File.write out_file, { :errors => errors }.to_json
|
29
|
-
ensure
|
30
|
-
source.destroy if source
|
31
|
-
::OpenSCAP.oscap_cleanup
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|