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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +22 -0
  3. data/LICENSE +5 -0
  4. data/README.md +2 -0
  5. data/Rakefile +102 -0
  6. data/lib/razor_risk/cassini/applications/microservice.rb +318 -0
  7. data/lib/razor_risk/cassini/applications/rest_framework/route_verb_dispatcher.rb +120 -0
  8. data/lib/razor_risk/cassini/applications/rest_framework/verb_handler.rb +117 -0
  9. data/lib/razor_risk/cassini/applications/route_verb_adaptors/utilities/collection_get_helper.rb +86 -0
  10. data/lib/razor_risk/cassini/applications/securable_microservice.rb +164 -0
  11. data/lib/razor_risk/cassini/applications/secured_microservice.rb +63 -0
  12. data/lib/razor_risk/cassini/applications/unsecured_microservice.rb +77 -0
  13. data/lib/razor_risk/cassini/authorisation/header_helpers.rb +271 -0
  14. data/lib/razor_risk/cassini/authorisation/security_model_helpers.rb +93 -0
  15. data/lib/razor_risk/cassini/authorisation.rb +27 -0
  16. data/lib/razor_risk/cassini/cli.rb +19 -0
  17. data/lib/razor_risk/cassini/common/version.rb +44 -0
  18. data/lib/razor_risk/cassini/common.rb +32 -0
  19. data/lib/razor_risk/cassini/constants.rb +68 -0
  20. data/lib/razor_risk/cassini/diagnostics/util_functions.rb +248 -0
  21. data/lib/razor_risk/cassini/diagnostics/zeroth_include.rb +35 -0
  22. data/lib/razor_risk/cassini/extensions/libclimate/common_options.rb +267 -0
  23. data/lib/razor_risk/cassini/extensions/libclimate.rb +26 -0
  24. data/lib/razor_risk/cassini/header_functions.rb +59 -0
  25. data/lib/razor_risk/cassini/main.rb +238 -0
  26. data/lib/razor_risk/cassini/mixin/razor_response_validator.rb +176 -0
  27. data/lib/razor_risk/cassini/testing/suppress_pantheios_logging.rb +31 -0
  28. data/lib/razor_risk/cassini/util/conversion_util.rb +176 -0
  29. data/lib/razor_risk/cassini/util/program_execution_util.rb +379 -0
  30. data/lib/razor_risk/cassini/util/secrets_util.rb +229 -0
  31. data/lib/razor_risk/cassini/util/version_util.rb +88 -0
  32. data/lib/razor_risk/sinatra/helpers/check_auth_helper.rb +209 -0
  33. data/lib/razor_risk/sinatra/helpers/validate_accept_helper.rb +69 -0
  34. data/lib/razor_risk/sinatra/helpers/validate_content_type_helper.rb +74 -0
  35. data/lib/razor_risk/sinatra/helpers/validate_query_parameters_helper.rb +198 -0
  36. data/test/scratch/cassini/util/convert_XML.rb +54 -0
  37. data/test/unit/applications/route_verb_adaptors/utilities/tc_collection_get_helper.rb +236 -0
  38. data/test/unit/applications/tc_verb_handler.rb +130 -0
  39. data/test/unit/mixin/tc_razor_response_validator.rb +328 -0
  40. data/test/unit/sinatra/helpers/tc_validate_query_parameters_helper.rb +134 -0
  41. data/test/unit/tc_authorisation_util.rb +265 -0
  42. data/test/unit/tc_load_secrets.rb +95 -0
  43. data/test/unit/util/tc_conversion_util.rb +393 -0
  44. data/test/unit/util/tc_program_execution_util.rb +462 -0
  45. metadata +380 -0
