foreman_scap_client 0.4.7 → 0.5.0

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
  SHA256:
3
- metadata.gz: 613e57e5fe5d504abb771c1924649c18d3a01869e3d75fbf33c4d2078647dcaa
4
- data.tar.gz: f5d061fd7061174a3ce2dd92348371a9cb672781b428950ccc7add94b1fa8b69
3
+ metadata.gz: 83d36963b277620c532c048595b0bc57f024918bcf0ee44073930bd0297b4b56
4
+ data.tar.gz: 9acaf0257a5c1b18ab6f096a2f4025e8d5732ee4e7a45ef195853fe70ab9dd55
5
5
  SHA512:
6
- metadata.gz: 6e7d76224ae9440cad7ba6592a0aee99909ec7be581e1da4bc9310b74161504127b9631148bd5371bc7616718eac76b64a6565c04250c0488ac24d2db5860104
7
- data.tar.gz: 2c6a1f7531f5a996847718255dca2e3bf4d1d5b091242402e71748450e3971ead373031217b3ce9b96d84aa568018374aacf37943786943db4becf068150d922
6
+ metadata.gz: 4d68a98ce43eb6ebae0f268a56c1ca87d2f84748e783c1bfda80ffbf170cf4443929b32543d9a30da85a6c554ff7b2952a275a90f98b521c63cae63ff562ebad
7
+ data.tar.gz: fc864752d527e1118ed4f4a147921ea4b5dd5c49f995e298a10a9400561f7df2bbf2a88bb8137a9c9262b781d791aad4fea672b652a1692d63e075aa3199e777
@@ -2,11 +2,22 @@
2
2
  require 'rubygems'
3
3
  require 'foreman_scap_client'
4
4
 
5
- if ARGV.size != 1
6
- puts "Usage: #{$0} policy_id"
7
- puts " where policy_id is a key used in config file"
8
- exit 2
5
+ if ARGV.last == '--skip-upload'
6
+ skip_upload = true
7
+ args = ARGV[0...-1]
9
8
  else
10
- ForemanScapClient::Client.new.run(ARGV[0].to_i)
9
+ skip_upload = false
10
+ args = ARGV
11
11
  end
12
12
 
13
+ if args.size == 1
14
+ ForemanScapClient::Client.new.run(args[0].to_i, skip_upload)
15
+ elsif args.size == 2 && args[0] == 'ds'
16
+ ForemanScapClient::Client.new.run(args[1].to_i, skip_upload)
17
+ elsif args.size == 2 && args[0] == 'oval'
18
+ ForemanScapClient::OvalClient.new.run(args[1].to_i, skip_upload)
19
+ else
20
+ puts "Usage: #{$0} [ds | oval] policy_id [--skip-upload]"
21
+ puts " where policy_id is a key used in config file"
22
+ exit 2
23
+ end
@@ -33,3 +33,7 @@
33
33
  2:
34
34
  :profile: 'xccdf_org.ssgproject.content_profile_common'
35
35
  :content_path: '/usr/share/xml/scap/ssg/fedora/ssg-fedora-ds.xml'
36
+
37
+ :oval:
38
+ 3:
39
+ :content_path: '/var/lib/openscap/oval_content/ansible-2.9.oval.xml.bz2'
@@ -1,2 +1,3 @@
1
1
  require "foreman_scap_client/version"
2
2
  require "foreman_scap_client/client"
