Simplifying FedRAMP Compliance with Teleport
Jun 27
Register Today
Teleport logoTry For Free
Home > Teleport Academy > Authentication and Privileges


Posted 15th Aug 2023 by Ben Arent


In this article, we will explore configuring Role-Based Access Control (RBAC) for Microsoft Azure Managed Kubernetes Service (AKS). Azure Kubernetes Service is Microsoft's managed Kubernetes service that makes it easy to run Kubernetes on Azure, on-premises, and at the edge. As teams have adopted Kubernetes, they need to set up role-based access control RBAC to limit who can access which pods, namespace, users and roles.

This post will provide a range of options for RBAC for AKS, with practical guides for using open-source Teleport to provide RBAC for both AKS and on-premises AKS clusters.

Key takeaways:

  • The basics of configuring RBAC for Kubernetes
  • Scaling az role assignment and azure rbac
  • How to provide pod-level access and RBAC to your team
  • Best practices for providing access to a Kubernetes user
  • How to securely share a Kubernetes group amount users
  • How to audit access to the Kubernetes API, including kubectl exec session recordings

Prerequisites: This article assumes that you have deployed a Teleport cluster and an AKS cluster, either with your AKS cluster via our helm chart or connected via Teleport Cloud. If you don’t have an AKS cluster, we recommend using `az aks create` azure cli to create the appropriate resources.

Options for configuring Kubernetes RBAC

Role-based access control is a method of regulating access to resources based on the roles of an individual user. For example, the DevOps team may need full access to Kubernetes, but software engineering might only have access to pods in the development namespace. RBAC is often combined with a central IDP and SSO provider, such as Okta, Active Directory, Managed ActiveDirectory, Azure AD or GitHub. These IDPs often contain extra metadata, such as groups. These groups are often used in combination with IDPs.

The core logical components of RBAC are:

  • Entity: A group, user or service account (an identity representing an application that wants to execute certain operations — actions — and requires permissions to do so).
  • Resource: A pod, service or secret that the entity wants to access using certain operations.
  • Role: Used to define rules for the actions the entity can take on various resources.
  • Role binding: This attaches (binds) a role to an entity, stating that the set of rules defines the actions permitted by the attached entity on the specified resources.

There are two types of Roles (Role, ClusterRole) and their respective bindings (RoleBinding, ClusterRoleBinding). These differentiate between authorization in a namespace or cluster-wide. For this article, we’ll be mainly focusing on how end users access a Kubernetes cluster and will focus on Kubernetes Groups, Users and Namespaces. For the purposes of this tutorial, we’re focused on human operators accessing Kubernetes. If you’re interested in machines / CI/CD interacting with Kubernetes, we recommend using MachineID.

A good way to know what a Kubernetes / kubectl user can currently do is to use `kubectl auth can-i --list`.

$ kubectl auth can-i --list$ kubectl auth can-i create pods --all-namespaces


Authorize actions in clusters using AKS role-based access control

Azure offers a range of options for defining RBAC. While Azure role-based access control (RBAC) provides a powerful and flexible way to manage permissions, there are some limitations:

  1. Granularity: Although Azure RBAC provides fine-grained control, it might not be granular enough for specific scenarios. The permissions are based on pre-defined roles, and while you can create custom roles, you can't define permissions at the individual resource level. For example, it lacks the ability to provide per-pod RBAC (more details below).
  2. Inheritance: RBAC permissions are inherited from the parent scope, which can sometimes lead to confusion or accidental permission assignments. For example, when assigning a role at the subscription level, the permissions are inherited by all resource groups and resources within that subscription. It's important to understand the inheritance model and use it wisely.
  3. Complexity: Managing RBAC roles and assignments can become complex, particularly in large organizations with multiple subscriptions, resource groups, and resources. Maintaining a clear understanding of roles, permissions, and inheritance requires good documentation and organization.
  4. No built-in support for temporary access: Azure RBAC doesn't have built-in support for temporary access to resources. If you want to grant temporary access, you'll need to implement custom solutions or rely on third-party tools. Just-in-time Access Requests are a good solution to this problem.
  5. Limited support for non-Azure resources: Azure RBAC is designed for managing access to Azure resources. If you need to manage access to resources outside of Azure, such as on-premises servers or other cloud platforms, you'll need to use other identity and access management solutions.
  6. No dynamic role assignments: RBAC role assignments are static, meaning you can't automatically change role assignments based on attributes or conditions. For dynamic access control, you'll need to consider other solutions like Azure Active Directory (AAD) Conditional Access. Using Azure Active Directory (AD) as a SSO provider for Teleport helps consolidate access into a central platform.
  7. Auditability: Although Azure provides logs and monitoring for RBAC changes, tracking and auditing role assignments and permissions can be challenging. It's important to integrate these logs with your organization's monitoring and auditing tools.