@@ -0,0 +1,209 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/sinatra/helpers/check_auth_helper.rb
5
+ #
6
+ # Purpose: Definition of the Sinatra helper CheckAuthHelper module,
7
+ # which provides Cassini security model checking via the
8
+ # +check_auth+ instance method
9
+ #
10
+ # Created: 1st December 2017
11
+ # Updated: 20th February 2018
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2017-2018, Razor Risk Technologies Pty Ltd
16
+ # All rights reserved.
17
+ #
18
+ # ######################################################################## #
19
+
20
+
21
+ # ##########################################################################
22
+ # requires
23
+
24
+ require 'razor_risk/cassini/authorisation'
25
+ require 'razor_risk/cassini/constants'
26
+ require 'razor_risk/cassini/header_functions'
27
+ require 'razor_risk/core/diagnostics/logger'
28
+
29
+ require 'xqsr3/quality/parameter_checking'
30
+
31
+ require 'sinatra/base'
32
+
33
+ # ##########################################################################
34
+ # module
35
+
36
+ module RazorRisk
37
+ module Sinatra
38
+ module Helpers
39
+
40
+ # ##########################################################################
41
+ # CheckAuthHelper
42
+
43
+ module CheckAuthHelper
44
+
45
+ include Cassini::Authorisation::HeaderHelpers
46
+ include Cassini::HeaderFunctions
47
+ include ::RazorRisk::Core::Diagnostics::Logger
48
+
49
+ include ::Xqsr3::Quality::ParameterChecking
50
+
51
+ private
52
+
53
+ HTTP_AUTHORIZATION = ::RazorRisk::Cassini::Constants::HTTP_AUTHORIZATION
54
+ public
55
+
56
+ RECOGNISED_AUTHENTICATION_SCHEMES = %w{ none basic authorisation_only jwt }.map { |v| v.to_sym }
57
+
58
+ RECOGNISED_ALGORITHMS = %w{ HS256 SHA256 AES-256-CBC }
59
+
60
+ # Checks the authentication information for one of the four accepted
61
+ # schemes - None, Basic, Authorisation-only (Razor Risk-specific),and
62
+ # JWT.
63
+ #
64
+ # @param env [::Hash] The request's +env+ hash.
65
+ # @param auth_scheme [::Symbol] The authorisation scheme.
66
+ # @param options [::Hash] The options hash.
67
+ #
68
+ # @option options [Boolean] :credentials (false) When true the function
69
+ # will return the credentials, if they can be obtained.
70
+ # @option options [Boolean] :halt_unless_auth (true) If true the
71
+ # function will invoke Sinatra's +halt+ with 401 when the authorisation
72
+ # field +HTTP_AUTHORIZATION+ is not present.
73
+ # @option options [Object] :auth_sentinel The value returned if
74
+ # +:halt_unless_auth+ is false.
75
+ # @option options [::String, Array<::String>] :auth_param_name
76
+ # ('HTTP_AUTHORIZATION') The authorisation parameter name(s).
77
+ # @option options [::String, ::Proc] :jwt_secret The JWT secret, or a
78
+ # lambda from which to obtain one, when +auth_scheme+ is +:jwt+.
79
+ # @option options [Boolean] :halt_unless_cred (true) If true the function
80
+ # will invoke Sinatra's +halt+ with 401 when the authorisation
81
+ # information does not contain valid credentials.
82
+ # @option options [Object] :cred_sentinel The value returned if
83
+ # +:halt_unless_cred+ is true.
84
+ #
85
+ #
86
+ # @return [Array<::String>] If option +:credentials+ and credentials can
87
+ # be obtained, returns an array containing the credentials appropriate
88
+ # for the specified +auth_sheme+.
89
+ # @return [true] If not option +:credentials+ and credentials can be
90
+ # obtained.
91
+ # @return [Object] Returns the value of the +:auth_sentinel+ if
92
+ # +:halt_unless_auth+ is false and the auth header is not present.
93
+ # @return [Object] Returns the value of the +:cred_sentinel+ if
94
+ # +:halt_unless_cred+ is false and no credentials could be obtained.
95
+ #
96
+ def check_auth env, auth_scheme, **options
97
+
98
+ trace ParamNames[ :env, :auth_scheme, :options ], env, auth_scheme, options
99
+
100
+ check_param env, 'env', type: ::Hash
101
+ check_param auth_scheme, 'auth_scheme', type: ::Symbol, values: RECOGNISED_AUTHENTICATION_SCHEMES
102
+ check_param options, 'options', type: ::Hash
103
+
104
+ check_param options[:credentials], 'credentials', treat_as_option: true, types: [ ::FalseClass, ::TrueClass ], allow_nil: true
105
+ check_param options[:halt_unless_auth], 'halt_unless_auth', treat_as_option: true, types: [ ::FalseClass, ::TrueClass ], allow_nil: true
106
+ check_param options[:auth_sentinel], 'auth_sentinel', treat_as_option: true, allow_nil: true
107
+ check_param options[:auth_param_name], 'auth_param_name', treat_as_option: true, types: [ ::String, [ ::String] ], allow_nil: true
108
+ check_param options[:jwt_secret], 'jwt_secret', treat_as_option: true, types: [ ::String, ::Proc ], allow_nil: :jwt != auth_scheme
109
+ check_param options[:halt_unless_cred], 'halt_unless_auth', treat_as_option: true, types: [ ::FalseClass, ::TrueClass ], allow_nil: true
110
+
111
+
112
+ options = {
113
+
114
+ auth_param_name: HTTP_AUTHORIZATION,
115
+ credentials: false,
116
+ halt_unless_auth: true,
117
+ halt_unless_cred: true,
118
+ }.merge options
119
+
120
+
121
+ auth = nil
122
+
123
+ auth_param_name = options[:auth_param_name] || HTTP_AUTHORIZATION
124
+ case auth_param_name
125
+ when ::Array
126
+
127
+ auth_param_name.each do |name|
128
+
129
+ break if auth = env[name]
130
+ end
131
+ else
132
+
133
+ # will be a ::String
134
+ auth = env[auth_param_name]
135
+ end
136
+
137
+
138
+ log :debug4, "auth(#{auth.class})='#{auth}'"
139
+
140
+
141
+ unless auth || :none == auth_scheme
142
+
143
+ return options[:auth_sentinel] unless options[:halt_unless_auth]
144
+ halt 401, make_WWW_auth_header(auth_scheme), 'Missing or invalid authenticate header'
145
+ end
146
+
147
+
148
+ return true unless options[:credentials]
149
+
150
+
151
+ credentials = nil
152
+
153
+ case auth_scheme
154
+ when :none
155
+
156
+ credentials = []
157
+ when :basic
158
+
159
+ credentials = credentials_from_Basic auth, nil: true
160
+ when :authorisation_only, :authorization_only
161
+
162
+ credentials = credentials_from_AuthorisationOnly(auth)
163
+ when :jwt
164
+
165
+ jwt_secret = options[:jwt_secret]
166
+ jwt_secret = jwt_secret.call() if ::Proc == jwt_secret
167
+
168
+ begin
169
+
170
+ credentials = credentials_from_JWT auth, jwt_secret, nil: true
171
+ rescue JWT::ValidationError => x
172
+
173
+ log "exception (#{x.class}): #{x.message}"
174
+ halt 401, make_WWW_auth_header(auth_scheme), 'Invalid credentials'
175
+ rescue JWT::DecodeError => x
176
+
177
+ log "exception (#{x.class}): #{x.message}"
178
+ halt 401, make_WWW_auth_header(auth_scheme), 'Missing or invalid authenticate header'
179
+ end
180
+ end
181
+
182
+ return credentials if credentials
183
+
184
+ return options[:cred_sentinel] unless options[:halt_unless_cred]
185
+
186
+ halt 401, make_WWW_auth_header(auth_scheme), 'Missing or invalid authenticate header'
187
+ end
188
+
189
+ end # module CheckAuthHelper
190
+
191
+ # ##########################################################################
192
+ # module
193
+
194
+ end # module Helpers
195
+ end # module Sinatra
196
+ end # module RazorRisk
197
+
198
+ # ##########################################################################
199
+ # Sinatra helpers
200
+
201
+ module Sinatra
202
+
203
+ helpers ::RazorRisk::Sinatra::Helpers::CheckAuthHelper
204
+
205
+ end # module Sinatra
206
+
207
+ # ############################## end of file ############################# #
208
+
209
+
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/sinatra/helpers/validate_accept_helper.rb
5
+ #
6
+ # Purpose: Definition of the Sinatra helper ValidateAcceptHelper
7
+ # module, which provides automatic 'Accept' header validation
8
+ #
9
+ # Created: 1st February 2018
10
+ # Updated: 11th August 2018
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
15
+ # All rights reserved.
16
+ #
17
+ # ######################################################################## #
18
+
19
+
20
+ # ##########################################################################
21
+ # requires
22
+
23
+ require 'xqsr3/quality/parameter_checking'
24
+
25
+ require 'sinatra/base'
26
+
27
+ # ##########################################################################
28
+ # module
29
+
30
+ module RazorRisk
31
+ module Sinatra
32
+ module Helpers
33
+
34
+ # ##########################################################################
35
+ # ValidateAcceptHelper
36
+
37
+ module ValidateAcceptHelper
38
+
39
+ include ::Xqsr3::Quality::ParameterChecking
40
+
41
+ def validate_accept *args, **options
42
+
43
+ rq = args.shift
44
+ ar = args.shift
45
+
46
+ halt 406, %Q<invalid accept type(s) (#{rq.accept.map { |a| "'#{a}'" }.join(', ')}), must be one of #{ar.map { |a| "'#{a}'" }.join(', ')}> unless ar.any? { |a| rq.accept? a }
47
+ end
48
+
49
+ end # module ValidateAcceptHelper
50
+
51
+ # ##########################################################################
52
+ # module
53
+
54
+ end # module Helpers
55
+ end # module Sinatra
56
+ end # module RazorRisk
57
+
58
+ # ##########################################################################
59
+ # Sinatra helpers
60
+
61
+ module Sinatra
62
+
63
+ helpers ::RazorRisk::Sinatra::Helpers::ValidateAcceptHelper
64
+
65
+ end # module Sinatra
66
+
67
+ # ############################## end of file ############################# #
68
+
69
+
@@ -0,0 +1,74 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/sinatra/helpers/validate_content_type_helper.rb
5
+ #
6
+ # Purpose: Definition of the Sinatra helper ValidateContentTypeHelper
7
+ # module, which provides automatic 'Content-Type' header
8
+ # validation
9
+ #
10
+ # Created: 1st February 2018
11
+ # Updated: 11th August 2018
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
16
+ # All rights reserved.
17
+ #
18
+ # ######################################################################## #
19
+
20
+
21
+ # ##########################################################################
22
+ # requires
23
+
24
+ require 'xqsr3/quality/parameter_checking'
25
+
26
+ require 'sinatra/base'
27
+
28
+ # ##########################################################################
29
+ # module
30
+
31
+ module RazorRisk
32
+ module Sinatra
33
+ module Helpers
34
+
35
+ # ##########################################################################
36
+ # ValidateContentTypeHelper
37
+
38
+ module ValidateContentTypeHelper
39
+
40
+ include ::Xqsr3::Quality::ParameterChecking
41
+
42
+ def validate_content_type *args, **options
43
+
44
+ rq = args.shift
45
+ ar = args.shift
46
+
47
+ halt 415, %Q<invalid content-type '('#{rq.content_type}')', must be one of #{ar.map { |a| "'#{a}'" }.join(', ')}> unless ar.any? do |ct|
48
+
49
+ rq.content_type.start_with? ct
50
+ end
51
+ end
52
+
53
+ end # module ValidateContentTypeHelper
54
+
55
+ # ##########################################################################
56
+ # module
57
+
58
+ end # module Helpers
59
+ end # module Sinatra
60
+ end # module RazorRisk
61
+
62
+ # ##########################################################################
63
+ # Sinatra helpers
64
+
65
+ module Sinatra
66
+
67
+ helpers ::RazorRisk::Sinatra::Helpers::ValidateContentTypeHelper
68
+
69
+ end # module Sinatra
70
+
71
+ # ############################## end of file ############################# #
72
+
73
+
74
+
@@ -0,0 +1,198 @@
1
+ # encoding: UTF-8
2
+
3
+ # ######################################################################## #
4
+ # File: razor_risk/sinatra/helpers/validate_query_parameters.rb
5
+ #
6
+ # Purpose: Definition of the Sinatra helper
7
+ # ValidateQueryParametersHelper module, which provides
8
+ # automatic query parameter validation
9
+ #
10
+ # Created: 11th August 2018
11
+ # Updated: 17th August 2018
12
+ #
13
+ # Author: Matthew Wilson
14
+ #
15
+ # Copyright (c) 2018, Razor Risk Technologies Pty Ltd
16
+ # All rights reserved.
17
+ #
18
+ # ######################################################################## #
19
+
20
+
21
+ # ##########################################################################
22
+ # requires
23
+
24
+ require 'pantheios'
25
+ require 'xqsr3/quality/parameter_checking'
26
+
27
+ require 'sinatra/base'
28
+
29
+ # ##########################################################################
30
+ # module
31
+
32
+ module RazorRisk
33
+ module Sinatra
34
+ module Helpers
35
+
36
+ # ##########################################################################
37
+ # ValidateQueryParametersHelper
38
+
39
+ module ValidateQueryParametersHelper
40
+
41
+ include ::Pantheios
42
+
43
+ include ::Xqsr3::Quality::ParameterChecking
44
+
45
+ module ValidateQueryParametersHelper_Constants
46
+
47
+ SINATRA_SPECIAL_PARAMS = %w{
48
+
49
+ captures
50
+ splat
51
+ }
52
+
53
+ end # module ValidateQueryParametersHelper_Constants
54
+
55
+ def validate_query_parameters *args, **options
56
+
57
+ trace ParamNames[ :args, :options], args, options
58
+
59
+
60
+ params = args.shift
61
+ spec = args.shift
62
+ rt_vars = args.shift || []
63
+
64
+ case spec
65
+ when nil
66
+
67
+ params
68
+ when ::Array
69
+
70
+ # interpreted as a complete list of optional parameters
71
+
72
+ unrecognised = params.keys - spec
73
+
74
+ unrecognised = unrecognised - rt_vars
75
+
76
+ unrecognised = unrecognised - ValidateQueryParametersHelper_Constants::SINATRA_SPECIAL_PARAMS
77
+
78
+ unless unrecognised.empty?
79
+
80
+ halt(*[ 422, {}, "One or more parameters - '#{unrecognised}' - are not supported on this route" ])
81
+ end
82
+
83
+ params
84
+ when ::Hash
85
+
86
+ # interpreted as a map of { query-parameter => [ 0+
87
+ # characteristics-symbols] }, where recognised characteristics are:
88
+ #
89
+ # - :allow_empty - means that the parameter value may be empty
90
+ # (subject to :strip);
91
+ # - :required - means that the parameter must be present;
92
+ # - :strip - causes the parameter to be (converted to string
93
+ # form and then) stripped;
94
+ #
95
+ # - :integral - causes the parameter to be converted to string;
96
+ # halts(422) if the conversion fails;
97
+ # - :negative - requires the value to be <0; operative only if
98
+ # :integral is specified;
99
+ # - :positive - requires the value to be >0; operative only if
100
+ # :integral is specified;
101
+ # - :non_negative - requires the value to be >=0; operative only
102
+ # if :integral is specified;
103
+ # - :non_positive - requires the value to be <=0; operative only
104
+ # if :integral is specified;
105
+
106
+ warn "validating query parameters from a #{::Hash} spec is not supported in the current version"
107
+
108
+ unrecognised = params.keys - spec.keys
109
+
110
+ unrecognised = unrecognised - rt_vars
111
+
112
+ unrecognised = unrecognised - ValidateQueryParametersHelper_Constants::SINATRA_SPECIAL_PARAMS
113
+
114
+ unless unrecognised.empty?
115
+
116
+ halt(*[ 422, {}, "One or more parameters - '#{unrecognised}' - are not supported on this route" ])
117
+ end
118
+
119
+ validated_params = params.dup
120
+
121
+ spec.each do |k, characteristics|
122
+
123
+ next if ValidateQueryParametersHelper_Constants::SINATRA_SPECIAL_PARAMS.include?(k)
124
+
125
+ next if rt_vars.include?(k)
126
+
127
+ case v
128
+ when nil
129
+
130
+ next
131
+ when ::Array
132
+
133
+ ;
134
+ else
135
+
136
+ characteristics = [ characteristics ]
137
+ end
138
+
139
+ if validated_params.has_key? k
140
+
141
+ value = validated_params[k]
142
+
143
+ value = value.to_s.strip if characteristics.include? :strip
144
+
145
+ unless characteristics.include? :allow_empty
146
+
147
+ if value.to_s.empty?
148
+
149
+ halt(*[ 422, {}, "Query parameter '#{k}' has missing value in URI" ])
150
+ end
151
+ end
152
+
153
+ if characteristics.include? :integral
154
+
155
+ # TODO : implement integral conversion and
156
+ # range-checking
157
+ end
158
+
159
+ validated_params[k] = value
160
+ else
161
+
162
+ if characteristics.include? :required
163
+
164
+ halt(*[ 422, {}, "Required query parameter '#{k}' not present in URI" ])
165
+ end
166
+ end
167
+ end
168
+
169
+ validated_params
170
+ else
171
+
172
+
173
+
174
+ warn "#{self.class}##{__method__}() : invalid spec type - '#{spec.class}' - given - ignoring"
175
+ end
176
+ end
177
+
178
+ end # module ValidateQueryParametersHelper
179
+
180
+ # ##########################################################################
181
+ # module
182
+
183
+ end # module Helpers
184
+ end # module Sinatra
185
+ end # module RazorRisk
186
+
187
+ # ##########################################################################
188
+ # Sinatra helpers
189
+
190
+ module Sinatra
191
+
192
+ helpers ::RazorRisk::Sinatra::Helpers::ValidateQueryParametersHelper
193
+
194
+ end # module Sinatra
195
+
196
+ # ############################## end of file ############################# #
197
+
198
+
@@ -0,0 +1,54 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *(['..'] * 4), 'lib')
4
+
5
+ unless $DEBUG
6
+
7
+ require 'pantheios/globals'
8
+ require 'pantheios/services/null_log_service'
9
+
10
+ ::Pantheios::Globals.INITIAL_SERVICE_CLASSES = [ ::Pantheios::Services::NullLogService ]
11
+ end
12
+
13
+ require 'razor_risk/cassini/util/conversion_util'
14
+
15
+ require 'libclimate'
16
+ require 'xqsr3/extensions/test/unit'
17
+
18
+ require 'pp'
19
+
20
+ include ::RazorRisk::Cassini::Util::ConversionUtil
21
+
22
+ climate = LibCLImate::Climate.new do |cl|
23
+
24
+ cl.usage_values = '<scheme> <Hash|json> [<xml-doc-path>]'
25
+ end
26
+
27
+ r = climate.run ARGV
28
+
29
+ scheme = r.values[0]
30
+ output_type = r.values[1]
31
+ xml_doc_path = r.values[2]
32
+
33
+ climate.abort 'too many values; use --help for usage' if r.values[3]
34
+ climate.abort "Output type may only be 'Hash' or 'JSON'; use --help for usage" unless output_type =~ /hash|json/i
35
+
36
+ if xml_doc_path
37
+
38
+ xml_doc = File.read(xml_doc_path)
39
+ else
40
+
41
+ xml_doc = $stdin.read
42
+ end
43
+
44
+ case output_type
45
+ when /hash/i
46
+
47
+ puts convert_XML_to_Hash xml_doc, scheme: scheme.to_sym
48
+ when /JSON/i
49
+
50
+ puts convert_XML_to_JSON xml_doc, scheme: scheme.to_sym
51
+ else
52
+
53
+ abort "output_type may only be 'Hash' or 'JSON' but was #{output_type}"
54
+ end