IK.AM

@making's tech note


KindでAzure ADのOpenID Connectと連携してRBACを設定するメモ

🗃 {Dev/CaaS/Kubernetes/kind}
🏷 Kubernetes 🏷 Kind 🏷 Azure AD 🏷 OIDC 🏷 OpenID Connect 
🗓 Updated at 2023-08-04T01:43:51Z  🗓 Created at 2023-08-03T07:01:10Z   🌎 English Page

Kindで作るK8sクラスタに対してOIDCを設定したく、OIDC ProviderとしてAzure ADを使用するメモです。

RBACの検証をローカルで行いたい場合や、任意のk8sクラスタでOIDC連携したい場合に使えます。

目次

Azure ADでアプリケーションの登録

https://azure.github.io/kubelogin/topics/k8s-oidc-aad.html を参考に以下の手順でAzure AD上でアプリケーション (OIDCクライアント) を登録します。ここではkind-oidcという名前で作成します。

ℹ️ Azure ADのアプリケーション作成に関しては https://www.pomerium.com/docs/identity-providers/azure も参考にしました。

image

"Allow public client flows"を"Yes"にします。

image

"Microsoft Graph"でpermissionを追加します。

image

Directory.Read.AllGroup.Read.AllUser.Read.Allのpermissionを追加します。

image

"Grant admin content for xxxx"を有効にします。

image image image

groups claimを追加します。

image image

OverviewからApplication (client) IDとDirectory (tenant) IDをコピーします。

image
AAD_CLIENT_ID=*****
AAD_TENANT_ID=*****

https://sts.windows.net/$AAD_TENANT_ID がOIDCのissuer urlになるので、次のURLでメタデータを取得できます。

curl -s https://sts.windows.net/$AAD_TENANT_ID/.well-known/openid-configuration

kubeloginのインストール

Azure ADからkubectl用のアクセストークンを取得するために、kubeloginを使用します。

以下のドキュメントに従ってインストールします。

https://azure.github.io/kubelogin/install.html

brew install Azure/kubelogin/kubelogin

次のコマンドを実行してトークンを取得できます。

$ kubelogin get-token --environment AzurePublicCloud --server-id $AAD_CLIENT_ID --client-id $AAD_CLIENT_ID --tenant-id $AAD_TENANT_ID
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code IU3PMB29G to authenticate.

出力されたメッセージにしたがって、ブラウザでログインします。

image

ログインが成功するとトークンが出力されます。

このトークンは~/.kube/cache/kubelogin以下にキャッシュされています。kubelogin remove-tokensでキャッシュを削除できます。

以下のコマンドでアクセストークンの中身をデコードしてclaimをみることが出来ます。

$ cat ~/.kube/cache/kubelogin/*.json | jq -r .access_token | jq -R 'split(".") | .[1] | @base64d | fromjson'

{
  "aud": "*****",
  "iss": "https://sts.windows.net/*****/",
  "iat": 1691042264,
  "nbf": 1691042264,
  "exp": 1691047580,
  "acr": "1",
  "aio": "*****",
  "amr": [
    "pwd",
    "mfa"
  ],
  "appid": "*****",
  "appidacr": "0",
  "email": "*****",
  "family_name": "*****",
  "given_name": "*****",
  "groups": [
    "*****",
    "*****"
  ],
  "idp": "*****",
  "ipaddr": "*****",
  "name": "*****",
  "oid": "*****",
  "rh": "*****",
  "scp": "User.Read",
  "sub": "*****",
  "tid": "*****",
  "unique_name": "*****",
  "uti": "*****",
  "ver": "1.0",
  "wids": [
    "*****",
    "*****"
  ]
}

Kind Clusterの作成

作成したOIDCクライアントを使った認可を行うためにAPI Serverにオプションを追加してkindでクラスタを作成します。

API Serverの設定に関するドキュメントは https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuring-the-api-server です。

