razorrisk-cassini-common 0.26.24
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/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
|
+
|