Skip to content

Commit

Permalink
Ruby: support for PSM security (grpc#25330)
Browse files Browse the repository at this point in the history
* support for PSM security, SSL fallback

* Ruby Server, support for PSM security, SSL fallback

* address review comments

* add more tests, address review comments

* add XdsChannelCredentials class for PSM security, ruby client

* XdsServerCredentials

* address review comments

* re-run tools/distrib/clang_format_code.sh

* address comments, add entries to grpc_class_init_test

* fix to pass end2end ci test

* re-run tools/distrib/clang_format_code.sh

* address comments
  • Loading branch information
HannahShiSFB authored Mar 4, 2021
1 parent 444e6e6 commit 0fc5210
Show file tree
Hide file tree
Showing 19 changed files with 668 additions and 9 deletions.
25 changes: 25 additions & 0 deletions src/ruby/end2end/grpc_class_init_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,31 @@ def get_test_proc(grpc_class)
return proc do
GRPC::Core::ChannelCredentials.new
end
when 'xds_channel_credentials'
return proc do
GRPC::Core::XdsChannelCredentials.new(GRPC::Core::ChannelCredentials.new)
end
when 'server_credentials'
return proc do
test_root = File.join(File.dirname(__FILE__), '..', 'spec', 'testdata')
files = ['ca.pem', 'server1.key', 'server1.pem']
creds = files.map { |f| File.open(File.join(test_root, f)).read }
GRPC::Core::ServerCredentials.new(
creds[0],
[{ private_key: creds[1], cert_chain: creds[2] }],
true)
end
when 'xds_server_credentials'
return proc do
test_root = File.join(File.dirname(__FILE__), '..', 'spec', 'testdata')
files = ['ca.pem', 'server1.key', 'server1.pem']
creds = files.map { |f| File.open(File.join(test_root, f)).read }
GRPC::Core::XdsServerCredentials.new(
GRPC::Core::ServerCredentials.new(
creds[0],
[{ private_key: creds[1], cert_chain: creds[2] }],
true))
end
when 'call_credentials'
return proc do
GRPC::Core::CallCredentials.new(proc { |noop| noop })
Expand Down
3 changes: 3 additions & 0 deletions src/ruby/end2end/grpc_class_init_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ def main
native_grpc_classes = %w( channel
server
channel_credentials
xds_channel_credentials
server_credentials
xds_server_credentials
call_credentials
compression_options )

Expand Down
11 changes: 10 additions & 1 deletion src/ruby/ext/grpc/rb_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "rb_completion_queue.h"
#include "rb_grpc.h"
#include "rb_server.h"
#include "rb_xds_channel_credentials.h"

/* id_channel is the name of the hidden ivar that preserves a reference to the
* channel on a call, so that calls are not GCed before their channel. */
Expand Down Expand Up @@ -242,7 +243,15 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) {
ch = grpc_insecure_channel_create(target_chars, &args, NULL);
} else {
wrapper->credentials = credentials;
creds = grpc_rb_get_wrapped_channel_credentials(credentials);
if (grpc_rb_is_channel_credentials(credentials)) {
creds = grpc_rb_get_wrapped_channel_credentials(credentials);
} else if (grpc_rb_is_xds_channel_credentials(credentials)) {
creds = grpc_rb_get_wrapped_xds_channel_credentials(credentials);
} else {
rb_raise(rb_eTypeError,
"bad creds, want ChannelCredentials or XdsChannelCredentials");
return Qnil;
}
ch = grpc_secure_channel_create(creds, target_chars, &args, NULL);
}

Expand Down
12 changes: 11 additions & 1 deletion src/ruby/ext/grpc/rb_channel_credentials.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,11 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv,
NULL, NULL);
}
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
rb_raise(rb_eRuntimeError,
"the call to grpc_ssl_credentials_create() failed, could not "
"create a credentials, see "
"https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for "
"debugging tips");
return Qnil;
}
wrapper->wrapped = creds;
Expand Down Expand Up @@ -270,7 +274,13 @@ void Init_grpc_channel_credentials() {
/* Gets the wrapped grpc_channel_credentials from the ruby wrapper */
grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v) {
grpc_rb_channel_credentials* wrapper = NULL;
Check_TypedStruct(v, &grpc_rb_channel_credentials_data_type);
TypedData_Get_Struct(v, grpc_rb_channel_credentials,
&grpc_rb_channel_credentials_data_type, wrapper);
return wrapper->wrapped;
}

/* Check if v is kind of ChannelCredentials */
bool grpc_rb_is_channel_credentials(VALUE v) {
return rb_typeddata_is_kind_of(v, &grpc_rb_channel_credentials_data_type);
}
4 changes: 4 additions & 0 deletions src/ruby/ext/grpc/rb_channel_credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define GRPC_RB_CREDENTIALS_H_

#include <ruby/ruby.h>
#include <stdbool.h>

#include <grpc/grpc_security.h>

Expand All @@ -29,4 +30,7 @@ void Init_grpc_channel_credentials();
/* Gets the wrapped credentials from the ruby wrapper */
grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v);

/* Check if v is kind of ChannelCredentials */
bool grpc_rb_is_channel_credentials(VALUE v);

