smart_proxy_openscap 0.6.4 → 0.6.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 75a10b67932ee57464ae6b077cb0de13414400f8
4
- data.tar.gz: 20d0b754e52f0a5c8c24f6c58cd1c460ac9cf0d5
3
+ metadata.gz: e666336bf02a0dc32630813e523d0af008006603
4
+ data.tar.gz: e5fbd577be166d0b2ca4d79841c7753a7b958577
5
5
  SHA512:
6
- metadata.gz: 0055e9a3aa52ef8ca032942cffe3a03cc3455411d90642446dc33bfe406c0fdf1392f590c83ccb787ac5f3a5f670b4bcfa3a9092230356c5467cc4558f0b4dba
7
- data.tar.gz: b12e3ebd02a8194528f49e88e253fb319bcd13f4c97579cea9c72d1094548f6558d78a8da2ae1250cc730a8fcf2b54f4dc119d07b82ca768ef8a1e9cf4db8032
6
+ metadata.gz: 76bfca9428e45706fcd289da3dabea7c145c540a1a58bcce5a9ecdd016cabaf4192b1b563035cf142deeb97f5058b69b0e332bbbdfb28d7cda8b746dbd6b8b04
7
+ data.tar.gz: 021058331dd2a2ebd832e0ea59c58021cfa8a22fc3b36265ae5743a7d8a7478ed6793d614e0033d4374d6a601d14a57e91779bbec4dc59cc071cb6e60f94e441
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ group :development do
5
5
  gem 'test-unit'
6
6
  gem 'pry'
7
7
  gem 'rubocop'
8
+ gem 'rack', '~> 1.6.8' if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2')
8
9
  gem 'smart_proxy', :github => "theforeman/smart-proxy", :branch => 'develop'
9
10
  end
