新しいことにはウェルカム

技術 | 電子工作 | ガジェット | ゲーム のメモ書き

Google Cloud Platform でサービスアカウントを使ってREST APIを呼び出す方法

普段GCPの操作は、コマンドラインツールかクライアントライブラリ経由で行えるので、REST APIを直接呼び出すことはありませんでした。

今GCP Batchというサービスを試しているのですが、まだプレビュー段階でコマンドラインツールやクライアントライブラリが十分に整備されておらず、REST APIを直接呼び出す必要がありました。

GCPでサービスアカウントを使ってREST APIを呼び出す方法が手間でしたので、ここに手順をメモしておこうと思います。

手順概要

  • サービスアカウントのキーファイルからトークンを取得し、トークンを呼び出しヘッダーのBearerトークンに設定してAPIアクセスする
  • アクセストークンの取得は、コマンドラインツールかクライアントライブラリで行う
  • 各サービスのAPIドキュメントは、各サービスのドキュメントの「リファレンス」にある

サービスアカウントのキーファイルからトークンを取得する手順は手間でかつ、認証周りを自分で実装するのはセキュリティリスクが伴うので、Googleが提供しているツール・ライブラリを使います。

サンプルとしてGCSのバケット一覧を取得してみます。

手順(コンソール共通)

  • コンソールの「APIとサービス」で使いたいAPIを有効にしておく
  • コンソールの「IAMと管理」でサービスアカウントを作成する
  • コンソールの「IAMと管理」でサービスアカウントのキーファイルを作成してダウンロードする
  • コンソールの「IAMと管理」でサービスアカウントに権限を付与する

手順(コマンドラインツールの場合)

  • 環境変数「GOOGLE_APPLICATION_CREDENTIALS」をサービスアカウントのキーファイルのパスに設定し、サービスアカウントをアプリケーションのデフォルト認証情報(ADC)にする
  • gcloud auth application-default print-access-tokenでトークンを取得する

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

手順(クライアントライブラリの場合)

  • クライアントライブラリに認証関連のモジュールがあるのでそれを使う
  • スコープは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言語

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

感想など

GCPだけでなくAWSもそうですが、サービスの機能リリースは、まずREST APIで機能が提供され、その後それをラップするライブラリが提供されます。また、ドキュメントの提供と翻訳もその順番で行われます。

ですので、REST APIが出てからドキュメントが揃ってライブラリで使えるようになるまで、タイムラグが生じてしまうことがあります。

サービスの利用はライブラリを介して行うのが一番簡単でかつ安全なのですが、REST APIを直接利用する方法を知っておくと、新機能を試したり、ライブラリが提供されていないケースでも使えるので、覚えておいて損はないかなと思いました。

関連カテゴリー(GCP)記事

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com

www.kwbtblog.com