英文:
Ruby's grpc(v1.3.2) gem SSL/TLS connection issue with grpc server built entirely in golang
问题
最近,我尝试使用版本为1.3.2的rubygem grpc作为客户端,并连接到一个使用golang构建的grpc服务器。我查阅了GRPC.IO上的文档,并在我的代码中使用了它。
irb(main):017:0> GRPC::Core::Credentials.new(File.read(CA_FILE_PATH))
NameError: uninitialized constant GRPC::Core::Credentials
from (irb):17
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/console.rb:110:in `start'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/console.rb:9:in `start'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:68:in `console'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
然而,他们的文档明确指出:
creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)
然后我遇到了ChannelCredentials,creds应该是ChannelCredentials对象或一个符号(例如*:this_channel_is_insecure*)。因此,我也尝试了一下。
我从grpc gem的源代码中获取了以下函数。这个函数在rspec测试用例中被调用来加载证书:
def load_certs
data_dir = "#{Rails.root}/certs"
files = ['ca.pem', 'server.key', 'server.pem']
files.map { |f| File.open(File.join(data_dir, f)).read }
end
然后我尝试了以下代码:
channel_creds = GRPC::Core::ChannelCredentials.new(load_certs)
stub = Helloworld::Greeter::Stub.new('myservice.example.com', channel_creds)
但是上述代码失败了,报错如下:
E0619 09:59:10.410575570 14208 ssl_transport_security.c:601] Could not load any root certificate.
E0619 09:59:10.410604954 14208 ssl_transport_security.c:1315] Cannot load server root certificates.
E0619 09:59:10.410622519 14208 security_connector.c:837] Handshaker factory creation failed with TSI_INVALID_ARGUMENT.
我还尝试了以下代码:
channel_creds = GRPC::Core::ChannelCredentials.new(File.read(CA_FILE_PATH))
stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)
但是我得到的只是来自日志或rpc服务器的错误:
2017/06/16 10:52:34 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:53:35 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:53:59 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:55:06 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
有人成功尝试过启用SSL/TLS的Ruby客户端和Golang服务器组合吗?
英文:
Recently, I was trying to use rubygem grpc version 1.3.2 as a clinet and connect to a grpc server which is built from golang. I went through the documentation at GRPC.IO and used it in my code as it.
irb(main):017:0> GRPC::Core::Credentials.new(File.read(CA_FILE_PATH))
NameError: uninitialized constant GRPC::Core::Credentials
from (irb):17
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/console.rb:110:in `start'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/console.rb:9:in `start'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:68:in `console'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
from /usr/local/share/gems/gems/railties-4.2.1/lib/rails/commands.rb:17:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
However their documentation specifically says,
creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)
Then I came across ChannelCredentials and the creds is supposed to be either ChannelCredentials object or a symbol(e.g. :this_channel_is_insecure). Hence, I gave it a try as well.
I've taken the following function from the grpc gem's source code itself. This function was called in rspec test cases for loading the certs:
def load_certs
data_dir = "#{Rails.root}/certs"
files = ['ca.pem', 'server.key', 'server.pem']
files.map { |f| File.open(File.join(data_dir, f)).read }
end
Then I gave it a try with,
channel_creds = GRPC::Core::ChannelCredentials.new(load_certs)
stub = Helloworld::Greeter::Stub.new('myservice.example.com', channel_creds)
But the above failed with
E0619 09:59:10.410575570 14208 ssl_transport_security.c:601] Could not load any root certificate.
E0619 09:59:10.410604954 14208 ssl_transport_security.c:1315] Cannot load server root certificates.
E0619 09:59:10.410622519 14208 security_connector.c:837] Handshaker factory creation failed with TSI_INVALID_ARGUMENT.
I also tried:
channel_creds = GRPC::Core::ChannelCredentials.new(File.read(CA_FILE_PATH))
stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)
But all I got was error from the logs or rpc server:
2017/06/16 10:52:34 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:53:35 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:53:59 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
2017/06/16 10:55:06 transport: http2Server.HandleStreams failed to receive the preface from client: EOF
Has anyone successfully tried this Ruby client Golang server combination with SSL/TLS enabled?
答案1
得分: 4
是的,客户端存根构造函数的第二个参数(creds参数)应该是一个GRPC::Core::ChannelCredentials
对象,或者更具体地说,是::this_channel_is_insecure
符号(如果传递后者,将使用不安全的连接)。
我要注意的是,使用以下代码的测试可能会产生误导,因为只有使用客户端的私钥和证书链才有意义(我相信该特定测试并未使用密钥和证书链)。
关于GRPC::Core::ChannelCredentials
构造函数:
有三种形式可以使用(在https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel_credentials.c#L128中的构造函数代码上方有一条注释对它们进行了说明),选项如下:
-
Credentials.new()
-
Credentials.new(pem_root_certs)
-
Credentials.new(pem_root_certs, pem_private_key, pem_cert_chain)
在所有情况下,根文件、私钥和证书链参数都是PEM编码的字符串。
请注意,如果不传递任何参数(使用Credentials.new()
),则服务器根证书将按照此头注释中描述的方式找到(请参阅当服务器根证书参数为null时的行为描述)。只有当您希望客户端使用私钥和证书链时,才需要使用最后一个构造函数。
英文:
> creds is supposed to be either ChannelCredentials object or a symbol
Yes the second argument of a client stub constructor (the creds argument), should be either a GRPC::Core::ChannelCredentials
object or <i>specifically</i> the ::this_channel_is_insecure
symbol (if the latter is passed, an insecure connection will be used).
I'd note that the test that uses
def load_certs
data_dir = "#{Rails.root}/certs"
files = ['ca.pem', 'server.key', 'server.pem']
files.map { |f| File.open(File.join(data_dir, f)).read }
end
might actually be misleading, since it only makes sense to construct channel credentials with the <i>client's</i> private key and certificate chain (that specific test I believe doesn't use the key and cert chain).
On the GRPC::Core::ChannelCredentials
constructor:
There are three forms that can be used, (there's a comment above the constructor code in https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel_credentials.c#L128 that goes over them), but the options are:
-
Credentials.new()
-
Credentials.new(pem_root_certs)
-
Credentials.new(pem_root_certs, pem_private_key, pem_cert_chain)
In all cases, the roots file, private key, and cert chain parameters are pem encoded strings.
Note that if no arguments are passed (Credentials.new()
is used), then the server root certificates will be found as described in this header comment (see the description for the behavior when server root certs parameter is null). And the last constructor is only needed if you want the <i>client</i> to use a private key and cert chain.
答案2
得分: 0
我可以确认这个是有效的。
channel_creds = GRPC::Core::ChannelCredentials.new(File.read("/home/user/.lnd/tls.cert"))
stub = Lnrpc::Lightning::Stub.new("127.0.0.1:10009", channel_creds)
obj = Lnrpc::GetInfoRequest.new
pp stub.get_info(obj)
英文:
I can confirm this works.
channel_creds = GRPC::Core::ChannelCredentials.new(File.read("/home/user/.lnd/tls.cert"))
stub = Lnrpc::Lightning::Stub.new("127.0.0.1:10009", channel_creds)
obj = Lnrpc::GetInfoRequest.new
pp stub.get_info(obj)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论