10
11
 
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ path = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib')
3
+ $:.unshift(path) if File.exist? path
4
+
5
+ require 'smart_proxy_openscap/arf_parser'
6
+
7
+ Proxy::OpenSCAP::ArfParser.new.parse ARGV[0], ARGV[1]
@@ -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 ArfParser
15
+ def parse(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
@@ -3,23 +3,19 @@ module Proxy::OpenSCAP
3
3
  include ::Proxy::Log
4
4
 
5
5
  def post_arf_report(cname, policy_id, date, data)
6
- parser = Proxy::OpenSCAP::Parse.new(data)
7
6
  begin
8
7
  foreman_api_path = upload_path(cname, policy_id, date)
9
- response = send_request(foreman_api_path, parser.as_json)
8
+ json = Proxy::OpenSCAP::Parse.new(cname, policy_id, date).as_json(data)
9
+ raise OpenSCAP::OpenSCAPError, "Failed to parse report" if json.nil? || json.empty?
10
+ response = send_request(foreman_api_path, json)
10
11
  # Raise an HTTP error if the response is not 2xx (success).
11
12
  response.value
12
13
  res = JSON.parse(response.body)
13
14
  raise StandardError, "Received response: #{response.code} #{response.msg}" unless res['result'] == 'OK'
14
- rescue OpenSCAP::OpenSCAPError => e
15
- logger.debug e.backtrace.join("\n\t")
16
- raise e
17
15
  rescue StandardError => e
18
16
  logger.debug response.body if response
19
17
  logger.debug e.backtrace.join("\n\t")
20
18
  raise e
21
- ensure
22
- parser.cleanup
23
19
  end
24
20
  res
25
21
  end
@@ -6,14 +6,12 @@ require 'openscap/xccdf/tailoring'
6
6
  module Proxy::OpenSCAP
7
7
  class ContentParser
8
8
  def initialize(scap_file, type = 'scap_content')
9
- OpenSCAP.oscap_init
10
9
  @source = OpenSCAP::Source.new(:content => scap_file)
11
10
  @type = type
12
11
  end
13
12
 
14
13
  def cleanup
15
14
  @source.destroy if @source
16
- OpenSCAP.oscap_cleanup
17
15
  end
18
16
 
19
17
  def allowed_types
@@ -0,0 +1,21 @@
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
@@ -9,6 +9,7 @@
9
9
  #
10
10
 
11
11
  require 'smart_proxy_openscap/version'
12
+ require 'smart_proxy_openscap/plugin_configuration'
12
13
 
13
14
  module Proxy::OpenSCAP
14
15
  class Plugin < ::Proxy::Plugin
@@ -23,5 +24,10 @@ module Proxy::OpenSCAP
23
24
  :reportsdir => File.join(APP_ROOT, 'openscap/reports'),
24
25
  :failed_dir => File.join(APP_ROOT, 'openscap/failed'),
25
26
  :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
26
32
  end
27
33
  end
@@ -1,110 +1,47 @@
1
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 'iconv' if RUBY_VERSION.start_with? '1.8'
11
-
12
- module Proxy::OpenSCAP
13
- class Parse
14
- def initialize(arf_data)
15
- OpenSCAP.oscap_init
16
- size = arf_data.size
17
- @arf_digest = Digest::SHA256.hexdigest(arf_data)
18
- @arf = OpenSCAP::DS::Arf.new(:content => arf_data, :path => 'arf.xml.bz2', :length => size)
19
- @test_result = @arf.test_result
20
-
21
- @results = @test_result.rr
22
- @sds = @arf.report_request
23
- bench_source = @sds.select_checklist!
24
- @benchmark = OpenSCAP::Xccdf::Benchmark.new(bench_source)
25
- @items = @benchmark.items
26
- end
27
-
28
- def cleanup
29
- @test_result.destroy if @test_result
30
- @benchmark.destroy if @benchmark
31
- @sds.destroy if @sds
32
- @arf.destroy if @arf
33
- OpenSCAP.oscap_cleanup
34
- end
35
-
36
- def as_json
37
- parse_report.to_json
38
- end
39
-
40
- private
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
41
15
 
42
- def parse_report
43
- report = {}
44
- report[:logs] = []
45
- passed = 0
46
- failed = 0
47
- othered = 0
48
- @results.each do |rr_id, result|
49
- next if result.result == 'notapplicable' || result.result == 'notselected'
50
- # get rules and their results
51
- rule_data = @items[rr_id]
52
- report[:logs] << populate_result_data(rr_id, result.result, rule_data)
53
- # create metrics for the results
54
- case result.result
55
- when 'pass', 'fixed'
56
- passed += 1
57
- when 'fail'
58
- failed += 1
59
- else
60
- othered += 1
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
61
34
  end
62
35
  end
63
- report[:digest] = @arf_digest
64
- report[:metrics] = { :passed => passed, :failed => failed, :othered => othered }
65
- report
66
- end
67
-
68
- def populate_result_data(result_id, rule_result, rule_data)
69
- log = {}
70
- log[:source] = ascii8bit_to_utf8(result_id)
71
- log[:result] = ascii8bit_to_utf8(rule_result)
72
- log[:title] = ascii8bit_to_utf8(rule_data.title)
73
- log[:description] = ascii8bit_to_utf8(rule_data.description)
74
- log[:rationale] = ascii8bit_to_utf8(rule_data.rationale)
75
- log[:references] = hash_a8b(rule_data.references.map(&:to_hash))
76
- log[:fixes] = hash_a8b(rule_data.fixes.map(&:to_hash))
77
- log[:severity] = ascii8bit_to_utf8(rule_data.severity)
78
- log
79
- end
80
-
81
- # Unfortunately openscap in ruby 1.9.3 outputs data in Ascii-8bit.
82
- # We transform it to UTF-8 for easier json integration.
83
36
 
84
- # :invalid ::
85
- # If the value is invalid, #encode replaces invalid byte sequences in
86
- # +str+ with the replacement character. The default is to raise the
87
- # Encoding::InvalidByteSequenceError exception
88
- # :undef ::
89
- # If the value is undefined, #encode replaces characters which are
90
- # undefined in the destination encoding with the replacement character.
91
- # The default is to raise the Encoding::UndefinedConversionError.
92
- # :replace ::
93
- # Sets the replacement string to the given value. The default replacement
94
- # string is "\uFFFD" for Unicode encoding forms, and "?" otherwise.
95
- def ascii8bit_to_utf8(string)
96
- return ascii8bit_to_utf8_legacy(string) if RUBY_VERSION.start_with? '1.8'
97
- string.to_s.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
98
- end
99
-
100
- # String#encode appeared first in 1.9, so we need a workaround for 1.8
101
- def ascii8bit_to_utf8_legacy(string)
102
- Iconv.conv('UTF-8//IGNORE', 'UTF-8', string.to_s)
103
- end
37
+ def filename
38
+ "#{@cname}-#{@policy_id}-#{@date}-"
39
+ end
104
40
 
105
- def hash_a8b(ary)
106
- ary.map do |hash|
107
- Hash[hash.map { |key, value| [ascii8bit_to_utf8(key), ascii8bit_to_utf8(value)] }]
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"
108
45
  end
109
46
  end
110
47
  end
@@ -0,0 +1,13 @@
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
@@ -28,7 +28,6 @@ module Proxy::OpenSCAP
28
28
  end
29
29
 
30
30
  def get_arf_html(digest)
31
- OpenSCAP.oscap_init
32
31
  xml = get_arf_file(digest)[:xml]
33
32
  size = get_arf_file(digest)[:size]
34
33
  arf_object = OpenSCAP::DS::Arf.new(:content => xml, :path => 'arf.xml.bz2', :length => size)
@@ -10,6 +10,6 @@
10
10
 
11
11
  module Proxy
12
12
  module OpenSCAP
13
- VERSION = '0.6.4'
13
+ VERSION = '0.6.5'
14
14
  end
15
15
  end
@@ -39,7 +39,9 @@ class OpenSCAPGetArfTest < Test::Unit::TestCase
39
39
  end
40
40
 
41
41
  def test_get_html_arf
42
+ OpenSCAP.oscap_init
42
43
  get "/arf/#{@arf_id}/#{@cname}/#{@date}/#{@filename}/html"
44
+ OpenSCAP.oscap_cleanup
43
45
  assert(last_response.successful?, "Should return OK")
44
46
  assert(last_response.body.start_with?('<!DOCTYPE'), 'File should start with html')
45
47
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_openscap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.4
4
+ version: 0.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Šimon Lukašík"
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-04-12 00:00:00.000000000 Z
13
+ date: 2017-07-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -98,10 +98,12 @@ files:
98
98
  - README.md
99
99
  - Rakefile
100
100
  - bin/smart-proxy-openscap-send
101
+ - bin/smart-proxy-parse-arf
101
102
  - bundler.d/openscap.rb
102
103
  - extra/rubygem-smart_proxy_openscap.spec
103
104
  - extra/smart-proxy-openscap-send.cron
104
105
  - lib/smart_proxy_openscap.rb
106
+ - lib/smart_proxy_openscap/arf_parser.rb
105
107
  - lib/smart_proxy_openscap/fetch_file.rb
106
108
  - lib/smart_proxy_openscap/fetch_scap_content.rb
107
109
  - lib/smart_proxy_openscap/fetch_tailoring_file.rb
@@ -111,9 +113,11 @@ files:
111
113
  - lib/smart_proxy_openscap/openscap_content_parser.rb
112
114
  - lib/smart_proxy_openscap/openscap_exception.rb
113
115
  - lib/smart_proxy_openscap/openscap_import_api.rb
116
+ - lib/smart_proxy_openscap/openscap_initializer.rb
114
117
  - lib/smart_proxy_openscap/openscap_lib.rb
115
118
  - lib/smart_proxy_openscap/openscap_plugin.rb
116
119
  - lib/smart_proxy_openscap/openscap_report_parser.rb
120
+ - lib/smart_proxy_openscap/plugin_configuration.rb
117
121
  - lib/smart_proxy_openscap/spool_forwarder.rb
118
122
  - lib/smart_proxy_openscap/storage.rb
119
123
  - lib/smart_proxy_openscap/storage_fs.rb
@@ -157,8 +161,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
161
  version: '0'
158
162
  requirements: []
159
163
  rubyforge_project:
160
- rubygems_version: 2.4.5
164
+ rubygems_version: 2.4.6
161
165
  signing_key:
162
166
  specification_version: 4
163
167
  summary: OpenSCAP plug-in for Foreman's smart-proxy.
164
168
  test_files: []
169
+ has_rdoc: