func printRolePermissions(name string, resp *clientv3.AuthRoleGetResponse) { fmt.Printf("Role %s\n", name) fmt.Println("KV Read:") printRange := func(perm *clientv3.Permission) { sKey := string(perm.Key) sRangeEnd := string(perm.RangeEnd) fmt.Printf("\t[%s, %s)", sKey, sRangeEnd) if strings.Compare(clientv3.GetPrefixRangeEnd(sKey), sRangeEnd) == 0 { fmt.Printf(" (prefix %s)", sKey) } fmt.Printf("\n") } for _, perm := range resp.Perm { if perm.PermType == clientv3.PermRead || perm.PermType == clientv3.PermReadWrite { if len(perm.RangeEnd) == 0 { fmt.Printf("\t%s\n", string(perm.Key)) } else { printRange((*clientv3.Permission)(perm)) } } } fmt.Println("KV Write:") for _, perm := range resp.Perm { if perm.PermType == clientv3.PermWrite || perm.PermType == clientv3.PermReadWrite { if len(perm.RangeEnd) == 0 { fmt.Printf("\t%s\n", string(perm.Key)) } else { printRange((*clientv3.Permission)(perm)) } } } }
// roleGrantPermissionCommandFunc executes the "role grant-permission" command. func roleGrantPermissionCommandFunc(cmd *cobra.Command, args []string) { if len(args) < 3 { ExitWithError(ExitBadArgs, fmt.Errorf("role grant command requires role name, permission type, and key [endkey] as its argument.")) } perm, err := clientv3.StrToPermissionType(args[1]) if err != nil { ExitWithError(ExitBadArgs, err) } rangeEnd := "" if 4 <= len(args) { if grantPermissionPrefix { ExitWithError(ExitBadArgs, fmt.Errorf("don't pass both of --prefix option and range end to grant permission command")) } rangeEnd = args[3] } else if grantPermissionPrefix { rangeEnd = clientv3.GetPrefixRangeEnd(args[2]) } _, err = mustClientFromCmd(cmd).Auth.RoleGrantPermission(context.TODO(), args[0], args[2], rangeEnd, perm) if err != nil { ExitWithError(ExitError, err) } fmt.Printf("Role %s updated\n", args[0]) }
func authTestPrefixPerm(cx ctlCtx) { if err := authEnable(cx); err != nil { cx.t.Fatal(err) } cx.user, cx.pass = "******", "root" authSetupTestUser(cx) prefix := "/prefix/" // directory like prefix // grant keys to test-user cx.user, cx.pass = "******", "root" if err := ctlV3RoleGrantPermission(cx, "test-role", grantingPerm{true, true, prefix, "", true}); err != nil { cx.t.Fatal(err) } // try a prefix granted permission cx.user, cx.pass = "******", "pass" for i := 0; i < 10; i++ { key := fmt.Sprintf("%s%d", prefix, i) if err := ctlV3Put(cx, key, "val", ""); err != nil { cx.t.Fatal(err) } } if err := ctlV3PutFailPerm(cx, clientv3.GetPrefixRangeEnd(prefix), "baz"); err != nil { cx.t.Fatal(err) } }
func (s *syncer) SyncBase(ctx context.Context) (<-chan clientv3.GetResponse, chan error) { respchan := make(chan clientv3.GetResponse, 1024) errchan := make(chan error, 1) // if rev is not specified, we will choose the most recent revision. if s.rev == 0 { resp, err := s.c.Get(ctx, "foo") if err != nil { errchan <- err close(respchan) close(errchan) return respchan, errchan } s.rev = resp.Header.Revision } go func() { defer close(respchan) defer close(errchan) var key string opts := []clientv3.OpOption{clientv3.WithLimit(batchLimit), clientv3.WithRev(s.rev)} if len(s.prefix) == 0 { // If len(s.prefix) == 0, we will sync the entire key-value space. // We then range from the smallest key (0x00) to the end. opts = append(opts, clientv3.WithFromKey()) key = "\x00" } else { // If len(s.prefix) != 0, we will sync key-value space with given prefix. // We then range from the prefix to the next prefix if exists. Or we will // range from the prefix to the end if the next prefix does not exists. opts = append(opts, clientv3.WithRange(clientv3.GetPrefixRangeEnd(s.prefix))) key = s.prefix } for { resp, err := s.c.Get(ctx, key, opts...) if err != nil { errchan <- err return } respchan <- (clientv3.GetResponse)(*resp) if !resp.More { return } // move to next key key = string(append(resp.Kvs[len(resp.Kvs)-1].Key, 0)) } }() return respchan, errchan }
// The keys attached to the lease has the format of "<leaseID>_<idx>" where idx is the ordering key creation // Since the format of keys contains about leaseID, finding keys base on "<leaseID>" prefix // determines whether the attached keys for a given leaseID has been deleted or not func (lc *leaseChecker) hasKeysAttachedToLeaseExpired(ctx context.Context, leaseID int64) (bool, error) { resp, err := lc.kvc.Range(ctx, &pb.RangeRequest{ Key: []byte(fmt.Sprintf("%d", leaseID)), RangeEnd: []byte(clientv3.GetPrefixRangeEnd(fmt.Sprintf("%d", leaseID))), }, grpc.FailFast(false)) plog.Debugf("hasKeysAttachedToLeaseExpired %v resp %v error (%v)", leaseID, resp, err) if err != nil { plog.Errorf("retriving keys attached to lease %v error: (%v)", leaseID, err) return false, err } return len(resp.Kvs) == 0, nil }