Kubernetes authorization

Set up authorization policies for cluster state updates

view on github

Requests authorization follows an allow list pattern: explicit policies must be set to allow state updates.


Table of contents

  1. Request types
  2. Authorization configuration
  3. Authorizers
  4. RBAC
  5. Node

Request types

Resource requests

  • Any request to kube-apiserver that includes an API group AND an API version is a resource request :
    • Specs for supported resource requests are available in the openapi API.
    • Resource requests can target cluster resources as well as workload resources.
    • kube-apiserver supports mutiple verbs for resource requests.
    • Authorized resource requests can lead to desired cluster state updates.
  • Examples: /api/v1, /apis/apps/v1, /apis/apps/v1/namespaces/{ns}/deployments/{dp}/status, etc ...

Non-resource requests

  • Any request to kube-apiserver not including an API group and version is a non-resource request :
    • Non-resources requests are not documented in the openapi API.
    • Non-resource requests exist mainly for cluster observability purposes.
    • As a result, kube-apiserver only supports GET for non-resource requests.
    • Authorized non-resource requests do not update the desired cluster state.
  • Examples : /api, /apis, /metrics/*, /healthz/*, etc ...

Authorization configuration

  • Authorizations are configured the same way for resource and non-resource requests.
  • Observability solutions relying on non-resource requests usually ship with the required authorizations.
  • As a result, authorization configuration for non-resource requests is considered out of scope for this document.

Authorizers

  • Relevant attributes for authorization are read from requests and evaluated against configured authorizers.
  • Configured authorizers for kube-apiserver can be set up with the --authorization-mode option.
  • For simplicity's sake, this document will focus on kubeadm init default authorizers RBAC and Node.
  • The following authorizers are relevant but considered out of scope :
    • ABAC authorizes requests based on attributes: this approach is too granular for practical use.
    • WebHook delegates authorization to an external system and is not needed for most use cases.

RBAC

  • Role-based authorization policies are implemented in the API group rbac.authorization.k8s.io/v1.
  • This API provides a set of resource types for management of authorization policies as part of the cluster state.
  • PolicyRule is a subresource authorizing verbs for an API version and a resource type.
  • The discovery API exposes supported resource types for all API groups and versions.
  • For instance, GET /apis/apps/v1 will list resource types for named API group apps.
  • resources for PolicyRule objects may refer to :
    • singular resource types if the verbs acts on a single resource.
    • plural resource types if the verbs acts on a collection of resources.
  • Role and ClusterRole objects store sets of permissions as lists of PolicyRule objects.
  • Role objects are namespaced as opposed to ClusterRole objects :
    • Role permissions only apply to objects in the same namespace.
    • ClusterRole permissions apply to all objects in the cluster.
  • Permissions for non namespaced objects (cluster resources) can only be managed using ClusterRole.
  • Subject is a subresource referencing the origin user of an authenticated request.
  • kind for Subject objects can be User (for normal users), ServiceAccount or Group.
  • RoleBinding and ClusterRoleBinding objects bind lists of Subject objects to existing roles :
    • RoleBinding objects are namespaced as opposed to ClusterRoleBinding objects.
    • RoleBinding restricts permissions granted by the role to objects in the same namespace.
    • ClusterRoleBinding systematically allows every permission granted by the role.
  • The roleRef property for both objects is immutable: the referenced role cannot change.

Built-in RBAC policies

  • When configured, the RBAC authorizer automatically provisions roles and bindings :
# list bindings and roles and mappings for default RBAC policies
kubectl get clusterrolebindings -l kubernetes.io/bootstrapping=rbac-defaults
kubectl get rolebindings -l kubernetes.io/bootstrapping=rbac-defaults --all-namespaces
  • Matching those policies against user groups provide default authorization settings for requests.

  • Most roles and bindings are reserved for component authorization (controllers, etc ...) except :

    ClusterRoleBinding Group subject description
    cluster-admin system:masters Full cluster control
    system:discovery system:authenticated Read discovery API
    system:basic-user system:authenticated Create self-subject reviews
    system:public-info-viewer Everyone Read version and health API

Notes :

  • Additional provisioning of RBAC policies is also done by kubeadm as well as by installed add-ons.
  • Modifying RBAC objects can lead to privilege escalation, however K8s performs additional security checks.
  • kubectl auth reconcile can be used as an alternative to kubectl apply to update RBAC objects without removing any existing permission: however, using it is not recommended.

  • The default configured, special purpose Node authorizer authorizes kubelet requests to kube-apiserver.
  • The default configured NodeRestriction admission controller restricts kubelet write requests to :
    1. Updates of the Node object for its own node.
    2. Updates of the Pod objects for pods running on its own node.
    3. Creation of Events.
    4. Creation of CSRs and self-review objects.
  • RBAC defaults also provision a system:node role and binding that seem to mirror Node permissions :
# YAML list of allowed verbs and resource types for the system:node role
kubectl get clusterrole system:node -o JSON | \
jq -r '.rules[] | {groups: (.apiGroups | join(", ")), resources: (.resources | join(", ")), verbs: (.verbs | join(", "))} | "- group: \(.groups)\n  resources: \(.resources)\n  verbs: \"\(.verbs)\""'
  • However, it is unsure whether or not those permissions are actually considered by the Node authorizer.