Securing Kubernetes [Authentication & Authorization ]

One of the cyber security discipline is Identity Access Management. Identity and access management controls “who has access to the system” [Authentication] and “what type(read/write/modify/delete) of access ]” [Authorization] .

Before jumping to authorization I will quickly touch base on identity and authentication. 

Identity/ Users 

A general model of identity can be constructed from a small set of axioms. In general, an entity (real or virtual) can have multiple identities and each identity can have multiple attributes

Kubernetes clusters have two types of users  1. Service accounts managed by kubernetes. 2. Normal users Normal users, can be stored in external directory as keystone, Active Directory or even in a file. Kubernetes itself does not store any normal users. Service accounts, these are managed by kubernetes API. They are bound to specify namespaces and can be created through API calls. 

Kubernetes API call are either tied to these (normal users / service ) accounts or are treated as anonymous request. This means any kubetcl command typed on command line or other wise should be tied to a type of account for authentication or will treated as anonymous user.

Authentication 

Below are some of the Kubernetes methods to authenticate through authentication plugins

  1. Client Certificates - for example , Client certificate authentication is enabled by passing the --client-ca-file=SOMEFILE option to API server. 
  2. Bearer tokens - The API server reads bearer tokens from a file when given the --token-auth-file=SOMEFILE option on the command line. When using bearer token authentication from an http client, the API server expects an Authorization header with a value of Bearer THETOKEN. A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests. 
  3. Authenticating Proxy / HTTP Basic auth - Basic authentication is enabled by passing the --basic-auth-file=SOMEFILE option to API server. The API server expects an Authorization header with a value of Basic BASE64ENCODED(USER:PASSWORD)
  4. Service account tokens - A service account is an automatically enabled authenticator that uses signed bearer tokens to verify requests.
  5. Webhook Token Authentication - Webhook authentication is a hook for verifying bearer tokens. You can describe the configuration by pasing config file path with parameter - --authentication-token-webhook-config-file

    Authentication time out can be defined by following parameter —authentication-token-webhook-cache-ttl. To make the it more secure we can enable multi factor authentication. Integration with other authentication protocols(LDAP, SAML etc) can be accomplished through Authenticating proxy. 

 Life Cycle of Authentication request against the API: If an organization has configured LDAP for signed tokens and system is also configured to respond web hook token authenticator requests 

  1. The user issues a kubectl command.
  2. Credential plugin prompts the user for LDAP credentials, exchanges credentials with external service for a token.
  3. Credential plugin returns token to client-go, which uses it as a bearer token against the API server.
  4. API server uses the webhook token authenticator to submit a TokenReview to the external service.
  5. External service verifies the signature on the token and returns the user’s username and groups.

Securing private keys and rotation of certificates

First step is to generate certificates for authentication but critical keeping everything secure is rotation of SSH certificates and keys. We can implement this through Privilege Access Manager(PAM), we can onboard the kubernetes service accounts and store the SSH certificates and private key into encrypted vaulting system. PAM can then be configured to rotate private keys and SSH certificates on appropiate servers. 

Authorization 

There are four authorization modules in kubernetes Nodes, ABAC, RBAC , Webhook

In this post I will just talk about ABAC and RBAC For any infrastructure, ensuring the reliability, security, and efficiency is critical but it quickly gets complicated. Kubernetes access can be controlled though ABAC and Role-based access control RBAC.

 Here policies can use any type of attributes (user attributes, resource attributes, object, environment attributes, etc).

Attribute-Based Access Control(ABAC)

Kubernetes Attribute-Based access control ABAC is powerful but very complex while RBAC is easier to manage using tool like kubetl and the Kubernetes API directly. Attribute-based access control (ABAC) defines an access control paradigm whereby access rights are granted to users through the use of policies which combine attributes together. This mode is not enabled by default . 

To enforce ABAC 

  • Create policies - File format of policy file is one jSON object per line 
 {“apiVersion": "abac.authorization.kubernetes.io/v1beta1", 
  "kind": "Policy", "spec": 
{"user": "alice", "namespace": "*", "resource": "*", "apiGroup": "*"}}
  • Enable ABAC - specify --authorization-policy-file=SOME_FILENAME and --authorization-mode=ABAC on startup