When setting up a new cluster, AKS will create a ‘cluster-admin’ role. This role has elevated privilege and we recommend applying the principle of least privilege to Kubernetes access.

Map SSO users to Kubernetes users and groups

Using Single Sign-On (SSO) for accessing the Kubernetes API offers several benefits that can enhance the security and usability of your Kubernetes cluster resources. Here are some reasons to consider SSO for Kubernetes API access:

  1. Simplified user management: SSO allows users to have a single set of credentials to access multiple applications, including the Kubernetes API. With the ability to map azure ad groups to Kubernetes groups and roles.
  2. Improved security: By centralizing user authentication, SSO enables organizations to implement consistent security policies, such as multi-factor authentication (MFA) and password complexity requirements, across all applications, including Kubernetes.
  3. Role-based access control (RBAC) integration: SSO can be easily integrated with Kubernetes RBAC, allowing administrators to map roles and permissions to users or groups managed by the IDP. This enables fine-grained access control over Kubernetes resources, ensuring that users only have access to the resources they need.

While this article is focused on RBAC, we have a complete guide for setting up SSO with AKS.

RBAC to Kubernetes users

In this section, we’ll look into authenticating to a Kubernetes cluster via Teleport; your Teleport roles must allow access as at least one Kubernetes user or group.

Step 1: Create a new Kubernetes user with limited access

Start by getting new Azure credentials, before creating the ServiceAccount, say 'readonlyuser'.

az aks get-credentials
kubectl create serviceaccount readonlyuser

Create cluster role, say 'readonlyuser'.

kubectl create clusterrole readonlyuser --verb=get --verb=list --verb=watch --resource=pods

Create cluster role binding, say 'readonlyuser'.

kubectl create clusterrolebinding readonlyuser --serviceaccount=default:readonlyuser --clusterrole=readonlyuser

This will create a new read only users that’s only able to watch pods. This is a restricted role.

Step 2: Create a RBAC rule in Teleport

Create a file called kube-access.yaml with the following content.

## teleport yaml
kind: role
  name: kube-access-readonly
version: v6
      '*': '*'
      - kind: pod
        namespace: "*"
        name: "*"
    - readonlyuser
  deny: {}

Apply your changes:

tctl create -f kube-access-readonly.yaml

Step 3: Assign that role to a user in Teleport

Assign the kube-access role to your Teleport user by running the following commands, depending on whether you authenticate as a local Teleport user or via the GitHub, SAML, or OIDC authentication connectors.

Now that Teleport RBAC is configured, you can authenticate to your Kubernetes cluster via Teleport. Log out of Teleport and log in again. When you log in using `tsh kube login` you’ll get a new kubeconfig with the current permissions.

tsh login --proxy=teleport --auth=github
tsh kube login cookie
kubectl version
kubectl get pods
kubectl config view

RBAC for Kubernetes namespaces and pods

In this section, we’ll set up RBAC that’ll limit access to Kubernetes resources, by limiting access to pods and nodes using Kubernetes namespaces. Note: namespaces are often used as a security boundary, but a Kubernetes namespace is not a security boundary in itself because there are things that are not namespaced, so there is no way to correlate security criteria to the namespace accurately. Learn more about securing Kubernetes from the Hacking Kubernetes episode of our Access Control podcast.

Step 1: Decide how you want to divide Kubernetes namespaces

Before setting up per-pod RBAC it’s important to know what namespaces and pods you have within a cluster. `kubectl get pods –all-namepsaces` is a helpful command to list all pods within a cluster.

kubectl get pods --all-namespaces

NAMESPACE        NAME                                       READY   STATUS        RESTARTS   AGE
kube-system      coredns-6f5f9b5d74-7g8rz                   1/1     Running       0          14d
kube-system      calico-node-4d7fz                          1/1     Running       0          14d
ingress          nginx-ingress-microk8s-controller-h56nn    0/1     Pending       0          14d
kube-system      hostpath-provisioner-69cd9ff5b8-wtqt6      1/1     Running       0          14d
ingress          nginx-ingress-microk8s-controller-l7hj5    1/1     Running       0          14d
kube-system      calico-node-vkfpl                          1/1     Running       0          18d
default          shell-demo                                 1/1     Running       0          14d
kube-system      calico-kube-controllers-69f8d4c8f6-2j6dg   0/1     Terminating   0          18d
kube-system      calico-kube-controllers-69f8d4c8f6-hz2wf   1/1     Running       0          14d
colormatic       colormatic-784db57b6-j7v6p                 1/1     Running       0          11d
teleport-agent   teleport-agent-0                           1/1     Running       0          14d