3
+ require "foreman_scap_client/oval_client"
@@ -0,0 +1,240 @@
1
+ require 'rubygems' if RUBY_VERSION.start_with? '1.8'
2
+ require 'yaml'
3
+ require 'tmpdir'
4
+ require 'net/http'
5
+ require 'net/https'
6
+ require 'uri'
7
+ require 'open-uri'
8
+ require 'open3'
9
+ require 'json'
10
+
11
+ module ForemanScapClient
12
+ class BaseClient
13
+ attr_reader :policy_id, :config
14
+
15
+ CONFIG_FILE = '/etc/foreman_scap_client/config.yaml'
16
+
17
+ def run(policy_id, skip_upload = false)
18
+ @policy_id = policy_id
19
+ load_config
20
+ ensure_scan_files
21
+ run_in_tmpdir skip_upload
22
+ end
23
+
24
+ private
25
+
26
+ def ensure_scan_files
27
+ raise NotImplementedError
28
+ end
29
+
30
+ def policy_namespace
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def upload_uri
35
+ raise NotImplementedError
36
+ end
37
+
38
+ def scan_command
39
+ raise NotImplementedError
40
+ end
41
+
42
+ def run_in_tmpdir(skip_upload)
43
+ if skip_upload
44
+ @tmp_dir = Dir.mktmpdir
45
+ scan
46
+ bzip
47
+ else
48
+ Dir.mktmpdir do |dir|
49
+ @tmp_dir = dir
50
+ scan
51
+ bzip
52
+ upload
53
+ end
54
+ end
55
+ end
56
+
57
+ def policy_from_config
58
+ config && config[policy_namespace] && config[policy_namespace][@policy_id]
59
+ end
60
+
61
+ def load_config
62
+ @config ||= YAML.load_file(CONFIG_FILE)
63
+ ensure_policy_exists
64
+ rescue => e
65
+ puts 'Config file could not be loaded'
66
+ puts e.message
67
+ exit(1)
68
+ end
69
+
70
+ def scan
71
+ puts "DEBUG: running: " + scan_command
72
+ puts "with ENV vars: #{scan_command_env_vars}" unless scan_command_env_vars.empty?
73
+
74
+ if RUBY_VERSION.start_with? '1.8'
75
+ legacy_run_scan
76
+ else
77
+ run_scan
78
+ end
79
+ end
80
+
81
+ def run_scan
82
+ stdout_str, error_str, result = Open3.capture3(scan_command_env_vars, scan_command)
83
+ if result.success? || result.exitstatus == 2
84
+ puts error_str.split("\n").select { |item| item.start_with?('WARNING:') || item.start_with?('Downloading') }.join("\n")
85
+ @report = results_path
86
+ else
87
+ puts 'Scan failed'
88
+ puts stdout_str
89
+ puts error_str
90
+ exit(2)
91
+ end
92
+ end
93
+
94
+ def legacy_run_scan
95
+ warn_proxy_not_supported
96
+ result = `#{scan_command}`
97
+
98
+ if $?.success? || $?.exitstatus == 2
99
+ @report = results_path
100
+ else
101
+ puts 'Scan failed'
102
+ puts result
103
+ exit(2)
104
+ end
105
+ end
106
+
107
+ def scan_command_env_vars
108
+ if http_proxy_uri
109
+ {
110
+ 'HTTP_PROXY' => http_proxy_uri,
111
+ 'HTTPS_PROXY' => http_proxy_uri
112
+ }
113
+ else
114
+ {}
115
+ end
116
+ end
117
+
118
+ def http_proxy_uri
119
+ return nil unless config[:http_proxy_server] && config[:http_proxy_port]
120
+ http_proxy_server = config[:http_proxy_server]
121
+ http_proxy_port = config[:http_proxy_port]
122
+ "http://#{http_proxy_server}:#{http_proxy_port}"
123
+ end
124
+
125
+ def results_path
126
+ "#{@tmp_dir}/results.xml"
127
+ end
128
+
129
+ def results_bzip_path
130
+ "#{results_path}.bz2"
131
+ end
132
+
133
+ def warn_proxy_not_supported
134
+ puts 'Configuration for HTTP(S) proxy found but not supported for ruby 1.8' if http_proxy_uri
135
+ end
136
+
137
+ def bzip_command
138
+ "/usr/bin/env bzip2 #{results_path}"
139
+ end
140
+
141
+ def bzip
142
+ puts 'DEBUG: running: ' + bzip_command
143
+ result = `#{bzip_command}`
144
+ if !$?.success?
145
+ puts 'bzip failed'
146
+ puts results
147
+ exit(2)
148
+ end
149
+ end
150
+
151
+ def upload
152
+ uri = URI.parse(upload_uri)
153
+ puts "Uploading results to #{uri}"
154
+ https = generate_https_object(uri)
155
+ https.read_timeout = config[:timeout] if config[:timeout]
156
+ request = Net::HTTP::Post.new uri.path
157
+ request.body = File.read(results_bzip_path)
158
+ request['Content-Type'] = 'text/xml'
159
+ request['Content-Encoding'] = 'x-bzip2'
160
+ begin
161
+ res = https.request(request)
162
+ value = res.value
163
+ foreman_upload_result res
164
+ rescue StandardError => e
165
+ puts res.body if res
166
+ puts "Upload failed: #{e.message}"
167
+ exit(4)
168
+ end
169
+ end
170
+
171
+ def foreman_proxy_uri
172
+ foreman_proxy_fqdn = config[:server]
173
+ foreman_proxy_port = config[:port]
174
+ "https://#{foreman_proxy_fqdn}:#{foreman_proxy_port}"
175
+ end
176
+
177
+ def generate_https_object(uri)
178
+ https = Net::HTTP.new(uri.host, uri.port)
179
+ https.use_ssl = true
180
+ https.ciphers = config[:ciphers] if config[:ciphers]
181
+ https.verify_mode = OpenSSL::SSL::VERIFY_PEER
182
+ https.ca_file = config[:ca_file]
183
+ begin
184
+ https.cert = OpenSSL::X509::Certificate.new File.read(config[:host_certificate])
185
+ https.key = OpenSSL::PKey::RSA.new File.read(config[:host_private_key])
186
+ rescue StandardError => e
187
+ puts 'Unable to load certs'
188
+ puts e.message
189
+ exit(3)
190
+ end
191
+ https
192
+ end
193
+
194
+ def ensure_policy_exists
195
+ if policy_from_config.nil?
196
+ puts "Policy id #{@policy_id} not found."
197
+ exit(1)
198
+ end
199
+ end
200
+
201
+ def ensure_file(dir, download_path, type_humanized)
202
+ return if File.exist?(policy_from_config[dir])
203
+ puts "File #{policy_from_config[dir]} is missing. Downloading it from proxy."
204
+ begin
205
+ FileUtils.mkdir_p(File.dirname(policy_from_config[dir]))
206
+ uri = URI.parse(download_uri(policy_from_config[download_path]))
207
+ puts "Download #{type_humanized} xml from: #{uri}"
208
+ request = generate_https_object(uri).get(uri.path)
209
+ request.value
210
+ content_xml = request.body
211
+ open(policy_from_config[dir], 'wb') do |file|
212
+ file << content_xml
213
+ end
214
+ rescue StandardError => e
215
+ puts "#{type_humanized} is missing and download failed with error: #{e.message}"
216
+ exit(5)
217
+ end
218
+ end
219
+
220
+ def download_uri(download_path)
221
+ foreman_proxy_uri + "#{download_path}"
222
+ end
223
+
224
+ def foreman_upload_result(response)
225
+ begin
226
+ print_upload_result JSON.parse(response.body)
227
+ rescue StandardError => e
228
+ # rescue and print nothing if older proxy version does not respond with json we expect
229
+ end
230
+ end
231
+
232
+ def print_upload_result(parsed)
233
+ if parsed['id']
234
+ puts "Report uploaded, report id: #{parsed['id']}"
235
+ else
236
+ puts "Report not uploaded from proxy to Foreman server, cause: #{parsed['result']}"
237
+ end
238
+ end
239
+ end
240
+ end
@@ -1,109 +1,28 @@
1
- require 'rubygems' if RUBY_VERSION.start_with? '1.8'
2
- require 'yaml'
3
- require 'tmpdir'
4
- require 'net/http'
5
- require 'net/https'
6
- require 'uri'
7
- require 'open-uri'
8
- require 'open3'
9
- require 'json'
1
+ require 'foreman_scap_client/base_client'
10
2
 