Authorization flow

  1. A request has attributes which correspond to the properties of a policy object
  2. Request is received attributes are determined 
  3. Property set to “*” will match corresponding attribute
  4. Tuple of attributes are checked for a match against every policy int he policy file. 

Role-based access control (RBAC)

RBAC is a method of regulating access to system /nfrastructure resources based on the roles of individual users within an enterprise. Enable RBAC - Start API server with these arguments --authorization-mode=RBAC

In kubernetes servers are grouped under namespaces so multiple namespaces makes a cluster. RBAC uses the rbac.authorization.k8s.io API group to drive authorization decisions, allowing admins to dynamically configure policies through the Kubernetes API

Role  In RBAC API, a role contains rules that represent a set of permissions.A role can be defined within a namespace. A Role can only be used to grant access to resources within a single namespace. In a RBAC rule, permissions are defined as verbs.

Cluster Role  Role whose scope is a cluster is known as cluster role. These role can assign access any namespaces resources across all namespaces in a cluster. 

Roles

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

Cluster Roles

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

a role definition contains kind, apiVersion, and metadata, but with the addition of rules. You can specify what resources within apiGroup(s) are permitted and how they can be accessed using verbs (including create, delete, delete, collection, get, list, patch, update, and watch).

Role / Cluster Role bindings 

A role binding grants the permissions defined in a role to a user or set of users. It holds users/groups/service accounts and reference to the role being granted. 

We use RoleBinding for binding role within namespace whereas clusterRoleBinding has cluster-wide scope.

roleRef is how you will actually create the binding. Below role boning example grants “pod-read” access to the user “jack” with the namespace default

In the example below, this RoleBinding is using roleRef to bind the user “Andrew” to the Role created above named pod-reader.

kind: RoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: read-pods

  namespace: default

subjects:

- kind: User

  name: Andrew

  apiGroup: rbac.authorization.k8s.io

roleRef:

  kind: Role

  name: pod-reader

  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding may be used to grant permission at the cluster level and in all namespaces. In the example below , ClusterRoleBinding allows any user in the group “manager” to read secrets in any namespace.

kind: ClusterRoleBinding  
apiVersion: rbac.authorization.k8s.io/v1     
metadata:                 
name: read-secrets-global                                                                                                    
subjects:                                                                                                                                            
 - kind:  Group                                                                                                                           
name: manager                                                                                                                            
apiGroup: rbac.authorization.k8s.io                                                                                                                           
roleRef:                                                                                                                                                                                       
 kind: ClusterRole                                                                                                                           
name: secret-reader                                                                                                                           
apiGroup: rbac.authorization.k8s.io

In roleBinding we may reference the role in the same namespace. Multiple roles can also be aggregated. 

Refer resources in bindings Resources can be defined through the URL, for example if we need to get log from the pods. Here log is sub resource of the pod. GET /api/v1/namespaces/{namespace}/pods/{name}/log

To define this is kubernetes RBAC role, you would write

kind: Role

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  namespace: default

  name: pod-and-pod-logs-reader

rules:

- apiGroups: [""]

  resources: ["pods", "pods/log"]

  verbs: ["get", "list"]

Best Practise 

Applying least privilege is crucial. 

 1. Avoid wild cards in verbs when creating a rule

 2. Assign permission if required, in a way of on request bases. 

 3. Avoid use of cluster roles and use roles insated.

Automate request access for kubernetes

 To keep the access in check one more way is to implement Governance tool. Iim tool will allow you to know if there any trailing access with a developer of user. You can also automate the access request. 

You can populate all the roles in request catalogue of the tool and a user can login in to the and request role is requires. This will then klick off request approval module. 

Check least privilege required

By integrating any IAM tool we also inherit all the functionalities that a IAM toll tools provides like least privilege access, monitoring. You generate access certification / attestation which will allow developer’s manager to remove any trailing or not needed access.

In conclusion, kubernetes has mature authentication and authorization API and we take help of Privilege Access Manager or Identity Manger tool to make secure. 

To view or add a comment, sign in

More articles by Deepak Pandey

Others also viewed

Explore content categories