Search code examples
javagoogle-oauthgoogle-kubernetes-enginegoogle-sheets-apiworkload-identity

Using Google Sheets API from Java using GKE Workload Identity


We've been successfully using the Java client for Google Sheets for a while within our GKE cluster, using the ComputeCredential class to provide credentials. The following code is more or less what we're doing:

import com.google.api.client.googleapis.compute.ComputeCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.sheets.v4.Sheets;

NetHttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
GsonFactory jsonFactory = GsonFactory.getDefaultInstance();
ComputeCredential credential = new ComputeCredential(transport, jsonFactory);
Sheets service = new Sheets.Builder(transport, jsonFactory, credential)
                .setApplicationName("myApplication")
                .build();

We've recently enabled Workload Identity on our cluster and this integration no longer works—we get a 403 with the message ACCESS_TOKEN_SCOPE_INSUFFICIENT. I think this is because the default scope encompasses Google Cloud APIs and doesn't allow you to specify the Google Sheets scopes that are needed.

I've found the ComputeEngineCredentials class in google-auth-library-oauth2-http which allows passing in scopes but isn't compatible with the Google Sheets library.

I've raised a GitHub issue but there's been no reply as yet.

Does anyone know how to use the Google Sheets library with Workload Identity?


Solution

  • I finally figured out a solution to this! For anyone else wondering, you can edit the token server URL on the ComputeCredential object to include the scopes, like this:

    import com.google.api.client.googleapis.compute.ComputeCredential;
    import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
    import com.google.api.client.http.javanet.NetHttpTransport;
    import com.google.api.client.json.gson.GsonFactory;
    import com.google.api.services.sheets.v4.Sheets;
    
    NetHttpTransport transport = GoogleNetHttpTransport.newTrustedTransport();
    GsonFactory jsonFactory = GsonFactory.getDefaultInstance();
    ComputeCredential.Builder builder = new ComputeCredential.Builder(transport, jsonFactory);
    GenericUrl url = builder.getTokenServerUrl().clone().set("scopes", "<your scopes here>");
    
    ComputeCredential credential = builder.setTokenServerUrl(url).build();
    
    Sheets service = new Sheets.Builder(transport, jsonFactory, credential)
            .setApplicationName("myApplication")
            .build();