はじめに
- GKE で Google アカウント認証を導入する場合 Cloud IAP を使うのが簡単。
- Cloud IAP は手軽ではあるが、アクセスを許可するメールアドレスなどの設定がプロジェクト単位になるため場合によっては要件とマッチしないことがある。
- そこで oauth2_proxy を使って Google アカウント認証プロキシを立てることで、任意のサービスで任意のアカウントやグループを対象にアクセスを制御することができるようになる。
- この記事では Nginx サーバーの前に oauth2_proxy を立ち上げてアクセスコントロールを行う設定手順を記載する。
基本的な流れ
- GCP コンソールで OAuth クライアントを作成する
- (必要であれば)サービスアカウントを作成し設定する
- Google アカウント認証を行う Nginx サービスを起動する
GKE クラスタの作成
- 任意のプロジェクトで任意の設定で GKE クラスタを作成し、クラスタに接続しておく。
OAuth クライアントの作成
- https://console.cloud.google.com にログイン
- プロジェクトの作成または選択
- "API とサービス" > "認証情報"
- "認証情報を作成" > "OAuth クライアント ID"
- "ウェブアプリケーション" を選択
- "承認済みのリダイレクト URI" にリダイレクト先の URL を入力(例: https://www.example.com/oauth2/callback)
- "作成"
- "クライアント ID" と "クライアントシークレット" をシークレットに登録する
echo -n "クライアント ID" > clientid
echo -n "クライアントシークレット" > clientsecret
kubectl create secret generic oauth-setting --from-file=./clientid --from-file=./clientsecret
アクセスを許可するメールアドレスやグループを指定するための設定
- oauth2_proxy では通常の OAuth 認証のあとにホワイトリストに記載されたメールアドレスやグループに所属するユーザーだけアクセスを許可する機能がある。
- この検証のために内部ではサービスアカウントを利用しているので、メールアドレスやグループを指定してアクセスコントロールを行いたい場合はこの節の設定が必要になる。
サービスアカウントの作成
- https://console.cloud.google.com にログイン
- "IAM と管理" > "サービスアカウント"
- "サービスアカウントの作成"
- "新しい秘密鍵の提供" にチェックをして "JSON" でダウンロード
API の有効化
- GCP コンソールメニューで "API とサービス" > "ライブラリ"
- "Admin SDK" を検索して有効化する
サービスアカウントの設定
- admin.google.com にログイン
- "セキュリティ" > "設定"
- "設定詳細" > "認証" > "API クライアント アクセスを管理する"
- "クライアント名" にサービスアカウント ID を入力
- "API スコープ" に "https://www.googleapis.com/auth/admin.directory.group.readonly, https://www.googleapis.com/auth/admin.directory.user.readonly" と入力
サービスアカウントの鍵ファイルをシークレットに入れる
- サービスアカウント作成時にダウンロードした鍵の入った JSON ファイルを Kubernetes の Secret に追加します。
kubectl create secret generic sa-setting --from-file=./KEY_FILE.json
SSL 証明書の作成
- OAuth 認証のためのページでは SSL を利用する必要がある。
- 検証のために Ingress で自己認証証明書を使って SSL 通信を提供する。
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
Docker image の作成
- oauth2_proxy を実行するための Docker image を作成し Google Container Registry にアップロードする
FROM golang:1.10
ADD https://github.com/bitly/oauth2_proxy/releases/download/v2.2/oauth2_proxy-2.2.0.linux-amd64.go1.8.1.tar.gz /tmp
RUN tar -xf /tmp/oauth2_proxy-2.2.0.linux-amd64.go1.8.1.tar.gz -C ./bin --strip-components=1 && rm /tmp/*.tar.gz
docker build -t oauth2-proxy:v1.0 .
docker tag oauth2-proxy:v1.0 gcr.io/PROJECT_NAME/oauth2-proxy
gcloud docker -- push gcr.io/PROJECT_NAME/oauth2-proxy
Google 認証をする Nginx コンテナを立ち上げる
Deployment の作成
- Nginx コンテナと oauth2_proxy コンテナを持つ Pod を Deployment から立ち上げる。
- oauth2_proxy の args の
-google-group
や-google-service-account-json
はメールアドレスやグループ単位でアクセス制御を行いたい場合のみ指定する。- サービスアカウントの鍵ファイルのマウントも同様に必要であれば行う。
deployment.yml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
# Nginx コンテナ
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
# oauth2_proxy コンテナ
- name: oauth2-proxy
image: gcr.io/PROJECT_NAME/oauth2-proxy
ports:
- containerPort: 4180
command: ["/go/bin/oauth2_proxy"]
args:
- "-upstream=http://0.0.0.0:80/" # 認証成功時に提供するコンテンツの URL
- "-http-address=0.0.0.0:4180" # oauth2_proxy が可動する URL
- "-email-domain=*" # アクセスを許可するドメイン名
- "-google-service-account-json=/etc/sa-setting/projectname-random.json" # サービスアカウントの鍵ファイルのパス
- "-google-group=groupname@yourcompany.com" # アクセスを許可するグループのメールアドレス(複数回指定可)(サービスアカウント設定もする必要がある)
- "-cookie-secret=5E3899D7-969C-449F-9EA7-41A21E690387" # クッキー名の seed 文字列
- "-google-admin-email=chiba@kakapoapps.com" # Google の管理者アカウントのメールアドレス. サービスアカウントでのリクエスト送信時に利用する
env:
- name: OAUTH2_PROXY_CLIENT_ID
valueFrom:
secretKeyRef:
name: oauth-setting
key: clientid
- name: OAUTH2_PROXY_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: oauth-setting
key: clientsecret
volumeMounts:
# サービスアカウントの鍵ファイルをマウントする
- name: sa-setting
mountPath: "/etc/sa-setting"
readOnly: true
# Ingress のヘルスチェック用に設定. oauth2_proxy では /ping で疎通確認を行うことができる.
readinessProbe:
httpGet:
path: /ping
port: 4180
initialDelaySeconds: 5
periodSeconds: 5
volumes:
# サービスアカウントの鍵ファイルの Secret をマウントできるようにボリュームとして設定する
- name: sa-setting
secret:
secretName: sa-setting
Service の作成
- TCP/80 で受けて oauth2_proxy の TCP/4180 に転送するサービスを作成する.
service.yml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 4180
protocol: TCP
name: http
selector:
app: nginx
Ingress の作成
ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
spec:
tls:
- hosts:
- www.example.com # 任意のドメイン名を指定
secretName: tls-secret # 作成した SSL 証明書の Secret を指定
rules:
- host: www.example.com
http:
paths:
- path: /*
backend:
serviceName: nginx-service
servicePort: 80
動作確認
-
kubectl get ingress
で Ingress の IP アドレスを確認したら/etc/hosts
などに指定したドメイン名と IP アドレスの設定を行いブラウザで動作確認を行う。