KEP-5284: Constrained Impersonation
KEP-5284: Constrained Impersonation
- Release Signoff Checklist
- Summary
- Motivation
- Proposal
- Design Details
- Production Readiness Review Questionnaire
- Implementation History
- Drawbacks
- Alternatives
Release Signoff Checklist
Items marked with (R) are required prior to targeting to a milestone / release.
- (R) Enhancement issue in release milestone, which links to KEP dir in kubernetes/enhancements (not the initial KEP PR)
- (R) KEP approvers have approved the KEP status as
implementable - (R) Design details are appropriately documented
- (R) Test plan is in place, giving consideration to SIG Architecture and SIG Testing input (including test refactors)
- e2e Tests for all Beta API Operations (endpoints)
- (R) Ensure GA e2e tests meet requirements for Conformance Tests
- (R) Minimum Two Week Window for GA e2e tests to prove flake free
- (R) Graduation criteria is in place
- (R) all GA Endpoints must be hit by Conformance Tests
- (R) Production readiness review completed
- (R) Production readiness review approved
- “Implementation History” section is up-to-date for milestone
- User-facing documentation has been created in kubernetes/website , for publication to kubernetes.io
- Supporting documentation—e.g., additional design documents, links to mailing list discussions/SIG meetings, relevant PRs/issues, release notes
Summary
This is to add additional access control over the existing impersonation action. An impersonator who impersonates another user is required to have the additional permissions to impersonate on certain group resources and verbs. In order for the request to succeed, the impersonated principal must have permission to perform the request, just like before.
Motivation
Today an impersonator can impersonate another user if the impersonator has the permission of
- verbs: ["impersonate"]
resources: ["users"]
resourceNames: ["someUser"]
However, current impersonation mechanism is the “unrestricted impersonation” (or “legacy impersonation”), the impersonator can get more power through impersonation. And because of this, it is strongly suggested not to allow the controller to impersonate. More detailed discussion is in this issue
There are use cases that needs a controller to be able to impersonate:
- A controller impersonates a node the controller is running on. This happens when per-node agents (CNI plugins for instance), want to read pods on a given node instead of unrestricted pod access.
- A controller runs as a deputy, receives request from the user, and impersonates the user to start/stop virtual machine or access vm console managed by kubevirt.
This proposal is to introduce additional permissions for impersonation, so that any impersonator can impersonate in a more restricted way.
Goals
- Define required permission rules for the impersonator to impersonate on certain resource/verb.
- Provide clear example on what permission the impersonator and user should have for the impersonator to impersonate user’s certain verbs on certain resources.
- This is an opt-in feature and existing impersonation flows keep working as-is.
- Client side semantics of impersonation is unchanged, the existing impersonation headers are re-used and no new headers are added.
Non-Goals
- Adding impersonator’s info to user.Info, so authorization webhooks can know both info of impersonated user and the requester.
Proposal
Introduce a set of verbs with prefix of impersonate-on:<mode>:, e.g. impersonate-on:user-info:create and
impersonate-on:arbitrary-node:get. The impersonator needs to have these verbs with certain resources to
impersonate.
Introduce verbs in the impersonate:<mode> format:
impersonate:user-infolimits the impersonator to impersonate “generic” users. The resources must beusers/uids/groups/userextrasand the user must not be a node (username with a prefix ofsystem:node:) and the user must not be a service account (username with a prefix ofsystem:serviceaccount:). The resource names must be usernames, uids, group names or values in the user extras accordingly.impersonate:serviceaccountthat limits the impersonator to impersonate the serviceaccount with the certain namespace/name. The resource must beserviceaccounts.impersonate:arbitrary-nodethat limits the impersonator to impersonate the node only. The resource must benodes, and the resourceName should be the name of the node. The impersonator must have this verb to impersonate a node.impersonate:associated-nodethat limits the impersonator to impersonate the node the impersonator is running on. The resources must benodes. For a controller impersonating the node that it is running on, it will need to know the node name obtained via downward API:
env:
- name: MY_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
and then set in the kubeconfig:
kubeConfig, _ := clientcmd.BuildConfigFromFlags("", "")
kubeConfig.Impersonate = rest.ImpersonationConfig{
UserName: "system:node:" + os.Getenv("MY_NODE_NAME"),
}
Two permissions will be required for impersonation. An example of how to express
“system:serviceaccount:default:default can impersonate a user named someUser solely to list
and watch pods in the default namespace” using Kubernetes RBAC:
- The permission to constrained impersonate a certain user. This is a cluster scoped permission.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: constrained-impersonate-only-someUser
rules:
- apiGroups:
- authentication.k8s.io
resources:
- users # allowed resources are users/groups/userextras/uids
resourceNames:
- someUser
verbs:
- impersonate:user-info
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: constrained-impersonate-only-someUser
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: constrained-impersonate-only-someUser
subjects:
- kind: ServiceAccount
name: default
namespace: default
- The permission to impersonate on certain resource with certain verbs. This can be either
cluster scoped or namespace scoped. Note that the verbs are prefixed with
impersonate-on:<mode>:so that permissions from different modes do not overlap.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: impersonate-allow-only-listwatch-pods
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- impersonate-on:user-info:list
- impersonate-on:user-info:watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: impersonate-allow-only-listwatch-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: impersonate-allow-only-listwatch-pods
subjects:
- kind: ServiceAccount
name: default
namespace: default
These permissions define: “The impersonator can impersonate a user with the name of
someUser to list and watch pods in the default namespace.”
Subject Access Review Details
When receiving an impersonation request to list pods cluster-wide from the user impersonator
with the header of Impersonate-User:someUser, the apiserver:
- Verifies if the impersonator has the permission to impersonate with the scope of the user. A subjectaccessreview is sent to the authorizer:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: users
name: someUser
verb: impersonate:user-info
user: impersonator
- Verifies if the impersonator has the permission to impersonate the target action with a subjectaccessreview request:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
resource: pods
namespace: default
verb: impersonate-on:user-info:list
user: impersonator
- Allows the impersonation if the above two conditions are met
- If the above check fails, verifies if the impersonator has the legacy
impersonatepermission, allow the impersonation if the condition met. A subjectaccessreview is sent to the authorizer:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
resource: users
name: someUser
verb: impersonate
user: impersonator
The impersonator does not need the permission for the target action.
workflow when the feature is enabled
flowchart TD
A[receive request] --> |feature enabled| B{Identify the target user via impersonation header}
B --> |Impersonate-User has the prefix of system:node:|C{The requester is on the same node}
C --> |yes| D{Requester is authorized to impersonate the target action with impersonate-on:associated-node:< verb >}
C --> |no| E{Requester is authorized to impersonate the target action with impersonate-on:arbitrary-node:< verb >}
D --> |yes| F{Requester is authorized to impersonate the target user/uid/groups/extra with impersonate:< mode >}
D --> |no| E
E --> |yes| F
E --> |no| H
F -->|yes| G[Allow]
A -->|feature disable| H{Requester has the legacy impersonate permission}
H -->|yes| G
F -->|no| H
B --> |Impersonate-User has the prefix of system:serviceaccount:| I{Requester is authorized to impersonate the target action with impersonate-on:serviceaccount:< verb >}
I --> |yes| F
I --> |no| H
B --> |Impersonate-User does not have the prefix of system:serviceaccount: or system:node:| J{Requester is authorized to impersonate the target action with impersonate-on:user-info:< verb >}
J --> |yes|F
J --> |no|HUser Stories (Optional)
Story 1
As a controller, I want to impersonate node I am running on to list/get pods on the node. The service account of the controller should have the permissions as below to perform the action:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate:arbitrary-node
rules:
- apiGroups:
- authentication.k8s.io
resources:
- nodes
verbs:
- impersonate:associated-node
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: impersonate:arbitrary-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: impersonate:arbitrary-node
subjects:
- kind: ServiceAccount
name: default
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate:arbitrary-node:list
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- impersonate-on:associated-node:list
- impersonate-on:associated-node:get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: impersonate:arbitrary-node:list
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: impersonate:arbitrary-node:list
subjects:
- kind: ServiceAccount
name: default
namespace: default
Story 2
As a controller, I am working as a deputy, receiving any user’s request to access virtual machine console
in the default namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate-user:vm:console
rules:
- apiGroups:
- authentication.k8s.io
resources:
- users
verbs:
- impersonate:user-info
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: impersonate-user:vm:console
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: impersonate-user:vm:console
subjects:
- kind: ServiceAccount
name: deputy
namespace: deputy-ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: impersonate:vm:console:get
namespace: default
rules:
- apiGroups:
- subresources.kubevirt.io
resources:
- virtualmachines/console
verbs:
- impersonate-on:user-info:get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: impersonate:vm:console:get
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: impersonate:vm:console:get
subjects:
- kind: ServiceAccount
name: deputy
namespace: deputy-ns
Risks and Mitigations
Permissions across authorization checks are unioned
This design works around the limitations of the SubjectAccessReview API by performing multiple checks.
Since the permissions are granted separately, the subject always has the union of all permissions.
This means it is not possible to express something like “The impersonator can impersonate a user with
the name of someUser to list and watch pods in the default namespace and can impersonate
someOtherUser to create secrets in the default namespace.” Instead, you can only express the
union of the permissions: “The impersonator can impersonate a user with the name of someUser or
someOtherUser to list and watch pods or create secrets in the default namespace.
This is an acceptable tradeoff as this design is still far safer than the existing impersonation flow
and does not require any changes to authorization or the SubjectAccessReview API. We specifically
include the mode in the impersonate-on:<mode>:<verb> check to prevent this unioning across modes.
The verbs with impersonate-on:<mode>: prefix has been used by other component.
There is possibility that the verbs with prefix of impersonate-on:<mode>: have been
used by other component, and been set in Role/ClusterRole. Since impersonate:<mode>
permission is also required for impersonator, the component will not get more
power when permission of impersonate-on:<mode>: is given.
High request volume leads to high load on authorization chain.
For the associated node case, it is possible that a high request volume node agent could be constantly performing impersonated requests, each of which would add two extra authorization checks. This could put load on the authorization chain. Comparing to other alternatives which would also introduce at least one authorization check for each request call, the proposal is able to satisfy more use cases. We will include some caching with short TTLs in the implementation to amortize the cost of these checks.
Delegating permission of impersonating wildcard action or wildcard subjects is not supported
Permissions must be delegated using specified verbs with the prefix of impersonate: and
impersonate-on:. Expressing a permission to impersonate ANY subject or ANY action is not
possible, since the authorization model does not have the concept of partial wildcard on verbs.
It should be ok since all these permission for constrained impersonation are strictly additive which
means it should be added when certain impersonation requests are needed.
Design Details
Verb impersonate:user-info
Same as legacy impersonation, when the request has header of Impersonate-User,
Impersonate-Group, Impersonate-Uid or Impersonate-Extra-, apiserver will check
verb impersonate:user-info with the related resources.
Header Impersonate-User is set
A subjectaccessreview
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: users
name: someUser
verb: impersonate:user-info
user: impersonator
will be sent to the authorizer
Header Impersonate-Group is set
A subjectaccessreview
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: groups
name: someGroup
verb: impersonate:user-info
user: impersonator
will be sent to the authorizer for each group.
Header Impersonate-Uid is set
A subjectaccessreview
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: uids
name: someUID
verb: impersonate:user-info
user: impersonator
will be sent to the authorizer.
Header with prefix Impersonate-Extra- is set
A subjectaccessreview
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: userextras
subresource: extraKey
name: extraValue
verb: impersonate:user-info
user: impersonator
will be sent to the authorizer for each key and value pair.
Verb impersonate:serviceaccount
Same as legacy impersonation, when the request has the header of Impersonate-User (and no other impersonation headers),
and the value of the header has a prefix of system:serviceaccount:, apiserver will check verb impersonate:serviceaccount
with the authorizer using the subjectaccessreview:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: serviceaccounts
name: serviceaccount-name
namespace: serviceaccount-namespace
verb: impersonate:serviceaccount
user: impersonator
Verb impersonate:arbitrary-node and impersonate:associated-node
When the request has the header of Impersonate-User (and no other impersonation headers), and the value has the prefix
of system:node:, this verb is checked instead of impersonate:user-info. The subjectaccessreview below will be sent
to the authorizer:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: nodes
name: someNode
verb: impersonate:arbitrary-node
user: impersonator
impersonate:associated-node is a special verb to check when two conditions are met:
- The impersonator is impersonating a node by setting the header
Impersonate-Userand the value has a prefix ofsystem:node:on the request. - The user info of the impersonator has an extra with key
authentication.kubernetes.io/node-name, and the value should be the same as the value in the request header ofImpersonate-Userafter removing prefixsystem:node:. It indicates that the impersonator is running on the same node it is impersonating.
The flow for checking these two verbs will be as following:
- If condition 1 is not met, verb
impersonate:user-infowill be checked instead if the impersonated user is not a SA or node. - If both conditions are met, the verb
impersonate:associated-nodewill be checked at first:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: nodes
verb: impersonate:associated-node
user: impersonator
- If check in step 2 is not passed, or only condition 1 is met, the verb impersonate:arbitrary-node will be checked:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
resourceAttributes:
group: authentication.k8s.io
resource: nodes
name: node1
verb: impersonate:arbitrary-node
user: impersonator
Auditing
Audit events already contain the impersonatedUser field to denote if impersonation was used.
To record the reason why the impersonation is allowed, a new sub-field impersonationConstraint will
be added under a new top level object called authenticationMetadata. The value will be the constrained impersonation
related verb. For example, impersonate:associated-node indicates that the impersonation request is
allowed because it impersonates an associated node. The specific action such as list or get
will not be included in the value given it can be inferred from the request itself.
There have been other feature requests that would fit under the authenticationMetadata object,
this KEP just happens to be the first design to reach implementation. When constrained impersonation
is not used, the impersonationConstraint field will not be set, and since it is currently the
only field in the authenticationMetadata object, that object will be omitted completely. This will
keep audit events generated from existing impersonation flows unchanged.
Example audit event where the system:admin user impersonates the panda user via constrained impersonation:
{
"kind": "Event",
"apiVersion": "audit.k8s.io/v1",
"level": "Metadata",
"auditID": "3eb9aee5-8edd-4663-be5f-a2a734ec1644",
"stage": "ResponseComplete",
"requestURI": "/api/v1/namespaces/default/pods?limit=500",
"verb": "list",
"user": {
"username": "system:admin",
"groups": [
"system:masters",
"system:authenticated"
],
"extra": {
"authentication.kubernetes.io/credential-id": [
"X509SHA256=29fd022fa9165a2a73d52a25f18f7752c2577898f846128668d956bf6b6cbb68"
]
}
},
"impersonatedUser": {
"username": "panda",
"groups": [
"system:authenticated"
]
},
"authenticationMetadata": { // this is a new object that may contain other data in the future
"impersonationConstraint": "impersonate:user-info" // this is the new field from this KEP
},
"sourceIPs": [
"::1"
],
"userAgent": "kubectl/v1.35.0 (darwin/arm64) kubernetes/801ee44",
"objectRef": {
"resource": "pods",
"namespace": "default",
"apiVersion": "v1"
},
"responseStatus": {
"metadata": {},
"status": "Failure",
"message": "pods is forbidden: User \"panda\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
},
"requestReceivedTimestamp": "2025-10-06T17:19:51.221674Z",
"stageTimestamp": "2025-10-06T17:19:51.222195Z",
"annotations": {
"authorization.k8s.io/decision": "forbid",
"authorization.k8s.io/reason": ""
}
}
Test Plan
[x] I/we understand the owners of the involved components may require updates to existing tests to make this code solid enough prior to committing the changes necessary to implement this enhancement.
Prerequisite testing updates
Unit tests
k8s.io/apiserver/pkg/endpoints/filters:2025/06/13-75.5%
Unit tests should cover authorization request with and without the feature enabled.
Integration tests
- SubjectAccessReview check on impersonating user.
- The impersonator can impersonate bob.
- The impersonator cannot impersonate alice.
- The impersonator can impersonate on listing and getting pods
- The impersonator cannot impersonate on updating pods
- The impersonator can impersonate on getting pods/exec subresource
- The impersonator cannot impersonate on get pods/log subresource For RBAC authz mode, this might look like:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate-bob
rules:
- apiGroups:
- authentication.k8s.io
resources:
- users
resourceNames:
- bob
verbs:
- impersonate:user-info
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: impersonate-pod-action
namespace: default
rules:
- resources:
- pods
- pod/exec
verbs:
- impersonate-on:user-info:list
- impersonate-on:user-info:get
SAR check on impersonating associated node with permissions. The impersonator has the user extra info of
"authentication.kubernetes.io/node-name": "node1"- The impersonator can impersonate node1.
- The impersonator cannot impersonate node2.
- The impersonator cannot impersonate bob.
- The impersonator can impersonate on listing pods.
- The impersonator cannot impersonate on updating pods,
with the permission like this:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: impersonate-associated-node
rules:
- apiGroups:
- authentication.k8s.io
resources:
- nodes
verbs:
- impersonate:associated-node
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: impersonate-pod-action
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- impersonate-on:associated-node:list
- SAR check on impersonating service account
- SAR check on impersonating nodes
Each test should cover positive and negative cases with multiple resources and verbs.
- Permission delegation:
- bob has the
impersonate:user-infopermission, and can delegate theimpersonate:user-infopermission to alice. - bob cannot delegate the
impersonate:arbitrary-nodepermission to alice. - bob has the
impersonate-on:user-info:listpermission onpodsresource, and can delegate the permission to alice. - bob cannot delegate the
impersonate-on:user-info:updatepermission onpodsresource to alice.
- bob has the
e2e tests
In addition to testing with unit and integration tests. E2E tests will be added covering below cases.
- A user cannot impersonate a subresource until the correct constrained impersonation permissions is set for the user.
- A sericeaccount with the correct constrained impersonation permission is able to impersonate the node to list pods.
An eventual conformance test is needed as part of GA.
Graduation Criteria
Alpha
- Feature implemented behind a feature flag
- Initial e2e tests completed and enabled
Beta
- Determine if additional tests are necessary
- Ensure reliability of existing tests
- Determine if some mechanism should be introduced to reduce the extra permission checks
- Alternatives have been reviewed, and we have consensus not to switch to an alternative approach.
GA
- At least one successful adoption of each user story (node agent and deputy).
- All bugs resolved and no new bugs requiring code change since the previous shipped release.
- Conformance tests are added.
Upgrade / Downgrade Strategy
On upgrade to a version that enables the feature
the previous impersonator with impersonate permission will still work, but it is highly recommended to use the new permissions with less privilege.
authorization webhooks needs to recognize the verb with prefix of
impersonate-on:andimpersonate:.
On downgrade to a version that does not enable the feature by default, or if the feature is disabled.
- No configuration is needed and the permission with
impersonate-on:<mode>:<verb>andimpersonate:<mode>verb will be ignored. - request sent to authorization webhooks will no longer include
impersonate-on:andimpersonate:verb.
Version Skew Strategy
New kube-apiserver, old impersonate permission
The impersonator will still be allowed to impersonate with unconstrained permission
Old kube-apiserver, new impersonate-on:<mode>:<verb> and impersonate:<mode> permission
The impersonator will be denied to impersonate. This is safer since the impersonator permission is not enlarged with old kube-apiserver.
Production Readiness Review Questionnaire
Feature Enablement and Rollback
How can this feature be enabled / disabled in a live cluster?
- Feature gate (also fill in values in
kep.yaml)- Feature gate name: ConstrainedImpersonation
- Components depending on the feature gate:
- kube-apiserver
Does enabling the feature change any default behavior?
No. Impersonator with existing impersonate permission will still be allowed to impersonate
Can the feature be disabled once it has been enabled (i.e. can we roll back the enablement)?
Yes. Set the feature gate to false and restart the kube-apiserver.
What happens if we reenable the feature if it was previously rolled back?
No additional configuration is needed.
Are there any tests for feature enablement/disablement?
Yes, this will be covered in the unit tests and integration tests.
Rollout, Upgrade and Rollback Planning
How can a rollout or rollback fail? Can it impact already running workloads?
There is no impact on rollout, the impersonator with existing impersonate permission can still perform the action.
When the system rollback, impersonator with impersonate-on: and impersonate: permission will no longer
be authorized to impersonate. Impersonator will need to have the unscoped impersonate permission.
What specific metrics should inform a rollback?
apiserver_authorization_decisions_total shows greatly increased number.
When webhook authorizer is used, if apiserver_authorization_webhook_evaluations_total and
apiserver_authorization_webhook_duration_seconds shows greatly increase number, users should
also pay attention.
See Monitoring Requirements below.
Were upgrade and rollback tested? Was the upgrade->downgrade->upgrade path tested?
Integration tests cover feature gate disablement and enablement.
Manual tests to cover upgrade->downgrade->upgrade:
- Deploy k8s 1.33
- create impersonate permissions for user bob and verify impersonation
- Upgrade to 1.34 and enable the
ConstrainedImpersonationfeaturegate. - Verify impersonation of user bob.
- create permission for constrained impersonation for user alice and verify impersonation
- Downgrade to 1.33. Verify impersonation for user bob and alice. Alice would not be able to impersonate while bob is able to.
Is the rollout accompanied by any deprecations and/or removals of features, APIs, fields of API types, flags, etc.?
No
Monitoring Requirements
There are existing metrics to record authz latency and request number:
- authorization latency
- authorization success
- webhook authorizer match condition latency
- webhook authorizer match condition success
These will be expanded to include metrics that cover the impersonation handler to give an overall sense for the cost of impersonation:
apiserver_impersonation_attempts_total{status}
This will be incremented whenever impersonation is attempted. On success, the
status label will capture which mode was successful. On failure, the status
label will be set to failed.
Labels and possible values:
status: associated-node, arbitrary-node, serviceaccount, user-info, legacy, failed
apiserver_impersonation_duration_seconds{status}
This is a Histogram metric that will track the time impersonation took to resolve
the impersonated user whenever impersonation is attempted. On success, the
status label will capture which mode was successful. On failure, the status
label will be set to failed.
Note that because of the caching performed within the handler, we expect this metric to reflect the amortized cost (in latency) of impersonation requests.
Labels and possible values:
status: associated-node, arbitrary-node, serviceaccount, user-info, legacy, failed
To give a sense for how many authorization checks are being performed, the following metrics will wrap all calls to the authorizer used by the handler:
apiserver_impersonation_authorization_attempts_total{mode, decision}
This will be incremented whenever an impersonation attempt causes the authorizer to be used.
Labels and possible values:
mode: associated-node, arbitrary-node, serviceaccount, user-info, legacy
decision: allowed, denied
apiserver_impersonation_authorization_duration_seconds{mode, decision}
This is a Histogram metric that will track the time the authorizer took whenever an impersonation attempt causes the authorizer to be used.
Labels and possible values:
mode: associated-node, arbitrary-node, serviceaccount, user-info, legacy
decision: allowed, denied
How can an operator determine if the feature is in use by workloads?
Check the metrics mentioned above as well as the audit logs.
How can someone using this feature know that it is working for their instance?
- Events
- Event Reason:
- API .status
- Condition name:
- Other field:
- Other (treat as last resort)
- Details: User creates the permission and check if the impersonate on certain action works. Confirm via audit logs that the expected impersonation mode was used.
What are the reasonable SLOs (Service Level Objectives) for the enhancement?
Use of this feature should not change existing API SLOs.
What are the SLIs (Service Level Indicators) an operator can use to determine the health of the service?
Use of this feature should not change existing API SLIs.
Are there any missing metrics that would be useful to have to improve observability of this feature?
No.
Dependencies
Does this feature depend on any specific services running in the cluster?
No.
Scalability
Will enabling / using this feature result in any new API calls?
Yes, enabling the feature will result in two additional SAR checks when kube-apiserver receives an impersonation request.
- A SAR request to check if the impersonator is authorized to impersonate the target user.
- A SAR request to check if the impersonater is authorized to perform the action via impersonation.
Successful impersonation attempts are cached for a short period to amortize the cost across multiple requests.
Will enabling / using this feature result in introducing new API types?
No.
Will enabling / using this feature result in any new calls to the cloud provider?
No.
Will enabling / using this feature result in increasing size or count of the existing API objects?
No.
Will enabling / using this feature result in increasing time taken by any operations covered by existing SLIs/SLOs?
The existing impersonation mechanism will introduce 1 access review for request with impersonation. While upon feature is enabled:
- When the check is passed, it will introduce 2-3 access review checks for request with impersonation.
- 2 access review check if the new access rule is passed.
- 3 access review check if the new access rule is not passed, and the legacy impersonate access rule is passed.
- When the check is disallowed, it will introduce 3 access review checks for request with impersonation.
Successful impersonation attempts are cached for a short period to amortize the cost across multiple requests.
Will enabling / using this feature result in non-negligible increase of resource usage (CPU, RAM, disk, IO, …) in any components?
NA
Can enabling / using this feature result in resource exhaustion of some node resources (PIDs, sockets, inodes, etc.)?
No, this feature does not touch nodes.
Troubleshooting
How does this feature react if the API server and/or etcd is unavailable?
This feature is fully contained within the API server.
What are other known failure modes?
- Impersonation permission is set but request is disallowed with external authorizer.
- Detection: metrics of
authorization successwill show the unauthorized requests - Mitigations: Stop sending the impersonation requests
- Diagnostics: APIServer log will show the reason why the request is unauthorized.
- Testing: There is no general test for that, user using external authorizer need to test for the specific authorizer.
- Detection: metrics of
What steps should be taken if SLOs are not being met to determine the problem?
Implementation History
- Kubernetes 1.34: Alpha version of the KEP.
Drawbacks
- Several additional authorization checks are added introducing some overhead.
Alternatives
Use impersonate:user-info instead of impersonate:serviceaccount and impersonate:arbitrary-node
Verb impersonate:serviceaccount and impersonate:arbitrary-node are special cases of verb
impersonate:user-info. Without these two verbs, it is still possible to use verb
impersonate:user-info with certain username, e.g. username with the prefix
system:serviceaccounts: or the prerix system:nodes. However, providing the two special
verbs would delegation of permissions and support more expressions:
- Verb
impersonate:serviceaccountcan support a permission to allow impersonating any serviceaccounts in a certain namespace. - Verb
impersonate:arbitrary-nodecan support a permission to allow impersonating any node.
Controller participation in SubjectAccessReview for impersonation
The controller can sends a SAR request, and then uses its own permission to perform the action. The main difference from impersonation is:
- the controller itself needs to have the permission for a certain action, while with impersonation
the controller does not need these permissions, but the permissions to
impersonate-oncertain action. - The audit log shows that controller performs the action, while with impersonatation audit log shows controller is impersonating and the target user performs the action.
- The admission chain is running against the controller, while with impersonation, the admission chain is running against the target user.
Setting a special APIGroup suffix instead of special verb
Instead of using the impersonate-on:<mode>:<verb> scheme, a special apigroup suffix/prefix can be set for
each resource to be impersonated, e.g. setting the apigroup with a suffix of .impersonation.k8s.io:
- apiGroups:
- apps.impersonation.k8s.io
resources:
- deployments
verbs:
- list
- watch
It is almost the same as the verb based approach in the proposal. However, since existing impersonation flows are verb based, so making the new flow verb based as well feels more consistent.
Check permission intersection of impersonator and target user
This is an approach to check intersected permission of the impersonator and the target user, and only allow the action if both have the correct permission. Comparing to the proposed approach: this approach requires the impersonator to have the permission who is not desired to have, while in the proposed apporch, the impersonator’s permission is clearer that it can only perform the action when impersonating.
Expand RBAC/SAR
Introduce additional API to define more fine-grained access control rule, and ref the rule in SAR. One example is
{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "default",
"verb": "get",
"group": "example.org",
"resource": "something"
},
"accessRule": {
"kind": "ClusterAccessRule",
"group version": "example.org/v1",
"name": "elevation-of-privilege"
},
"user": "impersonator",
"group": []
]
}
}
And authorizer checks the accessRule on whether a certain impersonate action is allowed. This is a more complicated approach that requires changes on existing RBAC/SAR, while the current proposal does not introduce change on RBAC/SAR.
Conditional Authorization
Conditional authorization is the emerging work to provide more complicated authorization policy with CEL expressions. Potentially it would be able to reduce the number of permission checks for the impersonation in this proposal. The work is still in very early stage, and will bring many changes in the existing authorization model. It is possible to enhance constrained impersonation in this proposal with conditional authorization in the future.