Node.GetNode ACL enforcement

This commit is contained in:
Michael Schurter
2017-09-14 20:59:18 -07:00
parent 5b22fd4b6d
commit 2d4ec79d75
3 changed files with 65 additions and 5 deletions

View File

@@ -503,6 +503,13 @@ func (n *Node) GetNode(args *structs.NodeSpecificRequest,
}
defer metrics.MeasureSince([]string{"nomad", "client", "get_node"}, time.Now())
// Check node read permissions
if aclObj, err := n.srv.resolveToken(args.SecretID); err != nil {
return err
} else if aclObj != nil && !aclObj.AllowNodeRead() {
return structs.ErrPermissionDenied
}
// Setup the blocking query
opts := blockingOptions{
queryOpts: &args.QueryOptions,

View File

@@ -666,7 +666,7 @@ func TestClientEndpoint_UpdateDrain_ACL(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
assert := assert.New(t)
// Create the alloc
// Create the node
node := mock.Node()
state := s1.fsm.State()
@@ -908,6 +908,59 @@ func TestClientEndpoint_GetNode(t *testing.T) {
}
}
func TestClientEndpoint_GetNode_ACL(t *testing.T) {
t.Parallel()
s1, root := testACLServer(t, nil)
defer s1.Shutdown()
codec := rpcClient(t, s1)
testutil.WaitForLeader(t, s1.RPC)
assert := assert.New(t)
// Create the node
node := mock.Node()
state := s1.fsm.State()
assert.Nil(state.UpsertNode(1, node), "UpsertNode")
// Create the namespace policy and tokens
validToken := CreatePolicyAndToken(t, state, 1001, "test-valid", NodePolicy(acl.PolicyRead))
invalidToken := CreatePolicyAndToken(t, state, 1003, "test-invalid", NodePolicy(acl.PolicyDeny))
// Lookup the node without a token and expect failure
req := &structs.NodeSpecificRequest{
NodeID: node.ID,
QueryOptions: structs.QueryOptions{Region: "global"},
}
{
var resp structs.SingleNodeResponse
assert.NotNil(msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp), "RPC")
}
// Try with a valid token
req.SecretID = validToken.SecretID
{
var resp structs.SingleNodeResponse
assert.Nil(msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp), "RPC")
assert.Equal(node.ID, resp.Node.ID)
}
// Try with a invalid token
req.SecretID = invalidToken.SecretID
{
var resp structs.SingleNodeResponse
err := msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp)
assert.NotNil(err, "RPC")
assert.Equal(err.Error(), structs.ErrPermissionDenied.Error())
}
// Try with a root token
req.SecretID = root.SecretID
{
var resp structs.SingleNodeResponse
assert.Nil(msgpackrpc.CallWithCodec(codec, "Node.GetNode", req, &resp), "RPC")
assert.Equal(node.ID, resp.Node.ID)
}
}
func TestClientEndpoint_GetNode_Blocking(t *testing.T) {
t.Parallel()
s1 := testServer(t, nil)
@@ -1703,7 +1756,7 @@ func TestClientEndpoint_Evaluate_ACL(t *testing.T) {
testutil.WaitForLeader(t, s1.RPC)
assert := assert.New(t)
// Create the alloc
// Create the node with an alloc
alloc := mock.Alloc()
node := mock.Node()
node.ID = alloc.NodeID

View File

@@ -73,9 +73,9 @@ The table below shows this endpoint's support for
[blocking queries](/api/index.html#blocking-queries) and
[required ACLs](/api/index.html#acls).
| Blocking Queries | ACL Required |
| ---------------- | ------------ |
| `YES` | `none` |
| Blocking Queries | ACL Required |
| ---------------- | ----------------- |
| `YES` | `node:read` |
### Parameters