2017-08-19 23:49:53 +00:00
|
|
|
package nomad
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
lru "github.com/hashicorp/golang-lru"
|
|
|
|
"github.com/hashicorp/nomad/acl"
|
2022-03-15 12:42:43 +00:00
|
|
|
"github.com/hashicorp/nomad/ci"
|
2017-09-29 16:58:48 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/uuid"
|
2017-08-19 23:49:53 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/mock"
|
|
|
|
"github.com/hashicorp/nomad/nomad/state"
|
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2017-10-23 19:50:37 +00:00
|
|
|
"github.com/hashicorp/nomad/testutil"
|
2017-08-19 23:49:53 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestResolveACLToken(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
2017-10-23 19:50:37 +00:00
|
|
|
|
2017-08-19 23:49:53 +00:00
|
|
|
// Create mock state store and cache
|
2017-10-13 21:36:02 +00:00
|
|
|
state := state.TestStateStore(t)
|
2017-08-19 23:49:53 +00:00
|
|
|
cache, err := lru.New2Q(16)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
// Create a policy / token
|
|
|
|
policy := mock.ACLPolicy()
|
|
|
|
policy2 := mock.ACLPolicy()
|
|
|
|
token := mock.ACLToken()
|
|
|
|
token.Policies = []string{policy.Name, policy2.Name}
|
|
|
|
token2 := mock.ACLToken()
|
|
|
|
token2.Type = structs.ACLManagementToken
|
|
|
|
token2.Policies = nil
|
2020-12-01 16:11:34 +00:00
|
|
|
err = state.UpsertACLPolicies(structs.MsgTypeTestSetup, 100, []*structs.ACLPolicy{policy, policy2})
|
2017-08-19 23:49:53 +00:00
|
|
|
assert.Nil(t, err)
|
2020-12-01 16:11:34 +00:00
|
|
|
err = state.UpsertACLTokens(structs.MsgTypeTestSetup, 110, []*structs.ACLToken{token, token2})
|
2017-08-19 23:49:53 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
snap, err := state.Snapshot()
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
2017-08-20 21:38:37 +00:00
|
|
|
// Attempt resolution of blank token. Should return anonymous policy
|
|
|
|
aclObj, err := resolveTokenFromSnapshotCache(snap, cache, "")
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.NotNil(t, aclObj)
|
|
|
|
|
2017-08-19 23:49:53 +00:00
|
|
|
// Attempt resolution of unknown token. Should fail.
|
2017-09-29 16:58:48 +00:00
|
|
|
randID := uuid.Generate()
|
2017-08-20 21:38:37 +00:00
|
|
|
aclObj, err = resolveTokenFromSnapshotCache(snap, cache, randID)
|
2017-08-21 03:18:18 +00:00
|
|
|
assert.Equal(t, structs.ErrTokenNotFound, err)
|
2017-08-19 23:49:53 +00:00
|
|
|
assert.Nil(t, aclObj)
|
|
|
|
|
|
|
|
// Attempt resolution of management token. Should get singleton.
|
|
|
|
aclObj, err = resolveTokenFromSnapshotCache(snap, cache, token2.SecretID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.NotNil(t, aclObj)
|
|
|
|
assert.Equal(t, true, aclObj.IsManagement())
|
2017-08-20 01:29:04 +00:00
|
|
|
if aclObj != acl.ManagementACL {
|
2017-08-19 23:49:53 +00:00
|
|
|
t.Fatalf("expected singleton")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attempt resolution of client token
|
|
|
|
aclObj, err = resolveTokenFromSnapshotCache(snap, cache, token.SecretID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.NotNil(t, aclObj)
|
|
|
|
|
|
|
|
// Check that the ACL object is sane
|
|
|
|
assert.Equal(t, false, aclObj.IsManagement())
|
|
|
|
allowed := aclObj.AllowNamespaceOperation("default", acl.NamespaceCapabilityListJobs)
|
|
|
|
assert.Equal(t, true, allowed)
|
|
|
|
allowed = aclObj.AllowNamespaceOperation("other", acl.NamespaceCapabilityListJobs)
|
|
|
|
assert.Equal(t, false, allowed)
|
|
|
|
|
|
|
|
// Resolve the same token again, should get cache value
|
|
|
|
aclObj2, err := resolveTokenFromSnapshotCache(snap, cache, token.SecretID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.NotNil(t, aclObj2)
|
|
|
|
if aclObj != aclObj2 {
|
|
|
|
t.Fatalf("expected cached value")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bust the cache by upserting the policy
|
2020-12-01 16:11:34 +00:00
|
|
|
err = state.UpsertACLPolicies(structs.MsgTypeTestSetup, 120, []*structs.ACLPolicy{policy})
|
2017-08-19 23:49:53 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
snap, err = state.Snapshot()
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
// Resolve the same token again, should get different value
|
|
|
|
aclObj3, err := resolveTokenFromSnapshotCache(snap, cache, token.SecretID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
assert.NotNil(t, aclObj3)
|
|
|
|
if aclObj == aclObj3 {
|
|
|
|
t.Fatalf("unexpected cached value")
|
|
|
|
}
|
|
|
|
}
|
2017-10-23 19:50:37 +00:00
|
|
|
|
|
|
|
func TestResolveACLToken_LeaderToken(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
2017-10-23 19:50:37 +00:00
|
|
|
assert := assert.New(t)
|
2019-12-04 00:15:11 +00:00
|
|
|
s1, _, cleanupS1 := TestACLServer(t, nil)
|
|
|
|
defer cleanupS1()
|
2017-10-23 19:50:37 +00:00
|
|
|
testutil.WaitForLeader(t, s1.RPC)
|
|
|
|
|
|
|
|
leaderAcl := s1.getLeaderAcl()
|
|
|
|
assert.NotEmpty(leaderAcl)
|
|
|
|
token, err := s1.ResolveToken(leaderAcl)
|
|
|
|
assert.Nil(err)
|
|
|
|
if assert.NotNil(token) {
|
|
|
|
assert.True(token.IsManagement())
|
|
|
|
}
|
|
|
|
}
|
2020-03-22 16:17:33 +00:00
|
|
|
|
|
|
|
func TestResolveSecretToken(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
2020-03-22 16:17:33 +00:00
|
|
|
|
|
|
|
s1, _, cleanupS1 := TestACLServer(t, nil)
|
|
|
|
defer cleanupS1()
|
|
|
|
testutil.WaitForLeader(t, s1.RPC)
|
|
|
|
|
|
|
|
state := s1.State()
|
|
|
|
leaderToken := s1.getLeaderAcl()
|
|
|
|
assert.NotEmpty(t, leaderToken)
|
|
|
|
|
|
|
|
token := mock.ACLToken()
|
|
|
|
|
2020-12-01 16:11:34 +00:00
|
|
|
err := state.UpsertACLTokens(structs.MsgTypeTestSetup, 110, []*structs.ACLToken{token})
|
2020-03-22 16:17:33 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
|
|
|
|
respToken, err := s1.ResolveSecretToken(token.SecretID)
|
|
|
|
assert.Nil(t, err)
|
|
|
|
if assert.NotNil(t, respToken) {
|
|
|
|
assert.NotEmpty(t, respToken.AccessorID)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|