mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
The Nomad clients store their Nomad identity in memory and within their state store. While active, it is not possible to dump the state to view the stored identity token, so having a way to view the current claims while running aids debugging and operations. This change adds a client identity workflow, allowing operators to view the current claims of the nodes identity. It does not return any of the signing key material.
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package client
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/go-jose/go-jose/v3/jwt"
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
|
)
|
|
|
|
type NodeIdentity struct {
|
|
c *Client
|
|
}
|
|
|
|
func newNodeIdentityEndpoint(c *Client) *NodeIdentity {
|
|
n := &NodeIdentity{c: c}
|
|
return n
|
|
}
|
|
|
|
func (n *NodeIdentity) Get(args *structs.NodeIdentityGetReq, resp *structs.NodeIdentityGetResp) error {
|
|
|
|
// Check for node read permissions.
|
|
if aclObj, err := n.c.ResolveToken(args.AuthToken); err != nil {
|
|
return err
|
|
} else if !aclObj.AllowNodeRead() {
|
|
return structs.ErrPermissionDenied
|
|
}
|
|
|
|
// Parse the signed JWT token from the node identity and extract the claims
|
|
// into a map. This is done to avoid exposing the key material of the signed
|
|
// JWT token, but still results in all the claims which is perfect for
|
|
// debugging and introspection purposes.
|
|
parsedJWT, err := jwt.ParseSigned(n.c.nodeIdentityToken())
|
|
if err != nil {
|
|
return fmt.Errorf("failed to parsed signed token: %w", err)
|
|
}
|
|
|
|
claims := make(map[string]any)
|
|
|
|
if err := parsedJWT.UnsafeClaimsWithoutVerification(&claims); err != nil {
|
|
return fmt.Errorf("failed to extract claims from token: %w", err)
|
|
}
|
|
|
|
resp.Claims = claims
|
|
return nil
|
|
}
|
|
|
|
func (n *NodeIdentity) Renew(args *structs.NodeIdentityRenewReq, _ *structs.NodeIdentityRenewResp) error {
|
|
|
|
// Check node write permissions.
|
|
if aclObj, err := n.c.ResolveToken(args.AuthToken); err != nil {
|
|
return err
|
|
} else if !aclObj.AllowNodeWrite() {
|
|
return structs.ErrPermissionDenied
|
|
}
|
|
|
|
// Store the node identity renewal request on the client, so it can be
|
|
// picked up at the next heartbeat.
|
|
n.c.identityForceRenewal.Store(true)
|
|
|
|
return nil
|
|
}
|