smart_proxy_openscap 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +41 -0
- data/.rubocop_todo.yml +111 -0
- data/.travis.yml +14 -0
- data/COPYING +674 -0
- data/Gemfile +14 -0
- data/README.md +107 -0
- data/Rakefile +16 -0
- data/bin/smart-proxy-arf-html +7 -0
- data/bin/smart-proxy-arf-json +7 -0
- data/bin/smart-proxy-openscap-send +61 -0
- 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/bundler.d/openscap.rb +6 -0
- data/extra/rubygem-smart_proxy_openscap.spec +101 -0
- data/extra/smart-proxy-openscap-send.cron +2 -0
- data/lib/smart_proxy_openscap.rb +14 -0
- data/lib/smart_proxy_openscap/arf_html.rb +22 -0
- data/lib/smart_proxy_openscap/arf_json.rb +114 -0
- data/lib/smart_proxy_openscap/arf_parser.rb +39 -0
- data/lib/smart_proxy_openscap/content_parser.rb +30 -0
- data/lib/smart_proxy_openscap/fetch_file.rb +60 -0
- data/lib/smart_proxy_openscap/fetch_scap_content.rb +17 -0
- data/lib/smart_proxy_openscap/fetch_tailoring_file.rb +17 -0
- data/lib/smart_proxy_openscap/foreman_forwarder.rb +40 -0
- data/lib/smart_proxy_openscap/http_config.ru +20 -0
- data/lib/smart_proxy_openscap/openscap_api.rb +187 -0
- data/lib/smart_proxy_openscap/openscap_exception.rb +9 -0
- data/lib/smart_proxy_openscap/openscap_html_generator.rb +38 -0
- data/lib/smart_proxy_openscap/openscap_import_api.rb +32 -0
- data/lib/smart_proxy_openscap/openscap_lib.rb +67 -0
- data/lib/smart_proxy_openscap/openscap_plugin.rb +27 -0
- 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 +52 -0
- data/lib/smart_proxy_openscap/scap_validation.rb +35 -0
- data/lib/smart_proxy_openscap/shell_wrapper.rb +77 -0
- data/lib/smart_proxy_openscap/spool_forwarder.rb +79 -0
- data/lib/smart_proxy_openscap/storage.rb +47 -0
- data/lib/smart_proxy_openscap/storage_fs.rb +102 -0
- data/lib/smart_proxy_openscap/version.rb +15 -0
- data/settings.d/openscap.yml.example +33 -0
- data/smart_proxy_openscap.gemspec +23 -0
- data/test/data/arf_report +0 -0
- data/test/data/corrupted_arf_report +0 -0
- data/test/data/spool/cleanup_spool/arf/2c101b95-033f-4b15-b490-f50bf9090dae/1/1484313035/fa2f68ffb944c917332a284dc63ec7f8fa76990cb815ddcad3318b5d9457f8a1 +0 -0
- data/test/data/spool/cleanup_spool/arf/e20b9695-f655-401a-9dda-8cca7a47a8c0/1/1484309984/fa2f68ffb944c917332a284dc63ec7f8fa76990cb815ddcad3318b5d9457f8a1 +0 -0
- data/test/data/spool/corrupted_spool/arf/e20b9695-f655-401a-9dda-8cca7a47a8c0/1/1484309984/a4dfba5db27b21795e6fa401b8dce7a70faeb25b7963891f07f6f4baaf052afb +0 -0
- data/test/data/spool/corrupted_spool/arf/e20b9695-f655-401a-9dda-8cca7a47a8c0/1/1484313035/fa2f68ffb944c917332a284dc63ec7f8fa76990cb815ddcad3318b5d9457f8a1 +0 -0
- data/test/data/spool/valid_spool/arf/e20b9695-f655-401a-9dda-8cca7a47a8c0/1/1484309984/fa2f68ffb944c917332a284dc63ec7f8fa76990cb815ddcad3318b5d9457f8a1 +0 -0
- data/test/data/spool/valid_spool/arf/e20b9695-f655-401a-9dda-8cca7a47a8c0/1/1484313035/fa2f68ffb944c917332a284dc63ec7f8fa76990cb815ddcad3318b5d9457f8a1 +0 -0
- data/test/data/ssg-rhel7-ds.xml +20271 -0
- data/test/data/tailoring.xml +31 -0
- data/test/fetch_scap_api_test.rb +73 -0
- data/test/fetch_tailoring_api_test.rb +37 -0
- data/test/get_report_xml_html_test.rb +58 -0
- data/test/post_report_api_test.rb +86 -0
- data/test/scap_content_parser_api_test.rb +69 -0
- data/test/script_class_test.rb +96 -0
- data/test/spool_forwarder_test.rb +84 -0
- data/test/test_helper.rb +13 -0
- metadata +180 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
module Proxy::OpenSCAP
|
2
|
+
class ImportApi < ::Sinatra::Base
|
3
|
+
include ::Proxy::Log
|
4
|
+
helpers ::Proxy::Helpers
|
5
|
+
authorize_with_trusted_hosts
|
6
|
+
|
7
|
+
require 'smart_proxy_openscap/openscap_lib'
|
8
|
+
|
9
|
+
post "/arf/:cname/:policy_id/:date" do
|
10
|
+
cn = params[:cname]
|
11
|
+
date = params[:date]
|
12
|
+
policy = params[:policy_id]
|
13
|
+
log_halt(500, "Insufficient data") if (cn.nil? || date.nil?)
|
14
|
+
|
15
|
+
post_to_foreman = ForemanForwarder.new.post_arf_report(cn, policy, date, request.body.string, Proxy::OpenSCAP::Plugin.settings.timeout)
|
16
|
+
begin
|
17
|
+
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.reportsdir, cn, post_to_foreman['id'], date).store_archive(request.body.string)
|
18
|
+
rescue Proxy::OpenSCAP::StoreReportError => e
|
19
|
+
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.failed_dir, cn, post_to_foreman['id'], date).store_failed(request.body.string)
|
20
|
+
logger.error "Failed to save Report in reports directory (#{Proxy::OpenSCAP::Plugin.settings.reportsdir}). Failed with: #{e.message}.
|
21
|
+
Saving file in #{Proxy::OpenSCAP::Plugin.settings.failed_dir}. Please copy manually to #{Proxy::OpenSCAP::Plugin.settings.reportsdir}"
|
22
|
+
rescue *HTTP_ERRORS => e
|
23
|
+
### If the upload to foreman fails then store it in the spooldir
|
24
|
+
logger.error "Failed to upload to Foreman, saving in spool. Failed with: #{e.message}"
|
25
|
+
Proxy::OpenSCAP::StorageFS.new(Proxy::OpenSCAP::Plugin.settings.spooldir, cn, policy, date).store_spool(request.body.string)
|
26
|
+
rescue Proxy::OpenSCAP::StoreSpoolError => e
|
27
|
+
log_halt 500, e.message
|
28
|
+
end
|
29
|
+
{:success => true, :arf_id => post_to_foreman['id']}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This software is licensed to you under the GNU General Public License,
|
5
|
+
# version 3 (GPLv3). There is NO WARRANTY for this software, express or
|
6
|
+
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
|
7
|
+
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
|
8
|
+
# along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'digest'
|
12
|
+
require 'fileutils'
|
13
|
+
require 'pathname'
|
14
|
+
require 'json'
|
15
|
+
require 'proxy/error'
|
16
|
+
require 'yaml'
|
17
|
+
require 'ostruct'
|
18
|
+
require 'proxy/request'
|
19
|
+
require 'smart_proxy_openscap/fetch_scap_content'
|
20
|
+
require 'smart_proxy_openscap/foreman_forwarder'
|
21
|
+
require 'smart_proxy_openscap/content_parser'
|
22
|
+
require 'smart_proxy_openscap/openscap_exception'
|
23
|
+
require 'smart_proxy_openscap/arf_parser'
|
24
|
+
require 'smart_proxy_openscap/spool_forwarder'
|
25
|
+
require 'smart_proxy_openscap/openscap_html_generator'
|
26
|
+
require 'smart_proxy_openscap/fetch_tailoring_file'
|
27
|
+
require 'smart_proxy_openscap/policy_parser'
|
28
|
+
require 'smart_proxy_openscap/profiles_parser'
|
29
|
+
|
30
|
+
module Proxy::OpenSCAP
|
31
|
+
extend ::Proxy::Log
|
32
|
+
|
33
|
+
def self.plugin_settings
|
34
|
+
@@settings ||= OpenStruct.new(read_settings)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.read_settings
|
38
|
+
::Proxy::OpenSCAP::Plugin.default_settings.merge(
|
39
|
+
YAML.load_file(File.join(::Proxy::SETTINGS.settings_directory, ::Proxy::OpenSCAP::Plugin.settings_file)))
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.common_name(request)
|
43
|
+
client_cert = request.env['SSL_CLIENT_CERT']
|
44
|
+
raise Proxy::Error::Unauthorized, "Client certificate required!" if client_cert.to_s.empty?
|
45
|
+
|
46
|
+
begin
|
47
|
+
client_cert = OpenSSL::X509::Certificate.new(client_cert)
|
48
|
+
rescue OpenSSL::OpenSSLError => e
|
49
|
+
raise Proxy::Error::Unauthorized, e.message
|
50
|
+
end
|
51
|
+
cn = client_cert.subject.to_a.detect { |name, value| name == 'CN' }
|
52
|
+
cn = cn[1] unless cn.nil?
|
53
|
+
raise Proxy::Error::Unauthorized, "Common Name not found in the certificate" unless cn
|
54
|
+
cn
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.send_spool_to_foreman(loaded_settings)
|
58
|
+
arf_dir = File.join(loaded_settings.spooldir, "/arf")
|
59
|
+
return unless File.exist? arf_dir
|
60
|
+
SpoolForwarder.new(loaded_settings).post_arf_from_spool(arf_dir)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.fullpath(path = Proxy::OpenSCAP::Plugin.settings.contentdir)
|
64
|
+
pathname = Pathname.new(path)
|
65
|
+
pathname.relative? ? pathname.expand_path(Sinatra::Base.root).to_s : path
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2014--2015 Red Hat Inc.
|
3
|
+
#
|
4
|
+
# This software is licensed to you under the GNU General Public License,
|
5
|
+
# version 3 (GPLv3). There is NO WARRANTY for this software, express or
|
6
|
+
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
|
7
|
+
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
|
8
|
+
# along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'smart_proxy_openscap/version'
|
12
|
+
|
13
|
+
module Proxy::OpenSCAP
|
14
|
+
class Plugin < ::Proxy::Plugin
|
15
|
+
plugin :openscap, Proxy::OpenSCAP::VERSION
|
16
|
+
|
17
|
+
http_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
|
18
|
+
https_rackup_path File.expand_path("http_config.ru", File.expand_path("../", __FILE__))
|
19
|
+
|
20
|
+
default_settings :spooldir => '/var/spool/foreman-proxy/openscap',
|
21
|
+
:openscap_send_log_file => File.join(APP_ROOT, 'logs/openscap-send.log'),
|
22
|
+
:contentdir => File.join(APP_ROOT, 'openscap/content'),
|
23
|
+
:reportsdir => File.join(APP_ROOT, 'openscap/reports'),
|
24
|
+
:failed_dir => File.join(APP_ROOT, 'openscap/failed'),
|
25
|
+
:tailoring_dir => File.join(APP_ROOT, 'openscap/tailoring')
|
26
|
+
end
|
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=nil)
|
10
|
+
::OpenSCAP.oscap_init
|
11
|
+
source = ::OpenSCAP::Source.new in_file
|
12
|
+
sds = ::OpenSCAP::DS::Sds.new source
|
13
|
+
sds.select_checklist
|
14
|
+
html = sds.html_guide policy
|
15
|
+
File.write(out_file, { :html => html.force_encoding('UTF-8') }.to_json)
|
16
|
+
ensure
|
17
|
+
sds.destroy if sds
|
18
|
+
source.destroy if source
|
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,52 @@
|
|
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
|
+
benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
47
|
+
ensure
|
48
|
+
sds.destroy if sds
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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
|
@@ -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
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Proxy::OpenSCAP
|
2
|
+
class SpoolForwarder
|
3
|
+
include ::Proxy::Log
|
4
|
+
|
5
|
+
def initialize(loaded_settings)
|
6
|
+
@loaded_settings = loaded_settings
|
7
|
+
end
|
8
|
+
|
9
|
+
def post_arf_from_spool(arf_dir)
|
10
|
+
Dir.foreach(arf_dir) do |cname|
|
11
|
+
next if cname == '.' || cname == '..'
|
12
|
+
cname_dir = File.join(arf_dir, cname)
|
13
|
+
forward_cname_dir(cname, cname_dir) if File.directory?(cname_dir)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def forward_cname_dir(cname, cname_dir)
|
20
|
+
Dir.foreach(cname_dir) do |policy_id|
|
21
|
+
next if policy_id == '.' || policy_id == '..'
|
22
|
+
policy_dir = File.join(cname_dir, policy_id)
|
23
|
+
if File.directory?(policy_dir)
|
24
|
+
forward_policy_dir(cname, policy_id, policy_dir)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
remove_if_empty(cname_dir)
|
28
|
+
end
|
29
|
+
|
30
|
+
def forward_policy_dir(cname, policy_id, policy_dir)
|
31
|
+
Dir.foreach(policy_dir) do |date|
|
32
|
+
next if date == '.' || date == '..'
|
33
|
+
date_dir = File.join(policy_dir, date)
|
34
|
+
if File.directory?(date_dir)
|
35
|
+
forward_date_dir(cname, policy_id, date, date_dir)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
remove_if_empty(policy_dir)
|
39
|
+
end
|
40
|
+
|
41
|
+
def forward_date_dir(cname, policy_id, date, date_dir)
|
42
|
+
Dir.foreach(date_dir) do |arf|
|
43
|
+
next if arf == '.' || arf == '..'
|
44
|
+
arf_path = File.join(date_dir, arf)
|
45
|
+
if File.file?(arf_path)
|
46
|
+
logger.debug("Uploading #{arf} to Foreman")
|
47
|
+
forward_arf_file(cname, policy_id, date, arf_path)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
remove_if_empty(date_dir)
|
51
|
+
end
|
52
|
+
|
53
|
+
def forward_arf_file(cname, policy_id, date, arf_file_path)
|
54
|
+
data = File.open(arf_file_path, 'rb') { |io| io.read }
|
55
|
+
post_to_foreman = ForemanForwarder.new.post_arf_report(cname, policy_id, date, data, @loaded_settings.timeout)
|
56
|
+
Proxy::OpenSCAP::StorageFS.new(@loaded_settings.reportsdir, cname, post_to_foreman['id'], date).store_archive(data)
|
57
|
+
File.delete arf_file_path
|
58
|
+
rescue Proxy::OpenSCAP::OpenSCAPException => e
|
59
|
+
logger.error "Failed to parse Arf Report at #{arf_file_path}, moving to #{@loaded_settings.corrupted_dir}"
|
60
|
+
|
61
|
+
Proxy::OpenSCAP::StorageFS.new(@loaded_settings.corrupted_dir, cname, policy_id, date).
|
62
|
+
move_corrupted(arf_file_path.split('/').last, @loaded_settings.spooldir)
|
63
|
+
rescue Proxy::OpenSCAP::ReportUploadError => e
|
64
|
+
logger.error "Failed to upload Arf Report at #{arf_file_path}, cause: #{e.message}, the report will be deleted."
|
65
|
+
File.delete arf_file_path
|
66
|
+
rescue StandardError => e
|
67
|
+
logger.error "smart-proxy-openscap-send failed to upload Compliance report for #{cname}, generated on #{Time.at date.to_i}. Cause: #{e}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def remove_if_empty(dir)
|
71
|
+
begin
|
72
|
+
Dir.delete dir if Dir["#{dir}/*"].empty?
|
73
|
+
logger.debug "Removing directory: #{dir}"
|
74
|
+
rescue StandardError => e
|
75
|
+
logger.error "Could not remove directory: #{e.message}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|