gruf 1.2.7 → 2.0.0
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +98 -119
- data/bin/gruf +9 -3
- data/lib/gruf.rb +4 -4
- data/lib/gruf/configuration.rb +11 -20
- data/lib/gruf/controllers/base.rb +82 -0
- data/lib/gruf/controllers/request.rb +96 -0
- data/lib/gruf/controllers/service_binder.rb +86 -0
- data/lib/gruf/error.rb +9 -0
- data/lib/gruf/errors/helpers.rb +40 -0
- data/lib/gruf/{hooks → interceptors}/active_record/connection_reset.rb +4 -10
- data/lib/gruf/interceptors/authentication/basic.rb +80 -0
- data/lib/gruf/interceptors/base.rb +51 -0
- data/lib/gruf/{instrumentation/output_metadata_timer.rb → interceptors/context.rb} +25 -15
- data/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb +59 -0
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/base.rb +15 -13
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/logstash.rb +15 -13
- data/lib/gruf/{instrumentation → interceptors/instrumentation}/request_logging/formatters/plain.rb +21 -19
- data/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb +191 -0
- data/lib/gruf/interceptors/instrumentation/statsd.rb +80 -0
- data/lib/gruf/interceptors/registry.rb +131 -0
- data/lib/gruf/{authentication/none.rb → interceptors/server_interceptor.rb} +8 -7
- data/lib/gruf/interceptors/timer.rb +79 -0
- data/lib/gruf/response.rb +1 -2
- data/lib/gruf/server.rb +40 -25
- data/lib/gruf/version.rb +1 -1
- metadata +19 -20
- data/lib/gruf/authentication.rb +0 -65
- data/lib/gruf/authentication/base.rb +0 -65
- data/lib/gruf/authentication/basic.rb +0 -74
- data/lib/gruf/authentication/strategies.rb +0 -107
- data/lib/gruf/hooks/base.rb +0 -66
- data/lib/gruf/hooks/registry.rb +0 -110
- data/lib/gruf/instrumentation/base.rb +0 -114
- data/lib/gruf/instrumentation/registry.rb +0 -104
- data/lib/gruf/instrumentation/request_context.rb +0 -82
- data/lib/gruf/instrumentation/request_logging/hook.rb +0 -185
- data/lib/gruf/instrumentation/statsd.rb +0 -80
- data/lib/gruf/service.rb +0 -333
@@ -0,0 +1,131 @@
|
|
1
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
5
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
6
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
7
|
+
#
|
8
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
9
|
+
# Software.
|
10
|
+
#
|
11
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
12
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
13
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
14
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
15
|
+
#
|
16
|
+
module Gruf
|
17
|
+
module Interceptors
|
18
|
+
##
|
19
|
+
# Handles registration of interceptors
|
20
|
+
#
|
21
|
+
class Registry
|
22
|
+
class InterceptorNotFoundError < StandardError; end
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@registry ||= []
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Add an interceptor to the registry
|
30
|
+
#
|
31
|
+
# @param [Gruf::Interceptors::Base] interceptor_class The class of the interceptor to add
|
32
|
+
# @param [Hash] options A hash of options to pass into the interceptor during initialization
|
33
|
+
#
|
34
|
+
def use(interceptor_class, options = {})
|
35
|
+
interceptors_mutex do
|
36
|
+
@registry << {
|
37
|
+
klass: interceptor_class,
|
38
|
+
options: options
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Insert an interceptor before another specified interceptor
|
45
|
+
#
|
46
|
+
# @param [Gruf::Interceptors::Base] before_class The interceptor to insert before
|
47
|
+
# @param [Gruf::Interceptors::Base] interceptor_class The class of the interceptor to add
|
48
|
+
# @param [Hash] options A hash of options to pass into the interceptor during initialization
|
49
|
+
#
|
50
|
+
def insert_before(before_class, interceptor_class, options = {})
|
51
|
+
interceptors_mutex do
|
52
|
+
pos = @registry.find_index { |opts| opts.fetch(:klass, '') == before_class }
|
53
|
+
raise InterceptorNotFoundError if pos.nil?
|
54
|
+
@registry.insert(
|
55
|
+
pos,
|
56
|
+
klass: interceptor_class,
|
57
|
+
options: options
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Insert an interceptor after another specified interceptor
|
64
|
+
#
|
65
|
+
# @param [Gruf::Interceptors::Base] after_class The interceptor to insert after
|
66
|
+
# @param [Gruf::Interceptors::Base] interceptor_class The class of the interceptor to add
|
67
|
+
# @param [Hash] options A hash of options to pass into the interceptor during initialization
|
68
|
+
#
|
69
|
+
def insert_after(after_class, interceptor_class, options = {})
|
70
|
+
interceptors_mutex do
|
71
|
+
pos = @registry.find_index { |opts| opts.fetch(:klass, '') == after_class }
|
72
|
+
raise InterceptorNotFoundError if pos.nil?
|
73
|
+
@registry.insert(
|
74
|
+
(pos + 1),
|
75
|
+
klass: interceptor_class,
|
76
|
+
options: options
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Load and return all interceptors for the given request
|
83
|
+
#
|
84
|
+
# @param [Gruf::Controllers::Request] request
|
85
|
+
# @param [Gruf::Error] error
|
86
|
+
# @return [Array<Gruf::Interceptors::Base>]
|
87
|
+
#
|
88
|
+
def prepare(request, error)
|
89
|
+
is = []
|
90
|
+
interceptors_mutex do
|
91
|
+
@registry.each do |o|
|
92
|
+
is << o[:klass].new(request, error, o[:options])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
is
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Clear the registry
|
100
|
+
#
|
101
|
+
def clear
|
102
|
+
interceptors_mutex do
|
103
|
+
@registry = []
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# @return [Integer] The number of interceptors currently loaded
|
109
|
+
#
|
110
|
+
def count
|
111
|
+
interceptors_mutex do
|
112
|
+
@registry ||= []
|
113
|
+
@registry.count
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
##
|
120
|
+
# Handle mutations to the interceptor registry in a thread-safe manner
|
121
|
+
#
|
122
|
+
def interceptors_mutex(&block)
|
123
|
+
@interceptors_mutex ||= begin
|
124
|
+
require 'monitor'
|
125
|
+
Monitor.new
|
126
|
+
end
|
127
|
+
@interceptors_mutex.synchronize(&block)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -15,17 +15,18 @@
|
|
15
15
|
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
16
|
#
|
17
17
|
module Gruf
|
18
|
-
module
|
18
|
+
module Interceptors
|
19
19
|
##
|
20
|
-
#
|
20
|
+
# Intercepts server requests
|
21
21
|
#
|
22
|
-
class
|
22
|
+
class ServerInterceptor < Base
|
23
|
+
include Gruf::Errors::Helpers
|
24
|
+
|
23
25
|
##
|
24
|
-
#
|
25
|
-
# @return [TrueClass] Always true for this passthrough strategy.
|
26
|
+
# Call the interceptor
|
26
27
|
#
|
27
|
-
def
|
28
|
-
|
28
|
+
def call
|
29
|
+
raise NotImplementedError
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
+
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
+
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
+
# Software.
|
11
|
+
#
|
12
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
+
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
+
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
#
|
17
|
+
module Gruf
|
18
|
+
module Interceptors
|
19
|
+
##
|
20
|
+
# Utility class that can be used by interceptors to time requests
|
21
|
+
#
|
22
|
+
class Timer
|
23
|
+
##
|
24
|
+
# Represents a timed result for an interceptor
|
25
|
+
#
|
26
|
+
class Result
|
27
|
+
attr_reader :message
|
28
|
+
attr_reader :elapsed
|
29
|
+
|
30
|
+
def initialize(message, elapsed, successful)
|
31
|
+
@message = message
|
32
|
+
@elapsed = elapsed.to_f
|
33
|
+
@successful = successful ? true : false
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# @return [Boolean] True if this was a successful request
|
38
|
+
#
|
39
|
+
def successful?
|
40
|
+
@successful
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# @return [String] The name of the message class
|
45
|
+
#
|
46
|
+
def message_class_name
|
47
|
+
@message.class.name
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Return the execution time rounded to a specified precision
|
52
|
+
#
|
53
|
+
# @param [Integer] precision The amount of decimal places to round to
|
54
|
+
# @return [Float] The execution time rounded to the appropriate decimal point
|
55
|
+
#
|
56
|
+
def elapsed_rounded(precision: 2)
|
57
|
+
@elapsed.to_f.round(precision)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Time a given code block and return a Timer::Result object
|
63
|
+
#
|
64
|
+
# @return [Gruf::Interceptors::Timer::Result]
|
65
|
+
#
|
66
|
+
def self.time
|
67
|
+
start_time = Time.now
|
68
|
+
message = yield
|
69
|
+
end_time = Time.now
|
70
|
+
elapsed = (end_time - start_time) * 1000.0
|
71
|
+
Result.new(message, elapsed, true)
|
72
|
+
rescue GRPC::BadStatus => e
|
73
|
+
end_time = Time.now
|
74
|
+
elapsed = (end_time - start_time) * 1000.0
|
75
|
+
Result.new(e, elapsed, false)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/gruf/response.rb
CHANGED
@@ -63,8 +63,7 @@ module Gruf
|
|
63
63
|
# @return [Float] The execution time of the response
|
64
64
|
#
|
65
65
|
def internal_execution_time
|
66
|
-
|
67
|
-
trailing_metadata[key].to_f
|
66
|
+
trailing_metadata['timer'].to_f
|
68
67
|
end
|
69
68
|
end
|
70
69
|
end
|
data/lib/gruf/server.rb
CHANGED
@@ -22,21 +22,24 @@ module Gruf
|
|
22
22
|
class Server
|
23
23
|
include Gruf::Loggable
|
24
24
|
|
25
|
-
# @return [Array<Class>] The services this server is handling
|
26
|
-
attr_accessor :services
|
27
25
|
# @return [GRPC::RpcServer] The underlying GRPC server instance
|
28
26
|
attr_reader :server
|
29
27
|
# @return [Integer] The port the server is bound to
|
30
28
|
attr_reader :port
|
29
|
+
# @return [Hash] Hash of options passed into the server
|
30
|
+
attr_reader :options
|
31
31
|
|
32
32
|
##
|
33
33
|
# Initialize the server and load and setup the services
|
34
34
|
#
|
35
|
-
# @param [
|
35
|
+
# @param [Hash] options
|
36
36
|
#
|
37
|
-
def initialize(
|
37
|
+
def initialize(options = {})
|
38
|
+
@options = options || {}
|
39
|
+
@interceptors = options.fetch(:interceptor_registry, Gruf.interceptors)
|
40
|
+
@interceptors = Gruf::Interceptors::Registry.new unless @interceptors.is_a?(Gruf::Interceptors::Registry)
|
41
|
+
@services = []
|
38
42
|
setup!
|
39
|
-
load_services(services)
|
40
43
|
end
|
41
44
|
|
42
45
|
##
|
@@ -44,11 +47,9 @@ module Gruf
|
|
44
47
|
#
|
45
48
|
def server
|
46
49
|
unless @server
|
47
|
-
@server = GRPC::RpcServer.new(
|
48
|
-
@port = @server.add_http2_port(Gruf.server_binding_url, ssl_credentials)
|
49
|
-
services.each
|
50
|
-
@server.handle(s)
|
51
|
-
end
|
50
|
+
@server = GRPC::RpcServer.new(options)
|
51
|
+
@port = @server.add_http2_port(options.fetch(:hostname, Gruf.server_binding_url), ssl_credentials)
|
52
|
+
@services.each { |s| @server.handle(s) }
|
52
53
|
end
|
53
54
|
@server
|
54
55
|
end
|
@@ -64,34 +65,48 @@ module Gruf
|
|
64
65
|
end
|
65
66
|
# :nocov:
|
66
67
|
|
67
|
-
|
68
|
+
##
|
69
|
+
# @param [Class] klass
|
70
|
+
#
|
71
|
+
def add_service(klass)
|
72
|
+
@services << klass unless @services.include?(klass)
|
73
|
+
end
|
68
74
|
|
69
75
|
##
|
70
|
-
#
|
76
|
+
# Add an interceptor to the server
|
71
77
|
#
|
72
|
-
# @param [
|
73
|
-
# @
|
78
|
+
# @param [Gruf::Interceptors::Base]
|
79
|
+
# @param [Hash]
|
74
80
|
#
|
75
|
-
def
|
76
|
-
|
77
|
-
@services = Gruf.services.concat(svcs)
|
78
|
-
@services.uniq!
|
79
|
-
end
|
80
|
-
@services
|
81
|
+
def add_interceptor(klass, opts = {})
|
82
|
+
@interceptors.use(klass, opts)
|
81
83
|
end
|
82
84
|
|
85
|
+
private
|
86
|
+
|
83
87
|
##
|
84
88
|
# Auto-load all gRPC handlers
|
85
89
|
#
|
86
90
|
# :nocov:
|
87
91
|
def setup!
|
88
|
-
|
92
|
+
return unless File.directory?(controllers_path)
|
93
|
+
path = File.realpath(controllers_path)
|
94
|
+
$LOAD_PATH.unshift(path)
|
95
|
+
Dir["#{path}/**/*.rb"].each do |f|
|
96
|
+
next if f.include?('_pb') # exclude if people include proto generated files in app/rpc
|
89
97
|
logger.info "- Loading gRPC service file: #{f}"
|
90
|
-
|
98
|
+
load File.realpath(f)
|
91
99
|
end
|
92
100
|
end
|
93
101
|
# :nocov:
|
94
102
|
|
103
|
+
##
|
104
|
+
# @param [String]
|
105
|
+
#
|
106
|
+
def controllers_path
|
107
|
+
options.fetch(:controllers_path, Gruf.controllers_path)
|
108
|
+
end
|
109
|
+
|
95
110
|
##
|
96
111
|
# Load the SSL/TLS credentials for this server
|
97
112
|
#
|
@@ -99,9 +114,9 @@ module Gruf
|
|
99
114
|
#
|
100
115
|
# :nocov:
|
101
116
|
def ssl_credentials
|
102
|
-
if Gruf.use_ssl
|
103
|
-
private_key = File.read Gruf.ssl_key_file
|
104
|
-
cert_chain = File.read Gruf.ssl_crt_file
|
117
|
+
if options.fetch(:use_ssl, Gruf.use_ssl)
|
118
|
+
private_key = File.read(options.fetch(:ssl_key_file, Gruf.ssl_key_file))
|
119
|
+
cert_chain = File.read(options.fetch(:ssl_crt_file, Gruf.ssl_crt_file))
|
105
120
|
certs = [nil, [{ private_key: private_key, cert_chain: cert_chain }], false]
|
106
121
|
GRPC::Core::ServerCredentials.new(*certs)
|
107
122
|
else
|
data/lib/gruf/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gruf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shaun McCormick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,35 +108,34 @@ files:
|
|
108
108
|
- bin/gruf
|
109
109
|
- gruf.gemspec
|
110
110
|
- lib/gruf.rb
|
111
|
-
- lib/gruf/authentication.rb
|
112
|
-
- lib/gruf/authentication/base.rb
|
113
|
-
- lib/gruf/authentication/basic.rb
|
114
|
-
- lib/gruf/authentication/none.rb
|
115
|
-
- lib/gruf/authentication/strategies.rb
|
116
111
|
- lib/gruf/client.rb
|
117
112
|
- lib/gruf/configuration.rb
|
113
|
+
- lib/gruf/controllers/base.rb
|
114
|
+
- lib/gruf/controllers/request.rb
|
115
|
+
- lib/gruf/controllers/service_binder.rb
|
118
116
|
- lib/gruf/error.rb
|
119
117
|
- lib/gruf/errors/debug_info.rb
|
120
118
|
- lib/gruf/errors/field.rb
|
121
|
-
- lib/gruf/
|
122
|
-
- lib/gruf/
|
123
|
-
- lib/gruf/
|
124
|
-
- lib/gruf/
|
125
|
-
- lib/gruf/
|
126
|
-
- lib/gruf/instrumentation/
|
127
|
-
- lib/gruf/instrumentation/
|
128
|
-
- lib/gruf/instrumentation/request_logging/formatters/
|
129
|
-
- lib/gruf/instrumentation/request_logging/formatters/
|
130
|
-
- lib/gruf/instrumentation/request_logging/
|
131
|
-
- lib/gruf/instrumentation/
|
132
|
-
- lib/gruf/
|
119
|
+
- lib/gruf/errors/helpers.rb
|
120
|
+
- lib/gruf/interceptors/active_record/connection_reset.rb
|
121
|
+
- lib/gruf/interceptors/authentication/basic.rb
|
122
|
+
- lib/gruf/interceptors/base.rb
|
123
|
+
- lib/gruf/interceptors/context.rb
|
124
|
+
- lib/gruf/interceptors/instrumentation/output_metadata_timer.rb
|
125
|
+
- lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb
|
126
|
+
- lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb
|
127
|
+
- lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb
|
128
|
+
- lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb
|
129
|
+
- lib/gruf/interceptors/instrumentation/statsd.rb
|
130
|
+
- lib/gruf/interceptors/registry.rb
|
131
|
+
- lib/gruf/interceptors/server_interceptor.rb
|
132
|
+
- lib/gruf/interceptors/timer.rb
|
133
133
|
- lib/gruf/loggable.rb
|
134
134
|
- lib/gruf/logging.rb
|
135
135
|
- lib/gruf/response.rb
|
136
136
|
- lib/gruf/serializers/errors/base.rb
|
137
137
|
- lib/gruf/serializers/errors/json.rb
|
138
138
|
- lib/gruf/server.rb
|
139
|
-
- lib/gruf/service.rb
|
140
139
|
- lib/gruf/timer.rb
|
141
140
|
- lib/gruf/version.rb
|
142
141
|
homepage: https://github.com/bigcommerce/gruf
|
data/lib/gruf/authentication.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
# Copyright (c) 2017-present, BigCommerce Pty. Ltd. All rights reserved
|
3
|
-
#
|
4
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
5
|
-
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
6
|
-
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
7
|
-
# persons to whom the Software is furnished to do so, subject to the following conditions:
|
8
|
-
#
|
9
|
-
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
10
|
-
# Software.
|
11
|
-
#
|
12
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
13
|
-
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
14
|
-
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
15
|
-
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
-
#
|
17
|
-
require_relative 'authentication/strategies'
|
18
|
-
require_relative 'authentication/base'
|
19
|
-
require_relative 'authentication/basic'
|
20
|
-
require_relative 'authentication/none'
|
21
|
-
|
22
|
-
module Gruf
|
23
|
-
##
|
24
|
-
# Handles authentication for gruf services
|
25
|
-
#
|
26
|
-
module Authentication
|
27
|
-
##
|
28
|
-
# Custom error class for handling unauthorized requests
|
29
|
-
#
|
30
|
-
class UnauthorizedError < StandardError; end
|
31
|
-
|
32
|
-
##
|
33
|
-
# Verify a given gruf request
|
34
|
-
#
|
35
|
-
# @param [GRPC::ActiveCall] call The gRPC active call with marshalled data that is being executed
|
36
|
-
# @param [Symbol] strategy The authentication strategy to use
|
37
|
-
# @return [Boolean]
|
38
|
-
#
|
39
|
-
def self.verify(call)
|
40
|
-
credentials = call && call.respond_to?(:metadata) ? call.metadata[Gruf.authorization_metadata_key] : nil
|
41
|
-
|
42
|
-
if Gruf::Authentication::Strategies.any?
|
43
|
-
verified = false
|
44
|
-
Gruf::Authentication::Strategies.each do |_label, klass|
|
45
|
-
begin
|
46
|
-
# if a strategy passes, we've successfully authenticated and can proceed
|
47
|
-
if klass.verify(call, credentials)
|
48
|
-
verified = true
|
49
|
-
break
|
50
|
-
end
|
51
|
-
rescue => e
|
52
|
-
Gruf.logger.error "#{e.message} - #{e.backtrace[0..4].join("\n")}"
|
53
|
-
# NOOP, we don't want to fail other strategies because of a bad neighbor
|
54
|
-
# or if a strategy throws an exception because of a failed auth
|
55
|
-
# we should just proceed to the next strategy
|
56
|
-
end
|
57
|
-
end
|
58
|
-
verified
|
59
|
-
else
|
60
|
-
# we're not using any strategies, so no auth
|
61
|
-
true
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|