1
0

More than 1 year has passed since last update.

GKEにデプロイしたアプリケーションをIAP(Identity-Aware Proxy)で保護するまで

Last updated at Posted at 2021-10-06

はじめに

業務都合で、GKEにデプロイしたアプリケーションを、 Identity-Aware Proxy で保護(認証・認可)する方法を調べたので実際の環境構築方法をメモしてみました。

Identity-Aware Proxyとは

ざっくりいうと、Googleアカウントによる認証と、ユーザに対する認可を一度にやってくれる機能です。
例えば許可のないユーザには、以下のような画面を出してアクセスをブロックしてくれます。

image.png

ただ本来自分たちがやりたいことをどこまで実現できるのかは調査中でして、それは次の記事で調べていこうと思います。
まずは環境構築までを書いてみました。

IAPによりアプリケーションの認証・認可を行う場合の前提条件

GKEに対してIAPを適用するための手順が こちら になります。
まず確認すべきはここに書かれている前提条件。

  1. 課金が有効になっている Google Cloud Console プロジェクト
  2. HTTPS ロードバランサで処理される 1 つ以上の GKE インスタンスを含むグループ
  3. ロードバランサのアドレスに登録されたドメイン名
  4. すべてのリクエストに ID があることを確認するアプリコード

4は作りの問題なのですが、問題は3ですね。FQDNがないとだめです。
要はINGRESSのGlobal IPだけではだめなので、何かしらそこに対する名前解決を定義しておく必要があります。
私は お名前.com と Cloud DNSのあわせ技で解決しました。(これは今回の趣旨とは直結しないため、末尾に参考情報として書きます)

環境構築手順

サンプルアプリケーションの実装

何かしらのアプリケーションをGKEにデプロイしないといけないので、まずはサンプルのアプリケーションを作りました。
それが こちら
ほぼNuxt.jsのテンプレです。

このあたり で、起動ポートは 3333 に変更してあるのと、 npm run dev にも外部から接続可能なようHOSTを付与しています。

また、pages配下に site-a.vue , site-b.vue を作ってあります。
執筆時点では、これを使ってページごとに認可対象を分けることができるといいな・・・という希望的観測に基づくものです。さて出来るのやら。

イメージ化、Google Cloud RegistryへのPUSH

Dockerfileは こんな 感じ。
これでイメージをビルド。
イメージタグは gke-iap:0.1 としてあります。

docker build -t gke-iap:0.1 --no-cache .

ローカルで動作確認したければ以下。

docker run -it -p 3333:3333 gke-iap:0.1

これで動作確認OKだったらイメージをCloud RegistryにPUSHします。

// dockerコマンドにgoogle authを付与
gcloud auth configure-docker 

// Google Cloud Registryに挙げられるようにタグを付与
docker tag [自分とこのDocker Image ID] gcr.io/[自身のGCP Project]/gke-iap
docker push gcr.io/[自身のGCP Project]/gke-iap

これでGoogle Cloud RegistryにイメージがPUSHされます。
どうやら今どきはArtifact Registryを使うほうがいいんですね。
それで検証しようとも思ったんですが、今回の本質からそれるのでやめました。

クラスタ作ってServiceを公開する

GKEのクラスタを作ります。

image.png

実際には cluster-1 という名前で作ってます。特段細かな設定は不要です。
強いて言うならノード数とか1でいい。(節約)

その後はCloud Shell等で以下を実施していきます。

// 認証
gcloud config set project [自身のGCP Project]
gcloud config set compute/zone asia-northeast3-a
gcloud container clusters get-credentials cluster-1

// イメージのデプロイ
kubectl create deployment --image=gcr.io/[自身のGCP Project]/gke-iap gke-iap

// Serviceの公開
kubectl expose deployment gke-iap --type=LoadBalancer --name=gke-iap --port=3333 --target-port=3333


$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
gke-iap-545c4fa97f-9dw8x   1/1     Running   0          2m19s

$ kubectl get deployments
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
gke-iap   1/1     1            1           2m25s

$ kubectl get services
NAME         TYPE           CLUSTER-IP   EXTERNAL-IP        PORT(S)          AGE
gke-iap      LoadBalancer   10.36.5.44   [Serviceの公開IP]   3333:30560/TCP   95s
kubernetes   ClusterIP      10.36.0.1    <none>             443/TCP          49m

こんな感じでServiceが公開されたら次に移ります。

OAuth同意画面の作成

そもそもOAuth同意画面とは何か・・・については このあたり を見ると分かります。
認証時に表示される画面ですね。

ここ に従って進めれば大きく困ることは有りませんでした。

image.png

まずこの画面で「作成」をクリック。あとは流れで作れます。

  • アプリケーション名は gke-iap に
  • 文書の任意項目の中で、デベロッパーの連絡先に自分のメールアドレスを入力
  • あとは「保存して次へ」を繰り返した

OAuth認証情報の作成

基本的にこちら の流れに沿ってやればOKです。
何を入れるか一瞬悩んだり、入力欄どこ?となった画面だけエッセンスを書いておきます。

image.png

アプリケーションの種類と名前だけ入れて「作成」ボタンクリック。
名前は gke-iap とした。

image.png

作成するとこの画面が出るが、この時点でJSONのダウンロードは不要。(後でやるので)
クライアントIDだけコピーしておく。

image.png

[承認済みのリダイレクト URI] フィールドに次の形式でユニバーサル リダイレクト URL を追加します。

については、この画面の下の方の「承認済みのリダイレクトURL」ボタンをクリックしてから行う。

承認済みのリダイレクトURLは手順書によると以下。

https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect

ここにコピーしたCLIEND_IDを使う。

で、最後にJSONダウンロード。

INGRESSを作る

INGRESSとはなにか・・・ですが、GCP Consoleには以下のように説明が書かれています。

Ingress は、受信接続がクラスタ サービスに到達できるようにするルールの集まりです。

いまいちよくわからん表現ではあるので、 こちら を見るのが良いと思います。(自分もこれからちゃんと読もうとしてます)

今のところは、Serviceの前段で動作するロードバランサーくらいに思っておけば良いかなと思います。
区別しなくてはいけないのは、Deploymentをexposeするときに --type=LoadBalancer としたと思いますが、これとは関係ない別なLoadBalancerです。
実際に Cloud Loadbalancer を作りに行き、そのバックエンドにGKEのクラスタを指定することになります。

基本的な流れは こちら に従えばいいのですが、同じくポイントだけ書いていきます。

image.png

まずGKEの ServiceとIngress のページで、サービス タブの下に出ているサービス名のチェックボックスをONにし、画面上部の INGRESSを作成 をクリックします。

image.png

INGRESS作成STEP1では、 Ingressタイプ名前 を入れます。
タイプは外部ロードバランサを選択しておけばOKです。

画面左下の Host and path rules をクリックしてSTEP2に行きます。

image.png

デフォルトルールだけ入れます。
Hosts , Paths はそのままでいいので、一番右の選択肢だけ gke-iap を選択します。(画面は選択前のものですね)
こんな感じ。

image.png

STEP3に進みます。

STEP3は画面を取り忘れたのですが、フロントエンド構成にHTTPSを選びます。
IAP構成の前提にHTTPなロードバランサがないとダメと言っておきながら、作るのがここというのが非常に謎ですが、HTTPSにして下さい。

また、HTTPSにするとSSL証明書の指定が必要となりますので、Google Managedな証明書をこの画面から作ってしまいます。
ここで、このINGRESSに対して指定したいFQDNを入力します。
で、自分の場合はこの証明書完成(ACTIVE)までに色々悩みました。その話は後述。

image.png

STEP4はYAML確認なだけです。

image.png

apiVersion: "extensions/v1beta1"
kind: "Ingress"
metadata:
  name: "gke-iap-ingress"
  namespace: "default"
spec: {}

「CREATE」をクリックします。

で、作成が完了するとこうなります。

image.png

画面ではまだIPアドレスが確定していませんが、暫く待つとIPが確定します。
確定後、そのIPで疎通が可能かを確認してみて下さい。
ただしSSL証明書がACTIVEになるまでには時間がかかります。
以下のコマンドで確認しておくと良いです。

gcloud compute ssl-certificates list

NAME: mcrt-ae120651-4787-425b-a6d1-7b0c802e0163
TYPE: MANAGED
CREATION_TIMESTAMP: 2021-10-05T01:28:19.604-07:00
EXPIRE_TIME: 2022-01-02T23:28:21.000-08:00
MANAGED_STATUS: ACTIVE

iap.gcp.example.com: ACTIVE <-- ACTIVEになれば作成成功

ただし、当然この時点では誰であってもリーチが出来てしまいます。
そこでIAPが出てきます。

IAPの有効化

手順に従うと このような 画面になります。

image.png

