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