cat <<EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
kubeadmConfigPatches:
- |-
  kind: ClusterConfiguration
  apiServer:
    extraArgs:
      oidc-client-id: $AAD_CLIENT_ID
      oidc-issuer-url: https://sts.windows.net/$AAD_TENANT_ID/
      oidc-username-claim: email
      oidc-groups-claim: groups
nodes:
- role: control-plane
EOF
kind create cluster --config kind-config.yaml --image kindest/node:v1.26.6

kubectlkubeloginを使ったuserを設定します。

kubectl config set-credentials "azure-user" \
  --exec-api-version=client.authentication.k8s.io/v1beta1 \
  --exec-command=kubelogin \
  --exec-arg=get-token \
  --exec-arg=--environment \
  --exec-arg=AzurePublicCloud \
  --exec-arg=--server-id \
  --exec-arg=$AAD_CLIENT_ID \
  --exec-arg=--client-id \
  --exec-arg=$AAD_CLIENT_ID \
  --exec-arg=--tenant-id \
  --exec-arg=$AAD_TENANT_ID

上記のuserを使用するcontextをkindクラスタに対して設定して、contextを切り替えます。

kubectl config set-context kind-oidc --cluster=kind-kind --user=azure-user
kubectl config use-context kind-oidc

このcontextで次のコマンドを実行すると次のようなエラーメッセージが出力されるはずです。

$ kubectl get pod   
Error from server (Forbidden): pods is forbidden: User "****" cannot list resource "pods" in API group "" in the namespace "default"

Azure ADでログインしたユーザーはまだなんの権限もないので、K8sに対して何もできません。

ADグループの作成とメンバー追加

Developer用のADグループを作成します。

GROUP_ID=$(az ad group create --display-name demo-developer --mail-nickname demo-developer --query id -o tsv)

az loginでログインしたの自分のアカウントをこのグループに追加します。

az login

UPN=$(az ad signed-in-user show --query userPrincipalName -o tsv)
OID=$(az ad user show --id ${UPN} --query id -o tsv)

az ad group member add --group demo-developer --member-id ${OID}

groupに追加されていることを確認します。

$ az ad group member list --group demo-developer
[
  {
    "@odata.type": "#microsoft.graph.user",
    "businessPhones": [],
    "displayName": "****",
    "givenName": "****",
    "id": "****",
    "jobTitle": null,
    "mail": "****",
    "mobilePhone": null,
    "officeLocation": null,
    "preferredLanguage": null,
    "surname": "****",
    "userPrincipalName": "****"
  }
]

GROUP_IDは次のコマンドでも取得できます。

GROUP_ID=$(az ad group list --filter "displayname eq 'demo-developer'" --query '[0].id' -o tsv)

ユーザーをグループに追加したら、トークンを取得し直します。

kubelogin remove-tokens
kubelogin get-token --environment AzurePublicCloud --server-id $AAD_CLIENT_ID --client-id $AAD_CLIENT_ID --tenant-id $AAD_TENANT_ID

以下のコマンドを実行し、groups claimに$GROUP_IDが追加されていることを確認してください。

cat ~/.kube/cache/kubelogin/*.json | jq -r .access_token | jq -R 'split(".") | .[1] | @base64d | fromjson'

グループに対するRoleBindingの作成

cluster-admin権限で作成したグループに対してdev namespaceのadmin clusterroleをbindします。

kubectl create ns dev --context kind-kind
kubectl create rolebinding -n dev --clusterrole=admin --group=${GROUP_ID} demo-admin --context kind-kind
$ kubectl get rolebinding -n dev -owide
NAME         ROLE                AGE   USERS   GROUPS                                 SERVICEACCOUNTS
demo-admin   ClusterRole/admin   14s           7afc7680-534d-46aa-9c95-0195655caf57  

これでdev namespaceにはadminとして操作が可能になりますが、他のnamespaceでは引き続き操作が制限されています。

$ kubectl get pod -n dev
No resources found in dev namespace.
$ kubectl get pod -n default
Error from server (Forbidden): pods is forbidden: User "****" cannot list resource "pods" in API group "" in the namespace "default"

✒️️ Edit  ⏰ History  🗑 Delete