gRPC Authenticationの翻訳

grpc.io のdeepl翻訳

私がわかっていなかった点としてgRPCのTLSを使用した認証により、クライアントをどうやって認証するのだ?という点。 ただこれは私の認識違いで、gRPCのTLSを使用した認証は、クライアント側でサーバーの認証を行うもの。 言われてみればその通り。 クライアントが正しいかどうかを検証するしか考えていなかった。

Overview

gRPCは、さまざまな認証メカニズムと連携するように設計されており、gRPCを使って他のシステムと安全に通信することができます。gRPCでは、Googleトークンベースの認証機能を備えたSSL/TLSや、Googleトークンベースの認証機能を備えていないSSL/TLSを使用することもできますし、gRPCが提供するコードを拡張して独自の認証システムを組み込むこともできます。

また、gRPCはシンプルな認証APIを提供しており、チャンネルの作成やコールの際に、必要な認証情報をすべてCredentialsとして提供することができます。

サポートされている認証メカニズム

gRPCには、以下の認証メカニズムが組み込まれています。

  • SSL/TLS:gRPCにはSSL/TLSが統合されており、サーバーを認証し、クライアントとサーバーの間で交換されるすべてのデータを暗号化するために、SSL/TLSの使用が促進されます。オプションで、クライアントが相互認証のための証明書を提供する仕組みも用意されています。
  • ALTS:アプリケーションがGoogle Cloud Platform(GCP)上で動作している場合、gRPCはトランスポートセキュリティメカニズムとしてALTSをサポートしています。詳細については、以下の言語別ページのいずれかを参照してください。ALTS in C++, ALTS in Go, ALTS in Java, ALTS in Python.
  • Googleとのトークンベースの認証:gRPCは、メタデータベースの認証情報をリクエストやレスポンスに添付するための汎用的なメカニズム(以下で説明)を提供します。gRPCを介してGoogle APIにアクセスする際にアクセストークン(通常はOAuth2トークン)を取得するための追加サポートが、特定の認証フローに対して提供されています:これがどのように機能するかは、以下のコード例で確認できます。GoogleSSL/TLS なしでの接続を許可しませんし、ほとんどの gRPC 言語の実装では、暗号化されていないチャンネルで認証情報を送信することはできません。

注意 Google の認証情報は、Google のサービスへの接続にのみ使用してください。Google が発行した OAuth2 トークンを Google 以外のサービスに送信すると、このトークンが盗まれ、クライアントが Google サービスになりすますために使用される可能性があります。

Authentication API

gRPCは、Credentialsオブジェクトという統一されたコンセプトに基づいたシンプルな認証APIを提供しています。このAPIは、gRPCチャネル全体または個々のコールを作成する際に使用できます。

クレデンシャルの種類

クレデンシャルには 2 つのタイプがあります。

  • チャンネル クレデンシャル: SSL クレデンシャルなど、チャンネルに添付される。
  • コールクレデンシャル: コール(C++ではClientContext)に添付されるもの。

また、これらをCompositeChannelCredentialsで組み合わせることもできます。これにより、たとえば、チャネルのSSL詳細と、チャネルで行われる各コールのコール資格情報を指定することができます。CompositeChannelCredentials は、ChannelCredentials と CallCredentials を関連付けて、新しい ChannelCredentials を作成します。その結果、チャンネルで行われる各通話ごとに、合成されたCallCredentialsに関連する認証データが送信されます。

たとえば、SslCredentials と AccessTokenCredentials から ChannelCredentials を作成することができます。この結果をChannelに適用すると、そのChannel上の各コールに対して適切なアクセストークンが送信されます。

個々の CallCredentials は、CompositeCallCredentials を使用して構成することもできます。結果のCallCredentialsを通話で使用すると、2つのCallCredentialsに関連する認証データの送信が開始されます。

Using client-side SSL/TLS

次に、サポートされている認証メカニズムの1つでクレデンシャルがどのように動作するかを見てみましょう。これは、クライアントがサーバを認証し、すべてのデータを暗号化するだけという、最もシンプルな認証シナリオです。この例は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パラメータで対応するオプションを設定できます。

Using Google token-based authentication

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);

このチャンネル資格情報オブジェクトは、サービスアカウントを使用するアプリケーションだけでなく、Google Compute Engine(GCE)で動作するアプリケーションでも機能します。前者の場合、サービスアカウントのプライベートキーは、環境変数GOOGLE_APPLICATION_CREDENTIALSで指定されたファイルから読み込まれます。この鍵は、対応するチャネルの各発信RPCに添付されるベアラートークンの生成に使用されます。

GCEで実行されるアプリケーションでは、VMのセットアップ時に、デフォルトのサービスアカウントとそれに対応するOAuth2スコープを構成できます。ランタイムには、このクレデンシャルが認証システムとの通信を処理してOAuth2アクセストークンを取得し、対応するチャネルの各発信RPCに添付します。

Extending gRPC to support other authentication mechanisms

クレデンシャル・プラグインAPIにより、開発者は独自のタイプのクレデンシャルをプラグインすることができます。これは以下のように構成されています。

MetadataCredentialsPlugin抽象クラスには、開発者が作成したサブクラスで実装する必要のある、純粋仮想のGetMetadataメソッドが含まれています。
MetadataCredentialsFromPlugin関数: MetadataCredentialsPluginからCallCredentialsを生成します。

以下は、カスタムヘッダに認証チケットを設定する、シンプルなクレデンシャルプラグインの例です。

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の内部では、SSL/TLSを他の暗号化メカニズムに切り替えることもできます。

Examples

これらの認証メカニズムは、gRPCがサポートするすべての言語で利用可能です。以下のセクションでは、上記の認証・認可機能が各言語でどのように表示されるかを示します。

Go

Base case - no encryption or authentication

Client:

conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
// error handling omitted
client := pb.NewGreeterClient(conn)
// ...

Server:

s := grpc.NewServer()
lis, _ := net.Listen("tcp", "localhost:50051")
// error handling omitted
s.Serve(lis)

With server authentication SSL/TLS

Client:

creds, _ := credentials.NewClientTLSFromFile(certFile, "")
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))
// error handling omitted
client := pb.NewGreeterClient(conn)
// ...

Server:

creds, _ := credentials.NewServerTLSFromFile(certFile, keyFile)
s := grpc.NewServer(grpc.Creds(creds))
lis, _ := net.Listen("tcp", "localhost:50051")
// error handling omitted
s.Serve(lis)