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
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem 'test-unit'
|
6
|
+
gem 'pry'
|
7
|
+
gem 'rubocop'
|
8
|
+
gem 'rack', '~> 1.6.8' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2')
|
9
|
+
gem 'smart_proxy', :github => "theforeman/smart-proxy", :branch => 'develop'
|
10
|
+
end
|
11
|
+
|
12
|
+
# load local gemfile
|
13
|
+
local_gemfile = File.join(File.dirname(__FILE__), 'Gemfile.local.rb')
|
14
|
+
self.instance_eval(Bundler.read_file(local_gemfile)) if File.exist?(local_gemfile)
|
data/README.md
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# OpenSCAP plug-in for Foreman Proxy
|
2
|
+
|
3
|
+
A plug-in to the Foreman Proxy which receives bzip2ed ARF files
|
4
|
+
and forwards them as JSON to the Foreman.
|
5
|
+
smart_proxy_openscap plugin is required for the normal operation of OpenSCAP in the Foreman.
|
6
|
+
|
7
|
+
## How it works
|
8
|
+
|
9
|
+
Incoming ARF files are authenticated using either puppet certificate or Katello certificate of
|
10
|
+
the client machine. The ARF files are parsed on the proxy and posted to the Foreman as JSON reports
|
11
|
+
and the ARF files are saved in a reports directory, where they can be accessed for full HTML report or
|
12
|
+
downloaded as bzip2ed xml report.
|
13
|
+
If posting is failed, the ARF files are saved in queue for later retry.
|
14
|
+
|
15
|
+
Learn more about [Foreman-OpenSCAP](https://github.com/theforeman/foreman_openscap) workflow.
|
16
|
+
|
17
|
+
## Installation from RPMs
|
18
|
+
|
19
|
+
- Install smart_proxy_openscap
|
20
|
+
|
21
|
+
```
|
22
|
+
# yum install rubygem-smart_proxy_openscap
|
23
|
+
```
|
24
|
+
|
25
|
+
## Installation from upstream git
|
26
|
+
- Add smart_proxy_openscap to your smart proxy `bundler.d/openscap.rb` gemfile:
|
27
|
+
|
28
|
+
```
|
29
|
+
~$ gem 'smart_proxy_openscap', :git => 'https://github.com/theforeman/smart_proxy_openscap.git'
|
30
|
+
```
|
31
|
+
|
32
|
+
If you don't install through RPM and you are using bundler, you may need to create
|
33
|
+
/var/spool/foreman-proxy & /usr/share/foreman-proxy/openscap directories manually and
|
34
|
+
set it's owner to the user under which foreman-proxy runs.
|
35
|
+
|
36
|
+
## Configuration
|
37
|
+
|
38
|
+
```
|
39
|
+
cp /etc/foreman-proxy/settings.d/openscap.yml{.example,}
|
40
|
+
```
|
41
|
+
Configure the following parameters so it would look like:
|
42
|
+
|
43
|
+
```
|
44
|
+
---
|
45
|
+
:enabled: true
|
46
|
+
|
47
|
+
# Log file for the forwarding script.
|
48
|
+
:openscap_send_log_file: /var/log/foreman-proxy/openscap-send.log
|
49
|
+
|
50
|
+
# Directory where OpenSCAP audits are stored
|
51
|
+
# before they are forwarded to Foreman
|
52
|
+
:spooldir: /var/spool/foreman-proxy/openscap
|
53
|
+
|
54
|
+
# Directory where OpenSCAP content XML are stored
|
55
|
+
# So we will not request the XML from Foreman each time
|
56
|
+
:contentdir: /var/lib/openscap/content
|
57
|
+
# Directory where OpenSCAP report XML are stored
|
58
|
+
# So Foreman can request arf xml reports
|
59
|
+
:reportsdir: /usr/share/foreman-proxy/openscap/content
|
60
|
+
```
|
61
|
+
|
62
|
+
- Deploy
|
63
|
+
|
64
|
+
```
|
65
|
+
~# service foreman-proxy restart
|
66
|
+
```
|
67
|
+
|
68
|
+
## Usage
|
69
|
+
|
70
|
+

|
71
|
+
|
72
|
+
### Exposed APIs
|
73
|
+
|
74
|
+
* POST "/compliance/arf/:policy" - API to recieve ARF files, parse them and post to the Foreman. `:policy` is the policy ID from Foreman. expects ARF bzip2 file as POST body
|
75
|
+
|
76
|
+
* GET "/compliance/arf/:id/:cname/:date/:digest/xml" - API to download bizped2 ARF file. `:id` - ArfReport id, `:cname` - Host name, `:date` - Report date, `:digest` - Digest of the Arf file
|
77
|
+
|
78
|
+
* GET "/compliance/arf/:id/:cname/:date/:digest/html" - API to fetch full HTML report. `:id` - ArfReport id, `:cname` - Host name, `:date` - Report date, `:digest` - Digest of the Arf file
|
79
|
+
|
80
|
+
* GET "/compliance/policies/:policy_id/content" - API to download and serve SCAP content file for policy. `:policy_id` - Policy id from Foreman
|
81
|
+
|
82
|
+
* POST "/compliance/scap_content/policies" - API to extract policies from SCAP content. expects SCAP content posted as the POST body
|
83
|
+
|
84
|
+
* POST "/compliance/scap_content/validator" - API to validate SCAP content. expects SCAP content posted as the POST body
|
85
|
+
|
86
|
+
* POST "/compliance/scap_content/guide/:policy" - API to return Policy's HTML guide. `:policy` - policy name. expects SCAP content posted as the POST body
|
87
|
+
|
88
|
+
### Binaries
|
89
|
+
|
90
|
+
* `smart_proxy_openscap_send` - Sends failed ARF files to Foreman (in case first try failed). When installed with RPM, a cron jobs is configured to run every 30 minutes.
|
91
|
+
|
92
|
+
## Copyright
|
93
|
+
|
94
|
+
Copyright (c) 2014--2015 Red Hat, Inc.
|
95
|
+
|
96
|
+
This program is free software: you can redistribute it and/or modify
|
97
|
+
it under the terms of the GNU General Public License as published by
|
98
|
+
the Free Software Foundation, either version 3 of the License, or
|
99
|
+
(at your option) any later version.
|
100
|
+
|
101
|
+
This program is distributed in the hope that it will be useful,
|
102
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
103
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
104
|
+
GNU General Public License for more details.
|
105
|
+
|
106
|
+
You should have received a copy of the GNU General Public License
|
107
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
desc 'Default: run unit tests.'
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
desc 'Test the Smart Proxy OpenSCAP.'
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << '.'
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.libs << 'test'
|
14
|
+
t.test_files = FileList['test/**/*_test.rb']
|
15
|
+
t.verbose = true
|
16
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (c) 2014--2015 Red Hat Inc.
|
4
|
+
#
|
5
|
+
# This software is licensed to you under the GNU General Public License,
|
6
|
+
# version 3 (GPLv3). There is NO WARRANTY for this software, express or
|
7
|
+
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
|
8
|
+
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv3
|
9
|
+
# along with this software; if not, see http://www.gnu.org/licenses/gpl.txt
|
10
|
+
#
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift '/usr/share/foreman-proxy/lib'
|
13
|
+
$LOAD_PATH.unshift '/usr/share/foreman-proxy/modules'
|
14
|
+
|
15
|
+
require 'smart_proxy'
|
16
|
+
require 'smart_proxy_main'
|
17
|
+
require 'smart_proxy_openscap'
|
18
|
+
require 'smart_proxy_openscap/openscap_lib'
|
19
|
+
|
20
|
+
loaded_settings = Proxy::OpenSCAP.plugin_settings
|
21
|
+
|
22
|
+
# Don't run if OpenSCAP plugin is disabled or settings are missing.
|
23
|
+
if !loaded_settings.enabled || loaded_settings.nil? || loaded_settings.empty?
|
24
|
+
exit 436
|
25
|
+
end
|
26
|
+
|
27
|
+
module Proxy
|
28
|
+
module Log
|
29
|
+
@@logger = ::Logger.new(Proxy::OpenSCAP.fullpath(Proxy::OpenSCAP.plugin_settings.openscap_send_log_file), 6, 1024*1024*10)
|
30
|
+
@@logger.level = ::Logger.const_get(Proxy::SETTINGS.log_level.upcase)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
include Proxy::Log
|
34
|
+
|
35
|
+
if !Proxy::SETTINGS.foreman_url
|
36
|
+
logger.error "Foreman URL not configured"
|
37
|
+
exit 437
|
38
|
+
end
|
39
|
+
|
40
|
+
lockfile = File.join(loaded_settings.spooldir, "spool.lock")
|
41
|
+
|
42
|
+
Signal.trap("TERM") {
|
43
|
+
FileUtils.rm(lockfile) if File.exist?(lockfile)
|
44
|
+
exit
|
45
|
+
}
|
46
|
+
|
47
|
+
if File.exist? lockfile
|
48
|
+
logger.debug "Lock file #{lockfile} for openscap spool exists, not sending spool to server"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
FileUtils.touch lockfile
|
54
|
+
Proxy::OpenSCAP::send_spool_to_foreman(loaded_settings)
|
55
|
+
rescue StandardError => e
|
56
|
+
logger.error e
|
57
|
+
puts "#{e} See #{Proxy::OpenSCAP.fullpath(loaded_settings.openscap_send_log_file)}"
|
58
|
+
exit 438
|
59
|
+
ensure
|
60
|
+
FileUtils.rm lockfile
|
61
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
%global gem_name smart_proxy_openscap
|
2
|
+
|
3
|
+
%global foreman_proxy_bundlerd_dir /usr/share/foreman-proxy/bundler.d
|
4
|
+
%global foreman_proxy_pluginconf_dir /etc/foreman-proxy/settings.d
|
5
|
+
%global spool_dir /var/spool/foreman-proxy/openscap
|
6
|
+
%global proxy_user foreman-proxy
|
7
|
+
|
8
|
+
Name: rubygem-%{gem_name}
|
9
|
+
Version: 0.3.0
|
10
|
+
Release: 1%{?dist}
|
11
|
+
Summary: OpenSCAP plug-in for Foreman's smart-proxy.
|
12
|
+
Group: Applications/Internet
|
13
|
+
License: GPLv2+
|
14
|
+
URL: http://github.com/openscap/smart_proxy_openscap
|
15
|
+
Source0: https://rubygems.org/gems/%{gem_name}-%{version}.gem
|
16
|
+
#Requires: ruby(release)
|
17
|
+
Requires: ruby(rubygems)
|
18
|
+
Requires: foreman-proxy >= 1.7.0-0.develop.201410221520
|
19
|
+
Requires: crontabs
|
20
|
+
#BuildRequires: ruby(release)
|
21
|
+
BuildRequires: rubygems-devel
|
22
|
+
BuildRequires: ruby
|
23
|
+
BuildArch: noarch
|
24
|
+
Provides: rubygem(%{gem_name}) = %{version}
|
25
|
+
Obsoletes: rubygem-foreman-proxy_openscap
|
26
|
+
|
27
|
+
%description
|
28
|
+
A plug-in to the Foreman's smart-proxy which receives bzip2ed ARF files
|
29
|
+
and forwards them to the Foreman.
|
30
|
+
|
31
|
+
%prep
|
32
|
+
gem unpack %{SOURCE0}
|
33
|
+
%setup -q -D -T -n %{gem_name}-%{version}
|
34
|
+
gem spec %{SOURCE0} -l --ruby > %{gem_name}.gemspec
|
35
|
+
|
36
|
+
%build
|
37
|
+
# Create the gem as gem install only works on a gem file
|
38
|
+
gem build %{gem_name}.gemspec
|
39
|
+
|
40
|
+
# %%gem_install compiles any C extensions and installs the gem into ./%gem_dir
|
41
|
+
# by default, so that we can move it into the buildroot in %%install
|
42
|
+
%gem_install
|
43
|
+
|
44
|
+
%install
|
45
|
+
mkdir -p %{buildroot}%{gem_dir}
|
46
|
+
cp -a .%{gem_dir}/* \
|
47
|
+
%{buildroot}%{gem_dir}/
|
48
|
+
mv %{buildroot}%{gem_instdir}/%{gem_name}.gemspec %{buildroot}/%{gem_spec}
|
49
|
+
rm %{buildroot}%{gem_instdir}/extra/*.spec # this specfile
|
50
|
+
|
51
|
+
# executables
|
52
|
+
mkdir -p %{buildroot}%{_bindir}
|
53
|
+
mv %{buildroot}%{gem_instdir}/bin/* \
|
54
|
+
%{buildroot}%{_bindir}
|
55
|
+
|
56
|
+
# bundler file
|
57
|
+
mkdir -p %{buildroot}%{foreman_proxy_bundlerd_dir}
|
58
|
+
mv %{buildroot}%{gem_instdir}/bundler.d/openscap.rb \
|
59
|
+
%{buildroot}%{foreman_proxy_bundlerd_dir}
|
60
|
+
|
61
|
+
# sample config
|
62
|
+
mkdir -p %{buildroot}%{foreman_proxy_pluginconf_dir}
|
63
|
+
mv %{buildroot}%{gem_instdir}/settings.d/openscap.yml.example \
|
64
|
+
%{buildroot}%{foreman_proxy_pluginconf_dir}/
|
65
|
+
|
66
|
+
# crontab
|
67
|
+
mkdir -p %{buildroot}%{_sysconfdir}/cron.d/
|
68
|
+
mv %{buildroot}%{gem_instdir}/extra/smart-proxy-openscap-send.cron \
|
69
|
+
%{buildroot}%{_sysconfdir}/cron.d/%{name}
|
70
|
+
|
71
|
+
# create spool directory
|
72
|
+
mkdir -p %{buildroot}%{spool_dir}
|
73
|
+
|
74
|
+
%files
|
75
|
+
%dir %{gem_instdir}
|
76
|
+
%{gem_libdir}
|
77
|
+
%exclude %{gem_cache}
|
78
|
+
%{gem_spec}
|
79
|
+
|
80
|
+
%attr(-,%{proxy_user},%{proxy_user}) %{spool_dir}
|
81
|
+
%{foreman_proxy_bundlerd_dir}/openscap.rb
|
82
|
+
%{_bindir}/smart-proxy-openscap-send
|
83
|
+
%doc %{foreman_proxy_pluginconf_dir}/openscap.yml.example
|
84
|
+
%config(noreplace) %attr(0644, root, root) %{_sysconfdir}/cron.d/%{name}
|
85
|
+
|
86
|
+
%{gem_docdir}
|
87
|
+
%{gem_instdir}/README.md
|
88
|
+
%{gem_instdir}/COPYING
|
89
|
+
|
90
|
+
%changelog
|
91
|
+
* Tue Jan 20 2015 Šimon Lukašík <slukasik@redhat.com> - 0.3.0-1
|
92
|
+
- new upstream release
|
93
|
+
|
94
|
+
* Tue Jan 20 2015 Šimon Lukašík <slukasik@redhat.com> - 0.1.0-2
|
95
|
+
- renamed to smart_proxy_openscap
|
96
|
+
|
97
|
+
* Fri Oct 24 2014 Šimon Lukašík <slukasik@redhat.com> - 0.1.0-1
|
98
|
+
- rebuilt
|
99
|
+
|
100
|
+
* Fri Jul 18 2014 Šimon Lukašík <slukasik@redhat.com> - 0.0.1-1
|
101
|
+
- Initial package
|
@@ -0,0 +1,14 @@
|
|
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 'smart_proxy_openscap/openscap_plugin'
|
12
|
+
|
13
|
+
module Proxy::OpenSCAP
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
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
|
+
ensure
|
11
|
+
::OpenSCAP.oscap_cleanup
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_arf_html(file_in)
|
15
|
+
arf_object = ::OpenSCAP::DS::Arf.new(file_in)
|
16
|
+
# @TODO: Drop this when support for 1.8.7 ends
|
17
|
+
return arf_object.html if RUBY_VERSION.start_with? '1.8'
|
18
|
+
arf_object.html.force_encoding('UTF-8')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# encoding=utf-8
|
2
|
+
require 'openscap'
|
3
|
+
require 'openscap/ds/arf'
|
4
|
+
require 'openscap/xccdf/testresult'
|
5
|
+
require 'openscap/xccdf/ruleresult'
|
6
|
+
require 'openscap/xccdf/rule'
|
7
|
+
require 'openscap/xccdf/fix'
|
8
|
+
require 'openscap/xccdf/benchmark'
|
9
|
+
require 'json'
|
10
|
+
require 'digest'
|
11
|
+
|
12
|
+
module Proxy
|
13
|
+
module OpenSCAP
|
14
|
+
class ArfJson
|
15
|
+
def as_json(file_in, file_out, proxy_name, proxy_url)
|
16
|
+
::OpenSCAP.oscap_init
|
17
|
+
arf_digest = Digest::SHA256.hexdigest(File.read(file_in))
|
18
|
+
|
19
|
+
arf = ::OpenSCAP::DS::Arf.new(file_in)
|
20
|
+
test_result = arf.test_result
|
21
|
+
|
22
|
+
results = test_result.rr
|
23
|
+
sds = arf.report_request
|
24
|
+
bench_source = sds.select_checklist!
|
25
|
+
benchmark = ::OpenSCAP::Xccdf::Benchmark.new(bench_source)
|
26
|
+
items = benchmark.items
|
27
|
+
|
28
|
+
report = parse_results(items, results, arf_digest)
|
29
|
+
report[:openscap_proxy_name] = proxy_name
|
30
|
+
report[:openscap_proxy_url] = proxy_url
|
31
|
+
|
32
|
+
File.write file_out, report.to_json
|
33
|
+
ensure
|
34
|
+
cleanup test_result, benchmark, sds, arf
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def parse_results(items, results, arf_digest)
|
40
|
+
report = {}
|
41
|
+
report[:logs] = []
|
42
|
+
passed = 0
|
43
|
+
failed = 0
|
44
|
+
othered = 0
|
45
|
+
results.each do |rr_id, result|
|
46
|
+
next if result.result == 'notapplicable' || result.result == 'notselected'
|
47
|
+
# get rules and their results
|
48
|
+
rule_data = items[rr_id]
|
49
|
+
report[:logs] << populate_result_data(rr_id, result.result, rule_data)
|
50
|
+
# create metrics for the results
|
51
|
+
case result.result
|
52
|
+
when 'pass', 'fixed'
|
53
|
+
passed += 1
|
54
|
+
when 'fail'
|
55
|
+
failed += 1
|
56
|
+
else
|
57
|
+
othered += 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
report[:digest] = arf_digest
|
61
|
+
report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
|
62
|
+
report
|
63
|
+
end
|
64
|
+
|
65
|
+
def populate_result_data(result_id, rule_result, rule_data)
|
66
|
+
log = {}
|
67
|
+
log[:source] = ascii8bit_to_utf8(result_id)
|
68
|
+
log[:result] = ascii8bit_to_utf8(rule_result)
|
69
|
+
log[:title] = ascii8bit_to_utf8(rule_data.title)
|
70
|
+
log[:description] = ascii8bit_to_utf8(rule_data.description)
|
71
|
+
log[:rationale] = ascii8bit_to_utf8(rule_data.rationale)
|
72
|
+
log[:references] = hash_a8b(rule_data.references.map(&:to_hash))
|
73
|
+
log[:fixes] = hash_a8b(rule_data.fixes.map(&:to_hash))
|
74
|
+
log[:severity] = ascii8bit_to_utf8(rule_data.severity)
|
75
|
+
log
|
76
|
+
end
|
77
|
+
|
78
|
+
def cleanup(*args)
|
79
|
+
args.compact.map(&:destroy)
|
80
|
+
::OpenSCAP.oscap_cleanup
|
81
|
+
end
|
82
|
+
|
83
|
+
# Unfortunately openscap in ruby 1.9.3 outputs data in Ascii-8bit.
|
84
|
+
# We transform it to UTF-8 for easier json integration.
|
85
|
+
|
86
|
+
# :invalid ::
|
87
|
+
# If the value is invalid, #encode replaces invalid byte sequences in
|
88
|
+
# +str+ with the replacement character. The default is to raise the
|
89
|
+
# Encoding::InvalidByteSequenceError exception
|
90
|
+
# :undef ::
|
91
|
+
# If the value is undefined, #encode replaces characters which are
|
92
|
+
# undefined in the destination encoding with the replacement character.
|
93
|
+
# The default is to raise the Encoding::UndefinedConversionError.
|
94
|
+
# :replace ::
|
95
|
+
# Sets the replacement string to the given value. The default replacement
|
96
|
+
# string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
|
97
|
+
def ascii8bit_to_utf8(string)
|
98
|
+
return ascii8bit_to_utf8_legacy(string) if RUBY_VERSION.start_with? '1.8'
|
99
|
+
string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
|
100
|
+
end
|
101
|
+
|
102
|
+
# String#encode appeared first in 1.9, so we need a workaround for 1.8
|
103
|
+
def ascii8bit_to_utf8_legacy(string)
|
104
|
+
Iconv.conv('UTF-8//IGNORE', 'UTF-8', string.to_s)
|
105
|
+
end
|
106
|
+
|
107
|
+
def hash_a8b(ary)
|
108
|
+
ary.map do |hash|
|
109
|
+
Hash[hash.map { |key, value| [ascii8bit_to_utf8(key), ascii8bit_to_utf8(value)] }]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|