自分向けのメモとして、Azure Kubernetes Service のカスタマイズについて学びます。RBACをActiveDirectoryと統合して使ってみたいと思います。
AzureADサーバーコンポーネントの作成
ServicePrincipalとそのアプリケーション、AzureADグループメンバーシップを作成します。AKSとAzure AD の認証は、OpenID Connectで実施されます。Kubernetes側は、webhook authenticationという仕組みを使っている様子。
AD アプリケーションの作成と、グループメンバーシップクレームの設定変更
ADアプリケーションを作ったのちに、groupMembershipClaim
というプロパティを変更します。 設定の意味や取りうるオプションはこちら。Azure Active Directory app manifest、ユーザーか、もしくは、アプリが期待するOAuth2.0のアクセストークンのグループのクレームのコンフィグレーションです。全てのセキュリティグループを受けいれるよう設定しています。claim は、疑わしいものに対して正しいかを認める行為です。
aksname="tsushicluster"
# Create the Azure AD application
serverApplicationId=$(az ad app create \
--display-name "${aksname}Server" \
--identifier-uris "https://${aksname}Server" \
--query appId -o tsv)
# Update the application group memebership claims
az ad app update --id $serverApplicationId --set groupMembershipClaims=All
サービスプリンシパルの作成
先ほど作成したアプリケーションのIDを使って、サービスプリンシパルを作成して、クレデンシャルをリセットしています。これは、自動でパスワードを取得するためです。パスワードは作成時しか獲得できないからです。
# Create a service principal for the Azure AD application
az ad sp create --id $serverApplicationId
# Get the service principal secret
serverApplicationSecret=$(az ad sp credential reset \
--name $serverApplicationId \
--credential-description "AKSPassword" \
--query password -o tsv)
パーミッションの付与とGrant
パーミッションを設定します。また、それに許可を与えます。このコマンドだけをみるとわけがわからないのですが、MicrosoftGraphのAPIに対して
- Directory のデータの読み込み
- Sin in と、ユーザプロファイルの読み込み
の権限を与えています。
az ad app permission add \
--id $serverApplicationId \
--api 00000003-0000-0000-c000-000000000000 \
--api-permissions e1fe6dd8-ba31-4d61-89e7-88639da4683d=Scope 06da0dbc-49e2-44d2-8312-53f166ab848a=Scope 7ab1d382-f21e-4acd-a863-ba3e13f7da61=Role
GUI でやる手順が出ているので、そちらをみるとイメージしやすいと思います。
* Use Azure Portal
次に設定したパーミッションを有効化します。ADのAdminの権限が必要です。
az ad app permission grant --id $serverApplicationId --api 00000003-0000-0000-c000-000000000000
az ad app permission admin-consent --id $serverApplicationId
当初自分の環境では、az ad app permission admin-consent
が見つからないと言われた。AzureCLIのバージョンを最新にしてみたら動作しました。2.0.58
では動作せず2.0.69
では動作しました。
Consent とは
辞書で調べると、Consent は何かをする権限を与えることで、ADにはコンセントフレームワークと言うものがあります。
Azure AD クライアントコンポーネントの作成
次に、同じように、Azure AD アプリケーションを作成します。これは、ユーザがAKSのクラスタにkubectlを使ってコマンドを発行するときに使われます。ユーザからの認証リクエストを取得して、クレデンシャルを認証、認可します。サーバーのそれと同じように作ります。
clientApplicationId=$(az ad app create \
--display-name "${aksname}Client" \
--native-app \
--reply-urls "https://${aksname}Client" \
--query appId -o tsv)
az ad sp create --id $clientApplicationId
OAtuh2 ID を取得します。
oAuthPermissionId=$(az ad app show --id $serverApplicationId --query "oauth2Permissions[0].id" -o tsv)
ちなみに、az ad app show --id $serverApplicationId
とすると詳細が帰ってきますが、oAuthPermissionの部分は次のようになります。
"oauth2Permissions": [
{
"adminConsentDescription": "Allow the application to access tsushiclusterServer on behalf of the signed-in user.",
"adminConsentDisplayName": "Access tsushiclusterServer",
"id": "<<上記のoauthPermissionIdがここに>>",
"isEnabled": true,
"type": "User",
"userConsentDescription": "Allow the application to access tsushiclusterServer on your behalf.",
"userConsentDisplayName": "Access tsushiclusterServer",
"value": "user_impersonation"
}
そしてパーミッションを与えます。これは、APIに対してパーミッションを与えるものです。ここでは、サーバーのAPIに対してパーミションを与えています。
az ad app permission add --id $clientApplicationId --api $serverApplicationId --api-permissions $oAuthPermissionId=Scope
az ad app permission grant --id $clientApplicationId --api $serverApplicationId
AKS クラスタの作成
Updateも試したがうまくいかなかった。新しいクラスタをデプロイする方が良さそう。
az group create --name myResourceGroup --location EastUStenantId=$(az account show --query tenantId -o tsv)
tenantId=$(az account show --query tenantId -o tsv)
az aks create \
--resource-group myResourceGroup \
--name $aksname \
--node-count 1 \
--generate-ssh-keys \
--aad-server-app-id $serverApplicationId \
--aad-server-app-secret $serverApplicationSecret \
--aad-client-app-id $clientApplicationId \
--aad-tenant-id $tenantId
az aks create \
--resource-group UshioTestGroup \
--name $aksname \
--node-count 1 \
--generate-ssh-keys \
--aad-server-app-id $serverApplicationId \
--aad-server-app-secret $serverApplicationSecret \
--aad-client-app-id $clientApplicationId \
--aad-tenant-id $tenantId
--aad-server-app-id
はサービスプリンシパルを付与した、Appで、タイプは、Web app/APIに何る。これは、KubernetesのAPIサーバーのアプリケーションになる。また、--aad-client-app-id
はNativeタイプで、kubectlを使うときのユーザ認証、認可で使われる。
admin ユーザのクレデンシャルを取得
kubectl で使うクレデンシャルを取得します。そのときに、Admin権限のものを取得しておきます。
az aks get-credentials --resource-group myResourceGroup --name $aksname --admin
RBAC バインディング
ClusterRoleBindingを作成します。Admin権限が必要です。
basic-azure-ad-binding.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: contoso-cluster-admins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: userPrincipalName_or_objectId
一番最後の、ユーザプリンシパルの名前か、オブジェクトIDのところをちゃんと埋めるようにします。同じテナントの場合は、ユーザプリンシパル名を使い、そうでない場合は、オブジェクトIDを使うのが良いらしいです。これで、取得できます。
az ad signed-in-user show --query userPrincipalName -o tsv
UPN(UserPrincipalName)って何だろう?と思ってし食べたら、システムユーザの名前らしい。ってシステムユーザーって何?
先ほどの、yamlを適用します。
kubectl apply -f basic-azure-ad-binding.yml
テスト
Admin権限ではなく、一般のユーザの権限に戻します。
az aks get-credentials --resource-group myResourceGroup --name $aksname --overwrite-existing
この状態で、kubectlを実行します。
kubectl get pods
すると、ブラウザでの認証が求められて、そのあと結果が帰って来れば成功
$ kubectl get pods --all-namespaces
To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code <<SOMECODE>> to authenticate.
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-696c56cf6f-d24hz 1/1 Running 0 44m
kube-system coredns-696c56cf6f-s97d4 1/1 Running 0 40m
kube-system coredns-autoscaler-bc55cb685-qh765 1/1 Running 0 44m
kube-system heapster-5678f88989-km7kr 2/2 Running 0 40m
kube-system kube-proxy-hbj7k 1/1 Running 0 41m
kube-system kubernetes-dashboard-7b749f655b-cp654 1/1 Running 1 44m
kube-system metrics-server-5b7d5c6f8d-m5l9h 1/1 Running 1 44m
kube-system tunnelfront-5db696d55d-h5997 1/1 Running 0 44m
では次は、セキュリティグループを使って、グループに対して、権限を付与するケースを試します。