Authorization

Details of Kubernetes authorization mechanisms and supported authorization modes.

Kubernetes authorization takes place following authentication. Usually, a client making a request must be authenticated (logged in) before its request can be allowed; however, Kubernetes also allows anonymous requests in some circumstances.

For an overview of how authorization fits into the wider context of API access control, read Controlling Access to the Kubernetes API.

Authorization verdicts

Kubernetes authorization of API requests takes place within the API server. The API server evaluates all of the request attributes against all policies, potentially also consulting external services, and then allows or denies the request.

All parts of an API request must be allowed by some authorization mechanism in order to proceed. In other words: access is denied by default.

Note:

Access controls and policies that depend on specific fields of specific kinds of objects are handled by admission controllers.

Kubernetes admission control happens after authorization has completed (and, therefore, only when the authorization decision was to allow the request).

When multiple authorization modules are configured, each is checked in sequence. If any authorizer approves or denies a request, that decision is immediately returned and no other authorizer is consulted. If all modules have no opinion on the request, then the request is denied. An overall deny verdict means that the API server rejects the request and responds with an HTTP 403 (Forbidden) status.

Request attributes used in authorization

Kubernetes reviews only the following API request attributes:

  • user - The user string provided during authentication.
  • group - The list of group names to which the authenticated user belongs.
  • extra - A map of arbitrary string keys to string values, provided by the authentication layer.
  • API - Indicates whether the request is for an API resource.
  • Request path - Path to miscellaneous non-resource endpoints like /api or /healthz.
  • API request verb - API verbs like get, list, create, update, patch, watch, delete, and deletecollection are used for resource requests. To determine the request verb for a resource API endpoint, see request verbs and authorization.
  • HTTP request verb - Lowercased HTTP methods like get, post, put, and delete are used for non-resource requests.
  • Resource - The ID or name of the resource that is being accessed (for resource requests only) — For resource requests using get, update, patch, and delete verbs, you must provide the resource name.
  • Subresource - The subresource that is being accessed (for resource requests only).
  • Namespace - The namespace of the object that is being accessed (for namespaced resource requests only).
  • API group - The API Group being accessed (for resource requests only). An empty string designates the core API group.

Request verbs and authorization

Non-resource requests

Requests to endpoints other than /api/v1/... or /apis/<group>/<version>/... are considered non-resource requests, and use the lower-cased HTTP method of the request as the verb. For example, making a GET request using HTTP to endpoints such as /api or /healthz would use get as the verb.

Resource requests

To determine the request verb for a resource API endpoint, Kubernetes maps the HTTP verb used and considers whether or not the request acts on an individual resource or on a collection of resources:

HTTP verbrequest verb
POSTcreate
GET, HEADget (for individual resources), list (for collections, including full object content), watch (for watching an individual resource or collection of resources)
PUTupdate
PATCHpatch
DELETEdelete (for individual resources), deletecollection (for collections)

Caution:

+The get, list and watch verbs can all return the full details of a resource. In terms of access to the returned data they are equivalent. For example, list on secrets will reveal the data attributes of any returned resources.

Kubernetes sometimes checks authorization for additional permissions using specialized verbs. For example:

  • Special cases of authentication
    • impersonate verb on users, groups, and serviceaccounts in the core API group, and the userextras in the authentication.k8s.io API group.
  • Authorization of CertificateSigningRequests
    • approve verb for CertificateSigningRequests, and update for revisions to existing approvals
  • RBAC
    • bind and escalate verbs on roles and clusterroles resources in the rbac.authorization.k8s.io API group.

Authorization context

Kubernetes expects attributes that are common to REST API requests. This means that Kubernetes authorization works with existing organization-wide or cloud-provider-wide access control systems which may handle other APIs besides the Kubernetes API.

Authorization modes

The Kubernetes API server may authorize a request using one of several authorization modes:

AlwaysAllow

This mode allows all requests, which brings security risks. Use this authorization mode only if you do not require authorization for your API requests (for example, for testing).

AlwaysDeny

This mode blocks all requests. Use this authorization mode only for testing.

ABAC (attribute-based access control)

