mirror of https://github.com/status-im/consul.git
New ACL API Tests (#4848)
* A few API mods and unit tests. * Update the unit tests to verify query/write metadata and to fix the rules endpoint tests. * Make sure the full information for the replication status is in the api packge
This commit is contained in:
parent
a7f83b62f3
commit
d238cb181c
|
@ -257,7 +257,7 @@ func (s *HTTPServer) ACLPolicyCreate(resp http.ResponseWriter, req *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixCreateTimeAndHash is used to help in decoding the CreateTime and Hash
|
// fixCreateTimeAndHash is used to help in decoding the CreateTime and Hash
|
||||||
// attributes from the ACL Token create/update requests. It is needed
|
// attributes from the ACL Token/Policy create/update requests. It is needed
|
||||||
// to help mapstructure decode things properly when decodeBody is used.
|
// to help mapstructure decode things properly when decodeBody is used.
|
||||||
func fixCreateTimeAndHash(raw interface{}) error {
|
func fixCreateTimeAndHash(raw interface{}) error {
|
||||||
rawMap, ok := raw.(map[string]interface{})
|
rawMap, ok := raw.(map[string]interface{})
|
||||||
|
@ -289,7 +289,7 @@ func (s *HTTPServer) ACLPolicyWrite(resp http.ResponseWriter, req *http.Request,
|
||||||
}
|
}
|
||||||
s.parseToken(req, &args.Token)
|
s.parseToken(req, &args.Token)
|
||||||
|
|
||||||
if err := decodeBody(req, &args.Policy, nil); err != nil {
|
if err := decodeBody(req, &args.Policy, fixCreateTimeAndHash); err != nil {
|
||||||
return nil, BadRequestError{Reason: fmt.Sprintf("Policy decoding failed: %v", err)}
|
return nil, BadRequestError{Reason: fmt.Sprintf("Policy decoding failed: %v", err)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
api/acl.go
66
api/acl.go
|
@ -2,6 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -61,12 +62,14 @@ type ACLEntry struct {
|
||||||
|
|
||||||
// ACLReplicationStatus is used to represent the status of ACL replication.
|
// ACLReplicationStatus is used to represent the status of ACL replication.
|
||||||
type ACLReplicationStatus struct {
|
type ACLReplicationStatus struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
Running bool
|
Running bool
|
||||||
SourceDatacenter string
|
SourceDatacenter string
|
||||||
ReplicatedIndex uint64
|
ReplicationType string
|
||||||
LastSuccess time.Time
|
ReplicatedIndex uint64
|
||||||
LastError time.Time
|
ReplicatedTokenIndex uint64
|
||||||
|
LastSuccess time.Time
|
||||||
|
LastError time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// ACLPolicy represents an ACL Policy.
|
// ACLPolicy represents an ACL Policy.
|
||||||
|
@ -398,31 +401,6 @@ func (a *ACL) TokenList(q *QueryOptions) ([]*ACLTokenListEntry, *QueryMeta, erro
|
||||||
return entries, qm, nil
|
return entries, qm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TokenUpgrade performs an almost identical operation as TokenUpdate. The only difference is
|
|
||||||
// that not all parts of the token must be specified here and the server will patch the token
|
|
||||||
// with the existing secret id, description etc.
|
|
||||||
func (a *ACL) TokenUpgrade(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMeta, error) {
|
|
||||||
if token.AccessorID == "" {
|
|
||||||
return nil, nil, fmt.Errorf("Must specify an AccessorID for Token Updating")
|
|
||||||
}
|
|
||||||
r := a.c.newRequest("PUT", "/v1/acl/token/upgrade"+token.AccessorID)
|
|
||||||
r.setWriteOptions(q)
|
|
||||||
r.obj = token
|
|
||||||
rtt, resp, err := requireOK(a.c.doRequest(r))
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
wm := &WriteMeta{RequestTime: rtt}
|
|
||||||
var out ACLToken
|
|
||||||
if err := decodeBody(resp, &out); err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &out, wm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) {
|
func (a *ACL) PolicyCreate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *WriteMeta, error) {
|
||||||
if policy.ID != "" {
|
if policy.ID != "" {
|
||||||
return nil, nil, fmt.Errorf("Cannot specify an ID in Policy Creation")
|
return nil, nil, fmt.Errorf("Cannot specify an ID in Policy Creation")
|
||||||
|
@ -523,9 +501,28 @@ func (a *ACL) PolicyList(q *QueryOptions) ([]*ACLPolicyListEntry, *QueryMeta, er
|
||||||
return entries, qm, nil
|
return entries, qm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ACL) PolicyTranslate(rules string) (string, error) {
|
func (a *ACL) RulesTranslate(rules io.Reader) (string, error) {
|
||||||
r := a.c.newRequest("POST", "/v1/acl/policy/translate")
|
r := a.c.newRequest("POST", "/v1/acl/rules/translate")
|
||||||
r.obj = rules
|
r.body = rules
|
||||||
|
rtt, resp, err := requireOK(a.c.doRequest(r))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
qm := &QueryMeta{}
|
||||||
|
parseQueryMeta(resp, qm)
|
||||||
|
qm.RequestTime = rtt
|
||||||
|
|
||||||
|
ruleBytes, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Failed to read translated rule body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(ruleBytes), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ACL) RulesTranslateToken(tokenID string) (string, error) {
|
||||||
|
r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+tokenID)
|
||||||
rtt, resp, err := requireOK(a.c.doRequest(r))
|
rtt, resp, err := requireOK(a.c.doRequest(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -541,5 +538,4 @@ func (a *ACL) PolicyTranslate(rules string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(ruleBytes), nil
|
return string(ruleBytes), nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
560
api/acl_test.go
560
api/acl_test.go
|
@ -1,7 +1,12 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/testutil/retry"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAPI_ACLBootstrap(t *testing.T) {
|
func TestAPI_ACLBootstrap(t *testing.T) {
|
||||||
|
@ -163,3 +168,558 @@ func TestAPI_ACLReplication(t *testing.T) {
|
||||||
t.Fatalf("bad: %v", qm)
|
t.Fatalf("bad: %v", qm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLPolicy_CreateReadDelete(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.PolicyRead(created.ID, 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)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
created, _, 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)
|
||||||
|
|
||||||
|
read, _, err := acl.PolicyRead(created.ID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created, read)
|
||||||
|
|
||||||
|
read.Rules += ` service_prefix "" { policy = "read" }`
|
||||||
|
read.Datacenters = nil
|
||||||
|
|
||||||
|
updated, wm, err := acl.PolicyUpdate(read, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created.ID, updated.ID)
|
||||||
|
require.Equal(t, created.Description, updated.Description)
|
||||||
|
require.Equal(t, read.Rules, updated.Rules)
|
||||||
|
require.Equal(t, created.CreateIndex, updated.CreateIndex)
|
||||||
|
require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
|
||||||
|
require.Nil(t, updated.Datacenters)
|
||||||
|
require.NotEqual(t, 0, wm.RequestTime)
|
||||||
|
|
||||||
|
updated_read, _, err := acl.PolicyRead(created.ID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, updated, updated_read)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLPolicy_List(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
created1, _, err := acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "policy1",
|
||||||
|
Description: "policy1 description",
|
||||||
|
Rules: `node_prefix "" { policy = "read" }`,
|
||||||
|
Datacenters: []string{"dc1"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created1)
|
||||||
|
require.NotEqual(t, "", created1.ID)
|
||||||
|
|
||||||
|
created2, _, err := acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "policy2",
|
||||||
|
Description: "policy2 description",
|
||||||
|
Rules: `service "app" { policy = "write" }`,
|
||||||
|
Datacenters: []string{"dc1", "dc2"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created2)
|
||||||
|
require.NotEqual(t, "", created2.ID)
|
||||||
|
|
||||||
|
created3, _, err := acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "policy3",
|
||||||
|
Description: "policy3 description",
|
||||||
|
Rules: `acl = "read"`,
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created3)
|
||||||
|
require.NotEqual(t, "", created3.ID)
|
||||||
|
|
||||||
|
policies, qm, err := acl.PolicyList(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, policies, 4)
|
||||||
|
require.NotEqual(t, 0, qm.LastIndex)
|
||||||
|
require.True(t, qm.KnownLeader)
|
||||||
|
|
||||||
|
policyMap := make(map[string]*ACLPolicyListEntry)
|
||||||
|
for _, policy := range policies {
|
||||||
|
policyMap[policy.ID] = policy
|
||||||
|
}
|
||||||
|
|
||||||
|
policy1, ok := policyMap[created1.ID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, policy1)
|
||||||
|
require.Equal(t, created1.Name, policy1.Name)
|
||||||
|
require.Equal(t, created1.Description, policy1.Description)
|
||||||
|
require.Equal(t, created1.CreateIndex, policy1.CreateIndex)
|
||||||
|
require.Equal(t, created1.ModifyIndex, policy1.ModifyIndex)
|
||||||
|
require.Equal(t, created1.Hash, policy1.Hash)
|
||||||
|
require.ElementsMatch(t, created1.Datacenters, policy1.Datacenters)
|
||||||
|
|
||||||
|
policy2, ok := policyMap[created2.ID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, policy2)
|
||||||
|
require.Equal(t, created2.Name, policy2.Name)
|
||||||
|
require.Equal(t, created2.Description, policy2.Description)
|
||||||
|
require.Equal(t, created2.CreateIndex, policy2.CreateIndex)
|
||||||
|
require.Equal(t, created2.ModifyIndex, policy2.ModifyIndex)
|
||||||
|
require.Equal(t, created2.Hash, policy2.Hash)
|
||||||
|
require.ElementsMatch(t, created2.Datacenters, policy2.Datacenters)
|
||||||
|
|
||||||
|
policy3, ok := policyMap[created3.ID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, policy3)
|
||||||
|
require.Equal(t, created3.Name, policy3.Name)
|
||||||
|
require.Equal(t, created3.Description, policy3.Description)
|
||||||
|
require.Equal(t, created3.CreateIndex, policy3.CreateIndex)
|
||||||
|
require.Equal(t, created3.ModifyIndex, policy3.ModifyIndex)
|
||||||
|
require.Equal(t, created3.Hash, policy3.Hash)
|
||||||
|
require.ElementsMatch(t, created3.Datacenters, policy3.Datacenters)
|
||||||
|
|
||||||
|
// make sure the 4th policy is the global management
|
||||||
|
policy4, ok := policyMap["00000000-0000-0000-0000-000000000001"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, policy4)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepTokenPolicies(t *testing.T, acl *ACL) (policies []*ACLPolicy) {
|
||||||
|
policy, _, err := acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "one",
|
||||||
|
Description: "one description",
|
||||||
|
Rules: `acl = "read"`,
|
||||||
|
Datacenters: []string{"dc1", "dc2"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, policy)
|
||||||
|
policies = append(policies, policy)
|
||||||
|
|
||||||
|
policy, _, err = acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "two",
|
||||||
|
Description: "two description",
|
||||||
|
Rules: `node_prefix "" { policy = "read" }`,
|
||||||
|
Datacenters: []string{"dc1", "dc2"},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, policy)
|
||||||
|
policies = append(policies, policy)
|
||||||
|
|
||||||
|
policy, _, err = acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "three",
|
||||||
|
Description: "three description",
|
||||||
|
Rules: `service_prefix "" { policy = "read" }`,
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, policy)
|
||||||
|
policies = append(policies, policy)
|
||||||
|
|
||||||
|
policy, _, err = acl.PolicyCreate(&ACLPolicy{
|
||||||
|
Name: "four",
|
||||||
|
Description: "four description",
|
||||||
|
Rules: `agent "foo" { policy = "write" }`,
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, policy)
|
||||||
|
policies = append(policies, policy)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLToken_CreateReadDelete(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
policies := prepTokenPolicies(t, acl)
|
||||||
|
|
||||||
|
created, wm, err := acl.TokenCreate(&ACLToken{
|
||||||
|
Description: "token created",
|
||||||
|
Policies: []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[0].ID,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[1].ID,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
Name: policies[2].Name,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
Name: policies[3].Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created)
|
||||||
|
require.NotEqual(t, "", created.AccessorID)
|
||||||
|
require.NotEqual(t, "", created.SecretID)
|
||||||
|
require.NotEqual(t, 0, wm.RequestTime)
|
||||||
|
|
||||||
|
read, qm, err := acl.TokenRead(created.AccessorID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created, read)
|
||||||
|
require.NotEqual(t, 0, qm.LastIndex)
|
||||||
|
require.True(t, qm.KnownLeader)
|
||||||
|
|
||||||
|
acl.c.config.Token = created.SecretID
|
||||||
|
self, _, err := acl.TokenReadSelf(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created, self)
|
||||||
|
acl.c.config.Token = "root"
|
||||||
|
|
||||||
|
_, err = acl.TokenDelete(created.AccessorID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
read, _, err = acl.TokenRead(created.AccessorID, nil)
|
||||||
|
require.Nil(t, read)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLToken_CreateUpdate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
policies := prepTokenPolicies(t, acl)
|
||||||
|
|
||||||
|
created, _, err := acl.TokenCreate(&ACLToken{
|
||||||
|
Description: "token created",
|
||||||
|
Policies: []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[0].ID,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
Name: policies[2].Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created)
|
||||||
|
require.NotEqual(t, "", created.AccessorID)
|
||||||
|
require.NotEqual(t, "", created.SecretID)
|
||||||
|
|
||||||
|
read, _, err := acl.TokenRead(created.AccessorID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created, read)
|
||||||
|
|
||||||
|
read.Policies = append(read.Policies, &ACLTokenPolicyLink{ID: policies[1].ID})
|
||||||
|
read.Policies = append(read.Policies, &ACLTokenPolicyLink{Name: policies[2].Name})
|
||||||
|
|
||||||
|
expectedPolicies := []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[0].ID,
|
||||||
|
Name: policies[0].Name,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[1].ID,
|
||||||
|
Name: policies[1].Name,
|
||||||
|
},
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[2].ID,
|
||||||
|
Name: policies[2].Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
updated, wm, err := acl.TokenUpdate(read, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, created.AccessorID, updated.AccessorID)
|
||||||
|
require.Equal(t, created.SecretID, updated.SecretID)
|
||||||
|
require.Equal(t, created.Description, updated.Description)
|
||||||
|
require.Equal(t, created.CreateIndex, updated.CreateIndex)
|
||||||
|
require.NotEqual(t, created.ModifyIndex, updated.ModifyIndex)
|
||||||
|
require.ElementsMatch(t, expectedPolicies, updated.Policies)
|
||||||
|
require.NotEqual(t, 0, wm.RequestTime)
|
||||||
|
|
||||||
|
updated_read, _, err := acl.TokenRead(created.AccessorID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, updated, updated_read)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLToken_List(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
policies := prepTokenPolicies(t, acl)
|
||||||
|
|
||||||
|
created1, _, err := acl.TokenCreate(&ACLToken{
|
||||||
|
Description: "token created1",
|
||||||
|
Policies: []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[0].ID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created1)
|
||||||
|
require.NotEqual(t, "", created1.AccessorID)
|
||||||
|
require.NotEqual(t, "", created1.SecretID)
|
||||||
|
|
||||||
|
created2, _, err := acl.TokenCreate(&ACLToken{
|
||||||
|
Description: "token created2",
|
||||||
|
Policies: []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[1].ID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created2)
|
||||||
|
require.NotEqual(t, "", created2.AccessorID)
|
||||||
|
require.NotEqual(t, "", created2.SecretID)
|
||||||
|
|
||||||
|
created3, _, err := acl.TokenCreate(&ACLToken{
|
||||||
|
Description: "token created3",
|
||||||
|
Policies: []*ACLTokenPolicyLink{
|
||||||
|
&ACLTokenPolicyLink{
|
||||||
|
ID: policies[2].ID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, created3)
|
||||||
|
require.NotEqual(t, "", created3.AccessorID)
|
||||||
|
require.NotEqual(t, "", created3.SecretID)
|
||||||
|
|
||||||
|
tokens, qm, err := acl.TokenList(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
// 3 + anon + master
|
||||||
|
require.Len(t, tokens, 5)
|
||||||
|
require.NotEqual(t, 0, qm.LastIndex)
|
||||||
|
require.True(t, qm.KnownLeader)
|
||||||
|
|
||||||
|
tokenMap := make(map[string]*ACLTokenListEntry)
|
||||||
|
for _, token := range tokens {
|
||||||
|
tokenMap[token.AccessorID] = token
|
||||||
|
}
|
||||||
|
|
||||||
|
token1, ok := tokenMap[created1.AccessorID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, token1)
|
||||||
|
require.Equal(t, created1.Description, token1.Description)
|
||||||
|
require.Equal(t, created1.CreateIndex, token1.CreateIndex)
|
||||||
|
require.Equal(t, created1.ModifyIndex, token1.ModifyIndex)
|
||||||
|
require.Equal(t, created1.Hash, token1.Hash)
|
||||||
|
require.ElementsMatch(t, created1.Policies, token1.Policies)
|
||||||
|
|
||||||
|
token2, ok := tokenMap[created2.AccessorID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, token2)
|
||||||
|
require.Equal(t, created2.Description, token2.Description)
|
||||||
|
require.Equal(t, created2.CreateIndex, token2.CreateIndex)
|
||||||
|
require.Equal(t, created2.ModifyIndex, token2.ModifyIndex)
|
||||||
|
require.Equal(t, created2.Hash, token2.Hash)
|
||||||
|
require.ElementsMatch(t, created2.Policies, token2.Policies)
|
||||||
|
|
||||||
|
token3, ok := tokenMap[created3.AccessorID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, token3)
|
||||||
|
require.Equal(t, created3.Description, token3.Description)
|
||||||
|
require.Equal(t, created3.CreateIndex, token3.CreateIndex)
|
||||||
|
require.Equal(t, created3.ModifyIndex, token3.ModifyIndex)
|
||||||
|
require.Equal(t, created3.Hash, token3.Hash)
|
||||||
|
require.ElementsMatch(t, created3.Policies, token3.Policies)
|
||||||
|
|
||||||
|
// make sure the there is an anon token
|
||||||
|
token4, ok := tokenMap["00000000-0000-0000-0000-000000000002"]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, token4)
|
||||||
|
|
||||||
|
// ensure the 5th token is the root master token
|
||||||
|
root, _, err := acl.TokenReadSelf(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, root)
|
||||||
|
token5, ok := tokenMap[root.AccessorID]
|
||||||
|
require.True(t, ok)
|
||||||
|
require.NotNil(t, token5)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_ACLToken_Clone(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
master, _, err := acl.TokenReadSelf(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, master)
|
||||||
|
|
||||||
|
cloned, _, err := acl.TokenClone(master.AccessorID, "cloned", nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, cloned)
|
||||||
|
require.NotEqual(t, master.AccessorID, cloned.AccessorID)
|
||||||
|
require.NotEqual(t, master.SecretID, cloned.SecretID)
|
||||||
|
require.Equal(t, "cloned", cloned.Description)
|
||||||
|
require.ElementsMatch(t, master.Policies, cloned.Policies)
|
||||||
|
|
||||||
|
read, _, err := acl.TokenRead(cloned.AccessorID, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, read)
|
||||||
|
require.Equal(t, cloned, read)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_RulesTranslate_FromToken(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
ae := ACLEntry{
|
||||||
|
Name: "API test",
|
||||||
|
Type: ACLClientType,
|
||||||
|
Rules: `key "" { policy = "deny" }`,
|
||||||
|
}
|
||||||
|
|
||||||
|
id, _, err := acl.Create(&ae, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var accessor string
|
||||||
|
acl.c.config.Token = id
|
||||||
|
|
||||||
|
// This relies on the token upgrade loop running in the background
|
||||||
|
// to assign an accessor
|
||||||
|
retry.Run(t, func(t *retry.R) {
|
||||||
|
token, _, err := acl.TokenReadSelf(nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEqual(t, "", token.AccessorID)
|
||||||
|
accessor = token.AccessorID
|
||||||
|
})
|
||||||
|
acl.c.config.Token = "root"
|
||||||
|
|
||||||
|
rules, err := acl.RulesTranslateToken(accessor)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "key_prefix \"\" {\n policy = \"deny\"\n}", rules)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAPI_RulesTranslate_Raw(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
c, s := makeACLClient(t)
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
acl := c.ACL()
|
||||||
|
|
||||||
|
input := `#start of policy
|
||||||
|
agent "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
node "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
service "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
key "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
session "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
event "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
query "" {
|
||||||
|
policy = "read"
|
||||||
|
}`
|
||||||
|
|
||||||
|
expected := `#start of policy
|
||||||
|
agent_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
node_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
service_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
key_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
session_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
event_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
query_prefix "" {
|
||||||
|
policy = "read"
|
||||||
|
}`
|
||||||
|
|
||||||
|
rules, err := acl.RulesTranslate(strings.NewReader(input))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expected, rules)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue