Closed maelvls closed 1 year ago
I had a look at this an I have to say I am a bit surprised. I checked the code and my understanding is that it should fail even before the TokenReview is sent. While it is true that the service account is populated with the audience of the JWT token before the review, the audience should be validated already here: https://github.com/hashicorp/vault-plugin-auth-kubernetes/blob/eabe60240605c4cc3c2d73038931c2fbf47ff6aa/path_login.go#L307
I wrote a simple unit test to check this and ran through with it in the debugger, and it seems to do exactly what you would expect ... I linked this issue in the commit.
Thanks for the detailed report, and also the follow-up investigation. I haven't gone too deep into this yet, but one thing I've noticed is a typo in the repro:
kubectl exec vault-0 -i -- vault write auth/kubernetes/role/with-audience \ bound_service_account_names=default \ bound_service_account_namespaces=default \ audiences=vault
The audiences
parameter there should be audience
. Unfortunately, providing the wrong parameters doesn't provide an error, it just gets silently ignored, so it's acting as though the audience hasn't been set at all. When I try the repro with audience
instead, I get an error on authenticating. I need to refresh my memory on the specifics of audience handling though, as I'm still not confident there isn't a bug here.
Hey Jakob and Tom,
Tom, you are correct: I incorrectly used audiences=
and Vault silently ignored it. I ran my tests with the correct audience=
, and I am now getting the expected error message:
* invalid audience (aud) claim: audience claim does not match any expected audience
Jakob, thank you for the unit test, it definitely proves that this is a false alarm. My apologies!
Hey @maelvls, I just wanted to say thanks for highlighting this - after taking a closer look, I think I identified some related improvements we could make. If you're interested, I'd welcome extra eyes: #179
Vault 1.12 (and all previous versions) has a bug that prevents checking the JWT audience. If you configure a Kubernetes auth role with the parameter
audience
set tovault
and expect Vault to refuse JWTs that don't have this audience, Vault will still accept any audience:The Vault documentation indicates that the audience claim will be verified:
The code in path_login.go goes something like this:
Vault is checking that the audience in the JWT matches the audience in the JWT, instead of checking that the audience in the JWT matches the role's audience.
Context: as part of The Vault issuer can now be given a serviceAccountRef (PR 5502), we wanted to use the audience claim verification to prevent someone hijacking a service account by creating a cert-manager Issuer.
Reproducing
First, setup Kubernetes 1.25 with Vault 1.12.1:
Let us create a role that expected the audience
with-audience
:Now, let us login using a token that has the audience
foobar
. It should fail since it doesn't matchvault
:The login call succeeds: Vault ignores the fact that the audience doesn't match.
Using mitmproxy (I documented the procedure in https://hackmd.io/@maelvls/vault-audience-kubernetes-auth), I captured the TokenReview call that is made to the Kubernetes API server:
The response is positive:
As you can see, Vault does not pass the audience
vault
to the TokenReview request. Instead, it copies whateveraud
is in the JWT into the TokenReview request.