Speee DEVELOPER BLOG

Speee開発陣による技術情報発信ブログです。 メディア開発・運用、スマートフォンアプリ開発、Webマーケティング、アドテクなどで培った技術ノウハウを発信していきます!

Auth0のデプロイをGitHub Actionsで自動化した話

はじめに

デジタルトランスフォーメーション(DX)事業本部で新規事業開発をしている八木です。
アウトプットの習慣をつけるために、簡単なところからでもブログ化していこうという思いから書いてみました。
今回はAuth0のデプロイ自動化のお話をさせていただきます。

Auth0のデプロイの自動化をした背景

現在、私のプロジェクトでは認証、認可機能を実装するためにAuth0を採用しているのですが、これまでデプロイまわりで以下の二つの問題を抱えていました。

一つ目は、単純に手間がかかることです。
フロント、バックエンドのデプロイに関してはテスト環境、本番環境のレポジトリにmergeされたら自動でその環境にデプロイされるようになっていました。ただ、Auth0のデプロイに関しては、手動で手元で実行していたため、通常のデプロイフローとは別にデプロイしなければならないという手間がかかっていました。

二つ目は、デプロイ内容が個々人の環境によって差分がある可能性があるという点です。
Auth0のデプロイにはAuth0のテナント情報と、設定や環境情報が記載されているデータが必要になります。
設定や環境情報が記載されているデータはJSONファイルでテンプレートはGit管理されておりましたが、デプロイ用の設定に関してはセキュリティ上の観点から、個々人のローカル環境で管理しており、デプロイ時にチームメンバーに設定があっているかの確認が発生していたり、不安が残る状態のデプロイが行われていました。 改善前のサービス全体のデプロイフローは以下のようになっていました。

f:id:GreatTower:20211114165250p:plain

今回、これらの問題を解決するためにAuth0のデプロイフローの改善に取り組みました。

Auth0のデプロイで使っているサービス、ライブラリ

  • GitHub Actions
    • デプロイの実行、管理に使用しています。
  • AWS Systems Manager
    • Parameter Storeを環境変数の管理に使用しています。
  • auth0-deploy-cli
    • Auth0のテナント設定は画面からもできますが、CI/CDパイプラインへの統合もサポートしてくれていて、そのためのツールがauth0-deploy-cliです。 以下に記載しているコマンドを実行することで、Auth0側に設定したい内容をデプロイすることができるようになります。 また、Auth0側の現在の状態をテナント設定情報が記載されたファイル(tenant.yaml)に書き出すことも可能です。 config.jsonは主にAuth0側への接続情報などが記載されているファイルです。
      a0deploy deploy -c config.json -i tenant.yaml
    

デプロイフロー

deploy-flow2

改善後からは画像のようなフローでデプロイを行なえるようになりました。
テスト環境、または本番環境へのmergeをトリガーにAWSへのログインとParameter Storeから必要な環境変数を取得して、その環境変数をもとにAuth0のテナント情報を更新するというようなフローになっています。

具体的な実装

GitHub Actions側のコード

GitHub Actions側でやっていることはシンプルで以下のことをしています。

  • nodeのコンテナを取得する
  • auth0-deploy-cliをinstallする
  • Parameter Storeから必要な値をとってきて、環境変数として読み込む
  • deployコマンドを叩く

actions.yml

name: deploy
on:
  push:
    branches:
      - main
    paths:
      - app/auth0/*
  workflow_dispatch:
    inputs:

defaults:
  run:
    working-directory: app/auth0

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.15.4]
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v1
        with:
          node-version: ${{matrix.node-version}}
      - name: "yarn install"
        run: yarn install
      - name: "AWS認証情報を設定"
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-region: ap-northeast-1
          aws-access-key-id: ${{ ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ SECRET_ACCESS_KEY }}
      - name: "AWS Parameter Store の値を環境変数に登録"
        run: |
          function set_env_from_parameter_store() {
            VALUE=$(aws ssm get-parameter --name $1 --with-decryption --query 'Parameter.Value' --output text)
            echo "$2=$VALUE" >> $GITHUB_ENV
            echo "::add-mask::$VALUE"
          }
          set_env_from_parameter_store '/test/auth0/AUTH0_DOMAIN' 'AUTH0_DOMAIN'
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      - name: "staging deploy"
        run: npm run deploy

GitHub Actionsで叩いているdeployコマンド

a0deploy deploy -c config.json -i tenant.yaml

元々、開発者各自のローカルでconfig.staging.json、config.production.jsonのように環境ごとのconfigファイルを管理しており、上記のコマンドを使用して各環境にデプロイしていました。
その運用を改善するために、JSONファイルで管理していた内容を、Parameter Storeに入れることにして環境変数から読む実装にしました。
JSONファイルは単なるデータファイルで環境変数を読み込めるような機能がなかったため、そもそも設定をJSONファイルで持つことをやめ、JavaScriptの実行ファイルを持ち、JSONデータとして扱うように変更したことで、自動化することができました。

package.json

  "scripts": {
    "staging-deploy": "node deploy.js tenant.yaml"
  },

deploy.js

const deploy = require("auth0-deploy-cli").deploy;
const tenant = process.argv[2];

const config = {
  AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
  # 省略
};

deploy({
  input_file: `${tenant}`,
  config: config,
  env: process.env,
})
  .then(() => {
    console.log("deploy was successful");
  })
  .catch((err) => {
    console.error(`Oh no, something went wrong. Error: ${err}`);
    process.exit(1); ※1
  });

※1 終了コードの指定 終了コードの指定をしないと、JavaScriptの実行結果がGitHub Actions側に返らないので、落ちても気づけなくなってしまいます。 また、GitHub Actions ToolkitというJavaScriptでActionを作成する時に使用する開発支援ツールの中に、終了コードを標準出力に出力してくれる機能もあるんですが、今回はここでしか使わなそうだったので使用はやめました。もし他の機能も使う方がいたら入れても良さそうです! 参照: https://github.com/actions/toolkit/tree/master/packages/core

まとめ

個人的には、手動で行っていたことが自動化できたのはもちろんのこと、昨今のインフラ設定、CI/CDはJSON、YAMLなどのデータファイルを使うことが多いがので、そこで環境変数を読み込みたいような場面も出てくると思っています 。
今回はそこをJavaScriptをクッションにして解決できたので、今後も使えそうだなという知見が得られたのでよかったです