The next task is to add a new user who will have access to check pods state and watch logs – any other operations must be prohibited.
AWS EKS uses AWS IAM for authentification in a Kubernetes cluster (check the Kubernetes: part 4 – AWS EKS authentification, aws-iam-authenticator and AWS IAM post for details), bot the authorization, e.g. to determine if a user has permissions for specific operations – Kubernetes uses its own Role-Based Authorization Control mechanism.
Previous parts of this series:
- Kubernetes: part 1 – architecture and main components overview
- Kubernetes: part 2 – a cluster set up on AWS with AWS cloud-provider and AWS LoadBalancer
- Kubernetes: part 3 – AWS EKS overview and manual EKS cluster set up
- Kubernetes: part 4 – AWS EKS authentification, aws-iam-authenticator and AWS IAM post for details
Let’s first take a quick overview of RBAC in general, and then create a new user with necessary permissions.
Kubernetes RBAC overview
Documentation – Authorization Overview and Using RBAC Authorization.
RBAC model in Kubernetes consists of the three main components:
- Roles: defines permissions boundaries
- Subjects: Users (human or an application), or user groups
- RoleBingdings: specifies which Subjects have which Roles
RBAC Role
A Role example named example-role which allows access to the mynamespace with get
, watch
, and list
operations:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: mynamespace
name: example-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
To obtain Kubernetes apiGroups
one can use kubectl api-resources
:
kubectl api-resources -o wide
NAME SHORTNAMES APIGROUP NAMESPACED KIND VERBS
...
pods po true Pod [create delete deletecollection get list patch update watch]
...
In the rules
above we:
-
apiGroups: [""]
– set core API group -
resources: ["pods"]
– which resources are allowed for access -
["get", "watch", "list"]
– which actions are allowed over the resources above
RBAC RoleBingding
To “map” those permissions to users we are using Kubernetes RoleBingding
, which sets example-role in the mynamespace for the example-user user:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-rolebinding
namespace: mynamespace
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: example-role
apiGroup: rbac.authorization.k8s.io
Here we set:
-
subjects
:-
kind: User
– an object type which will have access, in our case this is a regular user -
name: example-user
– a user’s name to set the permissions
-
-
roleRef
:-
kind: Role
– what exactly will be attached to the user, in this case, it is theRole
object type -
name: example-role
– and the role name as it was set in thename: example-role
in the example above
-
Role
vs ClusterRole
Alongside with the Role
and ClusterRole
which are set of rules to describe permissions – Kubernetes also has RoleBinding
and ClusterRoleBinding
objects.
The difference is that Role
is used inside of a namespace, while ClusterRole
is cluster-wide permission without a namespace boundaries, for example:
- allow access to a cluster nodes
- resources in all namespaces
- allow access to endpoints like
/healthz
A ClusterRole
looks similar to a Role with the only difference that we have to set its kind
as ClusterRole
:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrole
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
And a ClusterRoleBinding
example:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example-clusterrolebinding
subjects:
- kind: User
name: example-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: example-clusterrole
apiGroup: rbac.authorization.k8s.io
Keep in mind that once you’ll create a Binding you’ll not be able to edit its roleRef
value – instead, you’ll have to delete a Binding and recreate and again
EKS Authentification and Authorization
In a short, the Authentification and Authorization process flow is the next:
-
Authentification
- a client makes a request to a Kubernetes cluster passing the client’s token with a user’s ID
- Kubernetes using
aws-iam-authenticator
asks AWS IAM to check if such a user really exist and is he is really who he claims to be
-
Authorization
- if the user passed the Authentification step – Kubernetes sens him over the RBAC mechanism with all user’s data and action requests
- Kubernetes looks for a
RoleBinding
which maps a user with a Role - by a Rolу name, Kubernetes will check the user’s permissions
- and finally, Kubernreteds will allow or decline the user’s request
Next, we will:
- create an IAM user
- configure AWS CLI
- add an RBAC Role with the read-only permissions to pods
- add an RBAC RoleBinding to connect our user and the Role
IAM user
Let’s begin by creating an IAM user.
Add a new one with the only Programmatic Access:
Save its keys:
IAM policy
If a user will need to have access to the AWS API, for example, to get a list of clusters – need to add an IAM policy for him.
Go to the Policies – Add Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:ListClusters"
],
"Resource": "*"
}
]
}
Here we are allowing only two API calls – eks:DescribeCluster
and eks:ListClusters
, in all regions for all EKS clusters.
Save it and attach to the user:
AWS CLI config
To configure kubectl
, first we need to configure our AWS CLI, we can do it in a dedicated CLI profile, check the AWS: CLI named profiles post:
$ aws configure --profile eks-ro-user
AWS Access Key ID [None]: AKI***FYC
AWS Secret Access Key [None]: SzH***VGi
Default region name [None]: eu-north-1
Default output format [None]: json
Check the user ID you are using now:
$ aws --profile eks-ro-user sts get-caller-identity
{
"UserId": "AID***XGK",
"Account": "534***385",
"Arn": "arn:aws:iam::534***385:user/eks-ro-user"
}
And check access to the EKS clusters (better to say access to the AWS API):
$ aws --profile eks-ro-user eks list-clusters --output text
CLUSTERS eks-alb-testing-3
CLUSTERS eks-alb-testing-2
Kubernetes RBAC – an example
Role
Now, let’s create a real user and a Role.
We’ll begin from creating a Role to allow access to pods, their logs and to create a port-forwarding, and only for the get
, list
, create
operations:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: eks-ro-role
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/portforward"]
verbs: ["get", "list", "create"]
Apply it:
$ kubectl apply -f rbac-role.yml
role.rbac.authorization.k8s.io/eks-ro-role created
And check:
$ kubectl get roles -o yaml
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"eks-ro-role","namespace":"default"},"rules":[{"apiGroups":[""],"resources":["pods","pods/log"],"verbs":["get","list"]}]}
creationTimestamp: "2020-03-24T10:34:27Z"
name: eks-ro-role
namespace: default
resourceVersion: "681997"
selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/roles/eks-ro-role
uid: 09a78b6f-6dbb-11ea-827f-0a9eb3e1782e
rules:
- apiGroups:
- ""
resources:
- pods
- pods/log
verbs:
- get
- list
kind: List
metadata:
resourceVersion: ""
selfLink: ""
RoleBinding
The next thing is to add a RoleBinding to map our username and the Role created above:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: eks-ro-role-binding
subjects:
- kind: User
name: eks-ro-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: eks-ro-role
apiGroup: rbac.authorization.k8s.io
Apply:
$ kubectl apply -f rbac-rolebinding.yml
rolebinding.rbac.authorization.k8s.io/eks-ro-role-binding created
aws-auth ConfigMap
As we are using AWS – need to update the aws-auth ConfigMap
(see the AWS EKS aws-auth ConfigMap):
$ kubectl edit configmap aws-auth -n kube-system
Add the mapUsers
and specify the user’s ARN, name and his group(s):
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::534***385:role/eksctl-eks-alb-testing-2-nodegrou-NodeInstanceRole-M6BS1WV48RLR
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- userarn: arn:aws:iam::534***385:user/eks-ro-user
username: eks-ro-user
groups: eks-ro-role
Save, and check it:
$ kubectl get pods --as eks-ro-user
NAME READY STATUS RESTARTS AGE
nginx-7db9fccd9b-7d4rq 1/1 Running 0 58m
Try to get Worker Nodes – we did not gave access to this resource:
$ kubectl get nodes --as eks-ro-user
Error from server (Forbidden): nodes is forbidden: User "eks-ro-user" cannot list resource "nodes" in API group "" at the cluster scope
Great!
Now, let’s see a pod’s logs – run a port-forwarding to a testing pod with NGINX:
$ kubectl --as eks-ro-user port-forward nginx-7db9fccd9b-7d4rq 8000:80
Forwarding from 127.0.0.1:8000 -> 80
Forwarding from [::1]:8000 -> 80
Make a request to the pod:
$ curl -I localhost:8000
HTTP/1.1 200 OK
And check its logs:
$ kubectl --as eks-ro-user logs -f nginx-7db9fccd9b-7d4rq
127.0.0.1 - - [25/Mar/2020:07:29:06 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.69.1" "-"
Done.
Useful links
- Authentication and Authorization in Kubernetes
- Privilege escalation via pod creation
- Authenticating Across Clusters with kubeconfig
- Granting User Access to Your Kubernetes Cluster
- How to Add Limited Access IAM Users to an EKS Cluster
- Managing Users or IAM Roles for your Cluster
- Kubernetes Authorization
- How do I provide access to other users and roles after cluster creation in Amazon EKS?
- How do I manage permissions across namespaces for my IAM users in an Amazon EKS cluster?
- Amazon EKS Identity-Based Policy Examples
- Kubernetes RBAC — giving permissions for logging and port-forwarding
- Add new user to manage AWS EKS
- Configuring permissions in Kubernetes with RBAC
Top comments (1)
Excellent post series on complex aspect of kubernetes. Check this RBAC tool
github.com/alcideio/rbac-tool