smart_proxy_openscap 0.6.4 → 0.6.5

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