11
3
  module ForemanScapClient
12
- CONFIG_FILE = '/etc/foreman_scap_client/config.yaml'
13
-
14
- class Client
15
- attr_reader :config, :policy_id, :tailored
16
-
17
- def run(policy_id)
18
- @policy_id = policy_id
19
- load_config
20
- ensure_scan_file
21
- ensure_tailoring_file
22
- Dir.mktmpdir do |dir|
23
- @tmp_dir = dir
24
- scan
25
- bzip
26
- upload
27
- end
28
- end
4
+ class Client < BaseClient
5
+ attr_reader :tailored
29
6
 
30
7
  private
31
8
 
32
- def warn_proxy_not_supported
33
- puts 'Configuration for HTTP(S) proxy found but not supported for ruby 1.8' if http_proxy_uri
34
- end
35
-
36
- def load_config
37
- @config ||= YAML.load_file(CONFIG_FILE)
38
- ensure_policy_exist
39
- @tailored = @config[policy_id][:tailoring_path] && !@config[policy_id][:tailoring_path].empty?
40
- rescue => e
41
- puts 'Config file could not be loaded'
42
- puts e.message
43
- exit(1)
9
+ def policy_namespace
10
+ :ds
44
11
  end
45
12
 
46
- def scan
47
- puts "DEBUG: running: " + scan_command
48
- puts "with ENV vars: #{scan_command_env_vars}" unless scan_command_env_vars.empty?
49
-
50
- if RUBY_VERSION.start_with? '1.8'
51
- legacy_run_scan
52
- else
53
- run_scan
54
- end
13
+ # remove when we have made changes to puppet module/ansible role to start namespacing existing ds policies in config
14
+ def policy_from_config
15
+ super || @config[policy_id]
55
16
  end
