1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package etcdserver
16
17 import (
18 "encoding/base64"
19 "testing"
20 "time"
21
22 "golang.org/x/crypto/bcrypt"
23
24 betesting "go.etcd.io/etcd/server/v3/mvcc/backend/testing"
25
26 "github.com/stretchr/testify/assert"
27 "go.uber.org/zap/zaptest"
28
29 "go.etcd.io/etcd/api/v3/authpb"
30 pb "go.etcd.io/etcd/api/v3/etcdserverpb"
31 "go.etcd.io/etcd/server/v3/auth"
32 "go.etcd.io/etcd/server/v3/lease"
33 )
34
35 func TestCheckLeasePutsKeys(t *testing.T) {
36 lg := zaptest.NewLogger(t)
37
38 b, _ := betesting.NewDefaultTmpBackend(t)
39 defer betesting.Close(t, b)
40
41 simpleTokenTTLDefault := 300 * time.Second
42 tokenTypeSimple := "simple"
43 dummyIndexWaiter := func(index uint64) <-chan struct{} {
44 ch := make(chan struct{}, 1)
45 go func() {
46 ch <- struct{}{}
47 }()
48 return ch
49 }
50
51 tp, _ := auth.NewTokenProvider(zaptest.NewLogger(t), tokenTypeSimple, dummyIndexWaiter, simpleTokenTTLDefault)
52 as := auth.NewAuthStore(lg, b, tp, bcrypt.MinCost)
53 defer as.AuthDisable()
54
55 aa := authApplierV3{as: as}
56 assert.NoError(t, aa.checkLeasePutsKeys(lease.NewLease(lease.LeaseID(1), 3600)), "auth is disabled, should allow puts")
57 assert.NoError(t, enableAuthAndCreateRoot(aa.as), "error while enabling auth")
58 aa.authInfo = auth.AuthInfo{Username: "root"}
59 assert.NoError(t, aa.checkLeasePutsKeys(lease.NewLease(lease.LeaseID(1), 3600)), "auth is enabled, should allow puts for root")
60
61 l := lease.NewLease(lease.LeaseID(1), 3600)
62 l.SetLeaseItem(lease.LeaseItem{Key: "a"})
63 aa.authInfo = auth.AuthInfo{Username: "bob", Revision: 0}
64 assert.ErrorIs(t, aa.checkLeasePutsKeys(l), auth.ErrUserEmpty, "auth is enabled, should not allow bob, non existing at rev 0")
65 aa.authInfo = auth.AuthInfo{Username: "bob", Revision: 1}
66 assert.ErrorIs(t, aa.checkLeasePutsKeys(l), auth.ErrAuthOldRevision, "auth is enabled, old revision")
67
68 aa.authInfo = auth.AuthInfo{Username: "bob", Revision: aa.as.Revision()}
69 assert.ErrorIs(t, aa.checkLeasePutsKeys(l), auth.ErrPermissionDenied, "auth is enabled, bob does not have permissions, bob does not exist")
70 _, err := aa.as.UserAdd(&pb.AuthUserAddRequest{Name: "bob", Options: &authpb.UserAddOptions{NoPassword: true}})
71 assert.NoError(t, err, "bob should be added without error")
72 aa.authInfo = auth.AuthInfo{Username: "bob", Revision: aa.as.Revision()}
73 assert.ErrorIs(t, aa.checkLeasePutsKeys(l), auth.ErrPermissionDenied, "auth is enabled, bob exists yet does not have permissions")
74
75
76 _, err = aa.as.RoleAdd(&pb.AuthRoleAddRequest{Name: "bobsrole"})
77 assert.NoError(t, err, "bobsrole should be added without error")
78 _, err = aa.as.RoleGrantPermission(&pb.AuthRoleGrantPermissionRequest{
79 Name: "bobsrole",
80 Perm: &authpb.Permission{
81 PermType: authpb.READWRITE,
82 Key: []byte("a"),
83 RangeEnd: nil,
84 },
85 })
86 assert.NoError(t, err, "bobsrole should be granted permissions without error")
87 _, err = aa.as.UserGrantRole(&pb.AuthUserGrantRoleRequest{
88 User: "bob",
89 Role: "bobsrole",
90 })
91 assert.NoError(t, err, "bob should be granted bobsrole without error")
92
93 aa.authInfo = auth.AuthInfo{Username: "bob", Revision: aa.as.Revision()}
94 assert.NoError(t, aa.checkLeasePutsKeys(l), "bob should be able to access key 'a'")
95
96 }
97
98 func enableAuthAndCreateRoot(as auth.AuthStore) error {
99 _, err := as.UserAdd(&pb.AuthUserAddRequest{
100 Name: "root",
101 HashedPassword: encodePassword("root"),
102 Options: &authpb.UserAddOptions{NoPassword: false}})
103 if err != nil {
104 return err
105 }
106
107 _, err = as.RoleAdd(&pb.AuthRoleAddRequest{Name: "root"})
108 if err != nil {
109 return err
110 }
111
112 _, err = as.UserGrantRole(&pb.AuthUserGrantRoleRequest{User: "root", Role: "root"})
113 if err != nil {
114 return err
115 }
116
117 return as.AuthEnable()
118 }
119
120 func encodePassword(s string) string {
121 hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(s), bcrypt.MinCost)
122 return base64.StdEncoding.EncodeToString(hashedPassword)
123 }
124
View as plain text