TT Lab
Get started
Learn Learning paths Courses

KCSA — Kubernetes Security Associate

The same account name, different credentials

Continue in TT Lab

In one line

Revoking permissions changes what can be done, and a change of service account UID changes the identity an old token points to. Even if you recreate an account with the same name, the old token and the existing RoleBinding are not handled in the same way.

Why this was needed

Here is an example situation. You got word that a reader token was exposed. The operator deleted the account, recreated it with the same name, saw a 401 for the old token, and considered the response done. But when you look up with the new token, you see the same data as before. Did the token revocation fail?

Before jumping to a conclusion, you must check what was deleted and what was left. The account was created anew, but the RoleBinding that targets that name may be unchanged. Only by understanding the phenomenon of permissions being connected again to the new identity can you also set the closing condition of incident response precisely.

How it works

Same name, different UID

This experiment keeps the existing Pod and RoleBinding and recreates only the SA. The original token's sub is system:serviceaccount:kcsa-identity:reader. The newly issued token's sub is the same. But the service account UIDs of the two tokens differ. If you compare only the names visible to the human eye, you can mistake different objects for the same object.

In the probe, the SA was recreated before the old token expired. The TokenReview authentication result became false and the API lookup became a 401. Because exp and the observation time were recorded together, it can be distinguished from a result where the token simply expired after a long wait. The existing Pod UID was also checked so that the result would not be explained away as an effect of recreating the Pod.

Which subject does the binding point to

A RoleBinding's ServiceAccount subject uses a name and a namespace. This binding points to reader in kcsa-identity. It is not a structure that keeps the SA's old UID and allows only that object forever. Try to explain in each column why the results differ as follows.

State Old token New token Binding
Original account, least read permission Its own ConfigMap 200 Not yet Original binding exists
Empty the Role's rules Authenticated true, lookup 403 Not yet Still exists
After restoring the Role and recreating the SA Authenticated false, lookup 401 Lookup 200 once issued Still points to the same name
Remove the binding Still 401 Authenticated true, lookup 403 Removed

This table organizes the actual observations in this personal cluster for learning purposes. The new token's 200 is not evidence that the old token came back to life. It is the result of combining the authentication result with the new UID and name-based authorization. Also, the 403 after removing the binding does not mean the new token became invalid. A separate observation that authentication is still true supports this interpretation.

Do not trust names alone even when deleting

Read the current UID of the deletion target, compare it with the baseline, and then request deletion with UID and resourceVersion preconditions. If someone replaced the object during the investigation, you must stop and recheck instead of deleting a different object. The purpose of this helper is to change only the original account and binding, not to delete another object created later just because it has the same name.

What it looks like in the field

In incident response, you first investigate together the exposed credential, the APIs it can use, the connected workloads, and other bindings. Deleting an SA can also affect other jobs that use that account. Do not copy this experiment's delete and recreate into production as is. You must check the closing condition after coordinating least-privilege revocation, the scope of business disruption, credential reissuance and redeployment, and removal of the cause of re-exposure.

There is also a reason to send the other team's request along as well. If you check only the rejection of your own request, you can break the whole cluster and still look like a success. This time, we check that the other namespace reader's authentication UID, the synthetic ConfigMap UID, and the normal 200 response are unchanged. This is a verification of the scope of impact on these two namespaces, not a proof of platform-wide isolation or of uninterrupted work for all users.

We also separate offline JWT validation from online checks. A service that checks the signature and lifetime locally cannot know on its own whether the bound API object still exists. If the current binding state matters, an online validation such as TokenReview is needed. Conversely, since this unit's claim decoding is not an offline signature validation implementation, you must not report that you implemented and compared both methods.

Do not confuse the grace rules of an object pending deletion with the check of an object that has already disappeared or whose UID has changed. This time we observed the actual UID change and the API results together. A method that sleeps for a fixed time and then treats it as a success leaves no evidence of the identity transition.

What you will do in the next lab

You empty the permissions and then restore them, recreate the exact original SA under the same name, and issue a new token. Finally, you revoke only the original binding to tell apart old 401, new 403, and other team 200. For each observation, leave the time, UID, authentication result, and HTTP status, and interpret the records of past successes and the current state separately. The assignment is not to delete the files of earlier steps to make the records match but to explain what changed and when.

Official documentation