Step 2: Define a Teleport role

Next we’ll define a new Teleport role, kube-access; this role has a few RBAC mechanisms.

Here is a summary of what this role can do:

  1. Kubernetes labels: The role allows access to resources with specific labels. In this case, it permits access to resources with the label 'region' set to any value (denoted by '*') and the label 'platform' set to 'minikube'.
  2. Kubernetes resources: The role permits access to certain Kubernetes resources based on their kind, namespace and name.
  • For resources of kind 'pod' in the 'production' namespace, access is granted only if the name matches the regular expression "^webapp-[a-z0-9-]+$". This means that the name must start with "webapp-" followed by lowercase letters, digits or hyphens.
  • For resources of kind 'pod' in the 'development' namespace, access is granted for all names (denoted by '*').
  1. Kubernetes groups: The role grants access to the 'developers' group.
  2. Kubernetes users: The role grants access to the 'minikube' user.
  3. Deny: There are no explicit deny rules in this role configuration.
kind: role
  name: kube-access
version: v6
      'region': '*'
      'platform': 'minikube'
      ‘name’: ‘clustername’
      - kind: pod
        namespace: "production"
        name: "^webapp-[a-z0-9-]+$"
      - kind: pod
        namespace: "development"
        name: "*"
    - developers
    - minikube
  deny: {}

Create the role using ‘tctl create’.

tctl create kube-access.yaml

Step 3: Create the role & assign to user

Next, we’ll assign this new role to our Azure AD SSO connector. In this case, we’ve added ‘kube-acess’ to the `trainee-graviton` group.

kind: github


name: github


client_id: x

client_secret: x

display: github




- organization: asteroid-earth


- access

- kube-access

team: trainee-graviton

version: v3

See this Teleport docs webpage for other options.

Step 4: Access resources

The last step is to test the setup. In this case we’ll use Azure AD provider via Teleport to obtain a new kubeconfig.

tsh login --proxy=teleport --auth=azure

tsh kube login cookie

kubectl version

kubectl get pods

RBAC for Kubernetes gGroup

Kubernetes groups are useful for sharing a specific set of permissions for a group. E.g. the SRE team can access resources, and Developers can only view deployed pods. When combined with SSO, using external groups and Kubernetes groups, it can greatly simplify the access controls for kubernetes. By using Kubernetes groups in combination with Teleport, teams also get a per- user audit log for actions on the kubectl API or via kubectl execs.

Step 1: Create a new Kubernetes Group

Create a file called viewers-bind.yaml with the following contents:


kind: ClusterRoleBinding


name: viewers-crb


- kind: Group

# Bind the group "viewers", corresponding to the kubernetes_groups we assigned our "kube-access" role above

name: viewers



kind: ClusterRole

# "view" is a default ClusterRole that grants read-only access to resources

# See:

name: view


Apply the ClusterRoleBinding with kubectl:

kubectl apply -f viewers-bind.yaml

Step 2: Create Teleport RBAC mapping

Next we’ll create a Teleport RBAC mapping. This yaml file is used to provide access to the viewer group above.

kind: role


name: kube-access

version: v6




'*': '*'


- kind: pod

namespace: "*"

name: "*"


- viewers



deny: {}

Apply your changes:

tctl create -f kube-access.yaml

Step 3: Access Kubernetes cluster

The last step is to test the setup. In this case we’ll use GitHub SSO provider via Teleport to obtain a new kubeconfig.

tsh login --proxy=teleport --auth=github

tsh kube login cookie

kubectl version

kubectl get pods

Authentication flow for Kubernetes

If you’ve followed any of the above guides for setting up Kubernetes RBAC with Teleport, the end flow will look something like this.

tsh login --proxy=teleport --auth=github

tsh kube login cookie

kubectl exec --stdin --tty shell-demo -- /bin/bash

RBAC to Kubernetes Dashboard

Along with the underlying Kubernetes API, it’s important to secure any apps or admins tools such as the Kubernetes dashboard that also run in Kubernetes. This is possible using the Access Module.

Sharing Azure CLI

Since Teleport is a platform, we recommend using Teleport to protect Azure Portal and CLIs with Teleport Application Access. We cover this topic in more detail in Protect Azure CLIs with Teleport Application Access.


This article has covered three main areas that you may consider for Kubernetes RBAC for teams accessing k8s and providing access to Kubernetes users, groups and per-pod RBAC.  The examples highlight the capabilities of Teleport — here’s where you can try Teleport Team for 14 days free.

Other related posts: