mirror of
https://github.com/kemko/nomad.git
synced 2026-01-03 17:05:43 +03:00
/v1/client/stats ACL enforcement
This commit is contained in:
@@ -1,12 +1,26 @@
|
||||
package agent
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
)
|
||||
|
||||
func (s *HTTPServer) ClientStatsRequest(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
if s.agent.client == nil {
|
||||
return nil, clientNotRunning
|
||||
}
|
||||
|
||||
var secret string
|
||||
s.parseToken(req, &secret)
|
||||
|
||||
// Check node read permissions
|
||||
if aclObj, err := s.agent.Client().ResolveToken(secret); err != nil {
|
||||
return nil, err
|
||||
} else if aclObj != nil && !aclObj.AllowNodeRead() {
|
||||
return nil, structs.ErrPermissionDenied
|
||||
}
|
||||
|
||||
clientStats := s.agent.client.StatsReporter()
|
||||
return clientStats.LatestHostStats(), nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,11 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/nomad/acl"
|
||||
"github.com/hashicorp/nomad/nomad/mock"
|
||||
"github.com/hashicorp/nomad/nomad/structs"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestClientStatsRequest(t *testing.T) {
|
||||
@@ -21,3 +26,50 @@ func TestClientStatsRequest(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestClientStatsRequest_ACL(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
httpACLTest(t, nil, func(s *TestAgent) {
|
||||
state := s.Agent.server.State()
|
||||
req, err := http.NewRequest("GET", "/v1/client/stats/", nil)
|
||||
assert.Nil(err)
|
||||
|
||||
// Try request without a token and expect failure
|
||||
{
|
||||
respW := httptest.NewRecorder()
|
||||
_, err := s.Server.ClientStatsRequest(respW, req)
|
||||
assert.NotNil(err)
|
||||
assert.Equal(err.Error(), structs.ErrPermissionDenied.Error())
|
||||
}
|
||||
|
||||
// Try request with an invalid token and expect failure
|
||||
{
|
||||
respW := httptest.NewRecorder()
|
||||
token := mock.CreatePolicyAndToken(t, state, 1005, "invalid", mock.NodePolicy(acl.PolicyDeny))
|
||||
setToken(req, token)
|
||||
_, err := s.Server.ClientStatsRequest(respW, req)
|
||||
assert.NotNil(err)
|
||||
assert.Equal(err.Error(), structs.ErrPermissionDenied.Error())
|
||||
}
|
||||
|
||||
// Try request with a valid token
|
||||
{
|
||||
respW := httptest.NewRecorder()
|
||||
token := mock.CreatePolicyAndToken(t, state, 1007, "valid", mock.NodePolicy(acl.PolicyRead))
|
||||
setToken(req, token)
|
||||
_, err := s.Server.ClientStatsRequest(respW, req)
|
||||
assert.Nil(err)
|
||||
assert.Equal(http.StatusOK, respW.Code)
|
||||
}
|
||||
|
||||
// Try request with a management token
|
||||
{
|
||||
respW := httptest.NewRecorder()
|
||||
setToken(req, s.RootToken)
|
||||
_, err := s.Server.ClientStatsRequest(respW, req)
|
||||
assert.Nil(err)
|
||||
assert.Equal(http.StatusOK, respW.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ The table below shows this endpoint's support for
|
||||
|
||||
| Blocking Queries | ACL Required |
|
||||
| ---------------- | ------------ |
|
||||
| `NO` | `none` |
|
||||
| `NO` | `node:read` |
|
||||
|
||||
### Sample Request
|
||||
|
||||
|
||||
Reference in New Issue
Block a user