I thought it was possible to use a token without any role to perform the TokenReview call to the Kubernetes API server.
But no: for the TokenReview call, the service account associated to the token used to authenticate (i.e., the Ahtorization: Bearer token
HTTP header) must have the role system:auth-delegator
.
On the other side, the token within the TokenReview doesn't need to have any role attached.
First, let us create a token with no role attached:
token=$(kubectl create --raw /api/v1/namespaces/default/serviceaccounts/default/token -f- <<EOF | jq -r '.status.token'
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenRequest",
"spec": {
"audiences": ["https://kubernetes.default.svc.cluster.local"]
}
}
EOF
)
Now, let us use the TokenReview API to check that same token:
curl -sS -X POST $(kubectl config view --minify --flatten -ojson | jq '.clusters[0].cluster.server' -r)/apis/authentication.k8s.io/v1/tokenreviews \
--cacert <( kubectl config view --minify --flatten -ojson | jq '.clusters[0].cluster."certificate-authority-data"' -r | base64 -d) \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
-d@- <<EOF
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenReview",
"spec": {
"token": "$token",
"audiences": ["https://kubernetes.default.svc.cluster.local"]
}
}
EOF
gives:
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "tokenreviews.authentication.k8s.io is forbidden: User \"system:serviceaccount:default:default\" cannot create resource \"tokenreviews\" in API group \"authentication.k8s.io\" at the cluster scope",
"reason": "Forbidden",
"details": {
"group": "authentication.k8s.io",
"kind": "tokenreviews"
},
"code": 403
}
To fix that:
kubectl apply -f- <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: tokenreview
namespace: default
subjects:
- kind: ServiceAccount
namespace: default
name: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
EOF
And now it works.
kubectl run foo -n cert-manager --image=alpine/k8s:1.22.15 --restart=Never --overrides='{"spec":{"serviceAccountName": "cert-manager"}}' -q --rm -it -- bash
# And then, inside the container:
kubectl create --raw /api/v1/namespaces/sandbox/serviceaccounts/vault-issuer/token -f- <<EOF | jq -r '.status.token'
{
"apiVersion": "authentication.k8s.io/v1",
"kind": "TokenRequest",
"spec": {
"audiences": ["https://kubernetes.default.svc.cluster.local"],
"expirationSeconds": 600
}
}
EOF
🔥 Update 26 June 2023: I am abandoning "desktop" Linux! I can't bear having to work around everything all the time, not even counting the tons of problems that occur whenever I do a major version upgrade (e.g., when I upgraded from 21.10 to 22.04, my PPAs broken obviously, and also I lost all the hack I had made to the /etc to work around problems). I am officially back to macOS starting 26 June 2023. I'll still use my Linux workstation remotely over Mosh, but not as a desktop environment.
Jun 2, 2025To figure out whether it is being OOM killed:
May 29, 2025Gateway API = role-aware version of Ingress API + many more knobs (e.g., lets you to fine-tune the load balancer)
May 21, 2025Due to not having enough maintainers time, the NGINX Ingress Controller
May 20, 2025or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up