Kubernetes ABAC mode defines an access control paradigm whereby access rights are granted to users through the use of policies which combine attributes together. The policies can use any type of attributes (user attributes, resource attributes, object, environment attributes, etc).

RBAC (role-based access control)

Kubernetes RBAC is a method of regulating access to computer or network resources based on the roles of individual users within an enterprise. In this context, access is the ability of an individual user to perform a specific task, such as view, create, or modify a file.
In this mode, Kubernetes uses the rbac.authorization.k8s.io API group to drive authorization decisions, allowing you to dynamically configure permission policies through the Kubernetes API.

Node

A special-purpose authorization mode that grants permissions to kubelets based on the pods they are scheduled to run. To learn more about the Node authorization mode, see Node Authorization.

Webhook

Kubernetes webhook mode for authorization makes a synchronous HTTP callout, blocking the request until the remote HTTP service responds to the query.You can write your own software to handle the callout, or use solutions from the ecosystem.

Warning:Enabling the AlwaysAllow mode bypasses authorization; do not use this on a cluster where you do not trust all potential API clients, including the workloads that you run.

Authorization mechanisms typically return either a deny or no opinion result; seeauthorization verdicts for more on this. Activating the AlwaysAllow means that if all other authorizers return “no opinion”, the request is allowed. For example, --authorization-mode=AlwaysAllow,RBAC has the same effect as --authorization-mode=AlwaysAllow because Kubernetes RBAC does not provide negative (deny) access rules.

You should not use the AlwaysAllow mode on a Kubernetes cluster where the API server is reachable from the public internet.

Authorization mode configuration

You can configure the Kubernetes API server’s authorizer chain using either command line arguments only or, as a beta feature, using a configuration file.

You have to pick one of the two configuration approaches; setting both --authorization-config path and configuring an authorization webhook using the --authorization-mode and --authorization-webhook-* command line arguments is not allowed. If you try this, the API server reports an error message during startup, then exits immediately.

Command line authorization mode configuration

FEATURE STATE: Kubernetes v1.8 [stable]

You can use the following modes:

  • --authorization-mode=ABAC (Attribute-based access control mode)
  • --authorization-mode=RBAC (Role-based access control mode)
  • --authorization-mode=Node (Node authorizer)
  • --authorization-mode=Webhook (Webhook authorization mode)
  • --authorization-mode=AlwaysAllow (always allows requests; carries security risks)
  • --authorization-mode=AlwaysDeny (always denies requests)

You can choose more than one authorization mode; for example: --authorization-mode=Node,Webhook

Kubernetes checks authorization modules based on the order that you specify them on the API server’s command line, so an earlier module has higher priority to allow or deny a request.

You cannot combine the --authorization-mode command line argument with the --authorization-config command line argument used for configuring authorization using a local file.

For more information on command line arguments to the API server, read the kube-apiserver reference.

Configuring the API Server using an authorization config fileFEATURE STATE: Kubernetes v1.30 [beta]As a beta feature, Kubernetes lets you configure authorization chains that can include multiple webhooks. The authorization items in that chain can have well-defined parameters that validate requests in a particular order, offering you fine-grained control, such as explicit Deny on failures.

The configuration file approach even allows you to specifyCEL rules to pre-filter requests before they are dispatched to webhooks, helping you to prevent unnecessary invocations. The API server also automatically reloads the authorizer chain when the configuration file is modified.

You specify the path to the authorization configuration using the --authorization-config command line argument.

If you want to use command line arguments instead of a configuration file, that’s also a valid and supported approach. Some authorization capabilities (for example: multiple webhooks, webhook failure policy, and pre-filter rules) are only available if you use an authorization configuration file.

