At this year’s Ignite conference Microsoft announced the next major step of integrating Azure functionality into AKS: Azure RBAC for Kubernetes authorization.
-> https://docs.microsoft.com/en-us/azure/aks/manage-azure-rbac
Azure RBAC for Kubernetes authorization lets you assign built-in or custom roles onto the Azure Kubernetes Service object in Azure. So, you do not have to create Kubernetes roles and role bindings in Kubernetes assigning permissions to your developers.
Yes, you read it correctly with Azure RBAC for Kubernetes authorization you do your Kubernetes access management in Azure instead in Kubernetes itself.
The only requirement your AKS cluster needs to fulfill is the usage of the managed AAD integration. Also sometimes called the AAD integration v2. Besides the following limitations apply to the currently available preview version.
- Only new clusters are supported. Existing will be supported with the GA version.
- kubectl v1.18.3 or higher
- New role assignments can take up to 5 minutes to be pushed to the Kubernetes API server
- AAD tenant for the subscription and the managed AAD integration must be the same
- CRDs are not represented as data actions when it comes to custom role definitions. But they can be covered with Microsoft.ContainerService/managedClusters/*/read as data action.
Four built-in roles are available at the time of writing.
- Azure Kubernetes Service RBAC Reader
- Azure Kubernetes Service RBAC Writer
- Azure Kubernetes Service RBAC Admin
- Azure Kubernetes Service RBAC Cluster Admin
Those four built-in roles matching the permission set of the following Kubernetes cluster roles.
- view
- edit
- admin
- cluster-admin
Let us now dive in assigning one of the built-in roles and creating a custom role for our AKS cluster.
Built-in role – Azure Kubernetes Service RBAC Reader
In our first scenario we assign the Azure Kubernetes Service RBAC Reader role to the kube-system namespace. Yes, it is possible to do a role assignment on the whole cluster or only on a specific namespace.
I am using the following Azure CLI command assigning the Azure Kubernetes Service RBAC Reader role to my Azure AD user object onto the kube-system namespace.
> RESOURCE_ID="/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/azst-aks-demo/providers/Microsoft.ContainerService/managedClusters/azst-aks-demo" > az role assignment create --role "Azure Kubernetes Service RBAC Reader" \ --assignee xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ --scope $RESOURCE_ID/namespaces/kube-system
As seen in the screenshot, a role assignment on a child resource is not represented in the Azure portal.
Instead download the role assignments and select only Children.
There we go. As seen in the downloaded report, our role assignment was successful.
[ { "RoleAssignmentId": "20e9b3be-4924-4bb4-80b5-59393d8b0513", "Scope": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/azst-aks-demo/providers/Microsoft.ContainerService/managedClusters/azst-aks-demo/namespaces/kube-system", "DisplayName": "Daniel Neumann", "SignInName": "REDACTED", "RoleDefinitionName": "Azure Kubernetes Service RBAC Reader", "RoleDefinitionId": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Authorization/roleDefinitions/7f6c6a51-bcf8-42ba-9220-52d62157d7db", "ObjectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "ObjectType": "User" } ]
The Kubernetes permissions itself are represented as data actions in the Azure RBAC system.
Using kubectl to show the pods in the kube-system namespace works as intended.
> kubectl get pods -n kube-system To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code REDACTED to authenticate. NAME READY STATUS RESTARTS AGE aks-link-54b67dd945-5rwvs 2/2 Running 0 6h55m aks-link-54b67dd945-xfh69 2/2 Running 0 7h11m azure-policy-78c78fdfb4-zw78l 1/1 Running 0 6h55m azure-policy-webhook-75b4fffd8c-qhhbc 1/1 Running 0 6h55m calico-node-7mg46 1/1 Running 0 7h11m calico-node-dtp85 1/1 Running 0 7h11m calico-node-hvmxt 1/1 Running 0 7h9m calico-typha-deployment-5664ccf987-5rxmn 1/1 Running 0 6h55m calico-typha-horizontal-autoscaler-78dd9bb4b5-lp4mp 1/1 Running 0 6h55m coredns-748cdb7bf4-68ggr 1/1 Running 0 6h55m coredns-748cdb7bf4-jbdrg 1/1 Running 0 6h55m coredns-autoscaler-868b684fd4-2jxvr 1/1 Running 0 6h55m kube-proxy-gvfk6 1/1 Running 0 50m kube-proxy-qf9zv 1/1 Running 0 50m kube-proxy-zh74s 1/1 Running 0 51m metrics-server-58fdc875d5-x2qgg 1/1 Running 0 6h55m omsagent-2d4h7 1/1 Running 1 7h11m omsagent-6bs4v 1/1 Running 0 7h9m omsagent-mtk7f 1/1 Running 0 7h11m omsagent-rs-7cb7c7fb4-9sf56 1/1 Running 1 7h12m
Doing the same on another namespace throws a permission denied message.
> kubectl get pods -n gatekeeper-system Error from server (Forbidden): pods is forbidden: User "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" cannot list resource "pods" in API group "" in the namespace "gatekeeper-system": User does not have access to the resource in Azure. Update role assignment to allow access.
What is working with kubectl does not work with the Kubernetes resource view in the Azure portal as the resource view requires permission to list all namespaces on an AKS cluster.
We will solve this with a custom role.
Custom role – AKS Namespace Viewer
We have seen how to use one of the built-in roles but sometimes we need a custom role.
The following JSON body describes the role definition we want to create to list all namespaces on an AKS cluster.
{ "name": "AKS Namespace Viewer", "description": "Lets you view all namespaces.", "actions": [], "notActions": [], "dataActions": [ "Microsoft.ContainerService/managedClusters/namespaces/read" ], "notDataActions": [], "assignableScopes": [ "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ] }
The role only gives read access to resources of the type namespaces.
We use the Azure CLI again to do the role assignment after creating the role definition.
> JSON=' { "name": "AKS Namespace Viewer", "description": "Lets you view all namespaces.", "actions": [], "notActions": [], "dataActions": [ "Microsoft.ContainerService/managedClusters/namespaces/read" ], "notDataActions": [], "assignableScopes": [ "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ] } ' > az role definition create --role-definition $JSON > RESOURCE_ID="/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/azst-aks-demo/providers/Microsoft.ContainerService/managedClusters/azst-aks-demo" > az role assignment create --role "AKS Namespace Viewer" \ --assignee xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ --scope $RESOURCE_ID
Afterwards we can view pods in the kube-system namespace via the Kubernetes resource view in the Azure portal.
You find the full reference which data action for AKS are currently available on Azure docs.
Summary
I hope the Azure RBAC for Kubernetes authorization feature will GA soon. As this is a game changer on how to do permission assignments on an AKS cluster.
The good news is that permission assignments via roles and role bindings are still possible. So, for Kubernetes service accounts nothing changes. Furthermore, you can fallback to default Kubernetes mechanisms when a specific operation is not available yet as data action for AKS.