ここで一覧にあるトグルをONに倒せば有効化されます。
ただその前に右ペインでアクセスを許可したいユーザーを指定しておけます。

「プリンシパルを追加」ボタンをクリックすると以下のような画面になります。

image.png

今回は自分の個人ユーザを追加していますが、公式手順に従うと以下のものが追加可能と書かれています。

また、今回ロールとしては、同じく公式に従い IAP-secured Web App User を選択していますが、これ以外のRoleだと何が起きるのかがよくわかっていないので要検証です。

これでIAPをonにします。

Backend Configの構成

公式手順を見ると、こうしろと書かれています。

kubectl create secret generic my-secret --from-literal=client_id=client_id_key \
--from-literal=client_secret=client_secret_key

でkeyは以前の認証情報作成でダウンロードしたJSONから引っ張ってくればいいようです。

my-secret という名前もなんかあれなので名前を変えて以下のようにしました。

kubectl create secret generic gke-iap-secret --from-literal=[CLIEND_ID] --from-literal=client_secret=[CLIEND_SECRET]

secret/gke-iap-secret created

次に「BackendConfigへのIAPブロックの追加」にかかれている手順に進みます。
kubectlにてyamlをapplyするしか無いっぽいのですかね。

手順書だと2つのyamlが出てきますが、これらをマージしてapplyせよということのようで、結局以下のようにすればいいのだと思います。
私は順番にapplyしていきましたが。(metadata > annotationsがない状態でapplyして、annotations足してapplyして・・・)
一括でいいのだと思うので、別途検証してみようと思います。

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: config-default
  namespace: default
  annotations:
    beta.cloud.google.com/backend-config: '{"default": "config-default"}'
spec:
  iap:
    enabled: true
    oauthclientCredentials:
      secretName: dke-iap-secret

これをbackendconfig.yamlとして保存し、

kubectl apply -f backendconfig.yaml

これでBackendConfigの作成が終わり。

接続確認

ここまで終わったら該当のドメインにHTTPSで接続します。
IPでの接続ではダメです。FQDN必須。

すると以下のように認証画面に飛ばされます。

image.png

プリンシパルに追加していないユーザーの場合、 You don't have access なページに飛ばされログインが出来ないはずです。
一方追加したユーザーの場合は以下のように画面が表示されるかと思います。

image.png

これで基本的なIAPの構築は終わりました。
が、色々実用途に向けては調べなくてはならないことがあるので、それは次の記事で書きます。

まとめ

以上IAP構築の流れでしたが、基本的には 公式の手順 に従って行えば問題ないです。
自分の場合は自分で好きに使えるFQDNがないという問題が有りましたが、通常の開発用途ならその問題も引かないでしょうし。
あと個々のオブジェクトの意味が正しく理解できていないのでそれはこれから学習しようと思います。

ということで次回に続きます。
以下、自分がはまったFQDN無い問題をどう解いたかです。参考に書いておきます。

自分が悩んだ証明書作成

この問題は、

  • 署名書を作りたい
  • でも自分が取得したドメインについて、使ったレジストラでDNSSECがonになっていない
    • やろうとすると110円かかる()
  • DNSSECがoffだと、SSL証明書作成に失敗する(ように見える)

というどうでもいい問題をいかに解いたかです。
110円されど100円。

要するにお名前.comでドメインとったんですが、 .net だと1円じゃないですか。
その100倍かかるってのはなんか1円にした意味ないなぁって思っちゃうんですよね。
会社の業務のための検証だしねぇ・・・。
別に固定ドメインとか自分いらないんでね・・・。

あと上で「DNSSEC offだとだめなように見える」と書いた根拠はこのあたり。

https://qiita.com/Yukina_28/items/5f3f73714eaf0ef42dc9
https://github.com/GoogleCloudPlatform/gke-managed-certs/issues/13

ということで何をしたか。単純に サブドメインを定義してCloud DNSに飛ばして、そっちでDNSSEC onにした です。

まずCloud DNSで、取得したドメインに対するゾーンを切ります。

今回はゾーン名を gcp にしました。
また、このときにゾーンのDNSSECをonにします。

image.png

ゾーンが作成されたら、その詳細の、さらにNSレコードのリンクをたどると、以下のようにNSレコードとして登録すべきものが一覧出でてきます。

image.png

この4行をコピーするなどして、お名前.com側に以下のようにレコードを登録します。

image.png

これでしばらくするとドメイン情報が伝搬され、名前解決が出来るようになるはずです。

以上余談でした。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0