#endif /* GRPC_RB_CREDENTIALS_H_ */
4 changes: 4 additions & 0 deletions src/ruby/ext/grpc/rb_grpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "rb_loader.h"
#include "rb_server.h"
#include "rb_server_credentials.h"
#include "rb_xds_channel_credentials.h"
#include "rb_xds_server_credentials.h"

static VALUE grpc_rb_cTimeVal = Qnil;

Expand Down Expand Up @@ -321,8 +323,10 @@ void Init_grpc_c() {
Init_grpc_call();
Init_grpc_call_credentials();
Init_grpc_channel_credentials();
Init_grpc_xds_channel_credentials();
Init_grpc_server();
Init_grpc_server_credentials();
Init_grpc_xds_server_credentials();
Init_grpc_time_consts();
Init_grpc_compression_options();
}
14 changes: 13 additions & 1 deletion src/ruby/ext/grpc/rb_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "rb_completion_queue.h"
#include "rb_grpc.h"
#include "rb_server_credentials.h"
#include "rb_xds_server_credentials.h"

/* grpc_rb_cServer is the ruby class that proxies grpc_server. */
static VALUE grpc_rb_cServer = Qnil;
Expand Down Expand Up @@ -326,7 +327,18 @@ static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port,
StringValueCStr(port));
}
} else {
creds = grpc_rb_get_wrapped_server_credentials(rb_creds);
// TODO: create a common parent class for all server-side credentials,
// then we can have a single method to retrieve the underlying
// grpc_server_credentials object, and avoid the need for this reflection
if (grpc_rb_is_server_credentials(rb_creds)) {
creds = grpc_rb_get_wrapped_server_credentials(rb_creds);
} else if (grpc_rb_is_xds_server_credentials(rb_creds)) {
creds = grpc_rb_get_wrapped_xds_server_credentials(rb_creds);
} else {
rb_raise(rb_eTypeError,
"failed to create server because credentials parameter has an "
"invalid type, want ServerCredentials or XdsServerCredentials");
}
recvd_port = grpc_server_add_secure_http2_port(
s->wrapped, StringValueCStr(port), creds);
if (recvd_port == 0) {
Expand Down
22 changes: 19 additions & 3 deletions src/ruby/ext/grpc/rb_server_credentials.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ typedef struct grpc_rb_server_credentials {
} grpc_rb_server_credentials;

/* Destroys the server credentials instances. */
static void grpc_rb_server_credentials_free(void* p) {
static void grpc_rb_server_credentials_free_internal(void* p) {
grpc_rb_server_credentials* wrapper = NULL;
if (p == NULL) {
return;
Expand All @@ -59,6 +59,12 @@ static void grpc_rb_server_credentials_free(void* p) {
xfree(p);
}

/* Destroys the server credentials instances. */
static void grpc_rb_server_credentials_free(void* p) {
grpc_rb_server_credentials_free_internal(p);
grpc_ruby_shutdown();
}

/* Protects the mark object from GC */
static void grpc_rb_server_credentials_mark(void* p) {
grpc_rb_server_credentials* wrapper = NULL;
Expand Down Expand Up @@ -87,9 +93,9 @@ static const rb_data_type_t grpc_rb_server_credentials_data_type = {
};

/* Allocates ServerCredential instances.
Provides safe initial defaults for the instance fields. */
static VALUE grpc_rb_server_credentials_alloc(VALUE cls) {
grpc_ruby_init();
grpc_rb_server_credentials* wrapper = ALLOC(grpc_rb_server_credentials);
wrapper->wrapped = NULL;
wrapper->mark = Qnil;
Expand Down Expand Up @@ -202,7 +208,11 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
}
xfree(key_cert_pairs);
if (creds == NULL) {
rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
rb_raise(rb_eRuntimeError,
"the call to grpc_ssl_server_credentials_create_ex() failed, "
"could not create a credentials, see "
"https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for "
"debugging tips");
return Qnil;
}
wrapper->wrapped = creds;
Expand Down Expand Up @@ -237,7 +247,13 @@ void Init_grpc_server_credentials() {
/* Gets the wrapped grpc_server_credentials from the ruby wrapper */
grpc_server_credentials* grpc_rb_get_wrapped_server_credentials(VALUE v) {
grpc_rb_server_credentials* wrapper = NULL;
Check_TypedStruct(v, &grpc_rb_server_credentials_data_type);
TypedData_Get_Struct(v, grpc_rb_server_credentials,
&grpc_rb_server_credentials_data_type, wrapper);
return wrapper->wrapped;
}

/* Check if v is kind of ServerCredentials */
bool grpc_rb_is_server_credentials(VALUE v) {
return rb_typeddata_is_kind_of(v, &grpc_rb_server_credentials_data_type);
}
4 changes: 4 additions & 0 deletions src/ruby/ext/grpc/rb_server_credentials.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#define GRPC_RB_SERVER_CREDENTIALS_H_

#include <ruby/ruby.h>
#include <stdbool.h>

#include <grpc/grpc_security.h>

Expand All @@ -29,4 +30,7 @@ void Init_grpc_server_credentials();
/* Gets the wrapped server_credentials from the ruby wrapper */
grpc_server_credentials* grpc_rb_get_wrapped_server_credentials(VALUE v);

/* Check if v is kind of ServerCredentials */
bool grpc_rb_is_server_credentials(VALUE v);

#endif /* GRPC_RB_SERVER_CREDENTIALS_H_ */
Loading

0 comments on commit 0fc5210

Please sign in to comment.