Zenn
Closed20

k8s webhook トークン認証の流れ(aws-auth)

ピン留めされたアイテム
ishii1648ishii1648

k8s バージョン

v1.32.0

API サーバのリクエスト前処理は http.Handler(ミドルウェア)として登録されて実行されている。DefaultBuildHandlerChain() でまとめて登録されているので認証・認可周りの実装を見る場合はここがエントリになる

https://github.com/kubernetes/kubernetes/blob/70d3cc986aa8221cd1dfb1121852688902d3bf53/staging/src/k8s.io/apiserver/pkg/server/config.go#L1004-L1079

ishii1648ishii1648

起動オプション --authentication-token-webhook-config-file を指定していると []authenticator.Request に bearertoken.Authenticator が追加される。bearertoken.Authenticator には tokenReviewer が含まれる(tokenReviewer は aws-iam-authenticator へのリクエストで POST body として送られる)。なお、この段階では spec.token は空

TokenReview の例

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    "token": "(Bearerトークン)"
  }
}
ishii1648ishii1648

送信先の設定はここでやってた

https://github.com/kubernetes/kubernetes/blob/70d3cc986aa8221cd1dfb1121852688902d3bf53/staging/src/k8s.io/client-go/tools/clientcmd/client_config.go#L187-L197

--authentication-token-webhook-config-file で渡すファイルの中身は以下のような形式になっており、ここから clusters[].cluser.server を抜いている

# Kubernetes APIのバージョン
apiVersion: v1
# APIオブジェクトの種類
kind: Config
# clustersは、リモートサービスを指します。
clusters:
  - name: name-of-remote-authn-service
    cluster:
      certificate-authority: /path/to/ca.pem         # リモートサービスを検証するためのCA
      server: https://authn.example.com/authenticate # クエリするリモートサービスのURL。'https'を使用する必要があります。

# usersは、APIサーバーのWebhook設定を指します。
users:
  - name: name-of-api-server
    user:
      client-certificate: /path/to/cert.pem # Webhookプラグインを使うための証明書
      client-key: /path/to/key.pem          # 証明書に合致する鍵

# kubeconfigファイルにはコンテキストが必要です。APIサーバー用のものを用意してください。
current-context: webhook
contexts:
- context:
    cluster: name-of-remote-authn-service
    user: name-of-api-sever
  name: webhook

https://kubernetes.io/ja/docs/reference/access-authn-authz/authentication/#webhook-token-authentication

ishii1648ishii1648

API サーバから送られてきた Bearer Token を取り出す。そこから v1Prefix(k8s-aws-v1.)を除いた文字列を base64 デコードした値を parsedURL としてセット

コマンドで同様の処理したが確かに STS へのリクエスト URL 取り出せる

❯ aws eks get-token --cluster-name $CLUSTER_NAME \
    | jq -r '.status.token' \
    | sed 's/k8s-aws-v1.//g' \
    | base64 -d
https://sts.ap-northeast-1.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
ishii1648ishii1648

Mapper は ConfigMap 以外にもいくつか用意されていて BackendMapper.mappers として管理されていて、どれを使うかはコマンドオプション or 設定ファイル(.server.backendMode)で指定する

ちなみに2個以上設定できるようになっていて、その場合は(恐らく)先に指定した mapper が優先されるらしい

https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/8769c8f063f072830ccd737d29a049a5a4609571/pkg/server/server.go#L419-L440

ishii1648ishii1648

最後に TokenReview.Status を埋めて API サーバにレスポンスを返す

https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/8769c8f063f072830ccd737d29a049a5a4609571/pkg/server/server.go#L394-L404

成功した場合のレスポンス例

{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "status": {
    "authenticated": true,
    "user": {
      "username": "janedoe@example.com",
      "uid": "42",
      "groups": [
        "developers",
        "qa"
      ],
      "extra": {
        "extrafield1": [
          "extravalue1",
          "extravalue2"
        ]
      }
    }
  }
}

https://kubernetes.io/ja/docs/reference/access-authn-authz/authentication/#webhook-token-authentication

ishii1648ishii1648

以下のように .users[].user.exec が設定されているケースで kubectl get を実行して API サーバにリクエストが届くまでの間の処理の流れも見ていく

users:
- name: arn:aws:eks:ap-northeast-1:111111111111111:cluster/test-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1beta1
      args:
      - --region
      - ap-northeast-1
      - eks
      - get-token
      - --cluster-name
      - test-cluster
      - --output
      - json
      command: aws
ishii1648ishii1648

以下で .users[].user.exec に含まれるコマンドの実行+API サーバへのリクエストしてる

最終的に net/http パッケージの send() がコールされる。send() は RoundTripper.RoundTrip() で実際の HTTP tansaction を実行しているが、RoundTripper は interface になっていて、ここを client-go/rest パッケージで振る舞いを実装してる

このスクラップは23日前にクローズされました
ログインするとコメントできます