このガイドでは、Identity-Aware Proxy(IAP)を Anthos Service Mesh と統合する方法について説明します。IAP を Anthos Service Mesh と統合すると、Google の BeyondCorp の原則に基づいて、サービスに安全にアクセスできるようになります。IAP は、ユーザー ID とリクエストのコンテキストを確認し、ユーザーにアプリケーションまたはリソースへのアクセスを許可するかどうかを決定します。IAP を Anthos Service Mesh と統合すると、次のメリットがあります。
Anthos Service Mesh で実行されるワークロードに対するコンテキストアウェア アクセスの制御。発信元リクエストの属性(ユーザー ID、IP アドレス、デバイスの種類など)に基づいて、きめ細かいアクセス ポリシーを設定できます。リクエスト URL のホスト名とパスに基づいて、アクセス ポリシーと制限を組み合わせることができます。
Anthos Service Mesh 認証におけるコンテキストアウェア クレームのサポート。
Google Cloud ロードバランサを介したアプリケーションに対する、スケーラブルで安全かつ可用性の高いアクセス。高パフォーマンスの負荷分散では、組み込みの保護機能で分散型サービス拒否(DDoS)攻撃を防ぎ、グローバルなエニーキャスト IP アドレスを使用できます。
前提事項
このガイドでは、次の準備ができていることを前提としています。
Anthos Service Mesh によるクラスタの設定
IAP の統合には、プロジェクト、クラスタ、Anthos Service Mesh のインストール時に使用する構成ファイルに関する特定の設定が必要です。
新規インストール
このセクションの手順は、GKE での高度なインストールガイドの手順を補完するものです。これらの手順では、インストール ガイドで作成した環境変数を使用します。
プロジェクトを設定するときに、必要な他の API に加えて
iap.googleapis.com
も有効にします。gcloud services enable \ --project=PROJECT_ID \ iap.googleapis.com
クラスタを更新するときに、クラスタに必要な他の更新に加えて、
HttpLoadBalancing
アドオンも有効にします。HttpLoadBalancing
アドオンを使用すると、クラスタの HTTP(L7)負荷分散コントローラが有効になります。gcloud container clusters update ${CLUSTER_NAME} \ --project=PROJECT_ID \ --update-addons=HttpLoadBalancing=ENABLED
デフォルトのゾーンまたはリージョンを設定しなかった場合、前のコマンドでリージョン(--region=${CLUSTER_LOCATION})またはゾーン(--zone=${CLUSTER_LOCATION})を指定する必要があります。
クラスタを更新したら、インストール ガイドに沿って、認証情報と権限を設定し、インストール ファイルをダウンロードします。リソース構成ファイルの準備のところで作業を止めて、次の操作を行います。
Anthos Service Mesh パッケージのリソース構成ファイル用に新しいディレクトリを作成します。クラスタ名をディレクトリ名として使用することをおすすめします。
Anthos Service Mesh パッケージをダウンロードするディレクトリに変更します。
asm-iap
パッケージをダウンロードします。このパッケージは、istio-ingressgateway
サービスのtype
フィールドをNodePort
に設定します。この構成では、istio-ingressgateway
はサービス メッシュで特定のポートを開きます。また、ドメイン名に送信されたトラフィックがこのポートに転送されるようにロードバランサを設定できます。kpt pkg get https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm-iap@release-1.6-asm asm
クラスタが作成されたプロジェクトのプロジェクト ID を設定します。
kpt cfg set asm gcloud.core.project PROJECT_ID
フリート ホスト プロジェクトのプロジェクト番号を設定します。
kpt cfg set asm gcloud.project.environProjectNumber ${FLEET_PROJECT_NUMBER}
クラスタ名を設定します。
kpt cfg set asm gcloud.container.cluster ${CLUSTER_NAME}
デフォルトのゾーンまたはリージョンを設定します。
kpt cfg set asm gcloud.compute.location ${CLUSTER_LOCATION}
リビジョン ラベルを使用するように Webhook の検証を設定します。
kpt cfg set asm anthos.servicemesh.rev asm-1614-2
構成プロファイルを設定します。IAP 統合では、
asm-gcp
プロファイルを設定します。kpt cfg set asm anthos.servicemesh.profile asm-gcp
ロードバランサの HTTP とステータス ポートを設定します。デフォルトのステータス ポートは 31223、デフォルトの HTTP ポートは 31224 です。これらのポートがすでに使用されている場合は、以下のポートを設定します。
kpt cfg set asm gcloud.container.cluster.ingress.httpPort HTTP_PORT
kpt cfg set asm gcloud.container.cluster.ingress.statusPort STATUS_PORT
kpt
セッターの値を出力します。kpt cfg list-setters asm
コマンドの出力で、次のセッターの値が正しいことを確認します。
- anthos.servicemesh.rev
- gcloud.compute.location
- gcloud.container.cluster
- gcloud.container.cluster.ingress.httpPort
- gcloud.container.cluster.ingress.statusPort
- gcloud.core.project
- gcloud.project.environProjectNumber
Anthos Service Mesh のインストール セクションのインストール ガイドに進みます。Anthos Service Mesh のインストール後、このガイドに戻り、次のセクションに進んで IAP との統合を設定します。
アップグレード
このセクションの手順は、GKE での Anthos Service Mesh のアップグレードの手順を補完するものです。これらの手順では、アップグレード ガイドで作成した環境変数を使用します。このセクションでは、次のアップグレードのユースケースについて説明します。
IAP 統合はすでにセットアップ済みで、Anthos Service Mesh をアップグレードする。この例では、プロジェクトで
iap.googleapis.com
が、クラスタでHttpLoadBalancing
アドオンがすでに有効になっているため、ステップ 3 までスキップできます。Anthos Service Mesh をアップグレードし、初めて IAP との統合を設定する。この場合、以下の手順をすべて完了し、Anthos Service Mesh をアップグレードします。アップグレードが完了したらこのガイドに戻り、統合を完了します。
iap.googleapis.com
を有効にします。gcloud services enable \ --project=$PROJECT_ID \ iap.googleapis.com
HttpLoadBalancing
アドオンを有効にします。HttpLoadBalancing
アドオンを使用すると、クラスタの HTTP(L7)負荷分散コントローラが有効になります。gcloud container clusters update ${CLUSTER_NAME} \ --project=PROJECT_ID \ --update-addons=HttpLoadBalancing=ENABLED
デフォルトのゾーンまたはリージョンを設定しなかった場合、前のコマンドでリージョン(--region=${CLUSTER_LOCATION})またはゾーン(--zone=${CLUSTER_LOCATION})を指定する必要があります。
アップグレード ガイドに沿って、認証情報と権限を設定し、インストール ファイルをダウンロードしてください。リソース構成ファイルの準備のところで作業を止めて、次の操作を行います。
Anthos Service Mesh パッケージのリソース構成ファイル用に新しいディレクトリを作成します。クラスタ名をディレクトリ名として使用することをおすすめします。
Anthos Service Mesh パッケージをダウンロードするディレクトリに変更します。
asm-iap
パッケージをダウンロードします。このパッケージは、istio-ingressgateway
サービスのtype
フィールドをNodePort
に設定します。この構成では、istio-ingressgateway
はサービス メッシュで特定のポートを開きます。また、ドメイン名に送信されたトラフィックがこのポートに転送されるようにロードバランサを設定できます。kpt pkg get https://github.com/GoogleCloudPlatform/anthos-service-mesh-packages.git/asm-iap@release-1.6-asm asm
クラスタが作成されたプロジェクトのプロジェクト ID を設定します。
kpt cfg set asm gcloud.core.project PROJECT_ID
フリート ホスト プロジェクトのプロジェクト番号を設定します。
kpt cfg set asm gcloud.project.environProjectNumber ${FLEET_PROJECT_NUMBER}
クラスタ名を設定します。
kpt cfg set asm gcloud.container.cluster ${CLUSTER_NAME}
デフォルトのゾーンまたはリージョンを設定します。
kpt cfg set asm gcloud.compute.location ${CLUSTER_LOCATION}
リビジョン ラベルを使用するように Webhook の検証を設定します。
kpt cfg set asm anthos.servicemesh.rev asm-1614-2
構成プロファイルを設定します。IAP 統合では、
asm-gcp
プロファイルを設定します。kpt cfg set asm anthos.servicemesh.profile asm-gcp
ロードバランサの HTTP とステータス ポートを設定します。デフォルトのステータス ポートは 31223、デフォルトの HTTP ポートは 31224 です。
既存の HTTP Cloud ロードバランサを更新する場合は、次のコマンドを実行して既存の HTTP ポートとステータス ポートを保持してください。
kpt cfg set asm gcloud.container.cluster.ingress.httpPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
kpt cfg set asm gcloud.container.cluster.ingress.statusPort $(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')
必要に応じて、上記の
kpt
セッターを使用して、ポートの他の値を設定できます。kpt
セッターの値を出力します。kpt cfg list-setters asm
コマンドの出力で、次のセッターの値が正しいことを確認します。
- anthos.servicemesh.rev
- gcloud.compute.location
- gcloud.container.cluster
- gcloud.container.cluster.ingress.httpPort
- gcloud.container.cluster.ingress.statusPort
- gcloud.core.project
- gcloud.project.environProjectNumber
Anthos Service Mesh のアップグレード セクションのアップグレード ガイドをご覧ください。
静的 IP アドレスの予約と DNS の構成
Identity-Aware Proxy を Anthos Service Mesh と統合するには、Google Cloud HTTP(S) ロードバランサを設定する必要があります。この設定では、静的 IP アドレスを参照するドメイン名が必要です。静的外部 IP アドレスを予約すると、明示的に解放するまで、このアドレスを無期限でプロジェクトに割り当てることができます。
静的外部 IP アドレスを予約します。
gcloud compute addresses create example-static-ip --global
静的 IP アドレスを取得します。
gcloud compute addresses describe example-static-ip --global
ドメイン名登録事業者で、静的 IP アドレスを含む完全修飾ドメイン名(FQDN)を構成します。通常、DNS 設定に
A
レコードを追加します。FQDN のA
レコードを追加する構成手順と用語は、使用するドメイン名登録事業者によって異なります。DNS 設定が反映されるまでに、24~48 時間かかります。このガイドに従って引き続き設定を行うことはできますが、DNS 設定が反映されるまで設定のテストはできません。
サンプル アプリケーションのデプロイ
IAP を有効にする前に、GKE クラスタでアプリケーションを実行して、すべてのリクエストに ID があることを確認する必要があります。このガイドでは、Bookinfo サンプルを使用して、HTTP(S) ロードバランサを設定して IAP を有効にします。
Bookinfo をデプロイします。ロードバランサをデプロイするまで、Bookinfo アプリケーションは GKE クラスタの外部(ブラウザなど)からアクセスできません。
外部リクエスト
Bookinfo のゲートウェイ リソース(samples/bookinfo/networking/bookinfo-gateway.yaml
で定義)は、事前構成の istio-ingressgateway
を使用します。Anthos Service Mesh をデプロイするときに、istio-ingressgateway
に NodePort
を指定しました。これにより、サービス メッシュで特定のポートが開きます。クラスタ内のノードには外部 IP アドレスが設定されていますが、クラスタの外部からのリクエストは Google Cloud ファイアウォール ルールによってブロックされます。IAP を使用すると、ロードバランサを使用してアプリケーションを公共のインターネットに公開できます。IAP をバイパスするファイアウォール ルールを使用してノードアドレスを公開しないでください。
Bookinfo にリクエストをルーティングするには、Google Cloud プロジェクトに HTTP(S) ロードバランサを設定します。ロードバランサはプロジェクト内にあります。これはファイアウォールの内側にあるため、クラスタ内のノードにアクセスできます。静的 IP アドレスとドメイン名を使用してロードバランサを構成すると、ドメイン名にリクエストを送信できるようになります。ロードバランサは、これらのリクエストをクラスタ内のノードに転送します。
IAP の有効化
IAP を有効にする手順は以下のとおりです。
同意画面の構成
list コマンドを使用して、既存のブランドがあるかどうかを確認します。1 つのプロジェクトで使用できるブランドは 1 つだけです。
gcloud iap oauth-brands list
ブランドがある場合の gcloud のレスポンスは次のとおりです。
name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID] applicationTitle: [APPLICATION_TITLE] supportEmail: [SUPPORT_EMAIL] orgInternalOnly: true
ブランドが存在しない場合は、create コマンドを使用します。
gcloud iap oauth-brands create --application_title=APPLICATION_TITLE --support_email=SUPPORT_EMAIL
上記のフィールドは、この API を呼び出すときに必要になります。
supportEmail
: OAuth 同意画面に表示されるサポートメール。このメールアドレスは、ユーザーのアドレスでも、Google グループのエイリアスでもかまいません。サービス アカウントにもメールアドレスがありますが、これは実際のメールアドレスではないため、ブランドの作成には使用できません。ただし、サービス アカウントは Google グループのオーナーに設定できます。新しい Google グループを作成するか、既存のグループを構成し、目的のサービス アカウントをそのグループのオーナーに設定します。applicationTitle
: OAuth 同意画面に表示されるアプリケーション名。
レスポンスには、次のフィールドが含まれます。
name: projects/[PROJECT_NUMBER]/brands/[BRAND_ID] applicationTitle: [APPLICATION_TITLE] supportEmail: [SUPPORT_EMAIL] orgInternalOnly: true
IAP OAuth クライアントの作成
create コマンドを使用してクライアントを作成します。前のステップのブランド
name
を使用します。gcloud iap oauth-clients create projects/PROJECT_NUMBER/brands/BRAND-ID --display_name=NAME
レスポンスには、次のフィールドが含まれます。
name: projects/[PROJECT_NUMBER]/brands/[BRAND_NAME]/identityAwareProxyClients/[CLIENT_ID] secret: [CLIENT_SECRET] displayName: [NAME]
クライアント ID(上記の手順では
CLIENT_ID
)とCLIENT_SECRET
を使用して IAP を有効にします。OAuth クライアントのマテリアルを使用して Kubernetes Secret を作成します。kubectl create secret generic -n istio-system my-secret --from-literal=client_id=CLIENT_ID \ --from-literal=client_secret=CLIENT_SECRET
ロードバランサのデプロイ
Ingress リソースを使用すると、自動構成の SSL 証明書で HTTP(S) ロードバランサを作成できます。Google マネージド SSL 証明書はドメインに対してプロビジョニング、更新、管理が行われます。
ManagedCertificate リソースを作成します。このリソースは、SSL 証明書のドメインを指定します。
spec.domains
リストに複数のドメインを入れることはできません。ワイルドカード ドメインはサポートされていません。次の YAML で、DOMAIN_NAME
を外部静的 IP アドレス用に構成したドメイン名に置き換えます。cat <<EOF | kubectl apply -f - apiVersion: networking.gke.io/v1beta1 kind: ManagedCertificate metadata: name: example-certificate namespace: istio-system spec: domains: - DOMAIN_NAME EOF
BackendConfig リソースを作成します。このリソースは、Ingress Gateway でヘルスチェックを実行する方法と Identity-Aware Proxy の構成方法を GCLB に指示します。まず、Ingress Gateway からヘルスチェックに関するいくつかの値を収集します。
ヘルスチェックの Ingress ポート: istio-ingress のヘルスチェック ポート。
export HC_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="status-port")].nodePort}')
ヘルスチェック Ingress パス: istio-ingress のヘルスチェック パス。
export HC_INGRESS_PATH=$(kubectl -n istio-system get deployments istio-ingressgateway -o jsonpath='{.spec.template.spec.containers[?(@.name=="istio-proxy")].readinessProbe.httpGet.path}')
cat <<EOF | kubectl apply -n istio-system -f - apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: http-hc-config spec: healthCheck: checkIntervalSec: 2 timeoutSec: 1 healthyThreshold: 1 unhealthyThreshold: 10 port: ${HC_INGRESS_PORT} type: HTTP requestPath: ${HC_INGRESS_PATH} iap: enabled: true oauthclientCredentials: secretName: my-secret EOF
Ingress サービスに BackendConfig のアノテーションを付けます。
kubectl annotate -n istio-system service/istio-ingressgateway --overwrite \ cloud.google.com/backend-config='{"default": "http-hc-config"}' \ cloud.google.com/neg='{"ingress":false}'
ロードバランサを作成するには、Ingress リソースを定義します。
前の手順で作成した証明書の名前
example-certificate
をnetworking.gke.io/managed-certificates
アノテーションに設定します。予約した静的 IP アドレスの名前
example-static-ip
をkubernetes.io/ingress.global-static-ip-name
アノテーションに設定します。serviceName
をistio-ingressgateway
に設定します。これは、Bookinfo サンプルのゲートウェイ リソースで使用されます。
cat <<EOF | kubectl create -f - apiVersion: extensions/v1beta1 kind: Ingress metadata: name: example-ingress namespace: istio-system annotations: kubernetes.io/ingress.global-static-ip-name: example-static-ip networking.gke.io/managed-certificates: example-certificate spec: backend: serviceName: istio-ingressgateway servicePort: 80 EOF
Google Cloud コンソールで、[Kubernetes Engine] > [Services と Ingress] ページに移動します。
[ステータス] 列に「Creating Ingress」と表示されます。GKE に Ingress が完全にプロビジョニングされてから次に進みます。数分ごとにページを更新し、Ingress の最新ステータスを確認します。Ingress がプロビジョニングされると、「OK」ステータスが表示されるか、「All backend services are in UNHEALTHY state.」というエラーが表示されます。デフォルトのヘルスチェックでは、GKE がプロビジョニングするリソースの 1 つが対象になります。エラー メッセージが表示された場合、Ingress がプロビジョニングされ、デフォルトのヘルスチェックが実行されています。「OK」ステータスまたはエラーが表示されている場合は、次のセクションでロードバランサのヘルスチェックを構成します。
IAP アクセスリストを構成する
IAP のアクセス ポリシーにユーザーを追加するには:
gcloud beta iap web add-iam-policy-binding \ --member=user:EMAIL_ADDRESS \ --role=roles/iap.httpsResourceAccessor
EMAIL_ADDRESS
は、ユーザーの完全なメールアドレスです(例: alice@example.com
)。
ロードバランサをテストします。ブラウザで次の URL にアクセスします。
http://DOMAIN_NAME/productpage
ここで、
DOMAIN_NAME
は、外部静的 IP アドレスで構成したドメイン名です。Bookinfo アプリケーションの
productpage
が表示されます。ページを複数回更新すると、さまざまなバージョンのビューがラウンドロビン スタイル(赤い星、黒い星、星なし)で表示されます。Bookinfo への
https
アクセスもテストする必要があります。
サービス メッシュで RCToken サポートを有効にする
デフォルトでは、IAP は OAuth クライアントをスコープとする JSON Web Token(JWT)を生成します。Anthos Service Mesh では、RequestContextToken(RCToken)を生成するように IAP を構成できます。これは、JWT ですが、オーディエンスは構成可能です。RCToken を使用すると、JWT のオーディエンスに任意の文字列を構成できます。これを Anthos Service Mesh ポリシーで使用し、きめ細かい認証を実施できます。
RCToken を構成するには:
プロジェクト番号の環境変数を作成します。これは、プロジェクトの作成時に自動的に生成され、割り当てられた番号です(プロジェクト ID とは異なります)。
export PROJECT_NUMBER=YOUR_PROJECT_NUMBER
RCToken オーディエンスの環境変数を作成します。任意の文字列を指定できます。
export RCTOKEN_AUD="your-rctoken-aud"
既存の IAP 設定を取得します。
gcloud beta iap settings get --format json \ --project=${PROJECT_NUMBER} --resource-type=compute > iapSettings.json
RCToken オーディエンスで
IapSettings
を更新します。cat iapSettings.json | jq --arg RCTOKEN_AUD_STR $RCTOKEN_AUD \ '. + {applicationSettings: {csmSettings: {rctokenAud: $RCTOKEN_AUD_STR}}}' \ > updatedIapSettings.json
gcloud beta iap settings set updatedIapSettings.json --format json \ --project=${PROJECT_NUMBER} --resource-type=compute
Istio Ingress ゲートウェイで RCToken 認証を有効にします。
cat <<EOF | kubectl apply -f - apiVersion: "security.istio.io/v1beta1" kind: "RequestAuthentication" metadata: name: "ingressgateway-jwt-policy" namespace: "istio-system" spec: selector: matchLabels: app: istio-ingressgateway jwtRules: - issuer: "https://cloud.google.com/iap" jwksUri: "https://www.gstatic.com/iap/verify/public_key-jwk" audiences: - $RCTOKEN_AUD fromHeaders: - name: ingress-authorization prefix: "Istio " outputPayloadToHeader: "verified-jwt" forwardOriginalToken: true EOF
Bookinfo
productpage
へのリクエストが成功していることを確認します。http://DOMAIN_NAME/productpage
ポリシーをテストするには:
IapSettings
リクエスト オブジェクトを作成します。ただし、rctokenAud
には別の文字列を設定します。echo $(cat <<EOF { "name": "projects/${PROJECT_NUMBER}/iap_web/compute", "applicationSettings": { "csmSettings": { "rctokenAud": "some-other-arbitrary-string" } } } EOF ) > request.txt
IapSettings
API を呼び出して、RCtoken オーディエンスを設定します。curl --request PATCH --header "Authorization: Bearer $(gcloud beta auth application-default print-access-token)" ${IAP_SETTINGS_API}
Bookinfo
productpage
にリクエストを送信すると失敗します。http://DOMAIN_NAME/productpage
クリーンアップ
このチュートリアルを完了したら、アカウントで不要な請求が発生しないように、以下のリソースを削除します。
マネージド証明書を削除します。
kubectl delete managedcertificates example-certificate
Ingress を削除します。これにより、負荷分散リソースの割り当てが解除されます。
kubectl -n istio-system delete ingress example-ingress
静的 IP アドレスを削除します。
gcloud compute addresses delete example-static-ip --global
これを行う場合は、ドメイン登録事業者から IP アドレスを削除してください。
クラスタを削除します。これにより、クラスタを構成するリソース(コンピューティング インスタンス、ディスク、ネットワーク リソースなど)が削除されます。
gcloud container clusters delete ${CLUSTER_NAME}