56
17
 
57
- def run_scan
58
- stdout_str, error_str, result = Open3.capture3(scan_command_env_vars, scan_command)
59
- if result.success? || result.exitstatus == 2
60
- puts error_str.split("\n").select { |item| item.start_with?('WARNING:') || item.start_with?('Downloading') }.join("\n")
61
- @report = results_path
62
- else
63
- puts 'Scan failed'
64
- puts stdout_str
65
- puts error_str
66
- exit(2)
67
- end
18
+ def ensure_policy_exists
19
+ super
20
+ @tailored = policy_from_config[:tailoring_path] && !policy_from_config[:tailoring_path].empty?
68
21
  end
69
22
 
70
- def legacy_run_scan
71
- warn_proxy_not_supported
72
- result = `#{scan_command}`
73
-
74
- if $?.success? || $?.exitstatus == 2
75
- @report = results_path
76
- else
77
- puts 'Scan failed'
78
- puts result
79
- exit(2)
80
- end
81
- end
82
-
83
- def scan_command_env_vars
84
- if http_proxy_uri
85
- {
86
- 'HTTP_PROXY' => http_proxy_uri,
87
- 'HTTPS_PROXY' => http_proxy_uri
88
- }
89
- else
90
- {}
91
- end
92
- end
93
-
94
- def http_proxy_uri
95
- return nil unless config[:http_proxy_server] && config[:http_proxy_port]
96
- http_proxy_server = config[:http_proxy_server]
97
- http_proxy_port = config[:http_proxy_port]
98
- "http://#{http_proxy_server}:#{http_proxy_port}"
99
- end
100
-
101
- def results_path
102
- "#{@tmp_dir}/results.xml"
103
- end
104
-
105
- def results_bzip_path
106
- "#{results_path}.bz2"
23
+ def ensure_scan_files
24
+ ensure_scan_file
25
+ ensure_tailoring_file if tailored
107
26
  end
108
27
 
109
28
  def scan_command
@@ -124,120 +43,17 @@ module ForemanScapClient
124
43
  tailored ? "--tailoring-file #{config[policy_id][:tailoring_path]}" : ""
125
44
  end
126
45
 
127
- def bzip_command
128
- "/usr/bin/env bzip2 #{results_path}"
129
- end
130
-
131
- def bzip
132
- puts 'DEBUG: running: ' + bzip_command
133
- result = `#{bzip_command}`
134
- if !$?.success?
135
- puts 'bzip failed'
136
- puts results
137
- exit(2)
138
- end
139
- end
140
-
141
- def upload
142
- uri = URI.parse(upload_uri)
143
- puts "Uploading results to #{uri}"
144
- https = generate_https_object(uri)
145
- https.read_timeout = config[:timeout] if config[:timeout]
146
- request = Net::HTTP::Post.new uri.path
147
- request.body = File.read(results_bzip_path)
148
- request['Content-Type'] = 'text/xml'
149
- request['Content-Encoding'] = 'x-bzip2'
150
- begin
151
- res = https.request(request)
152
- value = res.value
153
- foreman_upload_result res
154
- rescue StandardError => e
155
- puts res.body if res
156
- puts "Upload failed: #{e.message}"
157
- exit(4)
158
- end
159
- end
160
46
 
161
47
  def upload_uri
162
48
  foreman_proxy_uri + "/compliance/arf/#{@policy_id}"
163
49
  end
164
50
 
