Google App Engine Admin API をシェルスクリプトから叩く為にTOKENを取得する


目的

GoogleのApp Engine Admin APIをcurlから叩く必要があった。
サーバ側などでシェルスクリプトとして動かすので、refresh_tokenを利用して何度も使える形でトークンを取得したい

前提

今回は、2018/12/06に社内で既に利用しているプロジェクトに対し設定したため、説明する手順を実行する際、人によっては課金情報の登録画面や、他の同意画面などが出るかもしれません。
そのあたりについては、適宜読み替えてください。

流れ

  1. Developer ConsoleのAPI Managerにアクセスして、App Engine Admin APIを選択しAPIを有効にする
  2. APIとサービス の 認証情報の画面から、OAuthクライアントIDを作成し、クライアントID,クライアントシークレットIDを取得する
  3. コードを取得する
  4. refresh_tokenを取得する
  5. シェル実行時に、クライアントID,クライアントシークレットID,refresh_tokenをもとにaccess_tokenを取得する
  6. access_tokenをheaderに含めてAPIを実行する

1. Developer ConsoleのAPI Managerにアクセスして、App Engine Admin APIを選択しAPIを有効にする

Developer ConsoleのAPI Managerにアクセスします。

今回、私の目的はApp Engine Admin APIなので、そちらを選択して有効にします。

2. APIとサービス の 認証情報の画面から、OAuthクライアントIDを作成し、クライアントID,クライアントシークレットIDを取得する

APIを有効にした後、APIとサービスの画面から[認証情報]に移動し、認証情報を作成からOAuthクライアントIDを作成します。

アプリケーションの種類を「その他」にし、名前を入力します。

その後、クライアントIDを設定してクライアント ID, クライアント シークレットを記録します。

3. コードを取得する

OAuth 2.0 Scopes for Google APIsを参考に、scopeを設定し、redirect_uri をurn:ietf:wg:oauth:2.0:oobとして、以下にアクセスしましょう

https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline

私はシェルを作成してURLを作成し、それをブラウザに貼り付けました。

gae_token.sh
#!/bin/sh

export CLIENT_ID="client_id.apps.googleusercontent.com"
export CLIENT_SECRET="CLIENT_SECRET"

export SCOPE="https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform"
export REDIRECT_URI="urn:ietf:wg:oauth:2.0:oob"

echo "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline"

確認画面が出た後、コードが表示されるので記録します。

4. refresh_tokenを取得する

先程のコードを取得してrefresh_tokenを取得します。

gae_token.sh
#!/bin/sh

export CLIENT_ID="client_id.apps.googleusercontent.com"
export CLIENT_SECRET="CLIENT_SECRET"
export AUTHORIZATION_CODE="4/AUTHORIZATION_CODE"
export REDIRECT_URI="urn:ietf:wg:oauth:2.0:oob"


curl -X POST --data "code=$AUTHORIZATION_CODE" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "redirect_uri=$REDIRECT_URI" --data "grant_type=authorization_code" --data "access_type=offline" https://www.googleapis.com/oauth2/v4/token

この時、取得したコードが時間たって無効になっているとBad Requestとでて悩むので注意してください。(それでしばらくハマりました)

{ 
  "error": "invalid_grant",
  "error_description": "Bad Request"
}

うまくいくとrefresh_tokenが取得できます。
access_tokenは今は無視して、refresh_tokenを記録します。

{ 
  "access_token": "access_tokenaccess_tokenaccess_tokenaccess_tokenaccess_tokenaccess_tokenaccess_token",
  "expires_in": 3600,
  "refresh_token": "1/REFRESH_TOKEN",
  "scope": "https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/appengine.admin",
  "token_type": "Bearer"
}%                                                                                                                                                                                                                                                                              

5. シェル実行時に、クライアントID,クライアントシークレットID,refresh_tokenをもとにaccess_tokenを取得する

refresh_tokenを元に、access_tokenを取得します。

gae_token.sh
#!/bin/sh

export CLIENT_ID="client_id.apps.googleusercontent.com"
export CLIENT_SECRET="CLIENT_SECRET"
export REFRESH_TOKEN="1/REFRESH_TOKEN"

curl -X POST --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token

うまくいけばアクセストークンが取得できます。

{
  "access_token": "access_tokenaccess_tokenaccess_tokenaccess_tokenaccess_tokenaccess_token",
  "expires_in": 3600,
  "scope": "https://www.googleapis.com/auth/appengine.admin https://www.googleapis.com/auth/cloud-platform",
  "token_type": "Bearer"
}%

6. access_tokenをheaderに含めてAPIを実行する

シェルスクリプトで、実行したい処理の前に、APIキーを取得するようにします。
jsonなので処理としてjqコマンドを使いたかったのですが、作業サーバに入っていなかったため、awkを使って処理しました。

gae_token.sh
#!/bin/sh

export CLIENT_ID="client_id.apps.googleusercontent.com"
export CLIENT_SECRET="CLIENT_SECRET"
export REFRESH_TOKEN="1/REFRESH_TOKEN"

# APIキーの取得処理
export API_KEY=`curl -X POST --data "refresh_token=$REFRESH_TOKEN" --data "client_id=$CLIENT_ID" --data "client_secret=$CLIENT_SECRET" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token 2> /dev/null | awk '/access_token/ {match($2, /"(.+)",/, token); print token[1]}'`

# API叩く例
export APPS_ID="test-porject"
export SERVICES_ID="test"
URL="https://appengine.googleapis.com/v1/apps/$APPS_ID/services/$SERVICES_ID/versions/"
curl -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -X GET $URL

参考

Google APIのAccess Tokenをお手軽に取得する https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5