7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Cloud Endpoints + ESPv2のデプロイをgit hub actionsで自動化する

Last updated at Posted at 2020-07-19

Cloud Runで動く自分用APIを保護するため、Cloud Endpointsを手順を参考にデプロイしてみた

CloudRunで作ったAPIが保護できるだけでなく、APIの実行状況監視(実行回数、レスポンスタイム、エラー回数)もCloudEndpointsの画面でできるようになってよき

この手順は用意されたスクリプトでESPv2コンテナをビルドし、
手動でCloud Runにデプロイしなければならないので、
これをGitHubActionsで自動化した

要はスクリプトの中身でやっていることをGitHub Actionsにした

openapiの中身には触れない
gcloudのコマンドも一通り打てる環境になっていることが前提

自分のAPIサーバコンテナをCloudRunにデプロイ

保護したいAPIエンドポイントを持つサーバコンテナをCloudRunにデプロイする
払い出されたエンドポイントURLは後ほど用いる

--no-allow-unauthenticated オプションをつけて未認証の呼び出しを許可しない設定とすること

ESPv2コンテナをCloudRunにデプロイ

手順を参考にESPv2コンテナをとりあえずデプロイ

これがゲートウェイになり、APIを保護する
払い出されたエンドポイントURLのホスト名は後ほど用いる

Cloud Endpointsをデプロイ

Cloud EndpointsをopenapiのドキュメントをデプロイするGitHubActionsを準備する
下記コマンドを打てば良い

gcloud endpoints services deploy openapi.yaml --project ${GCP_PROJECT}

openapi.yaml

openapi.yamlの中身は以下

【ENDPOINTS_HOST】にはESPv2コンテナをCloudRunにデプロイで払い出されたURLのホスト名、
【BACKEND_ADDRESS】には自分のAPIサーバコンテナをCloudRunにデプロイで払い出されたエンドポイントURLを指定

【apiの定義】にはopenapiの書式でAPIの仕様を記載する

securityDefinitionsとsecurityを下記の通り定義するとAPIキーによる保護ができるようになる

swagger: '2.0'
info:
  title: [サービス名]
  description: description
  version: 1.0.0
host: 【ENDPOINTS_HOST】
schemes:
  - https
produces:
  - application/json
x-google-backend:
  address: 【BACKEND_ADDRESS】
  protocol: h2
security:
  - api_key: []
paths:
  【apiの定義】
securityDefinitions:
  api_key:
    type: "apiKey"
    name: "key"
    in: "query"

ESPv2コンテナ再ビルド/デプロイ

ESPv2コンテナに上記CloudEndpointsの設定を載せて再ビルドし、CloudRunに再デプロイする

スクリプトを確認するとESPv2にはCloudEndpointsの設定情報の入ったservice.jsonが組み込まれていないといけない
この設定情報を取得するにはCloudEndpointsのConfigIDがいるので、[Cloud Endpointsをデプロイ](#Cloud Endpointsをデプロイ)でデプロイしたCloudEndpointsの最新ConfigIDをまず取得する
取得したConfigIDをもとにservice.jsonを取得してESPv2コンテナに組み込んでビルド
できたコンテナをCloudRunにデプロイする

こちらは--allow-unauthenticatedオプションをつけて未認証の呼び出しを許可する

上記をやるGitHubActionsが以下

update-gateway-cloud-run:
    runs-on: ubuntu-latest
    needs: update-cloud-endpoints
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v1
      - name: GCP Authenticate
        uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: '290.0.1'
          service_account_key: ${{ secrets.GCP_CI_SA_KEY }}
          project_id: ${{ secrets.GCP_PROJECT }}
      - name: get latest config id
        run: |-
          echo "::set-env name=CONFIG_ID::$(gcloud endpoints configs list \
            --service=${ENDPOINTS_HOST} \
            --sort-by='~CONFIG_ID' \
            --limit=1 \
            | tail -1 | cut -d' ' -f1)"
      - name: get service.json
        run: |-
          curl --fail -o "service.json" -H "Authorization: Bearer $(gcloud auth print-access-token)" \
          "https://servicemanagement.googleapis.com/v1/services/${ENDPOINTS_HOST}/configs/${CONFIG_ID}?view=FULL"
      - name: Build a docker image
        run:
          docker build -t asia.gcr.io/${GCP_PROJECT}/${GATEWAY_NAME}:${GITHUB_SHA::7} -f endpoints/Dockerfile .
      - name: Configure docker to use the gcloud cli
        run: gcloud auth configure-docker --quiet
      - name: Push the docker image
        run:
          docker push asia.gcr.io/${GCP_PROJECT}/${GATEWAY_NAME}:${GITHUB_SHA::7}
      - name: deploy
        run: |-
          gcloud run deploy "${GATEWAY_NAME}" \
            --quiet \
            --allow-unauthenticated \
            --region "${GCP_REGION}" \
            --image "asia.gcr.io/${GCP_PROJECT}/${GATEWAY_NAME}:${GITHUB_SHA::7}" \
            --project "${GCP_PROJECT}" \
            --platform "managed" \
            --service-account "${GCP_SA_EMAIL}"

Dockerfileはスクリプトで作っているものをそのままファイル化

必要権限の付与

作成されたCloudEndpointsはGCP上でサービスとして管理される(gcloud services listででてくる)
このサービスに対する下記権限を、ESPv2のCloudRunが動作するサービスアカウントに付与する必要がある
過不足あるかも

  • roles/servicemanagement.serviceController
    • gcloud endpoints services add-iam-policy-binding $(SERVICE_NAME) --member=serviceAccount:$(GCP_SA_EMAIL) --role=roles/servicemanagement.serviceController
  • roles/servicemanagement.configEditor
    • gcloud endpoints services add-iam-policy-binding $(SERVICE_NAME) --member=serviceAccount:$(GCP_SA_EMAIL) --role=roles/servicemanagement.configEditor

またESPv2CloudRunのサービスアカウントに自分のAPIサーバコンテナCloudRunの起動元権限を付与する必要がある

gcloud run services add-iam-policy-binding 自分のAPIサーバコンテナCloudRun名 \
		--member "serviceAccount:$(GCP_SA_EMAIL)" \
		--role "roles/run.invoker" \
		--platform managed \
		--project $(GCP_PROJECT) \
		--region $(GCP_REGION)

APIキーの発行

APIキーはGCP上で管理される
ESPv2CloudRunが動作するGCPプロジェクトで「APIとサービス」-「認証情報」から「認証情報の作成」で作成できる

キーを制限することで、APIキーを利用できるサービスを作成したCloudEndpointsのサービスに限定したり、
APIキー利用元(ソースIPアドレス等)を制限できる

APIアクセス

発行されたAPIキーを?key=APIキーの形で付与して、ESPv2コンテナ CloudRunのエンドポイントに対してAPIを呼び出すと成功
つけないと失敗する

$ curl -s -o /dev/null -w "%{http_code}" https://[CloudRunエンドポイント]/api/health?key=[APIキー]
200
$ curl -s -o /dev/null -w "%{http_code}" https://[CloudRunエンドポイント]/api/health
401

CloudEndpoints

APIの情報がCloudEndpointsの画面で見れるようになる

スクリーンショット 2020-07-19 12.01.07.png

まとめ

CloudRunのエンドポイント保護はCloudEndpoints + ESPv2で Google Cloud Api Gatewayが出てきてオワコンかも
ESPv2のCloud Runを建てなくてもいいっぽいのでこっちに移行したいと考えている

詳しいコードは実際作ったやつ参照

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?