使用應用層傳輸安全性 (ALTS) 的 Java 中的 gRPC 身份驗證
1. 概述
在本教程中,我們將探討ALTS(應用程式層傳輸安全性)在 gRPC 應用程式中的作用。眾所周知,在分散式架構中,確保身份驗證和資料安全是困難的,但卻是必不可少的。
ALTS 是 Google 內建的相互身份驗證和傳輸加密解決方案,僅在 Google 雲端基礎架構中提供。 ALTS 簡化了 gRPC 服務之間的身份驗證和資料加密,並且只需最少的程式碼變更即可啟用。因此,它在開發人員中很受歡迎,因為他們可以更專注於編寫業務邏輯。
2. ALTS 和 TLS 之間的主要區別
ALTS 與 TLS 類似,但具有針對 Google 基礎架構最佳化的不同信任模型。讓我們快速看一下它們之間的主要區別:
| 特徵 | ALTS | 傳輸層安全協定 |
|---|---|---|
| 信任模型 | 基於身份,依賴 GCP IAM 服務帳號 | 基於證書,需要證書管理,包括續約和吊銷 |
| 設計 | 更簡單 | 複雜的 |
| 使用上下文 | 用於保護在 Google 資料中心運作的 gRPC 服務 | 用於保護網頁瀏覽 (HTTPS)、電子郵件、即時訊息、VoIP 等。 |
| 訊息序列化 | 使用協定緩衝區 | 使用以 ASN.1 編碼的 X.509 證書 |
| 表現 | 專為一般用途而設計 | 針對 Google 資料中心的低延遲、高吞吐量通訊進行了最佳化 |
3. 使用 ALTS 的範例應用程式
Google Cloud Platform (GCP) 上預設啟用 ALTS 功能。它使用GCP 服務帳戶來保護 gRPC 服務之間的 RPC 呼叫。具體來說,它在 Google 基礎設施內的Google Compute Engine或Kubernetes Engine (GKE)上運作。
假設醫院中有一個手術室 (OT) 預訂系統,由前端和後端服務組成:
OT Booking 系統包含在 Google Cloud Platform (GCP) 中執行的兩項服務。前端服務對後端服務進行遠端過程呼叫。我們將使用 gRPC 框架開發服務。考慮到資料的敏感性,我們將利用 GCP 中內建的 ALTS 功能來對傳輸資料進行身份驗證和加密。
首先,我們定義 protobuf ot_booking.proto檔:
syntax = "proto3";
package otbooking;
option java_multiple_files = true;
option java_package = "com.baeldung.grpc.alts.otbooking";
service OtBookingService {
rpc getBookingInfo(BookingRequest) returns (BookingResponse) {}
}
message BookingRequest {
string patientID = 1;
string doctorID = 2;
string description = 3;
}
message BookingResponse {
string bookingDate = 1;
string condition = 2;
}
基本上,我們使用 RPC getBookingInfo()宣告了一個服務OtBookingService ,並在 protobuf 檔案中宣告了兩個 DTO BookingRequest和BookingResponse 。
接下來我們來看看這個應用程式的重要類別:
Maven 外掛程式編譯 protobuf 檔案並自動產生一些類,例如OtBookingServiceGrpc 、 OtBookingServiceImplBase 、 BookingRequest,和BookingResponse 。我們將使用 gRPC 庫類別AltsChannelBuilder來啟用 ALTS 在客戶端建立ManagedChannel物件。最後,我們將使用OtBookingServiceGrpc產生OtBookingServiceBlockingStub來呼叫伺服器端執行的 RPC getBookingInfo()方法。
與AltsChannelBuilder一樣, AltsServerBuilder類別有助於在伺服器端啟用 ALTS。我們註冊攔截器ClientAuthInterceptor來幫助驗證客戶端。最後,我們將OtBookingService註冊到io.grpc.Server物件中,然後啟動該服務。
此外,我們將在下一節中討論實作。
4. 使用 ALTS 實施應用程式
讓我們實作之前討論的類別。然後,我們將透過在 GCP 虛擬機器上執行服務來進行演示。
4.1.先決條件
由於 ALTS 是 GCP 中的內建功能,因此我們必須配置一些雲端資源來運行範例應用程式。
首先,我們將建立兩個 IAM 服務帳戶,分別將它們與前端和後端伺服器關聯:
然後,我們將建立兩台虛擬機,分別託管前端和後端服務:
虛擬機器prod-booking-client-vm與prod-ot-booking-client-svc服務帳號關聯。同樣, prod-booking-service-vm與prod-ot-booking-svc服務帳戶關聯。服務帳戶充當伺服器的身份,ALTS 使用它們進行授權和加密。
4.2.執行
首先,我們從pom.xml檔案中的條目開始,以解決Maven 依賴關係:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-alts</artifactId>
<version>1.63.0</version>
</dependency>
然後,我們將從AltsBookingServer類別開始實作後端:
public class AltsOtBookingServer {
public static void main(String[] args) throws IOException, InterruptedException {
final String CLIENT_SERVICE_ACCOUNT = args[0];
Server server = AltsServerBuilder.forPort(8080)
.intercept(new ClientAuthInterceptor(CLIENT_SERVICE_ACCOUNT))
.addService(new OtBookingService())
.build();
server.start();
server.awaitTermination();
}
}
gRPC 提供了一個特殊的類別AltsServerBuilder用於在 ALTS 模式下設定伺服器。我們已在伺服器上註冊了ClientAuthInterceptor ,以便在所有 RPC 到達OtBookingService類別中的端點之前攔截它們。
我們來看看ClientAuthInterceptor類別:
public class ClientAuthInterceptor implements ServerInterceptor {
String clientServiceAccount = null;
public ClientAuthInterceptor(String clientServiceAccount) {
this.clientServiceAccount = clientServiceAccount;
}
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
ServerCallHandler<ReqT, RespT> serverCallHandler) {
Status status = AuthorizationUtil.clientAuthorizationCheck(serverCall,
Lists.newArrayList(this.clientServiceAccount));
if (!status.isOk()) {
serverCall.close(status, new Metadata());
}
return serverCallHandler.startCall(serverCall, metadata);
}
}
所有 RPC 都會呼叫ClientAuthInterceptor中的intercept()方法。然後,我們呼叫gRPC函式庫類別AuthorizationUtil的clientAuthorizationCheck()方法來授權客戶端服務帳戶。最後,只有授權成功後,RPC 才會進一步進行。
接下來我們來看看前端服務:
public class AltsOtBookingClient {
public static void main(String[] args) {
final String SERVER_ADDRESS = args[0];
final String SERVER_ADDRESS_SERVICE_ACCOUNT = args[1];
ManagedChannel managedChannel = AltsChannelBuilder.forTarget(SERVER_ADDRESS)
.addTargetServiceAccount(SERVER_ADDRESS_SERVICE_ACCOUNT)
.build();
OtBookingServiceGrpc.OtBookingServiceBlockingStub OTBookingServiceStub = OtBookingServiceGrpc
.newBlockingStub(managedChannel);
BookingResponse bookingResponse = OTBookingServiceStub.getBookingInfo(BookingRequest.newBuilder()
.setPatientID("PT-1204")
.setDoctorID("DC-3904")
.build());
managedChannel.shutdown();
}
}
與AltsServerBuilder類似,gRPC 提供了AltsChannelBuilder類,用於在用戶端啟用 ALTS。我們可以多次呼叫addTargetServiceAccount()方法來新增多個潛在的目標服務帳戶。此外,我們透過呼叫存根上的getBookingInfo()方法來啟動 RPC。
同一服務帳戶可以與多個虛擬機器關聯。因此,它提供了一定程度的靈活性和敏捷性來水平擴展服務。
4.3.在 Google 計算引擎上運行
讓我們登入兩台伺服器,然後複製託管演示 gRPC 服務原始碼的 GitHub 儲存庫:
git clone https://github.com/eugenp/tutorials.git
克隆完成後,我們將編譯tutorials/grpc目錄中的程式碼:
mvn clean compile
編譯成功後,我們將在prod-booking-service-vm中啟動後端服務:
mvn exec: java -Dexec.mainClass="com.baeldung.grpc.alts.server.AltsOtBookingServer" \
-Dexec.arguments="prod-ot-booking-client-svc@grpc-alts-demo.iam.gserviceaccount.com"
我們使用前端客戶端的服務帳戶作為參數來執行AltsOtBookingServer類別。
服務啟動並執行後,我們將從虛擬機器prod-booking-client-vm上執行的前端服務啟動 RPC:
mvn exec:java -Dexec.mainClass="com.baeldung.grpc.alts.client.AltsOtBookingClient" \
-Dexec.arguments="10.128.0.2:8080,[email protected]"
我們使用兩個參數來執行AltsOtBookingClient類別。第一個參數是執行後端服務的目標伺服器,第二個參數是與後端伺服器關聯的服務帳戶。
命令成功運行,服務在驗證客戶端身份後回傳回應:
假設我們停用客戶服務帳戶:
結果,ALTS 阻止 RPC 到達後端服務:
RPC 失敗,狀態為UNAVAILABLE 。
現在,讓我們停用後端伺服器的服務帳戶:
令人驚訝的是,RPC 成功了,但在重新啟動伺服器後,它失敗了,就像之前的場景一樣:
似乎 ALTS 之前快取了服務帳戶狀態,但伺服器重新啟動後,RPC 失敗,狀態為UNKNOWN 。
5. 結論
在本文中,我們深入研究了支援 ALTS 的 gRPC Java 程式庫。只需最少的程式碼,就可以在 gRPC 服務中啟用 ALTS。它還在 GCP IAM 服務帳戶的幫助下提供了更大的靈活性來控制 gRPC 服務的授權。
但是,它僅適用於 GCP 基礎設施,因為它是開箱即用的。因此,要在 GCP 基礎架構之外運行 gRPC 服務,gRPC 中的 TLS 支援至關重要,並且必須手動設定。
與往常一樣,這裡使用的程式碼可以在 GitHub 上找到。