Search code examples
javagoogle-cloud-platformgoogle-bigquerygoogle-oauthservice-accounts

Bigquery insert job with default service account


I had some working code to use the rest api load the files into bigquery as described https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/insert During the process I was using ServiceAccountCredentials to read the private key and gendrate JWT token then finally get the OAuth token for the insert job. Now the same process I would need to run in a docker container within the gcp. I did not find the client to do so. That was the reason I went for Rest API the first moment. Is there a way I can generate the token using the default service account's credential? How can I reach the default service account within the java code?


Solution

  • Your question does not state what service the container is running in. Some services make Application Default Credentials (ADC) available to the container via metadata server or via secrets, others do not. For those services that do not provide ADC, you will need to specify the service account key file.

    For this answer, I will show you the correct method to obtain a Google OAuth Access Token. Unless you have specific technical reasons, do not create tokens from JWT.

    Obtain an Access Token from service account JSON key file:

    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.auth.oauth2.AccessToken;
    import  com.google.common.collect.Lists;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    
    class Main
    {
        public static void main(String args[])
        {
        String  sa_file = "/fullpath/serviceaccount.json";
        String  scopes = "https://www.googleapis.com/auth/cloud-platform";
    
            GoogleCredentials credentials;
    
            try {
                credentials = GoogleCredentials.fromStream(new FileInputStream(sa_file))
                    .createScoped(Lists.newArrayList(scopes));
            }
            catch (java.io.FileNotFoundException e) {
                System.out.println("FileNotFoundException");
                return;
            }
            catch (IOException e) {
                System.out.println("IOException");
                return;
            }
    
            try {
                AccessToken accessToken;
    
                accessToken = credentials.getAccessToken();
    
                if (accessToken == null) {
                    accessToken = credentials.refreshAccessToken();
                }
    
                if (accessToken != null) {
                    System.out.println("Access Token: " + accessToken.getTokenValue());
                }
            }
            catch (IOException e) {
                System.out.println("IOException");
                return;
            }
        }
    }
    

    If Application Default Credentails are available in your container, you can obtain credentials this way and using the above method extract the access token.

    var credential = GoogleCredential.GetApplicationDefault();
    

    If you are running on a Google service that supports the Metadata server (Compute Engine, etc.) you can obtain the Access Token by HTTP GET Request to this endpoint:

    http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
    

    You will need to include this HTTP header with the GET request:

    Metadata-Flavor: Google