👌

GKE で稼働している Atlantis で Azure に OIDC 認証を行う

2024/04/23に公開

目標

GKE 上で稼働している Atlantis で Azure のリソースを操作するために OIDC 認証する方法をまとめます。

はじめに

Terraform の CD ツールの 1 つとして Atlantis というツールが存在します。
https://www.runatlantis.io/

このツールを利用することで GitHub の PR などから Terraform を実行できます。
他のツールとは異なり、 PR をマージする前に Terraform を実行することで main ブランチ上では常に正常な状態なコードが管理されることになります。
また、 Atlantis 側でロック機構や、ポリシーチェック機能を備えておりチーム開発での利用にも適しています。


https://www.runatlantis.io/

この Atlantis ですが、便利な反面、色々なクラウドリソースを操作するため強力な権限を持ちがちです。
そのため ODIC 認証のような安全な認証方式を利用することが推奨されます。

今回の記事では GKE 上で稼働している Atlantis が Azure 上のリソースを操作するための権限を OIDC 認証経由で取得するまでの方法を解説します。

前提

Atlantis は v0.27.1 を利用しています。

GitHub との接続は GitHub App を利用しています。
https://www.runatlantis.io/docs/access-credentials.html#github-app

Azure への認証するところまでを目標としているため、実際の Azure provider の利用方法などは記載していません。

手順

Azure App を登録する

Azure ポータルからアプリケーションを登録します。
https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade

Name に適当な名前を設定します。
Supported account typesAccounts in this organizational directory only (XXX only - Single tenant) を選択します。

作成後 Overview 画面から Application (client) ID / Directory (tenant) ID をコピーしておきます。

Azure App に OIDC の設定を行う

まずは Atlantis を稼働している GKE から OIDC 用の情報を集めます。
GKE クラスタの ODIC 用の Issure URL は以下の情報から構成されます。

https://container.googleapis.com/v1/projects/< GCP プロジェクト名 >/locations/< GKE クラスタが稼働しているリージョン or ゾーン >/clusters/< GKE クラスタ名 >

先ほど作成した Azure App の詳細画面に戻ります。

Client credentialsAdd a certificate or secret から OIDC 用の情報を登録します。
項目をそれぞれ入力していきます。

Federated credentials タブから Add credential をクリックします。
フォームに以下の情報を記載します。

  • Federated credential scenario : Kubernetes accessing Azure resources
  • Cluster issuer URL : GKE クラスタの OIDC 用の Issuer URL
  • Namespace : Atlantis が稼働している GKE Namespace
  • Service account name : Atlantis が利用している GKE ServiceAccount
  • Audience : GKE クラスタの OIDC 用の Issuer URL

Atlantis で利用する Azure provider の設定を行う

今回は以下の provider を利用します。
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs

Provider 用環境変数

まずは provider に必要な以下の環境変数を Azure ポータルからコピーします。
ARM_CLIENT_ID / ARM_SUBSCRIPTION_ID / ARM_TENANT_ID

OIDC 用環境変数

GKE 上で稼働している Pod が利用している ServiceAccount 用のトークンのファイルパスを以下の環境変数を用いて設定します。
ARM_OIDC_TOKEN_FILE_PATH

この環境変数に設定するファイルパスには一工夫する必要があります。

デフォルトでは GKE は /var/run/secrets/kubernetes.io/serviceaccount/token に ServiceAccount 用のトークンが格納されています。
しかし Azure へ OIDC 認証する場合にはこちらのトークンは利用できません。
Azure への OIDC 認証する際のトークンは有効期限が 1 日以下のものを利用する必要があります。
GKE がデフォルトで発行する ServiceAccount 用のトークンは有効期限が 1 年に設定されているため以下のようなエラーとなります。

External OIDC Provider token must have a lifetime of less than or equal to 1.01:00:00.

そのため、デフォルトで発行されるトークンとは別に有効期限が短く設定されるトークンを利用します。

以下のように projected volume を利用することで ServiceAccount 用のトークンに有効期限を設定しながらボリュームマウントできます。
以下の例では 50 分の有効期限を持ったトークンを azure-token という名前で volume を作成しています。

volumes:
- name: azure-token
  projected:
    defaultMode: 420
    sources:
    - serviceAccountToken:
        expirationSeconds: 3000
        path: token

上記で作成した volume を volumeMounts で Pod にマウントします。

volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/azure-token
  name: azure-token

ARM_OIDC_TOKEN_FILE_PATH にはここでマウントしたパスを設定します。
上記の場合は /var/run/secrets/kubernetes.io/azure-token/token を設定します。

以上の設定することで GKE 上で稼働している Atlantis から OIDC 認証を用いて Azure へアクセスできます。

Discussion