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 も参考にしました。
"Allow public client flows"を"Yes"にします。
"Microsoft Graph"でpermissionを追加します。
Directory.Read.All
、Group.Read.All
、User.Read.All
のpermissionを追加します。
"Grant admin content for xxxx"を有効にします。
groups
claimを追加します。
OverviewからApplication (client) IDとDirectory (tenant) IDをコピーします。
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.
出力されたメッセージにしたがって、ブラウザでログインします。
ログインが成功するとトークンが出力されます。
このトークンは~/.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
kubectl
でkubelogin
を使った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"