はじめに
GoogleCloudにはWebに公開されているサービスへのアクセスを、RBACを元に制限するIdentity-Aware Proxyという機能があります。この機能は当然GKE上で動作するサービスにも対応しているのですが、設定の方法がingressを使って公開しているか、gatewayを使って公開しているかで微妙に異なります。
GoogleCloudの公式ドキュメント上に「GatewayをIAPで保護する」みたいなドンピシャの項目があるわけでなく、Gatewayの設定に関する汎用的な記事の中にまとめられている上に、IAPの設定に関するKubernetes上のリソース名が非常にわかりにくく(というかingressで設定するときのリソースとごっちゃにしやすい)、やや混乱したためまとめておきます。
結論から言えばドキュメント通りにやっただけなんですが、ドキュメントの書き方も相当にわかりにくく、一読して全て理解できるものでもないため、後日の自分のためにもまとめておきました。また、特定のパスへのアクセスのみIAPを有効にする方法もまとめます。
0. OAuth同意画面を作成する
IAPによるWebサービスへの保護を有効化する前に、OAuth同意画面を作成する必要があります。以下の画面にアクセスし、諸々の設定を行います。
また、各項目の詳細は以下のページから確認できます。
後でいくらでも変更可能なので、ひとまず必須の項目(アプリ名や連絡先)だけ埋めて作成します。このとき、ユーザの種類を「内部」にするか「外部」にするかだけは考えておいた方がいいです。「内部」にすると自分の組織内のユーザのみがアクセスできるようになります。「外部」にするとGoogleアカウントを有する全てのユーザがアクセスできるようになります。
より正確には、「アクセスできるようにすることができる」と言ったところです。明示的に許可されていないユーザは内部だろうが外部だろうがアクセスできません。
1. GKE上に必要なリソースをデプロイする
GKE上にアプリケーションのdeploymentリソース、Gatewayリソース、およびHTTPRouteリソースをデプロイし、インターネットからアクセス可能にします。このとき、HTTPRouteリソースの.spec.rules
に登録されたbackendごとにIAPの有効・無効を切り替えることができるようになります。なので、特定のパスだけIAPを有効にしたい、あるいは無効にしたい場合は、そのパスに対して個別のruleを作成する必要があります。
例えば/api
以下へのアクセスのみIAPを有効・無効にしたい場合は以下のようなHTTPRouteリソースを作成する必要があります。
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: gateway-sample-route
spec:
parentRefs:
- kind: Gateway
name: gateway-sample
hostnames:
- "example.net"
rules:
- matches:
- path:
value: /
backendRefs:
- name: frontend
port: 80
- matches: #/apiへのアクセスはこちらに流れる
- path:
value: /api
backendRefs:
- name: backend
port: 80
2. GoogleCloud上でIAPを有効化する
次にGoogleCloud側でIAPの設定を行います。基本的には、以下のページの指示に従いながら作業を進めることになります。
ここで注意するべき点として、「IAPアクセス権の設定」という項目の次に「BackendConfigの構成」という項目があるのですが、この項目を実施しないでください。GKE上でIAPを有効にする場合の必須項目かのようにも見えますが、この項目はingressでサービスを公開する場合の手順です。この項目を実施してもGatewayを使用する場合は無益なほか、不要なsecretリソースが作成されてしまいます(Gatewayを使用する場合もsecretリソースが必要なのですが、必要な項目が異なります)。
スクリーンショット付きで具体的な手順を見ていきます。
1.Identity-Aware Proxyのページで、対象のサービスの「IAP」トグルスイッチをONにする
2. 同ページで、対象のサービスをクリックすると右側にメニューが開くので、「プリンシパルを追加」をクリックし、対象のユーザやグループに「IAP-secured Web App User」を付与する
3. 同ページで、対象サービスの右側にある三点メニューボタンから「OAuth構成に移動」をクリック(右方向にスクロールする必要がある場合があります)
4. 移動先ページの右側の「クライアントID」と「クライアントシークレット」をコピーして手元に保存する
3. Gatewayを設定しIAPを有効化する
次にGatewayを設定し、アプリケーションへのアクセスをIAPで保護していきます。基本的にはこのページに従って操作します。
まず先ほど作成したクライアントシークレットをもとに、sercretリソースを作成します。
echo -n CLIENT_SECRET > iap-secret.txt
kubectl create secret generic SECRET_NAME --from-file=key=iap-secret.txt
このコマンドを実行するとSECRET_NAME
という名前のsecretリソースが作成されます。secretリソース自体の名前は任意に変更してください。
このsecretはiap-secret.txt
というkeyでクライアントシークレットを保存しています。キー名がどうあるべきか、公式ドキュメント上に指定がない(というか公式に従うとこのキー名で作成される)ので正直よくわからないのですが、少なくともこのキー名で動作することが確認できています。
次に、GCPBackendPolicyリソースを作成してIAPを有効にします。GCPBackendPolicyリソースのサンプルは以下のとおりです。
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
name: gateway-sample-httpbin-policy
spec:
default:
iap:
enabled: true
oauth2ClientSecret:
name: SECRET_NAME
clientID: CLIENT_ID
targetRef:
group: ""
kind: Service
name: backend
上記のサンプルのうち、CLIENT_IDは先ほど保存したクライアントIDに置き換えて使用します。また、SECRET_NAMEも先ほど作成したクライアントシークレットを含むsecretリソース名に置き換えます。
上記のリソースをデプロイすると、targetRef
に指定したリソースにトラフィックがルーティングされた場合、IAPを使用したアクセス制限が有効になります。本記事の例だと、先のHTTPRouteリソースで/api
へのアクセスはbackend
serviceへルーティングするよう設定しましたので、/api
へのアクセスがあった場合に認証が要求されます。
実際に/api
にアクセスすると以下のような画面が表示され、googleへのログインが要求されます。もしログイン済みでアクセス権が付与されている場合、アクセスを継続するか質問されます。
(「Spinnaker」に移動と表示されているのは、一番最初のOAuth同意画面の作成時にSpinnakerという名前で構成したためです)
もしアクセス権がないユーザーがアクセスした場合は、403エラーが表示されます。
まとめ
GoogleCloudには、インターネットに公開したアプリケーションへのアクセスを制限するIdentity-Aware Proxyという機能があり、GKEにも適用することができます。
しかし、適用に必要な手順がIngressを使用するかGatewayを使用するかで異なっているほか、設定手順の資料が散在しており、一貫して説明した資料が存在しません。
このため、本記事ではGatewayリソースを使用してIAPを有効化する手順についてまとめました。GoogleCloud上でIAPを有効化したのち、GCPBackendPolicyリソースでGatewayの動作を設定することで、IAPを有効にすることができます。また、その際特定のバックエンドへのアクセスのみIAPを有効化することができます。