Example configuration

  1. ---
  2. #
  3. # DO NOT USE THE CONFIG AS IS. THIS IS AN EXAMPLE.
  4. #
  5. apiVersion: apiserver.config.k8s.io/v1beta1
  6. kind: AuthorizationConfiguration
  7. authorizers:
  8. - type: Webhook
  9. # Name used to describe the authorizer
  10. # This is explicitly used in monitoring machinery for metrics
  11. # Note:
  12. # - Validation for this field is similar to how K8s labels are validated today.
  13. # Required, with no default
  14. name: webhook
  15. webhook:
  16. # The duration to cache 'authorized' responses from the webhook
  17. # authorizer.
  18. # Same as setting `--authorization-webhook-cache-authorized-ttl` flag
  19. # Default: 5m0s
  20. authorizedTTL: 30s
  21. # The duration to cache 'unauthorized' responses from the webhook
  22. # authorizer.
  23. # Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag
  24. # Default: 30s
  25. unauthorizedTTL: 30s
  26. # Timeout for the webhook request
  27. # Maximum allowed is 30s.
  28. # Required, with no default.
  29. timeout: 3s
  30. # The API version of the authorization.k8s.io SubjectAccessReview to
  31. # send to and expect from the webhook.
  32. # Same as setting `--authorization-webhook-version` flag
  33. # Required, with no default
  34. # Valid values: v1beta1, v1
  35. subjectAccessReviewVersion: v1
  36. # MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview
  37. # version the CEL expressions are evaluated against
  38. # Valid values: v1
  39. # Required, no default value
  40. matchConditionSubjectAccessReviewVersion: v1
  41. # Controls the authorization decision when a webhook request fails to
  42. # complete or returns a malformed response or errors evaluating
  43. # matchConditions.
  44. # Valid values:
  45. # - NoOpinion: continue to subsequent authorizers to see if one of
  46. # them allows the request
  47. # - Deny: reject the request without consulting subsequent authorizers
  48. # Required, with no default.
  49. failurePolicy: Deny
  50. connectionInfo:
  51. # Controls how the webhook should communicate with the server.
  52. # Valid values:
  53. # - KubeConfig: use the file specified in kubeConfigFile to locate the
  54. # server.
  55. # - InClusterConfig: use the in-cluster configuration to call the
  56. # SubjectAccessReview API hosted by kube-apiserver. This mode is not
  57. # allowed for kube-apiserver.
  58. type: KubeConfig
  59. # Path to KubeConfigFile for connection info
  60. # Required, if connectionInfo.Type is KubeConfig
  61. kubeConfigFile: /kube-system-authz-webhook.yaml
  62. # matchConditions is a list of conditions that must be met for a request to be sent to this
  63. # webhook. An empty list of matchConditions matches all requests.
  64. # There are a maximum of 64 match conditions allowed.
  65. #
  66. # The exact matching logic is (in order):
  67. # 1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
  68. # 2. If ALL matchConditions evaluate to TRUE, then the webhook is called.
  69. # 3. If at least one matchCondition evaluates to an error (but none are FALSE):
  70. # - If failurePolicy=Deny, then the webhook rejects the request
  71. # - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
  72. matchConditions:
  73. # expression represents the expression which will be evaluated by CEL. Must evaluate to bool.
  74. # CEL expressions have access to the contents of the SubjectAccessReview in v1 version.
  75. # If version specified by subjectAccessReviewVersion in the request variable is v1beta1,
  76. # the contents would be converted to the v1 version before evaluating the CEL expression.
  77. #
  78. # Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/
  79. #
  80. # only send resource requests to the webhook
  81. - expression: has(request.resourceAttributes)
  82. # only intercept requests to kube-system
  83. - expression: request.resourceAttributes.namespace == 'kube-system'
  84. # don't intercept requests from kube-system service accounts
  85. - expression: !('system:serviceaccounts:kube-system' in request.user.groups)
  86. - type: Node
  87. name: node
  88. - type: RBAC
  89. name: rbac
  90. - type: Webhook
  91. name: in-cluster-authorizer
  92. webhook:
  93. authorizedTTL: 5m
  94. unauthorizedTTL: 30s
  95. timeout: 3s
  96. subjectAccessReviewVersion: v1
  97. failurePolicy: NoOpinion
  98. connectionInfo:
  99. type: InClusterConfig

When configuring the authorizer chain using a configuration file, make sure all the control plane nodes have the same file contents. Take a note of the API server configuration when upgrading / downgrading your clusters. For example, if upgrading from Kubernetes 1.30 to Kubernetes 1.31, you would need to make sure the config file is in a format that Kubernetes 1.31 can understand, before you upgrade the cluster. If you downgrade to 1.30, you would need to set the configuration appropriately.

