smart_proxy_openscap 0.6.5 → 0.6.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|