mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
acl: remove timestamps from WhoAmI response (#19578)
In Nomad 1.7 we updated our JWT library to go-jose, but this changed the wire format of the embedded struct we have in the `IdentityClaims` struct that we return as part of the `WhoAmI` RPC response. This wasn't originally intended to be sent over the wire but other changes in Nomad 1.5+ added a caller to the client. The library change causes a deserialization error on Nomad 1.5 and 1.6 clients, which prevents access to Nomad Variables and SD via template blocks. Removed the incompatible fields from the response, which are unused by any current caller. In a future version of Nomad, we'll likely remove the `WhoAmI` callers from the client in lieu of using the public keys the clients have to check auth. Fixes: https://github.com/hashicorp/nomad/issues/19555
This commit is contained in:
3
.changelog/19578.txt
Normal file
3
.changelog/19578.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
```release-note:bug
|
||||
acl: Fixed a bug where 1.5 and 1.6 clients could not access Nomad Variables and Services via templates
|
||||
```
|
||||
@@ -2182,6 +2182,16 @@ func (a *ACL) WhoAmI(args *structs.GenericRequest, reply *structs.ACLWhoAmIRespo
|
||||
}
|
||||
|
||||
reply.Identity = args.GetIdentity()
|
||||
|
||||
// COMPAT: originally these were time.Time objects but switching to go-jose
|
||||
// changed them to int64 which aren't compatible with Nomad versions
|
||||
// <1.7. These aren't used by any existing callers of this handler.
|
||||
if reply.Identity.Claims != nil {
|
||||
reply.Identity.Claims.Expiry = nil
|
||||
reply.Identity.Claims.IssuedAt = nil
|
||||
reply.Identity.Claims.NotBefore = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1913,6 +1913,51 @@ func TestACLEndpoint_ResolveToken(t *testing.T) {
|
||||
assert.Nil(t, resp.Token)
|
||||
}
|
||||
|
||||
func TestACLEndpoint_WhoAmI(t *testing.T) {
|
||||
ci.Parallel(t)
|
||||
|
||||
s1, _, cleanupS1 := TestACLServer(t, nil)
|
||||
t.Cleanup(cleanupS1)
|
||||
codec := rpcClient(t, s1)
|
||||
testutil.WaitForKeyring(t, s1.RPC, "global")
|
||||
|
||||
// Create the register request
|
||||
token := mock.ACLToken()
|
||||
s1.fsm.State().UpsertACLTokens(structs.MsgTypeTestSetup, 1000, []*structs.ACLToken{token})
|
||||
|
||||
// Lookup via token
|
||||
get := &structs.GenericRequest{
|
||||
QueryOptions: structs.QueryOptions{Region: "global", AuthToken: token.SecretID},
|
||||
}
|
||||
var resp structs.ACLWhoAmIResponse
|
||||
err := msgpackrpc.CallWithCodec(codec, "ACL.WhoAmI", get, &resp)
|
||||
must.NoError(t, err)
|
||||
must.Eq(t, token, resp.Identity.ACLToken)
|
||||
|
||||
// Lookup non-existing token
|
||||
get.AuthToken = uuid.Generate()
|
||||
var resp2 structs.ACLWhoAmIResponse
|
||||
err = msgpackrpc.CallWithCodec(codec, "ACL.WhoAmI", get, &resp2)
|
||||
must.EqError(t, err, structs.ErrPermissionDenied.Error())
|
||||
must.Nil(t, resp2.Identity)
|
||||
|
||||
// Lookup identity claim
|
||||
alloc := mock.Alloc()
|
||||
s1.fsm.State().UpsertAllocs(structs.MsgTypeTestSetup, 1500, []*structs.Allocation{alloc})
|
||||
claims := structs.NewIdentityClaims(alloc.Job, alloc,
|
||||
wiHandle, // see encrypter_test.go
|
||||
alloc.LookupTask("web").Identity, time.Now().Add(-10*time.Minute))
|
||||
jwtToken, _, err := s1.encrypter.SignClaims(claims)
|
||||
must.NoError(t, err)
|
||||
|
||||
get.AuthToken = jwtToken
|
||||
var resp3 structs.ACLWhoAmIResponse
|
||||
err = msgpackrpc.CallWithCodec(codec, "ACL.WhoAmI", get, &resp3)
|
||||
must.NoError(t, err)
|
||||
must.NotNil(t, resp3.Identity.Claims)
|
||||
must.Eq(t, alloc.ID, resp3.Identity.Claims.AllocationID)
|
||||
}
|
||||
|
||||
func TestACLEndpoint_OneTimeToken(t *testing.T) {
|
||||
ci.Parallel(t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user