165
- def foreman_proxy_uri
166
- foreman_proxy_fqdn = config[:server]
167
- foreman_proxy_port = config[:port]
168
- "https://#{foreman_proxy_fqdn}:#{foreman_proxy_port}"
169
- end
170
-
171
- def generate_https_object(uri)
172
- https = Net::HTTP.new(uri.host, uri.port)
173
- https.use_ssl = true
174
- https.ciphers = config[:ciphers] if config[:ciphers]
175
- https.verify_mode = OpenSSL::SSL::VERIFY_PEER
176
- https.ca_file = config[:ca_file]
177
- begin
178
- https.cert = OpenSSL::X509::Certificate.new File.read(config[:host_certificate])
179
- https.key = OpenSSL::PKey::RSA.new File.read(config[:host_private_key])
180
- rescue StandardError => e
181
- puts 'Unable to load certs'
182
- puts e.message
183
- exit(3)
184
- end
185
- https
186
- end
187
-
188
- def ensure_policy_exist
189
- if config[@policy_id].nil?
190
- puts "Policy id #{@policy_id} not found."
191
- exit(1)
192
- end
193
- end
194
-
195
- def ensure_file(dir, download_path, type_humanized)
196
- return if File.exist?(config[policy_id][dir])
197
- puts "File #{config[policy_id][dir]} is missing. Downloading it from proxy."
198
- begin
199
- FileUtils.mkdir_p(File.dirname(config[policy_id][dir]))
200
- uri = URI.parse(download_uri(config[policy_id][download_path]))
201
- puts "Download #{type_humanized} xml from: #{uri}"
202
- request = generate_https_object(uri).get(uri.path)
203
- request.value
204
- ds_content_xml = request.body
205
- open(config[policy_id][dir], 'wb') do |file|
206
- file << ds_content_xml
207
- end
208
- rescue StandardError => e
209
- puts "#{type_humanized} is missing and download failed with error: #{e.message}"
210
- exit(5)
211
- end
212
- end
213
-
214
51
  def ensure_scan_file
215
52
  ensure_file :content_path, :download_path, "SCAP content"
216
53
  end
217
54
 
218
55
  def ensure_tailoring_file
219
- return unless tailored
220
56
  ensure_file :tailoring_path, :tailoring_download_path, "Tailoring file"
221
57
  end
222
-
223
- def download_uri(download_path)
224
- foreman_proxy_uri + "#{download_path}"
225
- end
226
-
227
- def foreman_upload_result(response)
228
- begin
229
- print_upload_result JSON.parse(response.body)
230
- rescue StandardError => e
231
- # rescue and print nothing if older proxy version does not respond with json we expect
232
- end
233
- end
234
-
235
- def print_upload_result(parsed)
236
- if parsed['id']
237
- puts "Report uploaded, report id: #{parsed['id']}"
238
- else
239
- puts "Report not uploaded from proxy to Foreman server, cause: #{parsed['result']}"
240
- end
241
- end
242
58
  end
243
59
  end
@@ -0,0 +1,31 @@
1
+ require 'foreman_scap_client/base_client'
2
+
3
+ module ForemanScapClient
4
+ class OvalClient < BaseClient
5
+ private
6
+
7
+ def policy_namespace
8
+ :oval
9
+ end
10
+
11
+ def ensure_scan_files
12
+ ensure_file :content_path, :download_path, "OVAL content"
13
+ end
14
+
15
+ def upload_uri
16
+ foreman_proxy_uri + "/compliance/oval_reports/#{@policy_id}"
17
+ end
18
+
19
+ def scan_command
20
+ "oscap oval eval --results #{results_path} #{policy_from_config[:content_path]}"
21
+ end
22
+
23
+ def print_upload_result(parsed)
24
+ if parsed['reported_at']
25
+ puts "Report successfully uploaded at #{parsed['reported_at']}"
26
+ else
27
+ puts "Report not uploaded, cause: #{parsed['result']}"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module ForemanScapClient
2
- VERSION = "0.4.7"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_scap_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.7
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marek Hulan
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-07-17 00:00:00.000000000 Z
13
+ date: 2021-05-18 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -56,7 +56,9 @@ files:
56
56
  - bin/foreman_scap_client
57
57
  - config/config.yaml.example
58
58
  - lib/foreman_scap_client.rb
59
+ - lib/foreman_scap_client/base_client.rb
59
60
  - lib/foreman_scap_client/client.rb
61
+ - lib/foreman_scap_client/oval_client.rb
60
62
  - lib/foreman_scap_client/version.rb
61
63
  homepage: https://github.com/openscap/foreman_scap_client
62
64
  licenses: