grpc 1.81.2-x86-linux-gnu → 1.82.0.pre1-x86-linux-gnu
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/etc/roots.pem +3939 -9011
- data/src/ruby/ext/grpc/rb_byte_buffer.c +1 -0
- data/src/ruby/ext/grpc/rb_call.c +3 -0
- data/src/ruby/ext/grpc/rb_call_credentials.c +1 -0
- data/src/ruby/ext/grpc/rb_channel.c +1 -0
- data/src/ruby/ext/grpc/rb_channel_args.c +1 -0
- data/src/ruby/ext/grpc/rb_channel_credentials.c +1 -0
- data/src/ruby/ext/grpc/rb_completion_queue.c +1 -0
- data/src/ruby/ext/grpc/rb_compression_options.c +1 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +4 -4
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +6 -6
- data/src/ruby/ext/grpc/rb_server.c +1 -0
- data/src/ruby/ext/grpc/rb_server_credentials.c +1 -0
- data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +1 -0
- data/src/ruby/ext/grpc/rb_xds_server_credentials.c +1 -0
- data/src/ruby/lib/grpc/3.2/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/3.3/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/3.4/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/4.0/grpc_c.so +0 -0
- data/src/ruby/lib/grpc/core/call_credentials.rb +86 -0
- data/src/ruby/lib/grpc/core/channel_credentials.rb +69 -0
- data/src/ruby/lib/grpc/core/credentials_helper.rb +126 -0
- data/src/ruby/lib/grpc/generic/client_stub.rb +86 -73
- data/src/ruby/lib/grpc/generic/interceptors.rb +1 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/lib/grpc.rb +25 -0
- data/src/ruby/spec/call_credentials_spec.rb +52 -2
- data/src/ruby/spec/credentials_helper_spec.rb +80 -0
- data/src/ruby/spec/generic/client_stub_spec.rb +27 -4
- data/src/ruby/spec/generic/server_interceptors_spec.rb +17 -3
- metadata +7 -2
data/src/ruby/ext/grpc/rb_call.c
CHANGED
|
@@ -23,8 +23,11 @@
|
|
|
23
23
|
#include <grpc/grpc.h>
|
|
24
24
|
#include <grpc/impl/codegen/compression_types.h>
|
|
25
25
|
#include <grpc/support/alloc.h>
|
|
26
|
+
#include <stdbool.h>
|
|
26
27
|
|
|
27
28
|
#include "rb_byte_buffer.h"
|
|
29
|
+
/* TODO(nnepal): Include grpc/grpc_security.h for pure ruby call
|
|
30
|
+
* credentials after rb_call_credentials gets removed */
|
|
28
31
|
#include "rb_call_credentials.h"
|
|
29
32
|
#include "rb_completion_queue.h"
|
|
30
33
|
#include "rb_grpc.h"
|
|
@@ -159,9 +159,9 @@ grpc_server_register_method_type grpc_server_register_method_import;
|
|
|
159
159
|
grpc_server_request_registered_call_type grpc_server_request_registered_call_import;
|
|
160
160
|
grpc_server_create_type grpc_server_create_import;
|
|
161
161
|
grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
|
|
162
|
+
grpc_server_config_fetcher_arg_vtable_type grpc_server_config_fetcher_arg_vtable_import;
|
|
162
163
|
grpc_server_config_fetcher_xds_create_type grpc_server_config_fetcher_xds_create_import;
|
|
163
|
-
|
|
164
|
-
grpc_server_set_config_fetcher_type grpc_server_set_config_fetcher_import;
|
|
164
|
+
grpc_server_config_fetcher_unref_type grpc_server_config_fetcher_unref_import;
|
|
165
165
|
grpc_server_add_http2_port_type grpc_server_add_http2_port_import;
|
|
166
166
|
grpc_server_start_type grpc_server_start_import;
|
|
167
167
|
grpc_server_shutdown_and_notify_type grpc_server_shutdown_and_notify_import;
|
|
@@ -448,9 +448,9 @@ void grpc_rb_load_imports(HMODULE library) {
|
|
|
448
448
|
grpc_server_request_registered_call_import = (grpc_server_request_registered_call_type) GetProcAddress(library, "grpc_server_request_registered_call");
|
|
449
449
|
grpc_server_create_import = (grpc_server_create_type) GetProcAddress(library, "grpc_server_create");
|
|
450
450
|
grpc_server_register_completion_queue_import = (grpc_server_register_completion_queue_type) GetProcAddress(library, "grpc_server_register_completion_queue");
|
|
451
|
+
grpc_server_config_fetcher_arg_vtable_import = (grpc_server_config_fetcher_arg_vtable_type) GetProcAddress(library, "grpc_server_config_fetcher_arg_vtable");
|
|
451
452
|
grpc_server_config_fetcher_xds_create_import = (grpc_server_config_fetcher_xds_create_type) GetProcAddress(library, "grpc_server_config_fetcher_xds_create");
|
|
452
|
-
|
|
453
|
-
grpc_server_set_config_fetcher_import = (grpc_server_set_config_fetcher_type) GetProcAddress(library, "grpc_server_set_config_fetcher");
|
|
453
|
+
grpc_server_config_fetcher_unref_import = (grpc_server_config_fetcher_unref_type) GetProcAddress(library, "grpc_server_config_fetcher_unref");
|
|
454
454
|
grpc_server_add_http2_port_import = (grpc_server_add_http2_port_type) GetProcAddress(library, "grpc_server_add_http2_port");
|
|
455
455
|
grpc_server_start_import = (grpc_server_start_type) GetProcAddress(library, "grpc_server_start");
|
|
456
456
|
grpc_server_shutdown_and_notify_import = (grpc_server_shutdown_and_notify_type) GetProcAddress(library, "grpc_server_shutdown_and_notify");
|
|
@@ -453,15 +453,15 @@ extern grpc_server_create_type grpc_server_create_import;
|
|
|
453
453
|
typedef void(*grpc_server_register_completion_queue_type)(grpc_server* server, grpc_completion_queue* cq, void* reserved);
|
|
454
454
|
extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import;
|
|
455
455
|
#define grpc_server_register_completion_queue grpc_server_register_completion_queue_import
|
|
456
|
+
typedef const grpc_arg_pointer_vtable*(*grpc_server_config_fetcher_arg_vtable_type)(void);
|
|
457
|
+
extern grpc_server_config_fetcher_arg_vtable_type grpc_server_config_fetcher_arg_vtable_import;
|
|
458
|
+
#define grpc_server_config_fetcher_arg_vtable grpc_server_config_fetcher_arg_vtable_import
|
|
456
459
|
typedef grpc_server_config_fetcher*(*grpc_server_config_fetcher_xds_create_type)(grpc_server_xds_status_notifier notifier, const grpc_channel_args* args);
|
|
457
460
|
extern grpc_server_config_fetcher_xds_create_type grpc_server_config_fetcher_xds_create_import;
|
|
458
461
|
#define grpc_server_config_fetcher_xds_create grpc_server_config_fetcher_xds_create_import
|
|
459
|
-
typedef void(*
|
|
460
|
-
extern
|
|
461
|
-
#define
|
|
462
|
-
typedef void(*grpc_server_set_config_fetcher_type)(grpc_server* server, grpc_server_config_fetcher* config_fetcher);
|
|
463
|
-
extern grpc_server_set_config_fetcher_type grpc_server_set_config_fetcher_import;
|
|
464
|
-
#define grpc_server_set_config_fetcher grpc_server_set_config_fetcher_import
|
|
462
|
+
typedef void(*grpc_server_config_fetcher_unref_type)(grpc_server_config_fetcher* config_fetcher);
|
|
463
|
+
extern grpc_server_config_fetcher_unref_type grpc_server_config_fetcher_unref_import;
|
|
464
|
+
#define grpc_server_config_fetcher_unref grpc_server_config_fetcher_unref_import
|
|
465
465
|
typedef int(*grpc_server_add_http2_port_type)(grpc_server* server, const char* addr, grpc_server_credentials* creds);
|
|
466
466
|
extern grpc_server_add_http2_port_type grpc_server_add_http2_port_import;
|
|
467
467
|
#define grpc_server_add_http2_port grpc_server_add_http2_port_import
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 gRPC authors.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module GRPC
|
|
18
|
+
module Core
|
|
19
|
+
# CallCredentials represents per-call credentials.
|
|
20
|
+
class CallCredentials
|
|
21
|
+
attr_reader :auth_proc
|
|
22
|
+
|
|
23
|
+
def initialize(auth_proc = nil, &block)
|
|
24
|
+
@auth_proc = auth_proc || block
|
|
25
|
+
fail TypeError, 'Argument to CallCredentials#new must be a proc' unless @auth_proc.is_a?(Proc)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_metadata(context)
|
|
29
|
+
@auth_proc.call(context)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def composite?
|
|
33
|
+
false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def compose(*others)
|
|
37
|
+
return self if others.empty?
|
|
38
|
+
valid_others = validate_credentials_list!(others)
|
|
39
|
+
CompositeCallCredentials.new([self] + valid_others)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def validate_credentials_list!(list)
|
|
45
|
+
list.flatten.each do |o|
|
|
46
|
+
fail TypeError, "Argument to compose must be a CallCredentials, got #{o.class}" \
|
|
47
|
+
unless o.is_a?(CallCredentials)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class CompositeCallCredentials < CallCredentials
|
|
53
|
+
def initialize(*creds)
|
|
54
|
+
flat_creds = creds.flatten.flat_map do |c|
|
|
55
|
+
c.composite? ? c.creds : c
|
|
56
|
+
end
|
|
57
|
+
@creds = flat_creds.uniq
|
|
58
|
+
super(proc { |context| get_metadata(context) })
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def composite?
|
|
62
|
+
true
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def get_metadata(context)
|
|
66
|
+
@creds.each_with_object({}) do |c, metadata|
|
|
67
|
+
creds_metadata = c.get_metadata(context)
|
|
68
|
+
next unless creds_metadata
|
|
69
|
+
metadata.merge!(
|
|
70
|
+
creds_metadata.is_a?(Hash) ? creds_metadata : fail(TypeError, "Call credentials must return Hash or nil, got #{creds_metadata.class}")
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def compose(*others)
|
|
76
|
+
return self if others.empty?
|
|
77
|
+
valid_others = validate_credentials_list!(others)
|
|
78
|
+
CompositeCallCredentials.new(@creds + valid_others)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
protected
|
|
82
|
+
|
|
83
|
+
attr_reader :creds
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 gRPC authors.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
module GRPC
|
|
18
|
+
module Core
|
|
19
|
+
# Provides shared #compose logic for channel credential classes.
|
|
20
|
+
# @api private
|
|
21
|
+
module ChannelCredentialsComposable
|
|
22
|
+
def compose(*others)
|
|
23
|
+
return self if others.empty?
|
|
24
|
+
flat_others = others.flatten
|
|
25
|
+
|
|
26
|
+
flat_others.each do |o|
|
|
27
|
+
fail TypeError, "Argument to compose must be a CallCredentials, got #{o.class}" \
|
|
28
|
+
unless o.is_a?(CallCredentials)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
call_creds = flat_others.size == 1 ? flat_others.first : CompositeCallCredentials.new(flat_others)
|
|
32
|
+
CompositeChannelCredentials.new(self, call_creds)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class ChannelCredentials
|
|
37
|
+
prepend ChannelCredentialsComposable
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class XdsChannelCredentials
|
|
41
|
+
prepend ChannelCredentialsComposable
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class CompositeChannelCredentials
|
|
45
|
+
attr_reader :channel_credentials, :call_credentials
|
|
46
|
+
|
|
47
|
+
def initialize(channel_creds, call_creds)
|
|
48
|
+
@channel_credentials = channel_creds
|
|
49
|
+
@call_credentials = call_creds
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def compose(*others)
|
|
53
|
+
return self if others.empty?
|
|
54
|
+
flat_others = others.flatten
|
|
55
|
+
|
|
56
|
+
flat_others.each do |o|
|
|
57
|
+
fail TypeError, "Argument to compose must be a CallCredentials, got #{o.class}" \
|
|
58
|
+
unless o.is_a?(CallCredentials)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if @call_credentials
|
|
62
|
+
CompositeChannelCredentials.new(@channel_credentials, @call_credentials.compose(*flat_others))
|
|
63
|
+
else
|
|
64
|
+
CompositeChannelCredentials.new(@channel_credentials, CompositeCallCredentials.new(flat_others))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Copyright 2026 gRPC authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
module GRPC
|
|
16
|
+
module Core
|
|
17
|
+
# Utility methods for resolving and applying call credentials to metadata.
|
|
18
|
+
# @api private
|
|
19
|
+
module CallCredentialsHelper
|
|
20
|
+
VALID_HEADER_KEY_PATTERN = /\A[a-z0-9\-_.]+\z/
|
|
21
|
+
|
|
22
|
+
# Composes channel and per-call credentials when both present, otherwise
|
|
23
|
+
# returns whichever is available.
|
|
24
|
+
def self.resolve(channel_call_creds, call_credentials)
|
|
25
|
+
return channel_call_creds.compose(call_credentials) if channel_call_creds && call_credentials
|
|
26
|
+
channel_call_creds || call_credentials
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns true if +key+ is a valid gRPC metadata header key.
|
|
30
|
+
def self.valid_header_key?(key)
|
|
31
|
+
!key.nil? && !key.empty? && VALID_HEADER_KEY_PATTERN.match?(key)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Parses an RPC method path into [service_url, method_name].
|
|
35
|
+
# e.g. '/echo.EchoServer/Echo' on 'foo.test.google.fr' gives
|
|
36
|
+
# ['https://foo.test.google.fr/echo.EchoServer', 'Echo'].
|
|
37
|
+
def self.parse_method_info(ssl_target, method)
|
|
38
|
+
return ["https://#{ssl_target}", nil] if method.nil? || method.empty?
|
|
39
|
+
last_slash = method.rindex('/')
|
|
40
|
+
service_path = last_slash&.positive? ? method[0, last_slash] : ''
|
|
41
|
+
[
|
|
42
|
+
"https://#{ssl_target}#{service_path}",
|
|
43
|
+
last_slash ? method[(last_slash + 1)..] : nil
|
|
44
|
+
]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Merges +creds_metadata+ into +metadata+, validating all keys.
|
|
48
|
+
# Raises GRPC::Unavailable on invalid type or illegal header keys.
|
|
49
|
+
def self.merge_creds_metadata!(creds_metadata, metadata)
|
|
50
|
+
return if creds_metadata.nil?
|
|
51
|
+
unless creds_metadata.is_a?(Hash)
|
|
52
|
+
fail GRPC::Unavailable, "Call credentials must return Hash or nil, got #{creds_metadata.class}"
|
|
53
|
+
end
|
|
54
|
+
creds_metadata.each do |key, value|
|
|
55
|
+
key_str = key.to_s
|
|
56
|
+
unless valid_header_key?(key_str)
|
|
57
|
+
fail GRPC::Unavailable, "Illegal metadata: '#{key_str}' is an invalid header key"
|
|
58
|
+
end
|
|
59
|
+
metadata[key_str] = value.is_a?(Array) ? value.map(&:to_s) : value.to_s
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Calls +credentials.get_metadata+ and merges the result into +metadata+.
|
|
64
|
+
# No-op when +credentials+ is nil or the channel is insecure.
|
|
65
|
+
# Raises GRPC::Unavailable on failure.
|
|
66
|
+
def self.apply(credentials, metadata, ssl_target, channel_creds, method = nil)
|
|
67
|
+
return unless credentials
|
|
68
|
+
return if channel_creds == :this_channel_is_insecure
|
|
69
|
+
service_url, method_name = parse_method_info(ssl_target, method)
|
|
70
|
+
context = { service_url: service_url, jwt_aud_uri: service_url, method_name: method_name }
|
|
71
|
+
begin
|
|
72
|
+
merge_creds_metadata!(credentials.get_metadata(context), metadata)
|
|
73
|
+
rescue GRPC::BadStatus
|
|
74
|
+
raise
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
fail GRPC::Unavailable, "Call credentials failed: #{e.message}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Prepended into ClientStub when the pure Ruby credentials path is active.
|
|
82
|
+
# Handles CompositeChannelCredentials splitting and applies credentials via
|
|
83
|
+
# metadata injection instead of the C extension set_credentials! path.
|
|
84
|
+
# @api private
|
|
85
|
+
module CompositeCredentialsHandler
|
|
86
|
+
def initialize(host, creds,
|
|
87
|
+
channel_override: nil,
|
|
88
|
+
timeout: nil,
|
|
89
|
+
propagate_mask: nil,
|
|
90
|
+
channel_args: {},
|
|
91
|
+
interceptors: [])
|
|
92
|
+
if creds.is_a?(Core::CompositeChannelCredentials)
|
|
93
|
+
pure_call_creds = creds.call_credentials
|
|
94
|
+
creds = creds.channel_credentials
|
|
95
|
+
super(host, creds,
|
|
96
|
+
channel_override: channel_override,
|
|
97
|
+
timeout: timeout,
|
|
98
|
+
propagate_mask: propagate_mask,
|
|
99
|
+
channel_args: channel_args,
|
|
100
|
+
interceptors: interceptors)
|
|
101
|
+
@call_creds = pure_call_creds
|
|
102
|
+
else
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# credentials is intentionally overridden to nil in super to skip set_credentials!
|
|
108
|
+
def new_active_call(method, marshal, unmarshal,
|
|
109
|
+
deadline: nil,
|
|
110
|
+
parent: nil,
|
|
111
|
+
credentials: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
112
|
+
super(method, marshal, unmarshal,
|
|
113
|
+
deadline: deadline,
|
|
114
|
+
parent: parent,
|
|
115
|
+
credentials: nil)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def resolve_call_metadata(metadata, credentials, method)
|
|
121
|
+
resolved = CallCredentialsHelper.resolve(@call_creds, credentials)
|
|
122
|
+
metadata.dup.tap { |m| CallCredentialsHelper.apply(resolved, m, @host, @channel_creds, method) }
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|