Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 4537

gRPC Authentication in Java Using Application Layer Transport Security (ALTS)

$
0
0
start here featured

1.  Overview

In this tutorial, we’ll explore the role of ALTS (Application Layer Transport Security) in gRPC applications. As we know, ensuring authentication and data security is difficult but essential in a distributed architecture.

ALTS is a custom built-in mutual authentication and transport encryption solution from Google that is available exclusively in Google’s cloud infrastructure. ALTS simplifies authentication and data encryption between gRPC services and can be enabled with minimal code changes. Hence, it’s popular among developers as they can focus more on writing business logic.

2. Key Differences Between ALTS and TLS

ALTS is similar to TLS but has a different trust model optimized for Google’s infrastructure. Let’s quickly take a look at the key differences between them:

Features ALTS TLS
Trust Model Identity-based relying on GCP IAM Service Accounts Certificate-based, requires certificate management, including renewal and revocation
Design Simpler Complex
Usage Context Used for securing gRPC services running on Google data centers Used for securing Web browsing (HTTPS), email, instant messaging, VoIP, etc.
Message Serialization Uses Protocol Buffers Uses X.509 certificates encoded with ASN.1
Performance Designed for general use Optimized for low-latency, high-throughput communications in Google’s data centers

3. Sample Application Using ALTS

The ALTS feature is enabled by default on the Google Cloud Platform (GCP). It uses GCP service accounts to secure RPC calls between gRPC services. Specifically, it runs on Google Compute Engine or Kubernetes Engine (GKE) within Google’s infrastructure.

Let’s assume there’s an Operation Theater (OT) booking system in a hospital that consists of a front-end and a backend service:

The OT Booking system comprises two services running in the Google Cloud Platform (GCP). A front-end service makes remote procedure calls to the backend service. We’ll develop the services using the gRPC framework. Considering the sensitive nature of the data, we’ll utilize the built-in ALTS feature in GCP to enable authentication and encryption for the transit data.

First, let’s define the protobuf ot_booking.proto file:

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

Basically, we declared a service OtBookingService with the RPC getBookingInfo(), and two DTOs BookingRequest and BookingResponse in the protobuf file.

Next, let’s have a look at the important classes of this application:

 

The Maven plugin compiles the protobuf file and auto-generates some classes such as OtBookingServiceGrpc, OtBookingServiceImplBase, BookingRequest, and BookingResponse. We’ll use the gRPC library class AltsChannelBuilder to enable ALTS to create the ManagedChannel object on the client side. Finally, we’ll use OtBookingServiceGrpc to generate the OtBookingServiceBlockingStub to call the RPC getBookingInfo() method running on the server side.

Like AltsChannelBuilder, the AltsServerBuilder class helps enable ALTS on the server side. We register the interceptor ClientAuthInterceptor to help authenticate the client. Finally, we register the OtBookingService to the io.grpc.Server object and then start the service.

Furthermore, we’ll discuss the implementation in the next section.

4. Application Implementation Using ALTS

Let’s implement the classes we discussed earlier. Then, we’ll demonstrate by running the services on the GCP virtual machines.

4.1. Prerequisite

Since ALTS is a built-in feature in GCP, we’ll have to provision a few cloud resources for running the sample application.

First, we’ll create two IAM service accounts to associate them with the front-end and back-end servers respectively:

 

Then, we’ll create two virtual machines hosting the front-end and back-end services respectively:

The virtual machine prod-booking-client-vm is associated with prod-ot-booking-client-svc service account. Similarly, prod-booking-service-vm is associated with prod-ot-booking-svc service account. The service accounts serve as the servers’ identities and ALTS uses them for authorization and encryption.

4.2. Implementation

Let’s first start with an entry into the pom.xml file to resolve the Maven dependency:

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-alts</artifactId>
    <version>1.63.0</version>
</dependency>

Then, we’ll implement the backend, starting with the AltsBookingServer class:

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 provides a special class AltsServerBuilder for configuring the server in ALTS mode. We’ve registered the ClientAuthInterceptor on the server to intercept all the RPCs before they hit the endpoints in the OtBookingService class.

Let’s take a look at the ClientAuthInterceptor class:

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

All the RPCs hit the intercept() method in ClientAuthInterceptor. Then, we invoke the clientAuthorizationCheck() method of the gRPC library class AuthorizationUtil to authorize the client service account. Finally, the RPC moves further only when the authorization is successful.

Next, let’s take a look at the front-end service:

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

Similar to AltsServerBuilder, gRPC offers an AltsChannelBuilder class for enabling ALTS on the client side. We can call the addTargetServiceAccount() method multiple times to add more than one potential target service account. Further, we initiate the RPC by calling the getBookingInfo() method on the stub.

The same service account can be associated with multiple virtual machines. Hence, it provides a certain degree of flexibility and agility to scale the services horizontally.

4.3. Run on Google Compute Engine

Let’s login to both servers and then clone the GitHub repository hosting the source code of the demo gRPC service:

git clone https://github.com/eugenp/tutorials.git

After cloning, we’ll compile the code in the tutorials/grpc directory:

mvn clean compile

Post successful compilation, we’ll start the backend service in 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"

We ran the AltsOtBookingServer class with the service account of the front-end client as an argument.

Once the service is up and running, we’ll initiate an RPC from the front-end service running on the virtual machine prod-booking-client-vm:

mvn exec:java -Dexec.mainClass="com.baeldung.grpc.alts.client.AltsOtBookingClient" \
-Dexec.arguments="10.128.0.2:8080,prod-ot-booking-svc@grpc-alts-demo.iam.gserviceaccount.com"

We ran the AltsOtBookingClient class with two arguments. The first argument is the target server where the backend service is running and the second is the service account associated with the backend server.

The command runs successfully and the service returns a response after authenticating the client:

Let’s suppose we disable the client service account:

As a result, the ALTS prevents the RPC from reaching the backend service:

The RPC fails with the status UNAVAILABLE.

Now, let’s disable the service account of the backend server:

Surprisingly, the RPC goes through but after restarting the servers it fails like the earlier scenario:

It seems that ALTS was caching the service account status earlier, but after the server restart, the RPC failed with the status UNKNOWN.

5. Conclusion

In this article, we delved into the gRPC Java library supporting ALTS. With minimal code, ALTS can be enabled in gRPC services. It also provides greater flexibility in controlling the authorization of gRPC services with the help of GCP IAM service accounts.

However, it works only in GCP infrastructure as it’s provided out of the box. Hence, to run gRPC services outside of GCP infrastructure, TLS support in gRPC is crucial and must be manually configured.

As usual, the code used here is available over on GitHub.

       

Viewing all articles
Browse latest Browse all 4537

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>