ぴろログ

Output Driven

SaaS も Terraform で管理しよう! / Terraform で「Auth0」を apply してみた

「Infrastructure as Code ( IaC )」で有名な「Terraform」。「インフラ」の構成管理ツールだとばかり思っていましたが、なんと SaaS にも対応しているみたいなんです! 定義ファイルをテンプレート化すると、同じ構成で SaaS を展開できるので、 CIer の方にとってはかなり便利だと思います。

今回は、認証・認可の SaaS である 「Auth0」terraform applyを試してみたので、作業ログを記事にしました。

Terraform と Auth0

どちらもまだ初心者クラスですが、これまでに2つの記事を書きました。機能紹介やセットアップ方法、コマンドの動作などの情報が知りたい方は、こちらををご参照ください。

↓ Terraform のインストール方法やコマンドの使い方を紹介しています。 blog.pirox.dev

↓ Auth0 の機能概要やアカウント作成方法を紹介しています。 blog.pirox.dev

Terraform の「Resource」と「Provider」

Terraform の定義ファイル(.tf)に記述する代表的なブロックが「Resource」「Provider」です。 たとえば、 AWSVPC を管理(作成)するには以下のように記述します。

# Configure the AWS Provider
provider "aws" {
  version = "~> 2.0"
  region = "us-east-1"
}

# Create a VPC
resource "aws_vpc" "example" {
  cidr_block = "10.0.0.0/16"
}

Provider: AWS - Terraform by HashiCorp

Terraform が公式サポートしている Provider は、執筆時点(2019/05/31)で103個もあります。冒頭で紹介した通り、 GitHub や Datadog といった SaaS も多く含まれています。

Custom Provider を使う(作る)ことで、サポート対象外のサービスも Terraform で扱えるようになります。 (対象サービスが API を公開している必要あり。) www.terraform.io

(現時点では) Auth0 もサポート対象外なので、 Custom Provider を作ります。 運良く Auth0 Communnity で開発中の GitHub リポジトリが見つかったので、利用させていただきました。感謝!

github.com

※ Terraform の Community Providers には別の GitHub リポジトリが掲載されていますが、2017年から更新がなかったため利用を見送りました。

Custom Provider の作成

Example を参考にして、 Auth0 の Application ( client )の定義ファイルを作成します。
DomainClient IDClient Secretの値は、別途 Auth0 のダッシュボードで確認します。(確認方法は後述。)

# sample-auth0.tf

# provider に Auth0 を指定
provider "auth0" {
  domain = "<Domain>"
  client_id = "<Client ID>"
  client_secret = "<Client Secret>"
}

# 「 Example Application ( Managed by Terraform )」という名称の Application を作成
resource "auth0_client" "my_app_client" {
  name            = "Example Application (Managed by Terraform)"
  description     = "Example Application Loooooong Description"
  app_type        = "regular_web"
}

公式サポートされているProviderの場合、terraform initするとplugin(≒ SDK )が自動でダウンロードされます。 今回は以下のエラーが表示され、「手動で配置せよ」とのことです。

$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...

Provider "auth0" not available for installation.

A provider named "auth0" could not be found in the official repository.

This may result from mistyping the provider name, or the given provider may
be a third-party provider that cannot be installed automatically.

In the latter case, the plugin must be installed manually by locating and
downloading a suitable distribution package and placing the plugin's executable
file in the following directory:
    terraform.d/plugins/darwin_amd64

Terraform detects necessary plugins by inspecting the configuration and state.
To view the provider versions requested by each module, run
"terraform providers".

GitHub リポジトリを clone して、 Auth0 の Custom Provider を作成します。ソースは Golang で書かれており、 $GOPATH/bin にバイナリファイルの「terraform-provider-auth0」が作成されます。コレが Custom Provider です。

$ git clone https://github.com/alexkappa/terraform-provider-auth0.git
Cloning into 'terraform-provider-auth0'...
remote: Enumerating objects: 3878, done.
remote: Total 3878 (delta 0), reused 0 (delta 0), pack-reused 3878
Receiving objects: 100% (3878/3878), 7.83 MiB | 2.73 MiB/s, done.
Resolving deltas: 100% (1581/1581), done.
$ cd terraform-provider-auth0/
$ make build
==> Checking that code complies with gofmt requirements...
go install
$ ls -l $GOPATH/bin
 ・・・
-rwxr-xr-x  1 pirox  staff  26981684  5 30 14:17 terraform-provider-auth0

「terraform-provider-auth0」を以下のいずれかに配置することで、terraform initが成功します。

配置先に関する仕様はこちらです。Home - Extending Terraform - Terraform by HashiCorp

$ mkdir -p terraform.d/plugins/darwin_amd64
$ cp $GOPATH/bin/terraform-provider-auth0 ./terraform.d/plugins/darwin_amd64/terraform-provider-auth0
$ terraform init

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

これで Terraform 側の準備は完了です。

Auth0 のクレデンシャル情報を取得

ここからは Auth0 のダッシュボードを操作します。クレデンシャル情報(Client IDClient Secret)を取得するための Application ( Client ) を作成します。ここで2つのハマりポイントがあったので、気をつけください。

# sample-auth0.tf

# provider に Auth0 を指定
provider "auth0" {
  domain = "<Domain>"
  client_id = "<Client ID>"
  client_secret = "<Client Secret>"
}
...

「CREATE APPLICATION」をクリックして作成を開始します。

f:id:pirox07:20190530213416p:plain
Applications > CREATE APPLICATION

任意の名称を入力後、 Application Type として「Machine to Machine Applications」を選択します。(ハマりポイント①)

f:id:pirox07:20190531011924p:plain
Create application

「Auth0 Management APIに対して、必要となる権限 ( Scope )を付与します。(ハマりポイント②)
※今回は「 ALL 」を付与しましたが、実運用では必要最低限とすべきでしょう。

f:id:pirox07:20190531012132p:plain
Authorize Machine to Machine Application

これで Application が作成されるので、 Settings 画面で各値を確認し、.tf ファイルに記述します。(今回はハードコードで試しました。)

f:id:pirox07:20190531012414p:plain
Applications > settings

ハマりポイント①:Application Type

Auth0 の Application Type が4種類あり、それぞれ用途が異なります。(詳細: Auth0 Application Types
Terraform のようなコマンドラインツールで利用する場合は、 Machine to Machine Applications を選択します。他のタイプを選択するとterraform applyに失敗します。

$ terraform apply

...

Error: Error applying plan:

1 error(s) occurred:

* auth0_client.my_app_client: 1 error(s) occurred:

* auth0_client.my_app_client: Post https://b-pirox.auth0.com/api/v2/clients: oauth2: cannot fetch token: 403 Forbidden
Response: {"error":"access_denied","error_description":"Client is not authorized to access \"https://b-pirox.auth0.com/api/v2/\". You might probably want to create a \"client-grant\" associated to this API. See: https://auth0.com/docs/api/v2#!/Client_Grants/post_client_grants"}

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

公式ドキュメントに以下の記述があり、エラーの原因に気づくことができました。

With machine-to-machine (M2M) applications, such as CLIs, daemons, or services running on your back-end, the system authenticates and authorizes the app rather than a user.

auth0.com

ハマりポイント②: API のアクセス権限

ハマりポイント①を解決したと思ったら、またもや同様のエラーで悩むことに。。エラーメッセージが同一なので四苦八苦しましたが、クレデンシャルを取得した Application で、 API へのアクセス権限を設定しなかったことが原因でした。

Auth0 の API

Auth0 では2種類の API が用意されています。 Terraform は「Management APIを利用して、 Auth0 の構成を管理します。 auth0.com

参考: Auth0 APIs

  • Authentication API
    • Auth0 を使った認証処理で利用する API
  • Management API (v2)
    • Auth0 の設定変更で利用する管理用 API
    • JWT ( JSON Web Token )による認証、権限付与( granted scope )による認可
    • v1 の利用は非推奨

Management API を利用できるのはが「M2M Applications」のみのようです。(ハマりポイント①の背景がコレです。)他のタイプは SPA などのフロントエンドでの使用を想定したもので、 Authentication API に紐付いています。

terraform apply

以上を設定してterraform applyを実行すると、 Auth0 の Application が作成できました。

$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + auth0_client.my_app_client
      id:                                  <computed>
      app_type:                            "regular_web"
      client_id:                           <computed>
      client_secret:                       <computed>
      custom_login_page_on:                <computed>
      description:                         "Example Application Loooooong Description"
      grant_types.#:                       <computed>
      is_first_party:                      <computed>
      is_token_endpoint_ip_header_trusted: <computed>
      name:                                "Example Application (Managed by Terraform)"
      token_endpoint_auth_method:          <computed>


Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

auth0_client.my_app_client: Creating...
  app_type:                            "" => "regular_web"
  client_id:                           "" => "<computed>"
  client_secret:                       "<sensitive>" => "<sensitive>"
  custom_login_page_on:                "" => "<computed>"
  description:                         "" => "Example Application Loooooong Description"
  grant_types.#:                       "" => "<computed>"
  is_first_party:                      "" => "<computed>"
  is_token_endpoint_ip_header_trusted: "" => "<computed>"
  name:                                "" => "Example Application (Managed by Terraform)"
  token_endpoint_auth_method:          "" => "<computed>"
auth0_client.my_app_client: Creation complete after 2s (ID: OoWS2E7kJGWNT2QUmcIAaZWXHvSGOB6p)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

f:id:pirox07:20190530224548p:plain

terraform destroyによる削除にも成功しました。

$ terraform destroy
auth0_client.my_app_client: Refreshing state... (ID: OoWS2E7kJGWNT2QUmcIAaZWXHvSGOB6p)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - auth0_client.my_app_client


Plan: 0 to add, 0 to change, 1 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

auth0_client.my_app_client: Destroying... (ID: OoWS2E7kJGWNT2QUmcIAaZWXHvSGOB6p)
auth0_client.my_app_client: Destruction complete after 1s

Destroy complete! Resources: 1 destroyed.

まとめ

  • Custom Provider を使うことで、 Terraform で Auth0 の構成管理ができる
    • Auth0 のProviderはコミュニティで開発中
  • Auth0 の Management API の理解が深まった
    • CLI でアクセスするためには、 Machine to Machine Application のクレデンシャルを使用する
    • アクセス権の設定も必要( ApplicationのAuthorizeScope

今回「 Terraform で Application を作成するため」の Application (クレデンシャル取得用)を手動で作成しましたが、他にもっといい方法がある気がしています。また、社内ツールの認証に Auth0 を使って、認証基盤( Azure AD )と SSO したいと考えているので、引き続き検証を進めていきます。 Auth0 のprovider開発にも Contribute してみたいです。頑張ろう!!

参考リンク

Custom Provider の実装方法が丁寧に説明されている記事を見つけました。参考になりそう。 febc-yamamoto.hatenablog.jp