GKEのIngressでIdentity-Aware Proxy(IAP)を有効化する

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では GKE の Ingress リソースとして作成したロードバランサで Identity-Aware Proxy を有効化する方法を解説します。

当記事の概要

当記事では、GKE クラスタに Ingress リソースとして作成したアプリケーションロードバランサで Identity-Aware Proxy (以下、IAP)を有効化する手順を解説します。

IAP は、Web アプリケーションや仮想マシンなどのクラウドリソースに対して、アプリケーションレベルの認証機能を提供するサービスです。

IAP を用いることで、Web アプリケーションや仮想マシンにアクセスできるユーザーを、特定の IAM ロール がアタッチされた Google アカウント / グループ に制限することができます。

Ingress で IAP を使用することにより、バックエンドの Pod 上で動作するアプリケーションにアクセスする際に、IAM による認証を必須にすることができます。

IngressでIAPを有効化する

Kubernetes および GKE については、以下の記事で解説しています。

blog.g-gen.co.jp

blog.g-gen.co.jp

また、当記事に関連して、以下の記事では Ingress リソースとして作成したアプリケーションロードバランサで Cloud Armor を使用する方法について解説しています。
GKE 上で展開するウェブアプリケーションに接続元 IP アドレス制限などをかけたい場合は、こちらもご一読ください。

blog.g-gen.co.jp

GKE クラスタにサンプルアプリケーションをデプロイ

GKE クラスタの作成

当記事では Autopilot モードの GKE クラスタを使用します。

使用するクラスタのコントロールプレーンおよびノードのバージョンは以下のようになっています。

MASTER_VERSION: 1.27.8-gke.1067004 
NODE_VERSION: 1.27.8-gke.1067004

GKE クラスタの作成方法については 公式ドキュメント、または Terraform を使用した以下の記事を参照してください。

blog.g-gen.co.jp

Deployment リソースの作成

以下のマニフェストファイルを GKE クラスタに適用し、Deployment リソースを作成します。
この Deployment により、Google Cloud が公開しているサンプルアプリケーションのコンテナイメージを使用する Pod が作成されます。

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloweb
  labels:
    app: hello
spec:
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 200m
  

Google マネージド証明書の作成

静的外部 IP アドレスの作成

Ingress リソースとして作成される外部アプリケーションロードバランサに紐付ける、静的外部 IP アドレスを作成します。

# 静的外部 IP アドレスを作成する
$ gcloud compute addresses create helloweb-ip --global

DNS レコードの作成

利用可能なドメインと、さきほど作成した IP アドレスを使用して A レコードを登録します。

当記事では Cloud DNS を使用します。
Cloud DNS では、以下のように CLI でレコードを登録することができます。

# トランザクションの開始
$ gcloud dns record-sets transaction start --zone={DNS ゾーン名}
  
# A レコードを作成
$ gcloud dns record-sets transaction add {作成した IP アドレス} \
    --name={使用するドメイン} \
    --ttl=300 \
    --type=A \
    --zone={DNS ゾーン名}
  
# トランザクションの終了
$ gcloud dns record-sets transaction execute --zone={DNS ゾーン名}

ManagedCertificate リソースの作成

以下のマニフェストファイルを使用して、GKE の ManagedCertificate リソースとして Google マネージド SSL 証明書を作成します。
spec.domains には A レコードに設定したドメイン名を記述します。

# cert.yaml
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: hello-managed-cert
spec:
  domains:
  - {使用するドメイン}  # Aレコードで使用したドメイン
  

証明書の検証には20分ほどかかるため、検証待ちの間に以降の手順を実施します。

アプリケーションの公開

Ingress リソースの作成

IAP 有効化前後の動作の比較をするため、まずは IAP を有効化していない状態でロードバランサを作成し、IAM 認証なしでアプリケーションを公開します。

Ingress リソースとして、ここまでの手順で作成した静的外部 IP アドレス、Google マネージド証明書(ManagedCertificate リソース)を使用するアプリケーションロードバランサを作成します。
以下のマニフェストファイルを GKE クラスタに適用します。

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: helloweb
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: helloweb-ip  # 作成した静的外部 IP アドレスの名前
    networking.gke.io/managed-certificates: hello-managed-cert   # 作成した ManagedCertificate リソースの名前
  labels:
    app: hello
spec:
  defaultBackend:
    service:
      name: helloweb-backend
      port:
        number: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: helloweb-backend
  labels:
    app: hello
spec:
  type: NodePort
  selector:
    app: hello
  ports:
  - port: 8080
    targetPort: 8080
  

