---
title: Pivotal Container Service (PKS)でkubeloginを使う方法
tags: ["Kubernetes", "PKS", "UAA", "OpenID Connect"]
categories: ["Dev", "CaaS", "Kubernetes", "PKS"]
date: 2018-10-03T04:27:02Z
updated: 2019-08-21T08:36:17Z
---

> ⚠️ 【Updated】 ⚠️
> 
> Enterprise PKS 1.5で `pks get-kubeconfig <cluster name> --sso-auto` オプションが追加され、ブラウザでUAAログインできるようになりました。
> 
> 下記の作業は**行わないでください**。また、以下の設定を行なっている場合はPKS 1.5にアップグレードする前に削除してください。

[Pivotal Container Service (PKS) 1.2](https://docs.pivotal.io/runtimes/pks/1-2/)でUAAを使ったOpenID Connectに対応しました。
が、公式ドキュメントではCluster UserはcurlコマンドでID TokenとRefersh Tokenをとるように説明されています。
または[Knowledge Base](https://community.pivotal.io/s/article/script-to-automate-generation-of-the-kubeconfig-for-the-kubernetes-user)でトークン取得用の[スクリプト](https://pivotal.my.salesforce.com/sfc/p/U0000000YQaz/a/0e0000000lSX/8rROyDWP7fxbHx7KulEG.JLbbFxr0Xh4RPVOxq49q.k)が紹介されています。

curlで各トークンを抽出するのは手間がかかるので、[@int128さん](https://twitter.com/int128)作の[`kubelogin`](https://github.com/int128/kubelogin)を使う方法を説明します。


PKSでOIDC連携をする場合は、UAAのクライアントのclient_idは`pks_cluster_client`固定になります。デフォルトでは`authorization_code` grant_typeがサポートされていないので、
PKS管理者は`uaac`コマンドでクライアントの情報を更新します。また、`kubelogin`が期待するredirect_uriの[http://localhost:8000](http://localhost:8000)も設定します。


```
uaac target https://${PKS_DOMAIN}:8443 --skip-ssl-validation
uaac token client get admin -s ${ADMIN_SECRET}

uaac client update pks_cluster_client \
  --authorized_grant_types password,refresh_token,authorization_code \
  --redirect_uri http://localhost:8000
```


PKSのk8sクラスタユーザーは`~/.kube/config`に次の設定を行います。

```yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTi....
    server: https://demo.pks.example.com:8443
  name: demo
contexts:
- context:
    cluster: demo
    user: demo@example.com
  name: demo
current-context: demo
users:
- name: demo@example.com
  user:
    auth-provider:
      config:
        client-id: pks_cluster_client
        cluster_client_secret: ""
        idp-issuer-url: https://api.pks.example.com:8443/oauth/token
      name: oidc
```

PKSのk8sクラスタユーザーは[kubelogin](https://github.com/int128/kubelogin)をインストールします。

```
brew tap int128/kubelogin
brew install kubelogin
```

`kubelogin`でログインします。

```
kubelogin --insecure-skip-tls-verify
```

kubectl pluginに対応しているので、`kubectl login`でも利用可能です。

```
kubectl login --insecure-skip-tls-verify
```

UAAのログイン画面がWebブラウザで自動で開きます。

![image](https://user-images.githubusercontent.com/106908/45886776-eff0b680-bdf4-11e8-88fe-c8181fe083b1.png)

![image](https://user-images.githubusercontent.com/106908/45886808-06970d80-bdf5-11e8-87f9-a2f4d8b63fc6.png)

![image](https://user-images.githubusercontent.com/106908/45886815-0b5bc180-bdf5-11e8-91f4-73ac51387ad5.png)

次のようなログが出力されます。

```
2018/09/21 23:04:04 Reading ~/.kube/config
2018/09/21 23:04:04 Using current-context: demo
2018/09/21 23:04:04 Open http://localhost:8000 for authorization
2018/09/21 23:04:05 GET /
2018/09/21 23:04:24 GET /?code=j6Nob0u8a1&state=74d6d46531b2a620
2018/09/21 23:04:24 Got token for subject=f01a100c-e730-42a0-abf9-88c93606efa2
2018/09/21 23:04:24 Updated ~/.kube/config
```

`id-token`と`refresh-token`が`~/.kube/config`に自動で追加されます。

```yaml
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJTi....
    server: https://demo.pks.example.com:8443
  name: demo
contexts:
- context:
    cluster: demo
    user: demo@example.com
  name: demo
current-context: demo
users:
- name: demo@example.com
  user:
    auth-provider:
      config:
        client-id: pks_cluster_client
        cluster_client_secret: ""
        id-token: eyJhbGciOiJSUzI1NiIsImtp....
        idp-issuer-url: https://api.pks.example.com:8443/oauth/token
        refresh-token: eyJhbGciOiJSUzI1NiI....
        name: oidc
```


あとはPKSクラスタ管理者が`RoleBinding`の設定をすればOKです。

例:

```yaml
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: edit-binding
  namespace: demo
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: edit
subjects:
- kind: User
  name: demo@example.com
  namespace: demo
```

---

`uaac`コマンドを使わずにOpsManagerのapply changesでUAA ClientをアップデートするHackを紹介します。
このやり方だと、PKSアップデートのタイミングで`pks_cluster_client`がオーバーライドされてもその後からさらに更新をかけることができます。

次のようなRuntime Configを作成します。

```yaml
cat <<'EOF' > support-kubelogin.yml 
releases:
- name: os-conf
  version: "20.0.0"
  url: "https://bosh.io/d/github.com/cloudfoundry/os-conf-release?v=20.0.0"
  sha1: "a60187f038d45e2886db9df82b72a9ab5fdcc49d"
addons:
- name: support-kubelogin
  jobs:
  - name: pre-start-script
    release: os-conf
    properties:
      script: |
        #!/bin/bash
        echo "Waiting until UAA is up"
        until $(curl --output /dev/null -k --silent --head --fail https://((pks_api_hostname)):8443/info); do
          printf '.'
          sleep 5
        done
        ACCESS_TOKEN=$(curl -s -u ((uaa_client_id)):((uaa_client_secret)) -k  https://((pks_api_hostname)):8443/oauth/token -d grant_type=client_credentials | sed -n 's/.*access_token":"\([^"]*\).*/\1/p')
        curl -k https://((pks_api_hostname)):8443/oauth/clients/pks_cluster_client -X PUT \
            -H "Content-Type: application/json" \
            -H "Authorization: Bearer ${ACCESS_TOKEN}" \
            -d '{
          "client_id" : "pks_cluster_client",
          "authorized_grant_types" : [ "password", "refresh_token", "authorization_code" ],
          "redirect_uri" : [ "http://localhost:8000" ]
        }'
  include:
    jobs:
    - name: kube-apiserver
      release: kubo
EOF
```

`service_admin_client`など、`clients.admin` authorityを持ったUAAクライアントの情報を設定します。

`service_admin_client`のClient CredentialはOpsManagerから取得できます。

![image](https://user-images.githubusercontent.com/106908/52913677-c2585c80-3303-11e9-98a6-e9f49f33d50e.png)

```
bosh -n update-runtime-config --name=support-kubelogin support-kubelogin.yml -v pks_api_hostname=api.pks.example.com -v uaa_client_id=service_admin_client -v uaa_client_secret=<service_admin_clientのclient secret> --no-redact
```

でOps ManagerでApply Changes。
