本文档概述了gRPC认证机制,包括内置支持的身份验证机制,如何插入自己的身份验证系统,以及如何在支持的语言中使用gRPC认证机制的示例。
gRPC旨在与各种身份验证机制配合使用,可以轻松安全地使用gRPC与其他系统进行通信。可以使用我们支持的机制:
gRPC还提供了一个简单的身份验证API,允许在创建通道或发起调用时提供所有必要的身份验证信息作为凭据。
gRPC内置了以下身份验证机制:
警告:Google凭据只能用于连接Google服务。将Google发布的OAuth2令牌发送到非Google服务可能会导致此令牌被盗并用于冒充客户端访问Google服务。
gRPC提供基于凭据对象统一概念的简单认证API,可在创建整个gRPC通道或单个请求时使用。
凭据有两种类型:
ChannelCredentials
):附加到一个通道上,例如SSL凭据CallCredentials
):附加到一个调用上(或者是C++中的ClientContext
)还可以在综合通道凭据(CompositeChannelCredentials
)中组合使用这两种凭据。
例如,可以指定通道的SSL以及在通道中进行的每个调用的调用凭据。
综合通道凭据将通道凭据与调用凭据相关联,以创建新的通道凭据。结果就是将发送与在通道上进行的每次调用相关联的调用凭据组合而成的认证数据。
例如,可以从
SslCredentials
和AccessTokenCredentials
创建通道凭据。结果就是当应用在一个通道时将为此通道上的每个调用发送相应的访问令牌(token)。
单个调用凭据也可以使用综合调用凭据(CompositeCallCredentials
)组成。在一个调用中使用综合调用凭据生成的调用凭据时,将触发发送与两个调用凭据关联的认证数据。
现在让我们看看凭据如何与我们支持的认证机制一起工作。这是最简单的身份验证方案,客户端只想验证服务端并加密所有数据。该示例使用的是C++,所有编程语言的API都类似:可以在下面的示例部分中看到如何在更多语言中启用SSL/TLS。
// Create a default SSL ChannelCredentials object.
channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
// Create a channel using the credentials created in the previous step.
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
参数中设置相应的选项。
gRPC应用程序可以使用简单的API创建凭据,该凭据可用于在各种部署方案中与Google进行身份验证。同样,我们的示例是在C++中,但可以在我们的示例部分中找到其他语言的示例。
creds = grpc::GoogleDefaultCredentials();
// Create a channel, stub and make RPC calls (same as in the previous example)
channel = grpc::CreateChannel(server_name, creds);
std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
grpc::Status s = stub->sayHello(&context, *request, response);
此通道凭据对象适用于使用Service Account
的应用程序或者在Google Compute Engine(GCE)中运行的应用程序。
前一种情况下,Service Account
的私钥是从环境变量GOOGLE_APPLICATION_CREDENTIALS
中指定的文件加载的。密钥用于生成承载令牌,该令牌附加到相应通道的每个传出RPC上。
对于在GCE中运行的应用程序,可以在VM启动期间配置默认的Service Account
和对应的OAuth2作用域。在运行时,此凭据处理与身份验证系统的通信来获得OAuth2访问令牌,并将获得的访问令牌附加到相应通道的每个传出RPC上。
凭据插件API允许开发人员插入自己的凭据类型,包括:
MetadataCredentialsPlugin
抽象类,它包含需要由开发人员创建的子类实现的纯虚拟GetMetadata
方法。MetadataCredentialsFromPlugin
函数,它从MetadataCredentialsPlugin
创建调用凭据。下面是一个简单凭的据插件的示例,该插件在自定义标头中设置认证票据。
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_;
};
call_creds = grpc::MetadataCredentialsFromPlugin(
std::unique_ptr<grpc::MetadataCredentialsPlugin>(
new MyCustomAuthenticator("super-secret-ticket")));
通过在核心级别插入gRPC凭证可以实现更深入的集成。gRPC内部还允许使用其他加密机制切换SSL/TLS。
所有gRPC支持的编程语言都可以提供这样的身份认证机制。以下部分演示了如何在每种编程语言中使用上述身份验证和授权功能:即将推出更多语言。
// 客户端
conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
// error handling omitted
client := pb.NewGreeterClient(conn)
// ...
// 服务端
s := grpc.NewServer()
lis, _ := net.Listen("tcp", "localhost:50051")
// error handling omitted
s.Serve(lis)
// 客户端
creds, _ := credentials.NewClientTLSFromFile(certFile, "")
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))
// error handling omitted
client := pb.NewGreeterClient(conn)
// ...
// 服务端
creds, _ := credentials.NewServerTLSFromFile(certFile, keyFile)
s := grpc.NewServer(grpc.Creds(creds))
lis, _ := net.Listen("tcp", "localhost:50051")
// error handling omitted
s.Serve(lis)
pool, _ := x509.SystemCertPool()
// error handling omitted
creds := credentials.NewClientTLSFromCert(pool, "")
perRPC, _ := oauth.NewServiceAccountFromFile("service-account.json", scope)
conn, _ := grpc.Dial(
"greeter.googleapis.com",
grpc.WithTransportCredentials(creds),
grpc.WithPerRPCCredentials(perRPC),
)
// error handling omitted
client := pb.NewGreeterClient(conn)
// ...