Repository navigation
Multiple Impersonate-Group Not Possible #2474
Description
Activity
Node.js supports this use case by passing an array of strings. From the Node HTTP docs:
Use an array of strings here to send multiple headers with the same name.
I haven't tested to see if anything needs to be changed in this library, but it should at least be possible in theory.
karl-cardenas-coding commented
on Jun 5, 2025 ContributorAuthorMore actionsHey @cjihrig thanks for replying. Yeah I tried that like so
const opts = { method: 'GET', headers: { 'Impersonate-User': 'acme@example.com', 'Impersonate-Group': ['developer-write', 'developer-read'], }, agent: agent, }
In the Kubernetes audit logs I see the the two groups combined into a single string
"developer-write,developer-read". Below is the complete entry.{ "kind": "Event", "apiVersion": "audit.k8s.io/v1", "level": "RequestResponse", "auditID": "9078fc81-49d5-49f4-87b0-b412ce716065", "stage": "ResponseComplete", "requestURI": "/api/v1/pods", "verb": "list", "user": { "username": "system:serviceaccount:redacted****", "uid": "7532f6c9-8806-4a6b-ab3e-e3c07c5fa1b6", "groups": [ "system:serviceaccounts", "system:serviceaccounts:demo", "system:authenticated" ], "extra": { "authentication.kubernetes.io/credential-id": [ "JTI=5413f2f0-60c5-4035-8488-a037086b2851" ], "authentication.kubernetes.io/node-name": [ "kind-dev-control-plane" ], "authentication.kubernetes.io/node-uid": [ "c73bbe25-d743-46fb-8f9c-6212885c06b2" ], "authentication.kubernetes.io/pod-name": [ "dev-devspace-f8bb6b678-56jvv" ], "authentication.kubernetes.io/pod-uid": [ "ba8c4d5d-ccaa-477f-9513-f7b877514bbc" ] } }, "impersonatedUser": { "username": "acme@example.com", "groups": [ "developer-write,developer-read", "system:authenticated" ] }, "sourceIPs": [ "10.244.0.23" ], "userAgent": "node-fetch", "objectRef": { "resource": "pods", "apiVersion": "v1" }, "responseStatus": { "metadata": {}, "status": "Failure", "message": "pods is forbidden: User \"acme@example.com\" cannot list resource \"pods\" in API group \"\" at the cluster scope", "reason": "Forbidden", "details": { "kind": "pods" }, "code": 403 }, "responseObject": { "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "pods is forbidden: User \"acme@example.com\" cannot list resource \"pods\" in API group \"\" at the cluster scope", "reason": "Forbidden", "details": { "kind": "pods" }, "code": 403 }, "requestReceivedTimestamp": "2025-06-05T02:47:01.656892Z", "stageTimestamp": "2025-06-05T02:47:01.661320Z", "annotations": { "authorization.k8s.io/decision": "forbid", "authorization.k8s.io/reason": "" } }karl-cardenas-coding commented
on Jun 5, 2025 ContributorAuthorMore actionsThank you @mstruebing - you nudged me in the right direction. I noticed you used the
httplibrary, whereas I was usingfetch. If I replace the request with the http library it works, and I see the audit log show the groups in a separate entry."impersonatedUser": { "username": "acme@example.com", "groups": [ "developer-write", "developer-read", "system:authenticated" ] },
The issue probably lies in how fetch generates the Headers object
Reacted by Max StrübingI guess we should close this issue as can't/won't fix. As far as I can tell, this is just a fundamental limitation of fetch (it combines multiple values into a single header instead of specifying multiple headers like native Node does).
karl-cardenas-coding commented
on Jun 7, 2025 ContributorAuthorMore actions@cjihrig Yeah that's fair. To help others in the future, is there a place we could document this?
karl-cardenas-coding commented
on Jun 7, 2025 ContributorAuthorMore actionsSure. I can open up a PR with the change.

Describe the bug
The official Kubernetes documentation states that when performing user impersonation, multiple groups can be specified with a request through headers. The guidance is to place each group in an individual header entry, like so:
The challenge with this approach is that Node.js and other JavaScript runtime environments do not support adding identical keys to an object. This breaks the ability to specify multiple user groups through impersonation.
This will result in a single
Impersonate-Groupentry in the request with the value being the last entry of the identical key. In this example, that would bedeveloper-read.If I print out
optsbefore the request I get this:I'm not really sure what can get done from the SDK's perspective to fix this. Part of the reason I brought this issue to light is to help others who may encounter it. But also to see if we can maybe make some traction from a Kubernetes API perspective to pass in groups differently.
Client Version
In package.json I have
1.3.0of this SDK.Server Version
e.g.
1.32.2To Reproduce
You can create two roles with whatever permissions you want, such as list pods, and create a binding to the role and specify the group. Below is an example:
kubectl create clusterrole developer-read \ --verb=get,list,watch \ --resource=pods,services,configmaps \ --resource=deployments.apps \ --dry-run=client -o yaml | kubectl apply -f - && \ kubectl create clusterrolebinding developer-read-binding \ --clusterrole=developer-read \ --group=developer-read \ --dry-run=client -o yaml | kubectl apply -f - && \ kubectl create clusterrole developer-write \ --verb=create,update,delete,get,list \ --resource=pods,services,configmaps \ --resource=deployments.apps \ --dry-run=client -o yaml | kubectl apply -f - && \ kubectl create clusterrolebinding developer-write-binding \ --clusterrole=developer-write \ --group=developer-write \Try to use add multiple groups to the user impersonation header,
Expected behavior
I expect the same behavior I get with
kubectlif I were to use the impersonation flags.From an SDK perspective, I expect to be able to achieve the same capability.
Example Code
See above.
Environment (please complete the following information):
Additional context
There are other SDKs that are experiencing this issue, but no solution has presented itself.
If I try to pass in the values in a single entry comma-separated, I also get an error. The snipped below is from the Kubernetes Audit log
But if I only include one of the groups