« Previous 1 2 3 4 Next »
Secure access to Kubernetes
Avoiding Pitfalls
Accounts for Humans
Authenticating a human user with a certificate works in a similar way. First, generate a certificate signing request (CSR). It is important to store the username as a CommonName (CN) and map all the desired group memberships via organizations. With OpenSSL, this would be:
$ openssl req -new -keyout testuser.key -out testuser.csr -nodes -subj "/CN=testuser/O=app1"
Now sign the request with the CA certificate and the key of the Kubernetes cluster. If you use the ca
command in OpenSSL, you will typically have to modify openssl.cnf
to remove mandatory fields like country
.
The user then packs the certificate, including the key, into their ~/.kube/config
file. Instead of the token:
element in the service account, the client-certificate-data
and client-key-data
fields exist in the user context. They contain the Base64-encoded version of the certificate and private key, which the YAML configuration file expects in one line. If OpenSSL is used to generate the certificate, only the block between BEGIN CERTIFICATE
and END CERTIFICATE
is relevant and needs to be packaged.
Roles and Authorization
Now two entities are accessing the cluster that have passed the first step of authentication mentioned at the beginning, but they do not yet have any rights in the cluster. To change this, you need to shift the configuration focus to the authorization section.
The first concept you need to look into here is the role, which describes the goal of an action. The attributes of a role include:
- the namespace in which the role acts,
- the function it performs (read, write, create something, and so on),
- the type of objects it accesses (pods, services), and
- the API groups to which it belongs and that extend the Kubernetes API.
Besides the normal role that applies within a namespace, the ClusterRole
applies to the entire Kubernetes cluster. Kubernetes manages roles through the API (i.e., you can work at the command line with kubectl
).
YAML files describe the roles. Listing 3 shows a role file that allows an entity to read active pods. If you want to create a cluster role, you instead need to enter ClusterRole
in the kind
field and delete the namespace
entry from metadata
. Now, save the definition as pod-reader.yml
and create the role by typing:
Listing 3
Role as a YAML File
01 apiVersion: rbac.authorization.k8s.io/v1 02 kind: Role 03 metadata: 04 namespace: default 05 name: pod-reader 06 rules: 07 - apiGroups: [""] # "" stands for the core API group 08 resources: ["pods"] 09 verbs: ["get", "watch", "list"]
kubectl apply -f pod-reader.yml
Again, be sure to pay attention to the namespace in which you do this.
The question still arises as to who is allowed to work with the rights of this role. Enter RoleBinding
or ClusterRoleBinding
, with which you can assign users and service accounts to existing roles.
In concrete terms, Kubernetes determines in the first step of an incoming API request whether or not the user is allowed to authenticate at all. If this is the case, it tries to assign a role to the user with RoleBinding
. If this also works, Kubernetes finds out which rights the user has on the basis of the role found and then checks whether the request is within the permitted scope.
To specifically link testserviceaccount
and testuser
created previously with the pod-reader
role, you would create the RoleBinding
action (Listing 4). After creating the bindings, testuser
can finally read the pods in the default
namespace with kubectl get pods
.
Listing 4
RoleBinding Example
01 apiVersion: rbac.authorization.k8s.io/v1 02 kind: RoleBinding 03 metadata: 04 name: read-pods 05 namespace: default 06 subjects: 07 - kind: User 08 name: testuser 09 apiGroup: rbac.authorization.k8s.io 10 - kind: ServiceAccount 11 name: testserviceaccount 12 roleRef: 13 kind: Role 14 name: pod-reader 15 apiGroup: rbac.authorization.k8s.io
Role Behavior
If you want to manage what a user can access, you need to restrict the role. For example, some resources are arranged hierarchically. If testuser
should only be able to access the logs
child resource of the pods
resource, the entry under resources
in the role definition in Listing 4 is "pods/logs"
.
Once you have created your Kubernetes cluster with kubeadm
, you will see a ClusterRole
named cluster-admin
that provides full access. If you assign this role to a user, the user has unrestricted access privileges.
To avoid an inflation of single roles, at least on the level of the entire cluster, you can have aggregated roles among ClusterRoles
. In this case, the individual roles are assigned a label
field with a specific value. The aggregated role then gathers all roles that have a label with this value and thus forms a union of all these roles. A ClusterRole
created in this way can again be used in the ClusterRoleBinding
, and a user assigned to the role then enjoys all the rights assigned to the role.
In addition to the role-based authorization described above, attribute-based authorization applies a more complicated set of rules to API-based access by kubelets. For example, the Node Authorizer evaluates the requests by reference to the sender. In webhook mode, Kubernetes first sends all API requests from the users in JSON format to an external REST service, which then replies with True or False .
« Previous 1 2 3 4 Next »
Buy this article as PDF
(incl. VAT)