Welcome to new things

[Technical] [Electronic work] [Gadget] [Game] memo writing

How to call REST APIs with a service account on Google Cloud Platform

Normally, GCP operations can be done via command line tools or client libraries, so we never called the REST API directly.

I'm trying out a service called GCP Batch right now, but it's still in preview stage and the command line tools and client libraries are not fully developed, so I had to call the REST API directly.

It was a hassle to find a way to call the REST API using a service account in GCP, so I'll note the steps here.

Outline of Procedure

  • Obtain a token from the service account key file and set the token to the Bearer token in the call header to access the API
  • Access tokens can be obtained with a command line tool or a client library
  • API documentation for each service can be found in the "Reference" section of the documentation for each service.

The procedure for obtaining a token from a service account key file is time-consuming, and implementing the authentication process by yourself is a security risk, so we will use the tools and libraries provided by Google.

As a sample, let's try to get a list of GCS buckets.

Procedure (common to all consoles)

  • Enable the API you want to use in the "API and Services" section of the console.
  • Create a service account in "IAM and Administration" in the console
  • Create and download a key file for the service account in "IAM and Administration" in the console
  • Grant permissions to service accounts in "IAM and Administration" in the console

Procedure (for command line tool)

ShellScript

export GOOGLE_APPLICATION_CREDENTIALS=KEY_PATH

PROJECT_ID=PROJECT_ID
URL=https://storage.googleapis.com/storage/v1/b?project=${PROJECT_ID}

TOKEN=$(gcloud auth application-default print-access-token)

curl ${URL} \
  -X GET \
  -H "Authorization: Bearer ${TOKEN}"

Procedure (for client libraries)

  • There are authentication-related modules in the client library, so use them.
  • The scope is https://www.googleapis.com/auth/cloud-platform.

Node.js

import axios from 'axios';
import { GoogleAuth } from 'google-auth-library';

(async () => {
    try {
        const auth = new GoogleAuth({
            scopes: 'https://www.googleapis.com/auth/cloud-platform',
            keyFile: 'KEY_PATH',
        });
        const token = await auth.getAccessToken();

        const PROJECT_ID = 'PROJECT_ID';
        const url = `https://storage.googleapis.com/storage/v1/b?project=${PROJECT_ID}`;

        const res = await axios.request({
            method: 'GET',
            url,
            headers: {
                'Authorization': `Bearer ${token}`
            }
        });

        console.log(res.data);

    } catch (err) {
        console.error(err.response);
    }
})();

Go Language

package main

import (
    "context"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"

    "golang.org/x/oauth2/google"
)

func main() {
    ctx := context.Background()

    json, err := ioutil.ReadFile("KEY_PATH")
    if err != nil {
        log.Fatal(err)
    }

    creds, err := google.CredentialsFromJSON(
        ctx,
        json,
        "https://www.googleapis.com/auth/cloud-platform",
    )
    if err != nil {
        log.Fatal(err)
    }

    token, err := creds.TokenSource.Token()
    if err != nil {
        log.Fatal(err)
    }

    client := &http.Client{}

    projectID := "PROJECT_ID"
    req, err := http.NewRequest(
        "GET",
        fmt.Sprintf("https://storage.googleapis.com/storage/v1/b?project=%s", projectID),
        nil,
    )
    if err != nil {
        log.Fatal(err)
    }

    req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%s\n", body)
}

Impressions, etc.

As is the case with AWS as well as GCP, when a service is released with functionality, the functionality is first provided via a REST API, followed by a library that wraps it. Documentation and translation are also provided in that order.

Therefore, there may be a time lag between when the REST API is released and when the documentation is available for libraries to use.

Although it is easiest and safest to use the service through the library, I thought it would be good to know how to use the REST API directly so that I can try out new features and use it in cases where the library is not provided.

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com

www.ekwbtblog.com