mirror of
https://github.com/status-im/consul.git
synced 2025-02-19 17:14:37 +00:00
Add PolicyReadByName for API (#6615)
This commit is contained in:
parent
136099d834
commit
bafa69bb69
@ -217,7 +217,7 @@ func (s *HTTPServer) ACLPolicyCRUD(resp http.ResponseWriter, req *http.Request)
|
|||||||
|
|
||||||
switch req.Method {
|
switch req.Method {
|
||||||
case "GET":
|
case "GET":
|
||||||
fn = s.ACLPolicyRead
|
fn = s.ACLPolicyReadByID
|
||||||
|
|
||||||
case "PUT":
|
case "PUT":
|
||||||
fn = s.ACLPolicyWrite
|
fn = s.ACLPolicyWrite
|
||||||
@ -237,10 +237,11 @@ func (s *HTTPServer) ACLPolicyCRUD(resp http.ResponseWriter, req *http.Request)
|
|||||||
return fn(resp, req, policyID)
|
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{
|
args := structs.ACLPolicyGetRequest{
|
||||||
Datacenter: s.agent.config.Datacenter,
|
Datacenter: s.agent.config.Datacenter,
|
||||||
PolicyID: policyID,
|
PolicyID: policyID,
|
||||||
|
PolicyName: policyName,
|
||||||
}
|
}
|
||||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -268,6 +269,23 @@ func (s *HTTPServer) ACLPolicyRead(resp http.ResponseWriter, req *http.Request,
|
|||||||
return out.Policy, nil
|
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) {
|
func (s *HTTPServer) ACLPolicyCreate(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||||
if s.checkACLDisabled(resp, req) {
|
if s.checkACLDisabled(resp, req) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -374,6 +374,17 @@ func TestACL_HTTP(t *testing.T) {
|
|||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
require.Equal(t, policyMap[idMap["policy-read-all-nodes"]], policy)
|
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) {
|
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,
|
return a.srv.blockingQuery(&args.QueryOptions, &reply.QueryMeta,
|
||||||
func(ws memdb.WatchSet, state *state.Store) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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) {
|
func TestACLEndpoint_PolicyBatchRead(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ func init() {
|
|||||||
registerEndpoint("/v1/acl/policies", []string{"GET"}, (*HTTPServer).ACLPolicyList)
|
registerEndpoint("/v1/acl/policies", []string{"GET"}, (*HTTPServer).ACLPolicyList)
|
||||||
registerEndpoint("/v1/acl/policy", []string{"PUT"}, (*HTTPServer).ACLPolicyCreate)
|
registerEndpoint("/v1/acl/policy", []string{"PUT"}, (*HTTPServer).ACLPolicyCreate)
|
||||||
registerEndpoint("/v1/acl/policy/", []string{"GET", "PUT", "DELETE"}, (*HTTPServer).ACLPolicyCRUD)
|
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/roles", []string{"GET"}, (*HTTPServer).ACLRoleList)
|
||||||
registerEndpoint("/v1/acl/role", []string{"PUT"}, (*HTTPServer).ACLRoleCreate)
|
registerEndpoint("/v1/acl/role", []string{"PUT"}, (*HTTPServer).ACLRoleCreate)
|
||||||
registerEndpoint("/v1/acl/role/name/", []string{"GET"}, (*HTTPServer).ACLRoleReadByName)
|
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
|
// ACLPolicyGetRequest is used at the RPC layer to perform policy read operations
|
||||||
type ACLPolicyGetRequest struct {
|
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
|
Datacenter string // The datacenter to perform the request within
|
||||||
EnterpriseMeta
|
EnterpriseMeta
|
||||||
QueryOptions
|
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
|
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
|
// 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.
|
// rules for any policy as those should be retrieved by subsequent calls to PolicyRead.
|
||||||
func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) {
|
func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, error) {
|
||||||
|
@ -205,6 +205,41 @@ func TestAPI_ACLPolicy_CreateReadDelete(t *testing.T) {
|
|||||||
require.Error(t, err)
|
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) {
|
func TestAPI_ACLPolicy_CreateUpdate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeACLClient(t)
|
c, s := makeACLClient(t)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user