Authorization configuration and reloads

Kubernetes reloads the authorization configuration file when the API server observes a change to the file, and also on a 60 second schedule if no change events were observed.

Note:

You must ensure that all non-webhook authorizer types remain unchanged in the file on reload.

A reload must not add or remove Node or RBAC authorizers (they can be reordered, but cannot be added or removed).

Privilege escalation via workload creation or edits

Users who can create/edit pods in a namespace, either directly or through an object that enables indirect workload management, may be able to escalate their privileges in that namespace. The potential routes to privilege escalation include Kubernetes API extensions and their associated controllers.

Caution:

As a cluster administrator, use caution when granting access to create or edit workloads. Some details of how these can be misused are documented in escalation paths.

Escalation paths

There are different ways that an attacker or untrustworthy user could gain additional privilege within a namespace, if you allow them to run arbitrary Pods in that namespace:

  • Mounting arbitrary Secrets in that namespace
    • Can be used to access confidential information meant for other workloads
    • Can be used to obtain a more privileged ServiceAccount’s service account token
  • Using arbitrary ServiceAccounts in that namespace
    • Can perform Kubernetes API actions as another workload (impersonation)
    • Can perform any privileged actions that ServiceAccount has
  • Mounting or using ConfigMaps meant for other workloads in that namespace
    • Can be used to obtain information meant for other workloads, such as database host names.
  • Mounting volumes meant for other workloads in that namespace
    • Can be used to obtain information meant for other workloads, and change it.

Caution:

As a system administrator, you should be cautious when deploying CustomResourceDefinitions that let users make changes to the above areas. These may open privilege escalations paths. Consider the consequences of this kind of change when deciding on your authorization controls.

Checking API access

kubectl provides the auth can-i subcommand for quickly querying the API authorization layer. The command uses the SelfSubjectAccessReview API to determine if the current user can perform a given action, and works regardless of the authorization mode used.

  1. kubectl auth can-i create deployments --namespace dev

The output is similar to this:

  1. yes
  1. kubectl auth can-i create deployments --namespace prod

The output is similar to this:

  1. no

Administrators can combine this with user impersonation to determine what action other users can perform.

  1. kubectl auth can-i list secrets --namespace dev --as dave

The output is similar to this:

  1. no

Similarly, to check whether a ServiceAccount named dev-sa in Namespace dev can list Pods in the Namespace target:

  1. kubectl auth can-i list pods \
  2. --namespace target \
  3. --as system:serviceaccount:dev:dev-sa

The output is similar to this:

  1. yes

SelfSubjectAccessReview is part of the authorization.k8s.io API group, which exposes the API server authorization to external services. Other resources in this group include:

SubjectAccessReview

Access review for any user, not only the current one. Useful for delegating authorization decisions to the API server. For example, the kubelet and extension API servers use this to determine user access to their own APIs.

LocalSubjectAccessReview

Like SubjectAccessReview but restricted to a specific namespace.

SelfSubjectRulesReview

A review which returns the set of actions a user can perform within a namespace. Useful for users to quickly summarize their own access, or for UIs to hide/show actions.

These APIs can be queried by creating normal Kubernetes resources, where the response status field of the returned object is the result of the query. For example:

  1. kubectl create -f - -o yaml << EOF
  2. apiVersion: authorization.k8s.io/v1
  3. kind: SelfSubjectAccessReview
  4. spec:
  5. resourceAttributes:
  6. group: apps
  7. resource: deployments
  8. verb: create
  9. namespace: dev
  10. EOF

The generated SelfSubjectAccessReview is similar to:

  1. apiVersion: authorization.k8s.io/v1
  2. kind: SelfSubjectAccessReview
  3. metadata:
  4. creationTimestamp: null
  5. spec:
  6. resourceAttributes:
  7. group: apps
  8. resource: deployments
  9. namespace: dev
  10. verb: create
  11. status:
  12. allowed: true
  13. denied: false

What’s next