GKE で Google アカウント認証

# はじめに

* GKE の Ingress に [Cloud IAP](https://cloud.google.com/iap/docs/concepts-overview?hl=ja) を使った Google アカウント認証を組み込む手順
* 流れとしてはテスト用のバックエンドサービスと Ingress を作成し、Ingress の IAP を有効にしてアカウント認証できるようにする。

# クラスタの作成

* GCP メニューから Kubernetes Engine > Kubernetes クラスタ > "クラスタを作成" でクラスタを作成

```
gcloud beta container --project "{PROJECT_ID}" clusters create "cluster-1" --zone "asia-northeast1-a" --username "admin" --cluster-version "1.8.8-gke.0" --machine-type "f1-micro" --image-type "COS" --disk-size "100" --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only","https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring","https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly","https://www.googleapis.com/auth/trace.append" --num-nodes "3" --network "default" --enable-cloud-logging --enable-cloud-monitoring --subnetwork "default" --addons HorizontalPodAutoscaling,HttpLoadBalancing,KubernetesDashboard
```

# クラスタへ接続

* 作成したクラスタへ接続する

```
gcloud container clusters get-credentials cluster-1 --zone asia-northeast1-a --project {PROJECT_ID}
```

# SSL証明書の作成

* IAP が https でしか利用できないので https://github.com/kubernetes/ingress-nginx/blob/0e91c52adc605e4d4e5ebfd43be297865b9cad51/docs/examples/PREREQUISITES.md#tls-certificates に従って自己署名証明書を発行して GKE の secret に登録する。

```
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
```

# バックエンドサービスの作成

* https://github.com/kubernetes/ingress-nginx/blob/5ca39ae600b14bbc8e4532e39399a0d269d06a5b/docs/examples/http-svc.yaml を雛形にバックエンドの Deployment や Service を作成する。

```
kubectl apply -f http-svc.yaml
kubectl patch svc http-svc -p '{"spec":{"type": "LoadBalancer"}}'
```

# Ingress の作成

* https://github.com/kubernetes/ingress-nginx/blob/0e91c52adc605e4d4e5ebfd43be297865b9cad51/docs/examples/tls-termination/ingress.yaml を雛形に設定ファイルを作成する。
* 接続用のホスト名は `foo.bar.com` で hosts を使ってアクセスする。
* `spec.rules.http.paths.path` は IAP の認証後のリダイレクト先を含めるために `/*` に変更する。

```ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-test
spec:
  tls:
    - hosts:
      - foo.bar.com
      # This assumes tls-secret exists and the SSL 
      # certificate contains a CN for foo.bar.com
      secretName: tls-secret
  rules:
    - host: foo.bar.com
      http:
        paths:
        - path: /*
          backend:
            # This assumes http-svc exists and routes to healthy endpoints
            serviceName: http-svc
            servicePort: 80
```

# ここまでの動作確認

* 作成した Ingress あてに curl でアクセスして動作確認をする
  * Ingress の IP アドレス割当には時間がかかるのでリクエスト結果のステータスコードが 404 や 500 の場合は少し待ってから確認し直す

```
curl -Lk https://{INGRESS_IP_ADDR} -H 'Host:foo.bar.com'
```

# ドメイン名の設定

* 作成した Ingress の IP アドレスで hosts に設定する

```/etc/hosts
{INGRESS_IP_ADDR} foo.bar.com
```

# IAP の設定

* メニューから "セキュリティ" > "Identity-Aware Proxy"
* IAP を迂回できるファイアーウォール設定を削除
  * `default/http-svc` の「警告」を押下
  * 「EDIT FIREWALL」から対象のファイアーウォール設定を削除
* `default/http-svc` の IAP を有効にする
  * ドメイン名に `foo.bar.com` を指定して有効にする
* `Access` 欄にアクセス可能なアカウントを追加する

# IAP の動作確認

* `https://foo.bar.com` にブラウザからアクセスしアカウント認証された後に正常にコンテンツが表示されることを確認