LoginSignup
15
6

More than 3 years have passed since last update.

KubernetesのToken Review API

Last updated at Posted at 2017-12-06

KubernetesのAPIサーバと同じ認証を自前のpodとかでやりたいことがありませんか? 例えばAPIサーバにアクセスするためのIDトークンで認証しメールアドレスを使いたいとかサービスアカウントで認証したいとか。

そんなときはTokenReview APIを使ってみるといいかもしれません。

これはKubernetesのAPIサーバに対してBearerトークンをリクエストパラメータとして渡すと、APIサーバが有効かどうかを判断して結果を返してくれるAPIです。例えばServiceAccountのトークンや、OIDCを有効にしている場合にはID Tokenなんかを渡すことができます。

v1.7以降ではTokenReview APIには以下のURIでアクセスできます。

https://${API_SERVER_ADDR}/apis/authentication.k8s.io/v1/tokenreviews

リクエストパラメータは以下のようなJSONデータです。

{
    "apiVersion": "authentication.k8s.io/v1",
    "kind": "TokenReview",
    "spec": {
        "token": <USER_TOKEN>
    }
}

これをTokenReviewAPIにPOSTしてやるとレスポンスが返ってきます。

$ curl -H "Content-Type: application/json" \
       -H 'Authorization: Bearer ${SYTEM_TOKEN}' \
       -d '{"apiVersion": "authentication.k8s.io/v1","kind": "TokenReview","spec": {"token": <USER_TOKEN>}}'
       https://${API_SERVER_ADDR}/apis/authentication.k8s.io/v1/tokenreviews \

例えばkube-apiserverに対してOIDCの認証設定かつusernameのフィールドとしてemailを使う設定をしている場合などは、TokenReview APIにID Tokenを渡すと、認証した結果のusernameの値としてemailアドレスが入っています。

{
  "kind": "TokenReview",
  "apiVersion": "authentication.k8s.io/v1",
  "metadata": {
    "creationTimestamp": null
  },
  "spec": {
    "token": <USER_TOKEN>
  },
  "status": {
    "authenticated": true,
    "user": {
      "username": "foo@example.org"
      "groups": [
        "system:authenticated"
      ]
    }
  }
}

ServiceAccountトークンを渡した場合はusernameが以下のようなフォーマットの文字列になります。

system:serviceaccount:<namespace>:<name>

Tokenが有効でない場合や期限が切れている場合などは status.authenticated の値が false になります。

{
  "kind": "TokenReview",
  "apiVersion": "authentication.k8s.io/v1",
  "metadata": {
    "creationTimestamp": null
  },
  "spec": {
    "token": <USER_TOKEN>
  },
  "status": {
    "authenticated": false,
  }
}

このAPIを呼び出すには system:auth-delegator の権限が必要なので、TokenReview APIを呼びすアカウントに対してClusterRoleBindingまたはRoleBindingで権限を付与してあげてください。

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: sample-ns:system:auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
- kind: ServiceAccount
  name: default
  namespace: sample-ns

さらにGoLangのコードからこれらを呼び出す場合にはvaultのKubernetes Auth Backend プラグインのコードを参考にするとよいでしょう。client-goのパッケージを使ってTokenReview APIを呼び出しています。

最後にひとつ注意すべき点を記載しておきます。

今回TokenReview APIで扱っているID TokenやServiceAccount TokenはいずれもJWT形式なので署名を検証するための公開鍵さえあれば自前で検証できてしまいますが、TokenのRevokeや公開鍵ペアのローテーションが発生した場合の考慮を十分にしておく必要があります。

ID Tokenの場合にはトークンのclaimとしてexpなどが含まれているため、Revokeやキーのローテーションが発生したとしても最悪の場合でもexpの値である期限までしか使えませんが、ServiceAccount Tokenは期限を持っていないためRevokeやローテーションに関係なく永遠に使い続けられてしまいとても危険な状態になります。

よほど問題がない限りは正しくTokenReview APIを使って検証しましょう。

15
6
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
15
6