razorrisk-cassini-common 0.26.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +22 -0
- data/LICENSE +5 -0
- data/README.md +2 -0
- data/Rakefile +102 -0
- data/lib/razor_risk/cassini/applications/microservice.rb +318 -0
- data/lib/razor_risk/cassini/applications/rest_framework/route_verb_dispatcher.rb +120 -0
- data/lib/razor_risk/cassini/applications/rest_framework/verb_handler.rb +117 -0
- data/lib/razor_risk/cassini/applications/route_verb_adaptors/utilities/collection_get_helper.rb +86 -0
- data/lib/razor_risk/cassini/applications/securable_microservice.rb +164 -0
- data/lib/razor_risk/cassini/applications/secured_microservice.rb +63 -0
- data/lib/razor_risk/cassini/applications/unsecured_microservice.rb +77 -0
- data/lib/razor_risk/cassini/authorisation/header_helpers.rb +271 -0
- data/lib/razor_risk/cassini/authorisation/security_model_helpers.rb +93 -0
- data/lib/razor_risk/cassini/authorisation.rb +27 -0
- data/lib/razor_risk/cassini/cli.rb +19 -0
- data/lib/razor_risk/cassini/common/version.rb +44 -0
- data/lib/razor_risk/cassini/common.rb +32 -0
- data/lib/razor_risk/cassini/constants.rb +68 -0
- data/lib/razor_risk/cassini/diagnostics/util_functions.rb +248 -0
- data/lib/razor_risk/cassini/diagnostics/zeroth_include.rb +35 -0
- data/lib/razor_risk/cassini/extensions/libclimate/common_options.rb +267 -0
- data/lib/razor_risk/cassini/extensions/libclimate.rb +26 -0
- data/lib/razor_risk/cassini/header_functions.rb +59 -0
- data/lib/razor_risk/cassini/main.rb +238 -0
- data/lib/razor_risk/cassini/mixin/razor_response_validator.rb +176 -0
- data/lib/razor_risk/cassini/testing/suppress_pantheios_logging.rb +31 -0
- data/lib/razor_risk/cassini/util/conversion_util.rb +176 -0
- data/lib/razor_risk/cassini/util/program_execution_util.rb +379 -0
- data/lib/razor_risk/cassini/util/secrets_util.rb +229 -0
- data/lib/razor_risk/cassini/util/version_util.rb +88 -0
- data/lib/razor_risk/sinatra/helpers/check_auth_helper.rb +209 -0
- data/lib/razor_risk/sinatra/helpers/validate_accept_helper.rb +69 -0
- data/lib/razor_risk/sinatra/helpers/validate_content_type_helper.rb +74 -0
- data/lib/razor_risk/sinatra/helpers/validate_query_parameters_helper.rb +198 -0
- data/test/scratch/cassini/util/convert_XML.rb +54 -0
- data/test/unit/applications/route_verb_adaptors/utilities/tc_collection_get_helper.rb +236 -0
- data/test/unit/applications/tc_verb_handler.rb +130 -0
- data/test/unit/mixin/tc_razor_response_validator.rb +328 -0
- data/test/unit/sinatra/helpers/tc_validate_query_parameters_helper.rb +134 -0
- data/test/unit/tc_authorisation_util.rb +265 -0
- data/test/unit/tc_load_secrets.rb +95 -0
- data/test/unit/util/tc_conversion_util.rb +393 -0
- data/test/unit/util/tc_program_execution_util.rb +462 -0
- metadata +380 -0
@@ -0,0 +1,379 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# ######################################################################## #
|
4
|
+
#
|
5
|
+
# Utility methods for creating commands to execute microservices.
|
6
|
+
#
|
7
|
+
# Copyright (c) 2018 Razor Risk Technologies Pty Limited. All rights reserved.
|
8
|
+
#
|
9
|
+
# ######################################################################## #
|
10
|
+
|
11
|
+
|
12
|
+
require 'razor_risk/core/system/system_traits'
|
13
|
+
|
14
|
+
require 'pantheios'
|
15
|
+
require 'recls'
|
16
|
+
require 'xqsr3/quality/parameter_checking'
|
17
|
+
|
18
|
+
require 'uri'
|
19
|
+
|
20
|
+
require 'razor_risk/core/diagnostics/logger'
|
21
|
+
|
22
|
+
module RazorRisk
|
23
|
+
module Cassini
|
24
|
+
module Util
|
25
|
+
|
26
|
+
module ProgramExecutionUtil
|
27
|
+
|
28
|
+
include ::RazorRisk::Core::System::SystemTraits
|
29
|
+
|
30
|
+
include ::Pantheios
|
31
|
+
include ::Xqsr3::Quality::ParameterChecking
|
32
|
+
|
33
|
+
include ::RazorRisk::Core::Diagnostics::Logger
|
34
|
+
|
35
|
+
module Util_Internals_
|
36
|
+
|
37
|
+
include ::Pantheios
|
38
|
+
|
39
|
+
end # module Util_Internals_
|
40
|
+
|
41
|
+
module Constants
|
42
|
+
module SecretServer
|
43
|
+
DEFAULT_NAME = 'secret-server'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Command < ::Array
|
48
|
+
|
49
|
+
def cmd
|
50
|
+
self[0]
|
51
|
+
end
|
52
|
+
|
53
|
+
def uri
|
54
|
+
self[1]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def add_command_element_ s, a0, a1 = nil, **options
|
60
|
+
|
61
|
+
trace
|
62
|
+
|
63
|
+
case a0
|
64
|
+
when ::String
|
65
|
+
|
66
|
+
;
|
67
|
+
|
68
|
+
when ::Recls::Entry
|
69
|
+
|
70
|
+
a0 = a0.to_str
|
71
|
+
else
|
72
|
+
end
|
73
|
+
|
74
|
+
case a1
|
75
|
+
when ::String
|
76
|
+
|
77
|
+
;
|
78
|
+
when nil
|
79
|
+
|
80
|
+
;
|
81
|
+
when ::Recls::Entry
|
82
|
+
|
83
|
+
a1 = a1.to_str
|
84
|
+
else
|
85
|
+
end
|
86
|
+
|
87
|
+
a0 = %Q<"#{a0}"> if a0.include? ' '
|
88
|
+
a1 = %Q<"#{a1}"> if a1 && a1.to_s.include?(' ')
|
89
|
+
|
90
|
+
if options[:use_equal]
|
91
|
+
|
92
|
+
"#{s} #{a0}=#{a1}"
|
93
|
+
else
|
94
|
+
|
95
|
+
r = "#{s} #{a0}"
|
96
|
+
r += " #{a1}" if a1
|
97
|
+
|
98
|
+
r
|
99
|
+
end
|
100
|
+
end
|
101
|
+
public
|
102
|
+
|
103
|
+
def program_name_from_executable p
|
104
|
+
|
105
|
+
p.to_s.split(windows? ? /[;|]/ : /[:|]/)[0]
|
106
|
+
end
|
107
|
+
|
108
|
+
def make_secretserver_command \
|
109
|
+
cassini_root_directory,
|
110
|
+
secrets_path,
|
111
|
+
host,
|
112
|
+
port,
|
113
|
+
**options
|
114
|
+
|
115
|
+
trace ParamNames[ :cassini_root_directory, :secrets_path, :host, :port, :options ], cassini_root_directory, secrets_path, host, port, options
|
116
|
+
|
117
|
+
check_parameter cassini_root_directory, 'cassini_root_directory', types: [ ::Recls::Entry, ::String ]
|
118
|
+
check_parameter port, 'port', type: ::Integer
|
119
|
+
|
120
|
+
# 1. Form command
|
121
|
+
|
122
|
+
cmd = if options[:ruby_path]
|
123
|
+
options[:ruby_path]
|
124
|
+
else
|
125
|
+
"ruby" + (Recls::Ximpl::OS::OS_IS_WINDOWS ? '.exe' : '')
|
126
|
+
end
|
127
|
+
|
128
|
+
cmd = add_command_element_ cmd, '-d' if options[:debug]
|
129
|
+
|
130
|
+
if options[:path]
|
131
|
+
|
132
|
+
cmd = add_command_element_ cmd, options[:path]
|
133
|
+
else
|
134
|
+
|
135
|
+
cmd = add_command_element_ cmd, Recls.combine_paths(cassini_root_directory, 'tools/utilities', Constants::SecretServer::DEFAULT_NAME, 'ws.rb', canonicalise: true)
|
136
|
+
end
|
137
|
+
|
138
|
+
cmd = add_command_element_ cmd, '-h', host if host
|
139
|
+
|
140
|
+
cmd = add_command_element_ cmd, '-p', port
|
141
|
+
|
142
|
+
cmd = add_command_element_ cmd, '-w', options[:web_server] if options[:web_server]
|
143
|
+
|
144
|
+
cmd = add_command_element_ cmd, Recls.combine_paths(cassini_root_directory, secrets_path, canonicalise: true)
|
145
|
+
|
146
|
+
if lt = options[:log_threshold]
|
147
|
+
|
148
|
+
case lt
|
149
|
+
when :debug4, 'debug4'
|
150
|
+
|
151
|
+
lt = :debug
|
152
|
+
when ::Array
|
153
|
+
|
154
|
+
lt = lt.empty? ? nil : lt.join(',')
|
155
|
+
else
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
cmd = add_command_element_ cmd, '--log-threshold', lt, use_equal: true
|
160
|
+
end
|
161
|
+
|
162
|
+
if ld = options[:log_directory]
|
163
|
+
cmd = add_command_element_ cmd, '--log-directory', ld, use_equal: true
|
164
|
+
end
|
165
|
+
|
166
|
+
pr_name = options[:program_name] || Constants::SecretServer::DEFAULT_NAME
|
167
|
+
|
168
|
+
cmd = add_command_element_ cmd, '--program-name', pr_name, use_equal: true
|
169
|
+
|
170
|
+
if rc = options[:routes_config]
|
171
|
+
|
172
|
+
cmd = add_command_element_ cmd, rc
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
# 2. Form URL
|
177
|
+
|
178
|
+
url_path= '/'
|
179
|
+
scheme = options[:uri_scheme] || 'http'
|
180
|
+
host ||= 'localhost'
|
181
|
+
path = '/' == (url_path || '')[0] ? url_path : '/' + url_path
|
182
|
+
url = "#{scheme}://#{host}:#{port}#{path}"
|
183
|
+
uri = URI.parse url
|
184
|
+
|
185
|
+
|
186
|
+
# 3. Form return value
|
187
|
+
|
188
|
+
log :debug2, 'creating secret server: url=\'', url, '\'; cmd=\'', cmd, ?'
|
189
|
+
|
190
|
+
Command.[](cmd, uri)
|
191
|
+
end
|
192
|
+
|
193
|
+
# Creates a string that can be used to start a mircoservice from the CLI.
|
194
|
+
#
|
195
|
+
# @param microservice_name [::String] The name of the microservice.
|
196
|
+
# @param security_model [:basic, :authorisation_only, :jwt] The security
|
197
|
+
# model the microservice is to use.
|
198
|
+
# @param razor_executable [::String] The path to the RazorRequest
|
199
|
+
# executable file.
|
200
|
+
# @param cassini_root_directory [::String] The path to the root direcotry
|
201
|
+
# Cassini is installed in.
|
202
|
+
# @param clarite_config_path [::String] The path the ClarITe config XML
|
203
|
+
# file.
|
204
|
+
# @param host [::String] The URI host the microservice will be
|
205
|
+
# accessible at.
|
206
|
+
# @param port [::String] The URI port the microservice will be accessible
|
207
|
+
# at.
|
208
|
+
# @param url_path [::String] The URL path the microservice will be
|
209
|
+
# accessible at.
|
210
|
+
# @param options [::Hash] The options hash.
|
211
|
+
#
|
212
|
+
#
|
213
|
+
# @option options [::String] razor_environment The Razor environment to
|
214
|
+
# connect to.
|
215
|
+
# @option options [::String] razor_space The Razor space to
|
216
|
+
# connect to.
|
217
|
+
# @option options [::String] razor_alias The Razor alias to
|
218
|
+
# connect to.
|
219
|
+
# @option options [Boolean] :benchmark Causes the child processes to be
|
220
|
+
# run with benchmarking enabled.
|
221
|
+
# @option options [Boolean] :debug Determines whether to run child
|
222
|
+
# processes in debug mode.
|
223
|
+
# @option options [::Symbol] :log_threshold Specifies the log-threshold
|
224
|
+
# to be used with the child process.
|
225
|
+
# @option options ['http', 'https'] :uri_scheme Determines whether to the
|
226
|
+
# target URI is to be hit with the HTTPS protocol, rather than HTTP.
|
227
|
+
# @option options [::String] :path Specifies a specific path to be used,
|
228
|
+
# thereby suppressing the normal inference mechanism.
|
229
|
+
# @option options [::String, Array<::String>] :additional_arguments Some
|
230
|
+
# additional arguments to be incorporated, which will be ...
|
231
|
+
#
|
232
|
+
# @return [Array<::String, ::String>] A tuple of command + URL
|
233
|
+
def make_microservice_command \
|
234
|
+
microservice_name,
|
235
|
+
security_model,
|
236
|
+
razor_executable,
|
237
|
+
cassini_root_directory,
|
238
|
+
clarite_config_path,
|
239
|
+
host,
|
240
|
+
port,
|
241
|
+
url_path,
|
242
|
+
**options
|
243
|
+
|
244
|
+
trace ParamNames[ :microservice_name, :security_model, :razor_executable, :cassini_root_directory, :clarite_config_path, :host, :port, :url_path, :options ], microservice_name, security_model, razor_executable, cassini_root_directory, clarite_config_path, host, port, url_path, options
|
245
|
+
|
246
|
+
check_parameter security_model, 'security_model', type: ::Symbol, values: [ :basic, :authorisation_only, :jwt ]
|
247
|
+
check_parameter cassini_root_directory, 'cassini_root_directory', types: [ ::Recls::Entry, ::String ]
|
248
|
+
check_parameter port, 'port', type: ::Integer
|
249
|
+
|
250
|
+
|
251
|
+
# 1. Form command
|
252
|
+
|
253
|
+
cmd = if options[:ruby_path]
|
254
|
+
options[:ruby_path]
|
255
|
+
else
|
256
|
+
"ruby" + (Recls::Ximpl::OS::OS_IS_WINDOWS ? '.exe' : '')
|
257
|
+
end
|
258
|
+
|
259
|
+
cmd = add_command_element_ cmd, '-d' if options[:debug]
|
260
|
+
|
261
|
+
rel_l1 = options[:restful] ? 'tools/services/restful' : 'tools/services'
|
262
|
+
|
263
|
+
if options[:path]
|
264
|
+
|
265
|
+
cmd = add_command_element_ cmd, options[:path]
|
266
|
+
else
|
267
|
+
|
268
|
+
cmd = add_command_element_ cmd, Recls.combine_paths(cassini_root_directory, rel_l1, microservice_name, 'ws.rb', canonicalise: true)
|
269
|
+
end
|
270
|
+
|
271
|
+
cmd = add_command_element_ cmd, '-x', [razor_executable].flatten.join(windows? ? ';' : ':') if razor_executable
|
272
|
+
cmd = add_command_element_ cmd, '-e', options[:razor_environment] if options[:razor_environment]
|
273
|
+
cmd = add_command_element_ cmd, '--razor-alias', options[:razor_alias] if options[:razor_alias]
|
274
|
+
cmd = add_command_element_ cmd, '--razor-space', options[:razor_space] if options[:razor_space]
|
275
|
+
|
276
|
+
case security_model
|
277
|
+
when :basic
|
278
|
+
|
279
|
+
sm = 'b'
|
280
|
+
when :authorisation_only
|
281
|
+
|
282
|
+
sm = 'a'
|
283
|
+
when :jwt
|
284
|
+
|
285
|
+
sm = 'j'
|
286
|
+
else
|
287
|
+
|
288
|
+
log :violation, 'unrecognised security model \'', security_model, ?'
|
289
|
+
end
|
290
|
+
|
291
|
+
cmd = add_command_element_ cmd, '-a', sm
|
292
|
+
cmd = add_command_element_ cmd, '-h', host if host
|
293
|
+
cmd = add_command_element_ cmd, '-p', port
|
294
|
+
cmd = add_command_element_ cmd, '-o', clarite_config_path if clarite_config_path
|
295
|
+
cmd = add_command_element_ cmd, '-s', options[:secret_server] if options[:secret_server]
|
296
|
+
cmd = add_command_element_ cmd, '-j', options[:jwt_encoding_algorithm] if options[:jwt_encoding_algorithm]
|
297
|
+
cmd = add_command_element_ cmd, '-w', options[:web_server] if options[:web_server]
|
298
|
+
cmd = add_command_element_ cmd, '-u', options[:web_ui_server] if options[:web_ui_server]
|
299
|
+
cmd = add_command_element_ cmd, '--benchmark' if options[:benchmark]
|
300
|
+
cmd = add_command_element_ cmd, '--authorization-test-mode' if options[:auth_test_mode]
|
301
|
+
|
302
|
+
if lt = options[:log_threshold]
|
303
|
+
|
304
|
+
case lt
|
305
|
+
when :debug4, 'debug4'
|
306
|
+
|
307
|
+
lt = :debug
|
308
|
+
when ::Array
|
309
|
+
|
310
|
+
lt = lt.empty? ? nil : lt.join(',')
|
311
|
+
else
|
312
|
+
|
313
|
+
end
|
314
|
+
|
315
|
+
cmd = add_command_element_ cmd, '--log-threshold', lt, use_equal: true
|
316
|
+
end
|
317
|
+
|
318
|
+
if ld = options[:log_directory]
|
319
|
+
cmd = add_command_element_ cmd, '--log-directory', ld, use_equal: true
|
320
|
+
end
|
321
|
+
|
322
|
+
pr_name = options[:program_name] || microservice_name
|
323
|
+
|
324
|
+
cmd = add_command_element_ cmd, '--program-name', pr_name, use_equal: true
|
325
|
+
|
326
|
+
if rc = options[:routes_config]
|
327
|
+
|
328
|
+
cmd = add_command_element_ cmd, rc
|
329
|
+
end
|
330
|
+
|
331
|
+
case aa = options[:additional_arguments]
|
332
|
+
when nil
|
333
|
+
|
334
|
+
;
|
335
|
+
when ::Array
|
336
|
+
|
337
|
+
aa.each do |a|
|
338
|
+
|
339
|
+
case a
|
340
|
+
when ::Array
|
341
|
+
|
342
|
+
warn "processing additional arguments array element that does not contain exactly two elements" unless 2 == a.size
|
343
|
+
|
344
|
+
cmd = add_command_element_ cmd, a[0], a[1], use_equal: true
|
345
|
+
else # ::String
|
346
|
+
|
347
|
+
cmd = add_command_element_ cmd, a
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
else # ::String
|
352
|
+
|
353
|
+
cmd = add_command_element_ cmd, aa
|
354
|
+
end
|
355
|
+
|
356
|
+
# 2. Form URL
|
357
|
+
|
358
|
+
scheme = options[:uri_scheme] || 'http'
|
359
|
+
host ||= 'localhost'
|
360
|
+
path = '/' == (url_path || '')[0] ? url_path : "/#{url_path}"
|
361
|
+
url = "#{scheme}://#{host}:#{port}#{path}"
|
362
|
+
uri = URI.parse url
|
363
|
+
|
364
|
+
# 3. Form return value
|
365
|
+
|
366
|
+
log :debug2, 'creating microservice: url=\'', url, '\'; cmd=\'', cmd, ?'
|
367
|
+
|
368
|
+
Command.[](cmd, uri)
|
369
|
+
end
|
370
|
+
|
371
|
+
end # module ProgramExecutionUtil
|
372
|
+
|
373
|
+
end # module Util
|
374
|
+
end # module Cassini
|
375
|
+
end # module RazorRisk
|
376
|
+
|
377
|
+
# ############################## end of file ############################# #
|
378
|
+
|
379
|
+
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# ######################################################################## #
|
4
|
+
# File: razor_risk/cassini/util/secrets_util.rb
|
5
|
+
#
|
6
|
+
# Purpose: Security functions
|
7
|
+
#
|
8
|
+
# Created: 25th November 2017
|
9
|
+
# Updated: 15th February 2018
|
10
|
+
#
|
11
|
+
# Author: Matthew Wilson
|
12
|
+
#
|
13
|
+
# Copyright (c) 2017-2018, Razor Risk Technologies Pty Ltd
|
14
|
+
# All rights reserved.
|
15
|
+
#
|
16
|
+
# ######################################################################## #
|
17
|
+
|
18
|
+
|
19
|
+
# ##########################################################################
|
20
|
+
# requires
|
21
|
+
|
22
|
+
require 'razor_risk/extensions/hash/dig'
|
23
|
+
require 'razor_risk/core/diagnostics/logger'
|
24
|
+
|
25
|
+
require 'pantheios'
|
26
|
+
require 'recls'
|
27
|
+
require 'xqsr3/extensions/hash/deep_transform'
|
28
|
+
require 'xqsr3/quality/parameter_checking'
|
29
|
+
|
30
|
+
require 'json'
|
31
|
+
require 'net/http'
|
32
|
+
require 'resolv-replace'
|
33
|
+
require 'yaml'
|
34
|
+
|
35
|
+
module RazorRisk
|
36
|
+
module Cassini
|
37
|
+
module Util
|
38
|
+
|
39
|
+
# Include-module that introduces the +load_secrets+ function
|
40
|
+
module SecretsUtil
|
41
|
+
|
42
|
+
include ::Pantheios
|
43
|
+
include ::Xqsr3::Quality::ParameterChecking
|
44
|
+
include ::RazorRisk::Core::Diagnostics::Logger
|
45
|
+
|
46
|
+
def included receiver
|
47
|
+
|
48
|
+
receiver.extend self
|
49
|
+
end
|
50
|
+
|
51
|
+
# Gets the given secret - +category+ + +algorithm+ - from the given
|
52
|
+
# server (+secret_server_url+), according to the given options
|
53
|
+
#
|
54
|
+
# === Signature
|
55
|
+
#
|
56
|
+
# * *Parameters:*
|
57
|
+
# - +secret_server_url+:: [ ::String, ::URI ] The URI of the secret
|
58
|
+
# server
|
59
|
+
# - +category+:: [ ::String, ::Symbol ] The secret category. May be
|
60
|
+
# +nil+
|
61
|
+
# - +algorithm+:: [ ::String, ::Symbol ] The secret algorithm
|
62
|
+
#
|
63
|
+
# NOTE: all algorithm names are converted to lowercase before processing
|
64
|
+
def get_secret_from_server secret_server_url, category, algorithm, **options
|
65
|
+
|
66
|
+
trace ParamNames[ :secret_server_url, :category, :algorithm, :options ], secret_server_url, category, algorithm, options
|
67
|
+
|
68
|
+
check_parameter secret_server_url, 'secret_server_url', types: [ ::String, ::URI::Generic ]
|
69
|
+
check_parameter algorithm, 'algorithm', types: [ ::String, ::Symbol ]
|
70
|
+
check_parameter category, 'category', types: [ ::String, ::Symbol ], allow_nil: true
|
71
|
+
|
72
|
+
uri = URI.parse secret_server_url
|
73
|
+
host = uri.host
|
74
|
+
port = uri.port
|
75
|
+
|
76
|
+
headers = {
|
77
|
+
|
78
|
+
'Accept' => 'application/json',
|
79
|
+
}
|
80
|
+
|
81
|
+
params = { 'algorithm' => algorithm }
|
82
|
+
|
83
|
+
params['category'] = category if category
|
84
|
+
|
85
|
+
headers.reject! { |k, v| ::NilClass === v }
|
86
|
+
|
87
|
+
begin
|
88
|
+
|
89
|
+
# there are issues in sending through a path-less URI to the
|
90
|
+
# server, so we step in and assign it (as the root) if it
|
91
|
+
# does not exist
|
92
|
+
|
93
|
+
path = (uri.path || '').empty? ? '/' : uri.path
|
94
|
+
query = URI.encode_www_form params
|
95
|
+
|
96
|
+
log :debug0, "host: '#{host}'; port: '#{port}'; path: '#{path}'; query: '#{query}'"
|
97
|
+
|
98
|
+
response = Net::HTTP.start(host, port, :use_ssl => uri.scheme == 'https') do |http|
|
99
|
+
|
100
|
+
full_uri = URI::HTTP.build host: host, port: port, path: path, query: query
|
101
|
+
full_url = full_uri.to_s
|
102
|
+
|
103
|
+
log :debug0, 'issuing request to \'', full_uri, '\'; scheme=\'', uri.scheme, '\''
|
104
|
+
|
105
|
+
request = Net::HTTP::Get.new full_uri, headers
|
106
|
+
|
107
|
+
http.request request
|
108
|
+
end
|
109
|
+
|
110
|
+
if '200' != response.code.to_s
|
111
|
+
|
112
|
+
abort "could not obtain secret for algorithm '#{algorithm}' from server '#{secret_server_url}': #{response.code}: #{response.body}"
|
113
|
+
end
|
114
|
+
|
115
|
+
j = JSON.parse response.body
|
116
|
+
|
117
|
+
j['secret']
|
118
|
+
rescue Errno::ECONNREFUSED
|
119
|
+
|
120
|
+
log :warning, 'failed to contact secret server ', secret_server_url
|
121
|
+
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_secret_from_hash h, category, algorithm, **options
|
127
|
+
|
128
|
+
trace ParamNames[ :h, :category, :algorithm, :options ], h, category, algorithm, options
|
129
|
+
|
130
|
+
check_parameter h, 'h', type: ::Hash
|
131
|
+
check_parameter algorithm, 'algorithm', types: [ ::String, ::Symbol ]
|
132
|
+
check_parameter category, 'category', types: [ ::String, ::Symbol ], allow_nil: true
|
133
|
+
|
134
|
+
h = h['secrets'] if 1 == h.size && h.has_key?('secrets')
|
135
|
+
|
136
|
+
h = h.deep_transform { |k, v| [ k.to_s.downcase, v ] }
|
137
|
+
|
138
|
+
category ||= 'all'
|
139
|
+
|
140
|
+
category = category.downcase
|
141
|
+
algorithm = algorithm.downcase
|
142
|
+
|
143
|
+
secret = nil
|
144
|
+
secret ||= h.dig(category, algorithm) if 'all' != category
|
145
|
+
secret ||= h.dig('all', algorithm)
|
146
|
+
|
147
|
+
secret
|
148
|
+
end
|
149
|
+
|
150
|
+
# Loads the secrets for the given algorithms from the given source
|
151
|
+
#
|
152
|
+
# === Signature
|
153
|
+
#
|
154
|
+
# * *Parameters:*
|
155
|
+
# - +source+:: [::String, ::URI] The source of the secrets, which may
|
156
|
+
# be a URI of a secret server, or the path of a YAML file
|
157
|
+
# - +algorithms+:: An array of algorithms (::String or ::Symbol), or
|
158
|
+
# [ category, algorithm ] tuples
|
159
|
+
# - +options+:: Options
|
160
|
+
#
|
161
|
+
# * *Options:*
|
162
|
+
# - +:source_is+:: [::Symbol] If +:uri+, then +source+ is assumed to be
|
163
|
+
# a specified, then +source+ type is inferred from its type and
|
164
|
+
# content
|
165
|
+
#
|
166
|
+
# === Returns
|
167
|
+
# A hash representing the obtained secrets
|
168
|
+
#
|
169
|
+
# NOTE: all algorithm names are converted to lowercase before processing
|
170
|
+
def load_secrets source, *algorithms, **options
|
171
|
+
|
172
|
+
trace ParamNames[ :source, :algorithms, :options ], source, algorithms, options
|
173
|
+
|
174
|
+
check_parameter source, 'source', types: [ ::String, ::URI::Generic ]
|
175
|
+
check_parameter algorithms, 'algorithms', types: [ [ ::String, ::Symbol ] ]
|
176
|
+
check_option options, :source_is, type: ::Symbol, values: [ :path, :uri ], allow_nil: true
|
177
|
+
|
178
|
+
source_is = options[:source_is]
|
179
|
+
|
180
|
+
source_is ||= :uri if ::URI::Generic === source
|
181
|
+
source_is ||= :path if Recls.stat(source) rescue nil
|
182
|
+
source_is ||= :uri if URI.parse(source) rescue nil
|
183
|
+
|
184
|
+
raise ArgumentError, "could not identify whether source - '#{source}' - is a file-system path or a URI" unless source_is
|
185
|
+
|
186
|
+
acs = algorithms.map do |a|
|
187
|
+
|
188
|
+
alg = nil
|
189
|
+
cat = nil
|
190
|
+
|
191
|
+
case a
|
192
|
+
when ::String, ::Symbol
|
193
|
+
|
194
|
+
alg = a.to_s.downcase
|
195
|
+
else
|
196
|
+
|
197
|
+
log :warning, "unexpected element - '#{a}' (#{a.class}) - in array argument"
|
198
|
+
end
|
199
|
+
|
200
|
+
[ cat, alg ]
|
201
|
+
end.reject { |ar| ar[1].nil? }
|
202
|
+
|
203
|
+
secrets = {}
|
204
|
+
|
205
|
+
yaml = YAML.load_file(source) if :path == source_is
|
206
|
+
|
207
|
+
acs.each do |category, algorithm|
|
208
|
+
|
209
|
+
if :uri == source_is
|
210
|
+
|
211
|
+
secrets[algorithm] = get_secret_from_server source, category, algorithm, **options
|
212
|
+
else
|
213
|
+
|
214
|
+
secrets[algorithm] = get_secret_from_hash yaml, category, algorithm, **options
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
secrets
|
219
|
+
end
|
220
|
+
|
221
|
+
end # module SecretsUtil
|
222
|
+
|
223
|
+
end # module Util
|
224
|
+
end # module Cassini
|
225
|
+
end # module RazorRisk
|
226
|
+
|
227
|
+
# ############################## end of file ############################# #
|
228
|
+
|
229
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# ######################################################################## #
|
4
|
+
# File: razor_risk/cassini/util/version_util.rb
|
5
|
+
#
|
6
|
+
# Purpose: Conducts claimed version checks
|
7
|
+
#
|
8
|
+
# Created: 2nd January 2018
|
9
|
+
# Updated: 15th May 2018
|
10
|
+
#
|
11
|
+
# Author: Matthew Wilson
|
12
|
+
#
|
13
|
+
# Copyright (c) 2018, Razor Risk Technologies Pty Ltd
|
14
|
+
# All rights reserved.
|
15
|
+
#
|
16
|
+
# ######################################################################## #
|
17
|
+
|
18
|
+
|
19
|
+
# ##########################################################################
|
20
|
+
# requires
|
21
|
+
|
22
|
+
require 'pantheios'
|
23
|
+
require 'xqsr3/quality/parameter_checking'
|
24
|
+
|
25
|
+
=begin
|
26
|
+
=end
|
27
|
+
|
28
|
+
module RazorRisk
|
29
|
+
module Cassini
|
30
|
+
module Util
|
31
|
+
|
32
|
+
module VersionUtil
|
33
|
+
|
34
|
+
include ::Pantheios
|
35
|
+
include ::Xqsr3::Quality::ParameterChecking
|
36
|
+
|
37
|
+
def self.included receiver
|
38
|
+
|
39
|
+
receiver.extend self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Checks the required and actual version of a given library, aborting
|
43
|
+
# with a detailed message if not compatible
|
44
|
+
#
|
45
|
+
# === Signature
|
46
|
+
#
|
47
|
+
# * *Parameters:*
|
48
|
+
# - +actual_module_or_version+:: [ ::Module, ::String, [ ::String,
|
49
|
+
# Integer]] The module or version being tested. Recommended usage is
|
50
|
+
# to pass the module (which allows inference of the name)
|
51
|
+
# - +required_version+:: [ ::String, [ ::Integer ]] The required
|
52
|
+
# version, e.g. [ 0, 1, 2, 3] or '0.1.2.3'
|
53
|
+
# - +lib_name+:: [::String] The name of the library. May be +nil+ if
|
54
|
+
# +actual_module_or_version+ is a +::Module+, the name of which will
|
55
|
+
# be used instead
|
56
|
+
#
|
57
|
+
# * *Options:*
|
58
|
+
# - +:aborter+:: [ responds to :abort(::String) ] An aborter. May be
|
59
|
+
# +nil+, in which case +::Kernel+ is used
|
60
|
+
# - +:process_name+:: [::String] The name of the process. May be
|
61
|
+
# +nil+, in which case it is inferred from the calling script
|
62
|
+
def check_version_compatibility actual_module_or_version, required_version, lib_name = nil, **options
|
63
|
+
|
64
|
+
check_parameter actual_module_or_version, 'actual_module_or_version', types: [ ::Module, [ ::String, ::Integer ], ::String ]
|
65
|
+
check_parameter required_version, 'required_version', types: [ [ ::String, ::Integer ], ::String ]
|
66
|
+
|
67
|
+
check_option options, :aborter, allow_nil: true, responds_to: [ :abort ]
|
68
|
+
|
69
|
+
aborter = options[:aborter] || ::Kernel
|
70
|
+
process_name = options[:process_name] || ::Pantheios::Util::ProcessUtil.derive_process_name
|
71
|
+
|
72
|
+
lib_name ||= actual_module_or_version.to_s if ::Module === actual_module_or_version
|
73
|
+
|
74
|
+
actual_version = ::Module === actual_module_or_version ? actual_module_or_version::VERSION : actual_module_or_version
|
75
|
+
required_s = ::Array === required_version ? required_version.join('.') : required_version
|
76
|
+
|
77
|
+
aborter.abort "#{process_name}: FATAL: this program requires #{lib_name} version #{required_s} or later" if ::Pantheios::Util::VersionUtil.version_compare(required_version, actual_version) > 0
|
78
|
+
end
|
79
|
+
|
80
|
+
end # module VersionUtil
|
81
|
+
|
82
|
+
end # module Util
|
83
|
+
end # module Cassini
|
84
|
+
end # module RazorRisk
|
85
|
+
|
86
|
+
# ############################## end of file ############################# #
|
87
|
+
|
88
|
+
|