なお、kubectl apply で上記マニフェストファイルを適用すると、以下のような Warning メッセージが表示されます。

$ kubectl apply -f manifests/ingress.yaml 
Warning: annotation "kubernetes.io/ingress.class" is deprecated, please use 'spec.ingressClassName' instead
ingress.networking.k8s.io/helloweb created
service/helloweb-backend created

これは、2024年3月現在、Ingress の作成時にアノテーションとして kubernetes.io/ingress.class を使用するのが Kubernetes では非推奨になっているためです。
Kubernetes では非推奨になっているものの、GKE では引き続きこのアノテーションを使用して Ingress を作成します(参考)。

ブラウザからアプリケーションにアクセス

前の手順で作成した ManagedCertificate リソースの STATUS が ACTIVE になっていることを確認します。

$ kubectl get managedcertificates -w
NAME                 AGE    STATUS
hello-managed-cert   6m6s   Provisioning
hello-managed-cert   16m    Active

DNS に設定したドメイン名を使用してブラウザからアクセスすると、以下のようなサンプルアプリケーションの画面が表示されます。

GKE上のアプリケーションにアクセスする

OAuth 認証情報を格納する Secret リソースの作成

OAuth 同意画面の構成

プロジェクトで OAuth 同意画面 をまだ構成していない場合は、設定を行います。
手順はこちらのブログ記事の「OAuth 同意画面の設定」を参照してください。

OAuth 2.0 クライアント ID とシークレットの発行

Google Cloud コンソールの「API とサービス」から、OAuth 2.0 クライアント ID を作成していきます。

「OAuth クライアント ID」を選択する

以下の項目を入力し、「作成」を選択します。

項目
アプリケーションの種類 ウェブ アプリケーション
名前 任意の名前

「承認済みのリダイレクト URI」項目は後ほど設定するため、一旦は空欄のまま作成します。

OAuth クライアント ID を作成する

作成後、クライアント IDクライアント シークレット が表示されるので、この2つはメモしておきます。

クライアント ID とクライアント シークレットをメモしておく

作成したクライアント ID の編集画面を開き、「承認済みのリダイレクト URI」項目を設定します。
値には、先ほどメモしておいたクライアント ID を含む以下の URI を設定します(クライアント ID とシークレットの値は編集画面からも確認できます)。

「承認済みのリダイレクト URI」の設定値
https://iap.googleapis.com/v1/oauth/clientIds/{クライアント ID の値}:handleRedirect

「承認済みのリダイレクト URI」を設定する

Secret リソースの作成

OAuth 2.0 クライアント ID を作成したときにメモしておいたクライアント ID、クライアント シークレットの値を使用して、GKE クラスタに Secret リソースを作成します。

# Secret リソースを作成する
kubectl create secret generic iap-secret --from-literal=client_id={クライアント ID の値} \
    --from-literal=client_secret={クライアント シークレットの値}

IAP の有効化

BackendConfig リソースの作成

以下のマニフェストファイルを GKE クラスタに適用し、IAP 用の BackendConfig リソースを作成します。
spec.iap.oauthclientCredentials.secretName には、前の手順で作成した Secret リソースの名前を記述します。

# backendconfig.yaml
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: iap-backendconfig
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: iap-secret
  

Ingress リソースの更新

Ingress リソースのマニフェストファイルを更新し、先ほど作成した IAP 用の BackendConfig を紐付けます。

以下のように Service リソースに metadata.annotations.beta.cloud.google.com/backend-config を追記し、GKE クラスタに再適用します。

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: helloweb
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/ingress.global-static-ip-name: helloweb-ip
    networking.gke.io/managed-certificates: hello-managed-cert
  labels:
    app: hello
spec:
  defaultBackend:
    service:
      name: helloweb-backend
      port:
        number: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: helloweb-backend
  labels:
    app: hello
  annotations:  # この項目を追記
    beta.cloud.google.com/backend-config: '{"default": "iap-backendconfig"}'  # 作成した BackendConfig リソースの名前
spec:
  type: NodePort
  selector:
    app: hello
  ports:
  - port: 8080
    targetPort: 8080
  

IAP の動作確認

再度ブラウザからアプリケーションにアクセスし、以下のようなログイン画面が表示されれば、IAP による認証が有効化されています(有効化には少し時間がかかります)。

IAPのログイン画面

IAM で「IAP で保護されたウェブアプリ ユーザー(roles/iap.httpsResourceAccessor)」ロールが付与されたアカウントを使用することで、ログインすることができます。

参考手順

佐々木 駿太 (記事一覧)

G-gen最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。