认证

2017-09-12  本文已影响557人  竹天亮

本文预览一下gRPC认证,包含内置已支持的认证机制,如何添加自己的认证系统和如何在支持的语言里使用gRPC认证的例子。

简介

gRPC设计可以和很多认证机制工作,可以很简单安全的使用gRPC与其他系统沟通。可以使用我们已支持的机制 - SSL/TLS使用或者不适用Google基于token认证 - 或者可以添加你自己的认证系统通过扩展我们提供的代码。

gRPC同样提供了简单的认证API,让你提供所有需要的认证信息作为凭证(Credentials)在创建channel或者请求时。

已支持的认证机制

下面的认证机制是gRPC内置的:

警告:谷歌认证只允许用于谷歌服务。如果发送一个谷歌的OAuth2 token到非谷歌服务会导致这个token被窃取然后滥用谷歌的服务。

认证API

gRPC提供了简单的认证API,基于统一认证对象的概念,可以用在创建整个gRPC管道或单个调用的时候。

凭证类型

两种凭证类型:

也可以在CompositeChannelCredentials组合使用,允许你指定,比如SSL 凭证给channel,然后这个channel上的每个请求用call凭证。CompositeChannelCredentials结合ChannelCredentialsCallCredentials来创建一个新的ChannelCredentials。结果发送认证数据与channel上的每个请求CallCredentialswith组合。

比如,你可以创建SslCredentials的ChannelCredentialsAccessTokenCredentials。结果就是在Channel上使用时将会为Channel上的每个请求发送合适的认证token。

单个CallCredentials同样可以与CompositeCallCredentials组合。这会当CallCredentials使用在请求上是将会触发发送认证数据和两个CallCredentials

使用客户端SSL/TLS

现在我们看一下Credentials如何与我们支持的认证机制合作。这是最简单的认证场景:客户端指向认证服务器并加密所有的数据。例子是用C++,但是API对所有的语言都相同:你可以在我们下面的例子里看到很多语言里如何启用SSL/TLS:

// Create a default SSL ChannelCredentials object.
auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
// Create a channel using the credentials created in the previous step.
auto channel = grpc::CreateChannel(server_name, channel_creds);
// Create a stub on the channel.
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
// Make actual RPC calls on the stub.
grpc::Status s = stub->sayHello(&context, *request, response);

对于更高级的案例,比如修改根CA或者使用客户端证书,相应的选项可以在SslCredentialsOptions参数里设置传递给工厂方法。

基于谷歌token认证

gRPC应用可以使用简单的API创建认证,用于和Google各种开发场景认证。同样,我们的例子是C++,但是你可以找到其他语言的例子:

auto creds = grpc::GoogleDefaultCredentials();
// Create a channel, stub and make RPC calls (same as in the previous example)
auto channel = grpc::CreateChannel(server_name, creds);
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
grpc::Status s = stub->sayHello(&context, *request, response);

这个channel认证对象用于使用Service Accounts的应用,以及运行在Google Compute Engine (GCE)的应用.
在前一种情况下,服务账户的私钥会被环境变量里的GOOGLE_APPLICATION_CREDENTIALS文件加载。密钥用于生成无记名令牌附加到每个发送的RPC在相应的channel。

对于运行在GCE里的应用程序,默认的服务账户和相应的OAuth2域可以在VM设置期间配置。在运行时,这个凭证处理和认证系统通信获取OAuth2访问tokens,然后加在相应的channel里的发送的RPC。

扩展gRPC支持其他认证机制

认证插件API允许开发者加入自己的认证类型。这包括:

下面是一个简单认证插件例子,在自定义header里设置凭证ticket:

class MyCustomAuthenticator : public grpc::MetadataCredentialsPlugin {
 public:
  MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {}

  grpc::Status GetMetadata(
      grpc::string_ref service_url, grpc::string_ref method_name,
      const grpc::AuthContext& channel_auth_context,
      std::multimap<grpc::string, grpc::string>* metadata) override {
    metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_));
    return grpc::Status::OK;
  }

 private:
  grpc::string ticket_;
};

auto call_creds = grpc::MetadataCredentialsFromPlugin(
    std::unique_ptr<grpc::MetadataCredentialsPlugin>(
        new MyCustomAuthenticator("super-secret-ticket")));

更深层次的插件集成实现gRPC凭证实现是在源代码等级。gRPC内部同样可以与其他加密实现交换SSL/TLS。

示例

这些认证机制可以在gRPC支持的所有语言里可用。下面会演示如何认证和在每个语言里上面讲述的认证特性:更多语言准备中。

Java

基础案例 - 无需加密或认证

ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
    .usePlaintext(true)
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

使用服务端认证SSL/TLS
如果gRPC是TLS的,我们建议在Java里使用OpenSSL。可以在Security文档里查看如何安装和使用OpenSSL和其他必须的库。

在服务端启用TLS,证书链和密钥需要制定为PEM格式。标准的TLS端口是443,但是下面我们使用8443,以免需要系统的额外权限。

Server server = ServerBuilder.forPort(8443)
    // Enable TLS
    .useTransportSecurity(certChainFile, privateKeyFile)
    .addService(TestServiceGrpc.bindService(serviceImplementation))
    .build();
server.start();

如果客户端不知道发行证书机构,那么正确的配置SslContext或者SSLSocketFactory应该提供给NettyChannelBuilder或者OkHttpChannelBuilder

在客户端,服务端的SSL/TLS认证看起来像:

// With server authentication SSL/TLS
ManagedChannel channel = ManagedChannelBuilder.forAddress("myservice.example.com", 443)
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

// With server authentication SSL/TLS; custom CA root certificates; not on Android
ManagedChannel channel = NettyChannelBuilder.forAddress("myservice.example.com", 443)
    .sslContext(GrpcSslContexts.forClient().trustManager(new File("roots.pem")).build())
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);
谷歌认证

下面的代码片段演示如何使用服务账户和gRPC调用Google Cloud PubSub API。证书从已知的位置加载或者通过程序运行环境提供的自动发现,比如,Google Compute Engine。这个例子是指定谷歌和他的服务的,其他服务提供者可以使用相同的模式。

GoogleCredentials creds = GoogleCredentials.getApplicationDefault();
ManagedChannel channel = ManagedChannelBuilder.forTarget("greeter.googleapis.com")
    .build();
GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel)
    .withCallCredentials(MoreCallCredentials.from(creds));
上一篇下一篇

猜你喜欢

热点阅读