smart_proxy_openscap 0.6.5 → 0.6.6
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/bin/smart-proxy-arf-html +7 -0
- data/bin/{smart-proxy-parse-arf → smart-proxy-arf-json} +2 -2
- data/bin/smart-proxy-policy-guide +7 -0
- data/bin/smart-proxy-scap-profiles +7 -0
- data/bin/smart-proxy-scap-validation +7 -0
- data/lib/smart_proxy_openscap/arf_html.rb +21 -0
- data/lib/smart_proxy_openscap/arf_json.rb +111 -0
- data/lib/smart_proxy_openscap/arf_parser.rb +17 -93
- data/lib/smart_proxy_openscap/content_parser.rb +30 -0
- data/lib/smart_proxy_openscap/foreman_forwarder.rb +1 -2
- data/lib/smart_proxy_openscap/openscap_api.rb +8 -19
- data/lib/smart_proxy_openscap/openscap_html_generator.rb +38 -0
- data/lib/smart_proxy_openscap/openscap_lib.rb +5 -3
- data/lib/smart_proxy_openscap/openscap_plugin.rb +0 -6
- data/lib/smart_proxy_openscap/policy_guide.rb +23 -0
- data/lib/smart_proxy_openscap/policy_parser.rb +33 -0
- data/lib/smart_proxy_openscap/profiles_parser.rb +32 -0
- data/lib/smart_proxy_openscap/scap_profiles.rb +49 -0
- data/lib/smart_proxy_openscap/scap_validation.rb +34 -0
- data/lib/smart_proxy_openscap/shell_wrapper.rb +77 -0
- data/lib/smart_proxy_openscap/spool_forwarder.rb +1 -1
- data/lib/smart_proxy_openscap/storage.rb +0 -2
- data/lib/smart_proxy_openscap/storage_fs.rb +11 -16
- data/lib/smart_proxy_openscap/version.rb +1 -1
- data/test/get_report_xml_html_test.rb +0 -2
- data/test/scap_content_parser_api_test.rb +1 -1
- data/test/script_class_test.rb +94 -0
- data/test/test_helper.rb +1 -0
- metadata +20 -10
- data/lib/smart_proxy_openscap/openscap_content_parser.rb +0 -77
- data/lib/smart_proxy_openscap/openscap_initializer.rb +0 -21
- data/lib/smart_proxy_openscap/openscap_report_parser.rb +0 -48
- data/lib/smart_proxy_openscap/plugin_configuration.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29317c06a0e14367b00b34438becb736c48a3963
|
4
|
+
data.tar.gz: 43c1ab223379188365b5d2c739fbc4a8f047dfc2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3951f55a4c38a11d354d8e31d3b2e8d400923893238bd312bf272c4cd39df1caad03206ebbcd41edd625358be8cad1added830238899304045e0e546f0edac02
|
7
|
+
data.tar.gz: 4063007b806d2f811f8ca556fedb7450a78468b40f8e02968a0779fe0055005f4ce8690982daee8c0665f51e78cb24804b30ebf71b2d97c784451f71d1f4d9f1
|
@@ -2,6 +2,6 @@
|
|
2
2
|
path = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib')
|
3
3
|
$:.unshift(path) if File.exist? path
|
4
4
|
|
5
|
-
require 'smart_proxy_openscap/
|
5
|
+
require 'smart_proxy_openscap/arf_json'
|
6
6
|
|
7
|
-
Proxy::OpenSCAP::
|
7
|
+
Proxy::OpenSCAP::ArfJson.new.as_json ARGV[0], ARGV[1]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'openscap'
|
2
|
+
require 'openscap/ds/arf'
|
3
|
+
|
4
|
+
module Proxy
|
5
|
+
module OpenSCAP
|
6
|
+
class ArfHtml
|
7
|
+
def generate_html(file_in, file_out)
|
8
|
+
::OpenSCAP.oscap_init
|
9
|
+
File.write file_out, get_arf_html(file_in)
|
10
|
+
::OpenSCAP.oscap_cleanup
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_arf_html(file_in)
|
14
|
+
arf_object = ::OpenSCAP::DS::Arf.new(file_in)
|
15
|
+
# @TODO: Drop this when support for 1.8.7 ends
|
16
|
+
return arf_object.html if RUBY_VERSION.start_with? '1.8'
|
17
|
+
arf_object.html.force_encoding('UTF-8')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,111 @@
|
|
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)
|
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
|
+
File.write file_out, report.to_json
|
30
|
+
ensure
|
31
|
+
cleanup test_result, benchmark, sds, arf
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def parse_results(items, results, arf_digest)
|
37
|
+
report = {}
|
38
|
+
report[:logs] = []
|
39
|
+
passed = 0
|
40
|
+
failed = 0
|
41
|
+
othered = 0
|
42
|
+
results.each do |rr_id, result|
|
43
|
+
next if result.result == 'notapplicable' || result.result == 'notselected'
|
44
|
+
# get rules and their results
|
45
|
+
rule_data = items[rr_id]
|
46
|
+
report[:logs] << populate_result_data(rr_id, result.result, rule_data)
|
47
|
+
# create metrics for the results
|
48
|
+
case result.result
|
49
|
+
when 'pass', 'fixed'
|
50
|
+
passed += 1
|
51
|
+
when 'fail'
|
52
|
+
failed += 1
|
53
|
+
else
|
54
|
+
othered += 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
report[:digest] = arf_digest
|
58
|
+
report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
|
59
|
+
report
|
60
|
+
end
|
61
|
+
|
62
|
+
def populate_result_data(result_id, rule_result, rule_data)
|
63
|
+
log = {}
|
64
|
+
log[:source] = ascii8bit_to_utf8(result_id)
|
65
|
+
log[:result] = ascii8bit_to_utf8(rule_result)
|
66
|
+
log[:title] = ascii8bit_to_utf8(rule_data.title)
|
67
|
+
log[:description] = ascii8bit_to_utf8(rule_data.description)
|
68
|
+
log[:rationale] = ascii8bit_to_utf8(rule_data.rationale)
|
69
|
+
log[:references] = hash_a8b(rule_data.references.map(&:to_hash))
|
70
|
+
log[:fixes] = hash_a8b(rule_data.fixes.map(&:to_hash))
|
71
|
+
log[:severity] = ascii8bit_to_utf8(rule_data.severity)
|
72
|
+
log
|
73
|
+
end
|
74
|
+
|
75
|
+
def cleanup(*args)
|
76
|
+
args.compact.map(&:destroy)
|
77
|
+
::OpenSCAP.oscap_cleanup
|
78
|
+
end
|
79
|
+
|
80
|
+
# Unfortunately openscap in ruby 1.9.3 outputs data in Ascii-8bit.
|
81
|
+
# We transform it to UTF-8 for easier json integration.
|
82
|
+
|
83
|
+
# :invalid ::
|
84
|
+
# If the value is invalid, #encode replaces invalid byte sequences in
|
85
|
+
# +str+ with the replacement character. The default is to raise the
|
86
|
+
# Encoding::InvalidByteSequenceError exception
|
87
|
+
# :undef ::
|
88
|
+
# If the value is undefined, #encode replaces characters which are
|
89
|
+
# undefined in the destination encoding with the replacement character.
|
90
|
+
# The default is to raise the Encoding::UndefinedConversionError.
|
91
|
+
# :replace ::
|
92
|
+
# Sets the replacement string to the given value. The default replacement
|
93
|
+
# string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
|
94
|
+
def ascii8bit_to_utf8(string)
|
95
|
+
return ascii8bit_to_utf8_legacy(string) if RUBY_VERSION.start_with? '1.8'
|
96
|
+
string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
|
97
|
+
end
|
98
|
+
|
99
|
+
# String#encode appeared first in 1.9, so we need a workaround for 1.8
|
100
|
+
def ascii8bit_to_utf8_legacy(string)
|
101
|
+
Iconv.conv('UTF-8//IGNORE', 'UTF-8', string.to_s)
|
102
|
+
end
|
103
|
+
|
104
|
+
def hash_a8b(ary)
|
105
|
+
ary.map do |hash|
|
106
|
+
Hash[hash.map { |key, value| [ascii8bit_to_utf8(key), ascii8bit_to_utf8(value)] }]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -1,110 +1,34 @@
|
|
1
|
-
|
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'
|
1
|
+
require 'smart_proxy_openscap/shell_wrapper'
|
11
2
|
|
12
3
|
module Proxy
|
13
4
|
module OpenSCAP
|
14
|
-
class ArfParser
|
15
|
-
def parse(file_in, file_out)
|
16
|
-
::OpenSCAP.oscap_init
|
17
|
-
arf_digest = Digest::SHA256.hexdigest(File.read(file_in))
|
5
|
+
class ArfParser < ShellWrapper
|
18
6
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
File.write file_out, report.to_json
|
30
|
-
ensure
|
31
|
-
cleanup test_result, benchmark, sds, arf
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def parse_results(items, results, arf_digest)
|
37
|
-
report = {}
|
38
|
-
report[:logs] = []
|
39
|
-
passed = 0
|
40
|
-
failed = 0
|
41
|
-
othered = 0
|
42
|
-
results.each do |rr_id, result|
|
43
|
-
next if result.result == 'notapplicable' || result.result == 'notselected'
|
44
|
-
# get rules and their results
|
45
|
-
rule_data = items[rr_id]
|
46
|
-
report[:logs] << populate_result_data(rr_id, result.result, rule_data)
|
47
|
-
# create metrics for the results
|
48
|
-
case result.result
|
49
|
-
when 'pass', 'fixed'
|
50
|
-
passed += 1
|
51
|
-
when 'fail'
|
52
|
-
failed += 1
|
53
|
-
else
|
54
|
-
othered += 1
|
55
|
-
end
|
56
|
-
end
|
57
|
-
report[:digest] = arf_digest
|
58
|
-
report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
|
59
|
-
report
|
7
|
+
def initialize(cname, policy_id, date)
|
8
|
+
@cname = cname
|
9
|
+
@policy_id = policy_id
|
10
|
+
@date = date
|
11
|
+
@script_name = 'smart-proxy-arf-json'
|
60
12
|
end
|
61
13
|
|
62
|
-
def
|
63
|
-
|
64
|
-
log[:source] = ascii8bit_to_utf8(result_id)
|
65
|
-
log[:result] = ascii8bit_to_utf8(rule_result)
|
66
|
-
log[:title] = ascii8bit_to_utf8(rule_data.title)
|
67
|
-
log[:description] = ascii8bit_to_utf8(rule_data.description)
|
68
|
-
log[:rationale] = ascii8bit_to_utf8(rule_data.rationale)
|
69
|
-
log[:references] = hash_a8b(rule_data.references.map(&:to_hash))
|
70
|
-
log[:fixes] = hash_a8b(rule_data.fixes.map(&:to_hash))
|
71
|
-
log[:severity] = ascii8bit_to_utf8(rule_data.severity)
|
72
|
-
log
|
14
|
+
def as_json(arf_data)
|
15
|
+
execute_shell_command arf_data
|
73
16
|
end
|
74
17
|
|
75
|
-
def
|
76
|
-
|
77
|
-
::OpenSCAP.oscap_cleanup
|
18
|
+
def in_filename
|
19
|
+
"#{super}-#{@cname}-#{@policy_id}-#{@date}-"
|
78
20
|
end
|
79
21
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
# :invalid ::
|
84
|
-
# If the value is invalid, #encode replaces invalid byte sequences in
|
85
|
-
# +str+ with the replacement character. The default is to raise the
|
86
|
-
# Encoding::InvalidByteSequenceError exception
|
87
|
-
# :undef ::
|
88
|
-
# If the value is undefined, #encode replaces characters which are
|
89
|
-
# undefined in the destination encoding with the replacement character.
|
90
|
-
# The default is to raise the Encoding::UndefinedConversionError.
|
91
|
-
# :replace ::
|
92
|
-
# Sets the replacement string to the given value. The default replacement
|
93
|
-
# string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
|
94
|
-
def ascii8bit_to_utf8(string)
|
95
|
-
return ascii8bit_to_utf8_legacy(string) if RUBY_VERSION.start_with? '1.8'
|
96
|
-
string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
|
22
|
+
def out_filename
|
23
|
+
"#{in_filename}json-"
|
97
24
|
end
|
98
25
|
|
99
|
-
|
100
|
-
|
101
|
-
Iconv.conv('UTF-8//IGNORE', 'UTF-8', string.to_s)
|
26
|
+
def failure_message
|
27
|
+
"Failure when running script which parses reports"
|
102
28
|
end
|
103
29
|
|
104
|
-
def
|
105
|
-
|
106
|
-
Hash[hash.map { |key, value| [ascii8bit_to_utf8(key), ascii8bit_to_utf8(value)] }]
|
107
|
-
end
|
30
|
+
def command(in_file, out_file)
|
31
|
+
"#{script_location} #{in_file.path} #{out_file.path}"
|
108
32
|
end
|
109
33
|
end
|
110
34
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'smart_proxy_openscap/shell_wrapper'
|
2
|
+
|
3
|
+
module Proxy::OpenSCAP
|
4
|
+
class ContentParser < ShellWrapper
|
5
|
+
def initialize(type)
|
6
|
+
@type = type
|
7
|
+
@script_name = 'smart-proxy-scap-validation'
|
8
|
+
end
|
9
|
+
|
10
|
+
def validate(scap_file)
|
11
|
+
execute_shell_command scap_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def out_filename
|
15
|
+
"#{in_filename}json-"
|
16
|
+
end
|
17
|
+
|
18
|
+
def in_filename
|
19
|
+
"#{super}-#{@type}-validate-"
|
20
|
+
end
|
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}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -5,8 +5,7 @@ module Proxy::OpenSCAP
|
|
5
5
|
def post_arf_report(cname, policy_id, date, data)
|
6
6
|
begin
|
7
7
|
foreman_api_path = upload_path(cname, policy_id, date)
|
8
|
-
json = Proxy::OpenSCAP::
|
9
|
-
raise OpenSCAP::OpenSCAPError, "Failed to parse report" if json.nil? || json.empty?
|
8
|
+
json = Proxy::OpenSCAP::ArfParser.new(cname, policy_id, date).as_json(data)
|
10
9
|
response = send_request(foreman_api_path, json)
|
11
10
|
# Raise an HTTP error if the response is not 2xx (success).
|
12
11
|
response.value
|
@@ -42,7 +42,7 @@ module Proxy::OpenSCAP
|
|
42
42
|
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.failed_dir, cn, post_to_foreman['id'], date).store_failed(request.body.string)
|
43
43
|
logger.error "Failed to save Report in reports directory (#{Proxy::OpenSCAP::Plugin.settings.reportsdir}). Failed with: #{e.message}.
|
44
44
|
Saving file in #{Proxy::OpenSCAP::Plugin.settings.failed_dir}. Please copy manually to #{Proxy::OpenSCAP::Plugin.settings.reportsdir}"
|
45
|
-
rescue OpenSCAP::
|
45
|
+
rescue Proxy::OpenSCAP::OpenSCAPException => e
|
46
46
|
logger.error "Failed to parse Arf Report, moving to #{Proxy::OpenSCAP::Plugin.settings.corrupted_dir}"
|
47
47
|
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.corrupted_dir, cn, policy, date).store_corrupted(request.body.string)
|
48
48
|
rescue *HTTP_ERRORS => e
|
@@ -73,9 +73,11 @@ module Proxy::OpenSCAP
|
|
73
73
|
|
74
74
|
get "/arf/:id/:cname/:date/:digest/html" do
|
75
75
|
begin
|
76
|
-
Proxy::OpenSCAP::
|
76
|
+
Proxy::OpenSCAP::OpenscapHtmlGenerator.new(params[:cname], params[:id], params[:date], params[:digest]).get_html
|
77
77
|
rescue FileNotFound => e
|
78
78
|
log_halt 500, "Could not find requested file, #{e.message}"
|
79
|
+
rescue OpenSCAPException => e
|
80
|
+
log_halt 500, "Could not generate report in HTML"
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
@@ -114,28 +116,22 @@ module Proxy::OpenSCAP
|
|
114
116
|
end
|
115
117
|
|
116
118
|
post "/scap_content/policies" do
|
117
|
-
content_parser = create_content_parser
|
118
119
|
begin
|
119
|
-
|
120
|
+
Proxy::OpenSCAP::ProfilesParser.new('scap_content').profiles(request.body.string)
|
120
121
|
rescue *HTTP_ERRORS => e
|
121
122
|
log_halt 500, e.message
|
122
123
|
rescue StandardError => e
|
123
124
|
log_halt 500, "Error occurred: #{e.message}"
|
124
|
-
ensure
|
125
|
-
content_parser.cleanup
|
126
125
|
end
|
127
126
|
end
|
128
127
|
|
129
128
|
post "/tailoring_file/profiles" do
|
130
|
-
content_parser = create_content_parser
|
131
129
|
begin
|
132
|
-
|
130
|
+
Proxy::OpenSCAP::ProfilesParser.new('tailoring_file').profiles(request.body.string)
|
133
131
|
rescue *HTTP_ERRORS => e
|
134
132
|
log_halt 500, e.message
|
135
133
|
rescue StandardError => e
|
136
134
|
log_halt 500, "Error occurred: #{e.message}"
|
137
|
-
ensure
|
138
|
-
content_parser.cleanup
|
139
135
|
end
|
140
136
|
end
|
141
137
|
|
@@ -150,15 +146,12 @@ module Proxy::OpenSCAP
|
|
150
146
|
end
|
151
147
|
|
152
148
|
post "/scap_content/guide/:policy" do
|
153
|
-
content_parser = create_content_parser
|
154
149
|
begin
|
155
|
-
|
150
|
+
Proxy::OpenSCAP::PolicyParser.new(params[:policy]).guide(request.body.string)
|
156
151
|
rescue *HTTP_ERRORS => e
|
157
152
|
log_halt 500, e.message
|
158
153
|
rescue StandardError => e
|
159
154
|
log_halt 500, "Error occurred: #{e.message}"
|
160
|
-
ensure
|
161
|
-
content_parser.cleanup
|
162
155
|
end
|
163
156
|
end
|
164
157
|
|
@@ -166,16 +159,12 @@ module Proxy::OpenSCAP
|
|
166
159
|
|
167
160
|
def validate_scap_file(params)
|
168
161
|
begin
|
169
|
-
Proxy::OpenSCAP::ContentParser.new(
|
162
|
+
Proxy::OpenSCAP::ContentParser.new(params[:type]).validate(request.body.string)
|
170
163
|
rescue *HTTP_ERRORS => e
|
171
164
|
log_halt 500, e.message
|
172
165
|
rescue StandardError => e
|
173
166
|
log_halt 500, "Error occurred: #{e.message}"
|
174
167
|
end
|
175
168
|
end
|
176
|
-
|
177
|
-
def create_content_parser
|
178
|
-
Proxy::OpenSCAP::ContentParser.new(request.body.string)
|
179
|
-
end
|
180
169
|
end
|
181
170
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'smart_proxy_openscap/storage_fs'
|
2
|
+
require 'smart_proxy_openscap/shell_wrapper'
|
3
|
+
|
4
|
+
module Proxy
|
5
|
+
module OpenSCAP
|
6
|
+
class OpenscapHtmlGenerator < ShellWrapper
|
7
|
+
def initialize(cname, id, date, digest)
|
8
|
+
@cname = cname
|
9
|
+
@id = id
|
10
|
+
@date = date
|
11
|
+
@digest = digest
|
12
|
+
@script_name = 'smart-proxy-arf-html'
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_html
|
16
|
+
execute_shell_command
|
17
|
+
end
|
18
|
+
|
19
|
+
def out_filename
|
20
|
+
"#{super}-#{@cname}-#{@id}-#{@date}-#{@digest}-"
|
21
|
+
end
|
22
|
+
|
23
|
+
def command(in_file, out_file)
|
24
|
+
"#{script_location} #{file_path_in_storage} #{out_file.path}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message
|
28
|
+
"Failure when running script which generates html reports"
|
29
|
+
end
|
30
|
+
|
31
|
+
def file_path_in_storage
|
32
|
+
path_to_dir = Proxy::OpenSCAP::Plugin.settings.reportsdir
|
33
|
+
storage = Proxy::OpenSCAP::StorageFS.new(path_to_dir, @cname, @id, @date)
|
34
|
+
storage.get_path(@digest)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -16,12 +16,14 @@ require 'proxy/error'
|
|
16
16
|
require 'proxy/request'
|
17
17
|
require 'smart_proxy_openscap/fetch_scap_content'
|
18
18
|
require 'smart_proxy_openscap/foreman_forwarder'
|
19
|
-
require 'smart_proxy_openscap/
|
19
|
+
require 'smart_proxy_openscap/content_parser'
|
20
20
|
require 'smart_proxy_openscap/openscap_exception'
|
21
|
-
require 'smart_proxy_openscap/
|
21
|
+
require 'smart_proxy_openscap/arf_parser'
|
22
22
|
require 'smart_proxy_openscap/spool_forwarder'
|
23
|
-
require 'smart_proxy_openscap/
|
23
|
+
require 'smart_proxy_openscap/openscap_html_generator'
|
24
24
|
require 'smart_proxy_openscap/fetch_tailoring_file'
|
25
|
+
require 'smart_proxy_openscap/policy_parser'
|
26
|
+
require 'smart_proxy_openscap/profiles_parser'
|
25
27
|
|
26
28
|
module Proxy::OpenSCAP
|
27
29
|
extend ::Proxy::Log
|
@@ -9,7 +9,6 @@
|
|
9
9
|
#
|
10
10
|
|
11
11
|
require 'smart_proxy_openscap/version'
|
12
|
-
require 'smart_proxy_openscap/plugin_configuration'
|
13
12
|
|
14
13
|
module Proxy::OpenSCAP
|
15
14
|
class Plugin < ::Proxy::Plugin
|
@@ -24,10 +23,5 @@ module Proxy::OpenSCAP
|
|
24
23
|
:reportsdir => File.join(APP_ROOT, 'openscap/reports'),
|
25
24
|
:failed_dir => File.join(APP_ROOT, 'openscap/failed'),
|
26
25
|
:tailoring_dir => File.join(APP_ROOT, 'openscap/tailoring')
|
27
|
-
|
28
|
-
load_classes ::Proxy::OpenSCAP::PluginConfiguration
|
29
|
-
load_dependency_injection_wirings ::Proxy::OpenSCAP::PluginConfiguration
|
30
|
-
|
31
|
-
start_services :openscap_initializer
|
32
26
|
end
|
33
27
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'openscap'
|
2
|
+
require 'openscap/source'
|
3
|
+
require 'openscap/ds/sds'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Proxy
|
7
|
+
module OpenSCAP
|
8
|
+
class PolicyGuide
|
9
|
+
def generate_guide(in_file, out_file, policy)
|
10
|
+
::OpenSCAP.oscap_init
|
11
|
+
source = ::OpenSCAP::Source.new in_file
|
12
|
+
sds = ::OpenSCAP::DS::Sds.new source
|
13
|
+
sds.select_checklist
|
14
|
+
profile_id = policy ? nil : policy
|
15
|
+
html = sds.html_guide profile_id
|
16
|
+
File.write(out_file, { :html => html.force_encoding('UTF-8') }.to_json)
|
17
|
+
sds.destroy
|
18
|
+
source.destroy
|
19
|
+
::OpenSCAP.oscap_cleanup
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'smart_proxy_openscap/shell_wrapper'
|
2
|
+
|
3
|
+
module Proxy
|
4
|
+
module OpenSCAP
|
5
|
+
class PolicyParser < ShellWrapper
|
6
|
+
|
7
|
+
def initialize(policy)
|
8
|
+
@script_name = "smart-proxy-policy-guide"
|
9
|
+
@policy = policy
|
10
|
+
end
|
11
|
+
|
12
|
+
def guide(scap_file)
|
13
|
+
execute_shell_command scap_file
|
14
|
+
end
|
15
|
+
|
16
|
+
def in_filename
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def out_filename
|
21
|
+
"#{in_filename}json-"
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure_message
|
25
|
+
"Failure when running script which renders policy guide"
|
26
|
+
end
|
27
|
+
|
28
|
+
def command(in_file, out_file)
|
29
|
+
"#{script_location} #{in_file.path} #{out_file.path} #{@policy}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'smart_proxy_openscap/shell_wrapper'
|
2
|
+
|
3
|
+
module Proxy
|
4
|
+
module OpenSCAP
|
5
|
+
class ProfilesParser < ShellWrapper
|
6
|
+
def initialize(type)
|
7
|
+
@type = type
|
8
|
+
@script_name = 'smart-proxy-scap-profiles'
|
9
|
+
end
|
10
|
+
|
11
|
+
def profiles(scap_file)
|
12
|
+
execute_shell_command scap_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def out_filename
|
16
|
+
"#{in_filename}json-"
|
17
|
+
end
|
18
|
+
|
19
|
+
def in_filename
|
20
|
+
"#{super}-#{@type}-profiles-"
|
21
|
+
end
|
22
|
+
|
23
|
+
def failure_message
|
24
|
+
"Failure when running script which extracts profiles from scap file"
|
25
|
+
end
|
26
|
+
|
27
|
+
def command(in_file, out_file)
|
28
|
+
"#{script_location} #{in_file.path} #{out_file.path} #{@type}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,49 @@
|
|
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
|
+
source.destroy
|
17
|
+
::OpenSCAP.oscap_cleanup
|
18
|
+
end
|
19
|
+
|
20
|
+
def scap_content_profiles(source)
|
21
|
+
bench = benchmark_profiles source
|
22
|
+
profiles = collect_profiles bench
|
23
|
+
bench.destroy
|
24
|
+
profiles.to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
def tailoring_profiles(source)
|
28
|
+
tailoring = ::OpenSCAP::Xccdf::Tailoring.new(source, nil)
|
29
|
+
profiles = collect_profiles tailoring
|
30
|
+
tailoring.destroy
|
31
|
+
profiles.to_json
|
32
|
+
end
|
33
|
+
|
34
|
+
def collect_profiles(profile_source)
|
35
|
+
profile_source.profiles.inject({}) do |memo, (key, profile)|
|
36
|
+
memo.tap { |hash| hash[key] = profile.title.strip }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def benchmark_profiles(source)
|
41
|
+
sds = ::OpenSCAP::DS::Sds.new(source)
|
42
|
+
bench_source = sds.select_checklist!
|
43
|
+
benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
44
|
+
sds.destroy
|
45
|
+
benchmark
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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
|
+
source.destroy
|
30
|
+
::OpenSCAP.oscap_cleanup
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Proxy
|
4
|
+
module OpenSCAP
|
5
|
+
class ShellWrapper
|
6
|
+
include ::Proxy::Log
|
7
|
+
|
8
|
+
attr_reader :script_name
|
9
|
+
|
10
|
+
def script_location
|
11
|
+
raise NotImplementedError, 'Must have @script_name' unless script_name
|
12
|
+
path = File.join(File.dirname(File.expand_path(__FILE__)), '../../bin', script_name)
|
13
|
+
return path if File.exist? path
|
14
|
+
script_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute_shell_command(in_file_content = nil)
|
18
|
+
out_file = Tempfile.new(out_filename, "/var/tmp")
|
19
|
+
in_file = prepare_in_file in_file_content
|
20
|
+
comm = command(in_file, out_file)
|
21
|
+
logger.debug "Executing: #{comm}"
|
22
|
+
output = nil
|
23
|
+
begin
|
24
|
+
`#{comm}`
|
25
|
+
output = out_file.read
|
26
|
+
rescue => e
|
27
|
+
logger.debug failure_message
|
28
|
+
logger.debug e.message
|
29
|
+
logger.debug e.backtrace.join("\n\t")
|
30
|
+
ensure
|
31
|
+
close_unlink out_file, in_file
|
32
|
+
end
|
33
|
+
raise OpenSCAPException, exception_message if output.nil? || output.empty?
|
34
|
+
output
|
35
|
+
end
|
36
|
+
|
37
|
+
def close_unlink(*files)
|
38
|
+
files.compact.each do |file|
|
39
|
+
file.close
|
40
|
+
file.unlink
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def prepare_in_file(in_file_content)
|
45
|
+
return unless in_file_content
|
46
|
+
file = Tempfile.new(in_filename, "/var/tmp")
|
47
|
+
file.write in_file_content
|
48
|
+
file.rewind
|
49
|
+
file
|
50
|
+
end
|
51
|
+
|
52
|
+
def in_filename
|
53
|
+
@in_filename ||= unique_filename
|
54
|
+
end
|
55
|
+
|
56
|
+
def out_filename
|
57
|
+
@out_filename ||= unique_filename
|
58
|
+
end
|
59
|
+
|
60
|
+
def unique_filename
|
61
|
+
SecureRandom.uuid
|
62
|
+
end
|
63
|
+
|
64
|
+
def command(in_file, out_file)
|
65
|
+
raise NotImplementedError, "Must be implemented"
|
66
|
+
end
|
67
|
+
|
68
|
+
def failure_message
|
69
|
+
raise NotImplementedError, "Must be implemented"
|
70
|
+
end
|
71
|
+
|
72
|
+
def exception_message
|
73
|
+
failure_message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -51,7 +51,7 @@ module Proxy::OpenSCAP
|
|
51
51
|
post_to_foreman = ForemanForwarder.new.post_arf_report(cname, policy_id, date, data)
|
52
52
|
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.reportsdir, cname, post_to_foreman['id'], date).store_archive(data)
|
53
53
|
File.delete arf_file_path
|
54
|
-
rescue OpenSCAP::
|
54
|
+
rescue Proxy::OpenSCAP::OpenSCAPException => e
|
55
55
|
logger.error "Failed to parse Arf Report at #{arf_file_path}, moving to #{Proxy::OpenSCAP::Plugin.settings.corrupted_dir}"
|
56
56
|
|
57
57
|
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.corrupted_dir, cname, policy_id, date).
|
@@ -27,15 +27,6 @@ module Proxy::OpenSCAP
|
|
27
27
|
get_arf_file(digest)[:xml]
|
28
28
|
end
|
29
29
|
|
30
|
-
def get_arf_html(digest)
|
31
|
-
xml = get_arf_file(digest)[:xml]
|
32
|
-
size = get_arf_file(digest)[:size]
|
33
|
-
arf_object = OpenSCAP::DS::Arf.new(:content => xml, :path => 'arf.xml.bz2', :length => size)
|
34
|
-
# @TODO: Drop this when support for 1.8.7 ends
|
35
|
-
return arf_object.html if RUBY_VERSION.start_with? '1.8'
|
36
|
-
arf_object.html.force_encoding('UTF-8')
|
37
|
-
end
|
38
|
-
|
39
30
|
def delete_arf_file
|
40
31
|
path = "#{@path_to_dir}/#{@namespace}/#{@cname}/#{@id}"
|
41
32
|
raise FileNotFound, "Can't find path #{path}" if !File.directory?(path) || File.zero?(path)
|
@@ -43,6 +34,17 @@ module Proxy::OpenSCAP
|
|
43
34
|
{:id => @id, :deleted => true}.to_json
|
44
35
|
end
|
45
36
|
|
37
|
+
def get_arf_file(digest)
|
38
|
+
file = File.open(get_path digest)
|
39
|
+
{ :size => File.size(file), :xml => file.read }
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_path(digest)
|
43
|
+
full_path = @path + digest
|
44
|
+
raise FileNotFound, "Can't find path #{full_path}" if !File.file?(full_path) || File.zero?(full_path)
|
45
|
+
full_path
|
46
|
+
end
|
47
|
+
|
46
48
|
private
|
47
49
|
|
48
50
|
def store_arf(spool_arf_dir, data)
|
@@ -86,12 +88,5 @@ module Proxy::OpenSCAP
|
|
86
88
|
|
87
89
|
logger.debug "File #{target_path} stored in reports dir."
|
88
90
|
end
|
89
|
-
|
90
|
-
def get_arf_file(digest)
|
91
|
-
full_path = @path + digest
|
92
|
-
raise FileNotFound, "Can't find path #{full_path}" if !File.file?(full_path) || File.zero?(full_path)
|
93
|
-
file = File.open(full_path)
|
94
|
-
{ :size => File.size(file), :xml => file.read }
|
95
|
-
end
|
96
91
|
end
|
97
92
|
end
|
@@ -39,9 +39,7 @@ class OpenSCAPGetArfTest < Test::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def test_get_html_arf
|
42
|
-
OpenSCAP.oscap_init
|
43
42
|
get "/arf/#{@arf_id}/#{@cname}/#{@date}/#{@filename}/html"
|
44
|
-
OpenSCAP.oscap_cleanup
|
45
43
|
assert(last_response.successful?, "Should return OK")
|
46
44
|
assert(last_response.body.start_with?('<!DOCTYPE'), 'File should start with html')
|
47
45
|
end
|
@@ -28,7 +28,7 @@ class ScapContentParserApiTest < Test::Unit::TestCase
|
|
28
28
|
|
29
29
|
def test_invalid_scap_content_policies
|
30
30
|
post '/scap_content/policies', '<xml>blah</xml>', 'CONTENT_TYPE' => 'text/xml'
|
31
|
-
assert(last_response.body.include?('
|
31
|
+
assert(last_response.body.include?('Failure when running script which extracts profiles from scap file'))
|
32
32
|
end
|
33
33
|
|
34
34
|
def test_scap_content_validator
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'smart_proxy_openscap/arf_html'
|
3
|
+
require 'smart_proxy_openscap/arf_json'
|
4
|
+
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
|
+
|
9
|
+
class ScriptClassTest < Test::Unit::TestCase
|
10
|
+
def test_arf_generate_html
|
11
|
+
carry_out do |tmp|
|
12
|
+
Proxy::OpenSCAP::ArfHtml.new.generate_html("#{Dir.getwd}/test/data/arf_report", tmp.path)
|
13
|
+
content = File.read tmp
|
14
|
+
assert content.start_with?('<!DOCTYPE'), "File should be html"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
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)
|
21
|
+
json = read_json tmp
|
22
|
+
refute json['logs'].empty?
|
23
|
+
refute json['metrics'].empty?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_policy_guide
|
28
|
+
carry_out do |tmp|
|
29
|
+
profile = "xccdf_org.ssgproject.content_profile_stig-rhel7-workstation-upstream"
|
30
|
+
Proxy::OpenSCAP::PolicyGuide.new.generate_guide("#{Dir.getwd}/test/data/ssg-rhel7-ds.xml", tmp.path, profile)
|
31
|
+
guide = read_json tmp
|
32
|
+
assert guide['html'].start_with?('<!DOCTYPE'), "File should be html"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_scap_file_profiles
|
37
|
+
carry_out do |tmp|
|
38
|
+
Proxy::OpenSCAP::ScapProfiles.new.profiles("#{Dir.getwd}/test/data/ssg-rhel7-ds.xml", tmp.path, 'scap_content')
|
39
|
+
profiles = read_json tmp
|
40
|
+
refute profiles.empty?
|
41
|
+
assert profiles["xccdf_org.ssgproject.content_profile_common"]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_tailoring_file_profiles
|
46
|
+
carry_out do |tmp|
|
47
|
+
Proxy::OpenSCAP::ScapProfiles.new.profiles("#{Dir.getwd}/test/data/tailoring.xml", tmp.path, 'tailoring_file')
|
48
|
+
profiles = read_json tmp
|
49
|
+
refute profiles.empty?
|
50
|
+
assert profiles["xccdf_org.ssgproject.content_profile_stig-firefox-upstream_customized"]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_arf_json
|
55
|
+
carry_out do |tmp|
|
56
|
+
Proxy::OpenSCAP::ArfJson.new.as_json("#{Dir.getwd}/test/data/arf_report", tmp.path)
|
57
|
+
json = read_json tmp
|
58
|
+
refute json['logs'].empty?
|
59
|
+
refute json['metrics'].empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_scap_content_validation
|
64
|
+
carry_out do |tmp|
|
65
|
+
Proxy::OpenSCAP::ScapValidation.new.validate("#{Dir.getwd}/test/data/ssg-rhel7-ds.xml", tmp.path, 'scap_content')
|
66
|
+
res = read_json tmp
|
67
|
+
assert res['errors'].empty?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_tailoring_file_validation
|
72
|
+
carry_out do |tmp|
|
73
|
+
Proxy::OpenSCAP::ScapValidation.new.validate("#{Dir.getwd}/test/data/tailoring.xml", tmp.path, 'tailoring_file')
|
74
|
+
res = read_json tmp
|
75
|
+
assert res['errors'].empty?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def carry_out
|
82
|
+
tmp = Tempfile.new('test')
|
83
|
+
begin
|
84
|
+
yield tmp if block_given?
|
85
|
+
ensure
|
86
|
+
tmp.close
|
87
|
+
tmp.unlink
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def read_json(file)
|
92
|
+
JSON.parse(File.read file)
|
93
|
+
end
|
94
|
+
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_openscap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Šimon Lukašík
|
8
8
|
- Shlomi Zadok
|
9
9
|
- Marek Hulan
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-07
|
13
|
+
date: 2017-09-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -97,27 +97,37 @@ files:
|
|
97
97
|
- Gemfile
|
98
98
|
- README.md
|
99
99
|
- Rakefile
|
100
|
+
- bin/smart-proxy-arf-html
|
101
|
+
- bin/smart-proxy-arf-json
|
100
102
|
- bin/smart-proxy-openscap-send
|
101
|
-
- bin/smart-proxy-
|
103
|
+
- bin/smart-proxy-policy-guide
|
104
|
+
- bin/smart-proxy-scap-profiles
|
105
|
+
- bin/smart-proxy-scap-validation
|
102
106
|
- bundler.d/openscap.rb
|
103
107
|
- extra/rubygem-smart_proxy_openscap.spec
|
104
108
|
- extra/smart-proxy-openscap-send.cron
|
105
109
|
- lib/smart_proxy_openscap.rb
|
110
|
+
- lib/smart_proxy_openscap/arf_html.rb
|
111
|
+
- lib/smart_proxy_openscap/arf_json.rb
|
106
112
|
- lib/smart_proxy_openscap/arf_parser.rb
|
113
|
+
- lib/smart_proxy_openscap/content_parser.rb
|
107
114
|
- lib/smart_proxy_openscap/fetch_file.rb
|
108
115
|
- lib/smart_proxy_openscap/fetch_scap_content.rb
|
109
116
|
- lib/smart_proxy_openscap/fetch_tailoring_file.rb
|
110
117
|
- lib/smart_proxy_openscap/foreman_forwarder.rb
|
111
118
|
- lib/smart_proxy_openscap/http_config.ru
|
112
119
|
- lib/smart_proxy_openscap/openscap_api.rb
|
113
|
-
- lib/smart_proxy_openscap/openscap_content_parser.rb
|
114
120
|
- lib/smart_proxy_openscap/openscap_exception.rb
|
121
|
+
- lib/smart_proxy_openscap/openscap_html_generator.rb
|
115
122
|
- lib/smart_proxy_openscap/openscap_import_api.rb
|
116
|
-
- lib/smart_proxy_openscap/openscap_initializer.rb
|
117
123
|
- lib/smart_proxy_openscap/openscap_lib.rb
|
118
124
|
- lib/smart_proxy_openscap/openscap_plugin.rb
|
119
|
-
- lib/smart_proxy_openscap/
|
120
|
-
- lib/smart_proxy_openscap/
|
125
|
+
- lib/smart_proxy_openscap/policy_guide.rb
|
126
|
+
- lib/smart_proxy_openscap/policy_parser.rb
|
127
|
+
- lib/smart_proxy_openscap/profiles_parser.rb
|
128
|
+
- lib/smart_proxy_openscap/scap_profiles.rb
|
129
|
+
- lib/smart_proxy_openscap/scap_validation.rb
|
130
|
+
- lib/smart_proxy_openscap/shell_wrapper.rb
|
121
131
|
- lib/smart_proxy_openscap/spool_forwarder.rb
|
122
132
|
- lib/smart_proxy_openscap/storage.rb
|
123
133
|
- lib/smart_proxy_openscap/storage_fs.rb
|
@@ -139,6 +149,7 @@ files:
|
|
139
149
|
- test/get_report_xml_html_test.rb
|
140
150
|
- test/post_report_api_test.rb
|
141
151
|
- test/scap_content_parser_api_test.rb
|
152
|
+
- test/script_class_test.rb
|
142
153
|
- test/spool_forwarder_test.rb
|
143
154
|
- test/test_helper.rb
|
144
155
|
homepage: http://github.com/OpenSCAP/smart_proxy_openscap
|
@@ -161,9 +172,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
172
|
version: '0'
|
162
173
|
requirements: []
|
163
174
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.
|
175
|
+
rubygems_version: 2.6.8
|
165
176
|
signing_key:
|
166
177
|
specification_version: 4
|
167
178
|
summary: OpenSCAP plug-in for Foreman's smart-proxy.
|
168
179
|
test_files: []
|
169
|
-
has_rdoc:
|
@@ -1,77 +0,0 @@
|
|
1
|
-
require 'openscap/ds/sds'
|
2
|
-
require 'openscap/source'
|
3
|
-
require 'openscap/xccdf/benchmark'
|
4
|
-
require 'openscap/xccdf/tailoring'
|
5
|
-
|
6
|
-
module Proxy::OpenSCAP
|
7
|
-
class ContentParser
|
8
|
-
def initialize(scap_file, type = 'scap_content')
|
9
|
-
@source = OpenSCAP::Source.new(:content => scap_file)
|
10
|
-
@type = type
|
11
|
-
end
|
12
|
-
|
13
|
-
def cleanup
|
14
|
-
@source.destroy if @source
|
15
|
-
end
|
16
|
-
|
17
|
-
def allowed_types
|
18
|
-
{
|
19
|
-
'tailoring_file' => 'XCCDF Tailoring',
|
20
|
-
'scap_content' => 'SCAP Source Datastream'
|
21
|
-
}
|
22
|
-
end
|
23
|
-
|
24
|
-
def extract_policies
|
25
|
-
policies = {}
|
26
|
-
bench = benchmark_profiles
|
27
|
-
bench.profiles.each do |key, profile|
|
28
|
-
policies[key] = profile.title
|
29
|
-
end
|
30
|
-
bench.destroy
|
31
|
-
policies.to_json
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_profiles
|
35
|
-
tailoring = ::OpenSCAP::Xccdf::Tailoring.new(@source, nil)
|
36
|
-
profiles = tailoring.profiles.inject({}) do |memo, (key, profile)|
|
37
|
-
memo.tap { |hash| hash[key] = profile.title }
|
38
|
-
end
|
39
|
-
tailoring.destroy
|
40
|
-
profiles.to_json
|
41
|
-
end
|
42
|
-
|
43
|
-
def validate
|
44
|
-
errors = []
|
45
|
-
|
46
|
-
if @source.type != allowed_types[@type]
|
47
|
-
errors << "Uploaded file is #{@source.type}, unexpected file type"
|
48
|
-
end
|
49
|
-
|
50
|
-
begin
|
51
|
-
@source.validate!
|
52
|
-
rescue OpenSCAP::OpenSCAPError
|
53
|
-
errors << "Invalid SCAP file type"
|
54
|
-
end
|
55
|
-
{:errors => errors}.to_json
|
56
|
-
end
|
57
|
-
|
58
|
-
def guide(policy)
|
59
|
-
sds = OpenSCAP::DS::Sds.new @source
|
60
|
-
sds.select_checklist
|
61
|
-
profile_id = policy ? nil : policy
|
62
|
-
html = sds.html_guide profile_id
|
63
|
-
sds.destroy
|
64
|
-
{:html => html.force_encoding('UTF-8')}.to_json
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def benchmark_profiles
|
70
|
-
sds = ::OpenSCAP::DS::Sds.new(@source)
|
71
|
-
bench_source = sds.select_checklist!
|
72
|
-
benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
73
|
-
sds.destroy
|
74
|
-
benchmark
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'openscap'
|
2
|
-
|
3
|
-
module Proxy::OpenSCAP
|
4
|
-
class OpenscapInitializer
|
5
|
-
include ::Proxy::Log
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@mutex = Mutex.new
|
9
|
-
end
|
10
|
-
|
11
|
-
def start
|
12
|
-
logger.debug "Initializing openscap component"
|
13
|
-
@mutex.synchronize { OpenSCAP.oscap_init }
|
14
|
-
end
|
15
|
-
|
16
|
-
def stop
|
17
|
-
logger.debug "Stopping openscap component"
|
18
|
-
@mutex.synchronize { OpenSCAP.oscap_cleanup }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
require 'tempfile'
|
3
|
-
|
4
|
-
module Proxy
|
5
|
-
module OpenSCAP
|
6
|
-
class Parse
|
7
|
-
include ::Proxy::Log
|
8
|
-
include ::Proxy::Util
|
9
|
-
|
10
|
-
def initialize(cname, policy_id, date)
|
11
|
-
@cname = cname
|
12
|
-
@policy_id = policy_id
|
13
|
-
@date = date
|
14
|
-
end
|
15
|
-
|
16
|
-
def as_json(arf_data)
|
17
|
-
in_file = Tempfile.new("#{filename}json-", "/var/tmp")
|
18
|
-
json_file = Tempfile.new(filename, "/var/tmp")
|
19
|
-
begin
|
20
|
-
in_file.write arf_data
|
21
|
-
command = "#{script_location} #{in_file.path} #{json_file.path}"
|
22
|
-
logger.debug "Executing: #{command}"
|
23
|
-
`#{command}`
|
24
|
-
json_file.read
|
25
|
-
rescue => e
|
26
|
-
logger.debug "Failure when running script which parses reports"
|
27
|
-
logger.debug e.backtrace.join("\n\t")
|
28
|
-
return nil
|
29
|
-
ensure
|
30
|
-
in_file.close
|
31
|
-
in_file.unlink
|
32
|
-
json_file.close
|
33
|
-
json_file.unlink
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def filename
|
38
|
-
"#{@cname}-#{@policy_id}-#{@date}-"
|
39
|
-
end
|
40
|
-
|
41
|
-
def script_location
|
42
|
-
path = File.join(File.dirname(File.expand_path(__FILE__)), '../..','bin/smart-proxy-parse-arf')
|
43
|
-
return path if File.exist? path
|
44
|
-
"smart-proxy-parse-arf"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Proxy::OpenSCAP
|
2
|
-
class PluginConfiguration
|
3
|
-
def load_dependency_injection_wirings(container, settings)
|
4
|
-
container.singleton_dependency :openscap_initializer, ( lambda do
|
5
|
-
::Proxy::OpenSCAP::OpenscapInitializer.new
|
6
|
-
end)
|
7
|
-
end
|
8
|
-
|
9
|
-
def load_classes
|
10
|
-
require 'smart_proxy_openscap/openscap_initializer'
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|