How to Grant Access to the Kubernetes API
By default no access is granted to applications in Kubernetes. So we have to explicitly allow access to the parts of the API that your applications need.
Kubernetes includes a built-in role-based access control (RBAC) mechanism that enables you to configure specific sets of permissions that define how a given user (or group of users) can interact with any Kubernetes object in a specific Namespace of your cluster.
The RBAC API declares four kinds of Kubernetes object: Role, ClusterRole, RoleBinding and ClusterRoleBinding. In this article, I'll focus on Role and RoleBinding.
How can we grant access to the Kubernetes API?
Kubernetes provides two resources that control the access to the API:
- Role: specifies what access is granted (set of permissions). When we create a Role, we need to specify the Namespace it belongs in.
- RoleBinding: specifies who the Role applies to (links a Role to subjects).
Create a Role
Here is a yaml configuration file you can use to create a Role
that let us list the pods and get information on a particular pod:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: my-role
namespace: my-namespace
labels:
app: my-rbac-app
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "list"] # verbs to act on the that resource
A Role in isolation doesn't do anything until we bind it with a RoleBinding, so let's do that in the next step.
Create a RoleBinding
Here is a yaml configuration file you can use to create a RoleBinding
that give this role ("my-role") to all service accounts in the default namespace, meaning that all pods will have access to these APIs:
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in "my-namespace" namespace.
# You need to already have a Role named "my-role" in that namespace.
kind: RoleBinding
metadata:
name: my-rolebinding
namespace: my-namespace
labels:
app: my-rbac-app
subjects:
# You can specify more than one "subject"
- kind: Group
name: system:serviceaccounts # "name" is case sensitive
apiGroup: rbac.authorization.k8s.io
namespace: my-namespace
roleRef:
# "roleRef" specifies the binding to a Role
kind: Role #this must be Role
name: my-role # this must match the name of the Role you wish to bind to
apiGroup: ""
Create a Service Account
The best practice in security is to give as few permissions as possible. Kubernetes recommends to grant a role to an application-specific service account. This requires the application to specify a serviceAccountName
in its pod spec and for the service account to be created.
Here is a yaml configuration file you can use to create a basic ServiceAccount
:
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: my-namespace
labels:
app: my-rbac-app
We can start a pod with a ServiceAccount
by adding that to it's spec definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: my-namespace
labels:
app: my-app
rbac: my-service-account
spec:
replicas: 1
selector:
matchLabels:
app: my-app
namespace: my-namespace
rbac: my-service-account
template:
metadata:
labels:
app: my-app
namespace: my-namespace
rbac: my-service-account
spec:
serviceAccountName: my-service-account
containers:
- name: my-container
image: nginx:1.7.9
In the pod spec you can see serviceAccountName: my-service-account
. The pod will be run as this ServiceAccount
and all containers started from it will be running under that ServiceAccount
.
Last step is to apply all yaml files in the repository:
$ kubectl apply -f my-role.yaml -f my-rolebinding.yaml -f my-serviceaccount.yaml -f my-deployment.yaml -n my-namespace
For more information related to RBAC Authorization, please check the Kubernetes documentation.