Add PolicyReadByName for API (#6615)
This commit is contained in:
parent
0c5c97205f
commit
7d68d7eaa6
|
@ -217,7 +217,7 @@ func (s *HTTPServer) ACLPolicyCRUD(resp http.ResponseWriter, req *http.Request)
|
|||
|
||||
switch req.Method {
|
||||
case "GET":
|
||||
fn = s.ACLPolicyRead
|
||||
fn = s.ACLPolicyReadByID
|
||||
|
||||
case "PUT":
|
||||
fn = s.ACLPolicyWrite
|
||||
|
@ -237,10 +237,11 @@ func (s *HTTPServer) ACLPolicyCRUD(resp http.ResponseWriter, req *http.Request)
|
|||
return fn(resp, req, policyID)
|
||||
}
|
||||
|
||||
func (s *HTTPServer) ACLPolicyRead(resp http.ResponseWriter, req *http.Request, policyID string) (interface{}, error) {
|
||||
func (s *HTTPServer) ACLPolicyRead(resp http.ResponseWriter, req *http.Request, policyID, policyName string) (interface{}, error) {
|
||||
args := structs.ACLPolicyGetRequest{
|
||||
Datacenter: s.agent.config.Datacenter,
|
||||
PolicyID: policyID,
|
||||
PolicyName: policyName,
|
||||
}
|
||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||
return nil, nil
|
||||
|
@ -268,6 +269,23 @@ func (s *HTTPServer) ACLPolicyRead(resp http.ResponseWriter, req *http.Request,
|
|||
return out.Policy, nil
|
||||
}
|
||||
|
||||
func (s *HTTPServer) ACLPolicyReadByName(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
if s.checkACLDisabled(resp, req) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
policyName := strings.TrimPrefix(req.URL.Path, "/v1/acl/policy/name/")
|
||||
if policyName == "" {
|
||||
return nil, BadRequestError{Reason: "Missing policy Name"}
|
||||
}
|
||||
|
||||
return s.ACLPolicyRead(resp, req, "", policyName)
|
||||
}
|
||||
|
||||
func (s *HTTPServer) ACLPolicyReadByID(resp http.ResponseWriter, req *http.Request, policyID string) (interface{}, error) {
|
||||
return s.ACLPolicyRead(resp, req, policyID, "")
|
||||
}
|
||||
|
||||
func (s *HTTPServer) ACLPolicyCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
if s.checkACLDisabled(resp, req) {
|
||||
return nil, nil
|
||||
|
|
|
@ -374,6 +374,17 @@ func TestACL_HTTP(t *testing.T) {
|
|||
require.True(t, ok)
|
||||
require.Equal(t, policyMap[idMap["policy-read-all-nodes"]], policy)
|
||||
})
|
||||
|
||||
t.Run("Read Name", func(t *testing.T) {
|
||||
policyName := "read-all-nodes"
|
||||
req, _ := http.NewRequest("GET", "/v1/acl/policy/name/"+policyName+"?token=root", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
raw, err := a.srv.ACLPolicyReadByName(resp, req)
|
||||
require.NoError(t, err)
|
||||
policy, ok := raw.(*structs.ACLPolicy)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, policyMap[idMap["policy-"+policyName]], policy)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Role", func(t *testing.T) {
|
||||
|
|
|
@ -951,7 +951,16 @@ func (a *ACL) PolicyRead(args *structs.ACLPolicyGetRequest, reply *structs.ACLPo
|
|||
|
||||
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||
func(ws memdb.WatchSet, state *state.Store) error {
|
||||
index, policy, err := state.ACLPolicyGetByID(ws, args.PolicyID, &args.EnterpriseMeta)
|
||||
var (
|
||||
index uint64
|
||||
policy *structs.ACLPolicy
|
||||
err error
|
||||
)
|
||||
if args.PolicyID != "" {
|
||||
index, policy, err = state.ACLPolicyGetByID(ws, args.PolicyID, &args.EnterpriseMeta)
|
||||
} else {
|
||||
index, policy, err = state.ACLPolicyGetByName(ws, args.PolicyName, &args.EnterpriseMeta)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -2240,6 +2240,45 @@ func TestACLEndpoint_PolicyRead(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestACLEndpoint_PolicyReadByName(t *testing.T) {
|
||||
t.Parallel()
|
||||
dir1, s1 := testServerWithConfig(t, func(c *Config) {
|
||||
c.ACLDatacenter = "dc1"
|
||||
c.ACLsEnabled = true
|
||||
c.ACLMasterToken = "root"
|
||||
})
|
||||
defer os.RemoveAll(dir1)
|
||||
defer s1.Shutdown()
|
||||
codec := rpcClient(t, s1)
|
||||
defer codec.Close()
|
||||
|
||||
testrpc.WaitForLeader(t, s1.RPC, "dc1")
|
||||
|
||||
policy, err := upsertTestPolicy(codec, "root", "dc1")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
acl := ACL{srv: s1}
|
||||
|
||||
req := structs.ACLPolicyGetRequest{
|
||||
Datacenter: "dc1",
|
||||
PolicyName: policy.Name,
|
||||
QueryOptions: structs.QueryOptions{Token: "root"},
|
||||
}
|
||||
|
||||
resp := structs.ACLPolicyResponse{}
|
||||
|
||||
err = acl.PolicyRead(&req, &resp)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(resp.Policy, policy) {
|
||||
t.Fatalf("tokens are not equal: %v != %v", resp.Policy, policy)
|
||||
}
|
||||
}
|
||||
|
||||
func TestACLEndpoint_PolicyBatchRead(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ func init() {
|
|||
registerEndpoint("/v1/acl/policies", []string{"GET"}, (*HTTPServer).ACLPolicyList)
|
||||
registerEndpoint("/v1/acl/policy", []string{"PUT"}, (*HTTPServer).ACLPolicyCreate)
|
||||
registerEndpoint("/v1/acl/policy/", []string{"GET", "PUT", "DELETE"}, (*HTTPServer).ACLPolicyCRUD)
|
||||
registerEndpoint("/v1/acl/policy/name/", []string{"GET"}, (*HTTPServer).ACLPolicyReadByName)
|
||||
registerEndpoint("/v1/acl/roles", []string{"GET"}, (*HTTPServer).ACLRoleList)
|
||||
registerEndpoint("/v1/acl/role", []string{"PUT"}, (*HTTPServer).ACLRoleCreate)
|
||||
registerEndpoint("/v1/acl/role/name/", []string{"GET"}, (*HTTPServer).ACLRoleReadByName)
|
||||
|
|
|
@ -1238,7 +1238,8 @@ func (r *ACLPolicyDeleteRequest) RequestDatacenter() string {
|
|||
|
||||
// ACLPolicyGetRequest is used at the RPC layer to perform policy read operations
|
||||
type ACLPolicyGetRequest struct {
|
||||
PolicyID string // id used for the policy lookup
|
||||
PolicyID string // id used for the policy lookup (one of PolicyID or PolicyName is allowed)
|
||||
PolicyName string // name used for the policy lookup (one of PolicyID or PolicyName is allowed)
|
||||
Datacenter string // The datacenter to perform the request within
|
||||
EnterpriseMeta
|
||||
QueryOptions
|
||||
|
|
26
api/acl.go
26
api/acl.go
|
@ -666,6 +666,32 @@ func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMe
|
|||
return &out, qm, nil
|
||||
}
|
||||
|
||||
// PolicyReadByName retrieves the policy details including the rule set with name.
|
||||
func (a *ACL) PolicyReadByName(policyName string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) {
|
||||
r := a.c.newRequest("GET", "/v1/acl/policy/name/"+url.QueryEscape(policyName))
|
||||
r.setQueryOptions(q)
|
||||
found, rtt, resp, err := requireNotFoundOrOK(a.c.doRequest(r))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
qm := &QueryMeta{}
|
||||
parseQueryMeta(resp, qm)
|
||||
qm.RequestTime = rtt
|
||||
|
||||
if !found {
|
||||
return nil, qm, nil
|
||||
}
|
||||
|
||||
var out ACLPolicy
|
||||
if err := decodeBody(resp, &out); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return &out, qm, nil
|
||||
}
|
||||
|
||||
// PolicyList retrieves a listing of all policies. The listing does not include the
|
||||
// rules for any policy as those should be retrieved by subsequent calls to PolicyRead.
|
||||
func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) {
|
||||
|
|
|
@ -205,6 +205,41 @@ func TestAPI_ACLPolicy_CreateReadDelete(t *testing.T) {
|
|||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAPI_ACLPolicy_CreateReadByNameDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeACLClient(t)
|
||||
defer s.Stop()
|
||||
|
||||
acl := c.ACL()
|
||||
|
||||
created, wm, err := acl.PolicyCreate(&ACLPolicy{
|
||||
Name: "test-policy",
|
||||
Description: "test-policy description",
|
||||
Rules: `node_prefix "" { policy = "read" }`,
|
||||
Datacenters: []string{"dc1"},
|
||||
}, nil)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, created)
|
||||
require.NotEqual(t, "", created.ID)
|
||||
require.NotEqual(t, 0, wm.RequestTime)
|
||||
|
||||
read, qm, err := acl.PolicyReadByName(created.Name, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, 0, qm.LastIndex)
|
||||
require.True(t, qm.KnownLeader)
|
||||
|
||||
require.Equal(t, created, read)
|
||||
|
||||
wm, err = acl.PolicyDelete(created.ID, nil)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, 0, wm.RequestTime)
|
||||
|
||||
read, _, err = acl.PolicyRead(created.ID, nil)
|
||||
require.Nil(t, read)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAPI_ACLPolicy_CreateUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeACLClient(t)
|
||||
|
|
Loading…
Reference in New Issue