mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Merge pull request #4966 from mitake/auth-role-grant
*: support granting key permission to role in v3 auth
This commit is contained in:
commit
27480f9ea4
@ -10,6 +10,7 @@
|
||||
|
||||
It has these top-level messages:
|
||||
User
|
||||
Permission
|
||||
Role
|
||||
*/
|
||||
package authpb
|
||||
@ -29,6 +30,29 @@ var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
type Permission_Type int32
|
||||
|
||||
const (
|
||||
READ Permission_Type = 0
|
||||
WRITE Permission_Type = 1
|
||||
READWRITE Permission_Type = 2
|
||||
)
|
||||
|
||||
var Permission_Type_name = map[int32]string{
|
||||
0: "READ",
|
||||
1: "WRITE",
|
||||
2: "READWRITE",
|
||||
}
|
||||
var Permission_Type_value = map[string]int32{
|
||||
"READ": 0,
|
||||
"WRITE": 1,
|
||||
"READWRITE": 2,
|
||||
}
|
||||
|
||||
func (x Permission_Type) String() string {
|
||||
return proto.EnumName(Permission_Type_name, int32(x))
|
||||
}
|
||||
|
||||
// User is a single entry in the bucket authUsers
|
||||
type User struct {
|
||||
Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
@ -40,9 +64,20 @@ func (m *User) Reset() { *m = User{} }
|
||||
func (m *User) String() string { return proto.CompactTextString(m) }
|
||||
func (*User) ProtoMessage() {}
|
||||
|
||||
// Permission is a single entity
|
||||
type Permission struct {
|
||||
Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
PermType Permission_Type `protobuf:"varint,2,opt,name=permType,proto3,enum=authpb.Permission_Type" json:"permType,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Permission) Reset() { *m = Permission{} }
|
||||
func (m *Permission) String() string { return proto.CompactTextString(m) }
|
||||
func (*Permission) ProtoMessage() {}
|
||||
|
||||
// Role is a single entry in the bucket authRoles
|
||||
type Role struct {
|
||||
Name []byte `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
KeyPermission []*Permission `protobuf:"bytes,2,rep,name=keyPermission" json:"keyPermission,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Role) Reset() { *m = Role{} }
|
||||
@ -51,7 +86,9 @@ func (*Role) ProtoMessage() {}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*User)(nil), "authpb.User")
|
||||
proto.RegisterType((*Permission)(nil), "authpb.Permission")
|
||||
proto.RegisterType((*Role)(nil), "authpb.Role")
|
||||
proto.RegisterEnum("authpb.Permission_Type", Permission_Type_name, Permission_Type_value)
|
||||
}
|
||||
func (m *User) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
@ -92,6 +129,37 @@ func (m *User) MarshalTo(data []byte) (int, error) {
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Permission) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
n, err := m.MarshalTo(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data[:n], nil
|
||||
}
|
||||
|
||||
func (m *Permission) MarshalTo(data []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key != nil {
|
||||
if len(m.Key) > 0 {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintAuth(data, i, uint64(len(m.Key)))
|
||||
i += copy(data[i:], m.Key)
|
||||
}
|
||||
}
|
||||
if m.PermType != 0 {
|
||||
data[i] = 0x10
|
||||
i++
|
||||
i = encodeVarintAuth(data, i, uint64(m.PermType))
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *Role) Marshal() (data []byte, err error) {
|
||||
size := m.Size()
|
||||
data = make([]byte, size)
|
||||
@ -109,12 +177,24 @@ func (m *Role) MarshalTo(data []byte) (int, error) {
|
||||
_ = l
|
||||
if m.Name != nil {
|
||||
if len(m.Name) > 0 {
|
||||
data[i] = 0x12
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintAuth(data, i, uint64(len(m.Name)))
|
||||
i += copy(data[i:], m.Name)
|
||||
}
|
||||
}
|
||||
if len(m.KeyPermission) > 0 {
|
||||
for _, msg := range m.KeyPermission {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintAuth(data, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@ -166,6 +246,21 @@ func (m *User) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Permission) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
if m.Key != nil {
|
||||
l = len(m.Key)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovAuth(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.PermType != 0 {
|
||||
n += 1 + sovAuth(uint64(m.PermType))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *Role) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
@ -175,6 +270,12 @@ func (m *Role) Size() (n int) {
|
||||
n += 1 + l + sovAuth(uint64(l))
|
||||
}
|
||||
}
|
||||
if len(m.KeyPermission) > 0 {
|
||||
for _, e := range m.KeyPermission {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovAuth(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -322,6 +423,106 @@ func (m *User) Unmarshal(data []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Permission) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAuth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: Permission: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: Permission: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAuth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthAuth
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Key = append(m.Key[:0], data[iNdEx:postIndex]...)
|
||||
if m.Key == nil {
|
||||
m.Key = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field PermType", wireType)
|
||||
}
|
||||
m.PermType = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAuth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
m.PermType |= (Permission_Type(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipAuth(data[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthAuth
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Role) Unmarshal(data []byte) error {
|
||||
l := len(data)
|
||||
iNdEx := 0
|
||||
@ -351,7 +552,7 @@ func (m *Role) Unmarshal(data []byte) error {
|
||||
return fmt.Errorf("proto: Role: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 2:
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
@ -382,6 +583,37 @@ func (m *Role) Unmarshal(data []byte) error {
|
||||
m.Name = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field KeyPermission", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowAuth
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthAuth
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.KeyPermission = append(m.KeyPermission, &Permission{})
|
||||
if err := m.KeyPermission[len(m.KeyPermission)-1].Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipAuth(data[iNdEx:])
|
||||
|
@ -16,7 +16,21 @@ message User {
|
||||
int64 tombstone = 3;
|
||||
}
|
||||
|
||||
// Permission is a single entity
|
||||
message Permission {
|
||||
bytes key = 1;
|
||||
|
||||
enum Type {
|
||||
READ = 0;
|
||||
WRITE = 1;
|
||||
READWRITE = 2;
|
||||
}
|
||||
Type permType = 2;
|
||||
}
|
||||
|
||||
// Role is a single entry in the bucket authRoles
|
||||
message Role {
|
||||
bytes name = 2;
|
||||
bytes name = 1;
|
||||
|
||||
repeated Permission keyPermission = 2;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/etcd/auth/authpb"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
@ -36,6 +37,7 @@ var (
|
||||
ErrUserAlreadyExist = errors.New("auth: user already exists")
|
||||
ErrUserNotFound = errors.New("auth: user not found")
|
||||
ErrRoleAlreadyExist = errors.New("auth: role already exists")
|
||||
ErrRoleNotFound = errors.New("auth: role not found")
|
||||
)
|
||||
|
||||
type AuthStore interface {
|
||||
@ -56,6 +58,9 @@ type AuthStore interface {
|
||||
|
||||
// RoleAdd adds a new role
|
||||
RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
|
||||
|
||||
// RoleGrant grants a permission to a role
|
||||
RoleGrant(r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error)
|
||||
}
|
||||
|
||||
type authStore struct {
|
||||
@ -195,6 +200,56 @@ func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse,
|
||||
return &pb.AuthRoleAddResponse{}, nil
|
||||
}
|
||||
|
||||
func (as *authStore) RoleGrant(r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) {
|
||||
tx := as.be.BatchTx()
|
||||
tx.Lock()
|
||||
defer tx.Unlock()
|
||||
|
||||
_, vs := tx.UnsafeRange(authRolesBucketName, []byte(r.Name), nil, 0)
|
||||
if len(vs) != 1 {
|
||||
return nil, ErrRoleNotFound
|
||||
}
|
||||
|
||||
role := &authpb.Role{}
|
||||
err := role.Unmarshal(vs[0])
|
||||
if err != nil {
|
||||
plog.Errorf("failed to unmarshal a role %s: %s", r.Name, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !updateExistingPermission(role.KeyPermission, string(r.Perm.Key), r.Perm.PermType) {
|
||||
newPerm := &authpb.Permission{
|
||||
Key: []byte(r.Perm.Key),
|
||||
PermType: r.Perm.PermType,
|
||||
}
|
||||
|
||||
role.KeyPermission = append(role.KeyPermission, newPerm)
|
||||
}
|
||||
|
||||
marshaledRole, merr := role.Marshal()
|
||||
if merr != nil {
|
||||
plog.Errorf("failed to marshal updated role %s: %s", r.Name, merr)
|
||||
return nil, merr
|
||||
}
|
||||
|
||||
tx.UnsafePut(authRolesBucketName, []byte(r.Name), marshaledRole)
|
||||
|
||||
plog.Noticef("role %s's permission of key %s is updated as %s", r.Name, r.Perm.Key, authpb.Permission_Type_name[int32(r.Perm.PermType)])
|
||||
|
||||
return &pb.AuthRoleGrantResponse{}, nil
|
||||
}
|
||||
|
||||
func updateExistingPermission(perms []*authpb.Permission, key string, newPerm authpb.Permission_Type) bool {
|
||||
for _, perm := range perms {
|
||||
if strings.Compare(string(perm.Key), key) == 0 {
|
||||
perm.PermType = newPerm
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func NewAuthStore(be backend.Backend) *authStore {
|
||||
tx := be.BatchTx()
|
||||
tx.Lock()
|
||||
|
@ -15,6 +15,10 @@
|
||||
package clientv3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/coreos/etcd/auth/authpb"
|
||||
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
@ -26,6 +30,15 @@ type (
|
||||
AuthUserDeleteResponse pb.AuthUserDeleteResponse
|
||||
AuthUserChangePasswordResponse pb.AuthUserChangePasswordResponse
|
||||
AuthRoleAddResponse pb.AuthRoleAddResponse
|
||||
AuthRoleGrantResponse pb.AuthRoleGrantResponse
|
||||
|
||||
PermissionType authpb.Permission_Type
|
||||
)
|
||||
|
||||
const (
|
||||
PermRead = authpb.READ
|
||||
PermWrite = authpb.WRITE
|
||||
PermReadWrite = authpb.READWRITE
|
||||
)
|
||||
|
||||
type Auth interface {
|
||||
@ -41,8 +54,11 @@ type Auth interface {
|
||||
// UserChangePassword changes a password of a user.
|
||||
UserChangePassword(ctx context.Context, name string, password string) (*AuthUserChangePasswordResponse, error)
|
||||
|
||||
// RoleAdd adds a new user to an etcd cluster.
|
||||
// RoleAdd adds a new role to an etcd cluster.
|
||||
RoleAdd(ctx context.Context, name string) (*AuthRoleAddResponse, error)
|
||||
|
||||
// RoleGrant grants a permission to a role.
|
||||
RoleGrant(ctx context.Context, name string, key string, permType PermissionType) (*AuthRoleGrantResponse, error)
|
||||
}
|
||||
|
||||
type auth struct {
|
||||
@ -85,3 +101,20 @@ func (auth *auth) RoleAdd(ctx context.Context, name string) (*AuthRoleAddRespons
|
||||
resp, err := auth.remote.RoleAdd(ctx, &pb.AuthRoleAddRequest{Name: name})
|
||||
return (*AuthRoleAddResponse)(resp), err
|
||||
}
|
||||
|
||||
func (auth *auth) RoleGrant(ctx context.Context, name string, key string, permType PermissionType) (*AuthRoleGrantResponse, error) {
|
||||
perm := &authpb.Permission{
|
||||
Key: []byte(key),
|
||||
PermType: authpb.Permission_Type(permType),
|
||||
}
|
||||
resp, err := auth.remote.RoleGrant(ctx, &pb.AuthRoleGrantRequest{Name: name, Perm: perm})
|
||||
return (*AuthRoleGrantResponse)(resp), err
|
||||
}
|
||||
|
||||
func StrToPermissionType(s string) (PermissionType, error) {
|
||||
val, ok := authpb.Permission_Type_value[strings.ToUpper(s)]
|
||||
if ok {
|
||||
return PermissionType(val), nil
|
||||
}
|
||||
return PermissionType(-1), fmt.Errorf("invalid permission type: %s", s)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package command
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
@ -29,6 +30,7 @@ func NewRoleCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
ac.AddCommand(newRoleAddCommand())
|
||||
ac.AddCommand(newRoleGrantCommand())
|
||||
|
||||
return ac
|
||||
}
|
||||
@ -41,6 +43,14 @@ func newRoleAddCommand() *cobra.Command {
|
||||
}
|
||||
}
|
||||
|
||||
func newRoleGrantCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "grant <role name> <permission type> <key>",
|
||||
Short: "grant a key to a role",
|
||||
Run: roleGrantCommandFunc,
|
||||
}
|
||||
}
|
||||
|
||||
// roleAddCommandFunc executes the "role add" command.
|
||||
func roleAddCommandFunc(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 1 {
|
||||
@ -54,3 +64,22 @@ func roleAddCommandFunc(cmd *cobra.Command, args []string) {
|
||||
|
||||
fmt.Printf("Role %s created\n", args[0])
|
||||
}
|
||||
|
||||
// roleGrantCommandFunc executes the "role grant" command.
|
||||
func roleGrantCommandFunc(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 3 {
|
||||
ExitWithError(ExitBadArgs, fmt.Errorf("role grant command requires role name, permission type, and key as its argument."))
|
||||
}
|
||||
|
||||
perm, err := clientv3.StrToPermissionType(args[1])
|
||||
if err != nil {
|
||||
ExitWithError(ExitBadArgs, err)
|
||||
}
|
||||
|
||||
_, err = mustClientFromCmd(cmd).Auth.RoleGrant(context.TODO(), args[0], args[2], perm)
|
||||
if err != nil {
|
||||
ExitWithError(ExitError, err)
|
||||
}
|
||||
|
||||
fmt.Printf("Role %s updated\n", args[0])
|
||||
}
|
||||
|
@ -70,8 +70,11 @@ func (as *AuthServer) RoleRevoke(ctx context.Context, r *pb.AuthRoleRevokeReques
|
||||
}
|
||||
|
||||
func (as *AuthServer) RoleGrant(ctx context.Context, r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) {
|
||||
plog.Info("not implemented yet")
|
||||
return nil, nil
|
||||
resp, err := as.authenticator.RoleGrant(ctx, r)
|
||||
if err != nil {
|
||||
return nil, togRPCError(err)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (as *AuthServer) UserAdd(ctx context.Context, r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) {
|
||||
|
@ -40,4 +40,5 @@ var (
|
||||
ErrUserAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name already exists")
|
||||
ErrUserNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: user name not found")
|
||||
ErrRoleAlreadyExist = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name already exists")
|
||||
ErrRoleNotFound = grpc.Errorf(codes.FailedPrecondition, "etcdserver: role name not found")
|
||||
)
|
||||
|
@ -43,6 +43,8 @@ func togRPCError(err error) error {
|
||||
return rpctypes.ErrUserNotFound
|
||||
case auth.ErrRoleAlreadyExist:
|
||||
return rpctypes.ErrRoleAlreadyExist
|
||||
case auth.ErrRoleNotFound:
|
||||
return rpctypes.ErrRoleNotFound
|
||||
default:
|
||||
return grpc.Errorf(codes.Internal, err.Error())
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ type applierV3 interface {
|
||||
UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
|
||||
UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
|
||||
RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
|
||||
RoleGrant(ua *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error)
|
||||
}
|
||||
|
||||
type applierV3backend struct {
|
||||
@ -93,6 +94,8 @@ func (s *EtcdServer) applyV3Request(r *pb.InternalRaftRequest) *applyResult {
|
||||
ar.resp, ar.err = s.applyV3.UserChangePassword(r.AuthUserChangePassword)
|
||||
case r.AuthRoleAdd != nil:
|
||||
ar.resp, ar.err = s.applyV3.RoleAdd(r.AuthRoleAdd)
|
||||
case r.AuthRoleGrant != nil:
|
||||
ar.resp, ar.err = s.applyV3.RoleGrant(r.AuthRoleGrant)
|
||||
default:
|
||||
panic("not implemented")
|
||||
}
|
||||
@ -496,6 +499,10 @@ func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddRes
|
||||
return a.s.AuthStore().RoleAdd(r)
|
||||
}
|
||||
|
||||
func (a *applierV3backend) RoleGrant(r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) {
|
||||
return a.s.AuthStore().RoleGrant(r)
|
||||
}
|
||||
|
||||
type quotaApplierV3 struct {
|
||||
applierV3
|
||||
q Quota
|
||||
|
@ -36,7 +36,8 @@ type InternalRaftRequest struct {
|
||||
AuthUserDelete *AuthUserDeleteRequest `protobuf:"bytes,12,opt,name=auth_user_delete" json:"auth_user_delete,omitempty"`
|
||||
AuthUserChangePassword *AuthUserChangePasswordRequest `protobuf:"bytes,13,opt,name=auth_user_change_password" json:"auth_user_change_password,omitempty"`
|
||||
AuthRoleAdd *AuthRoleAddRequest `protobuf:"bytes,14,opt,name=auth_role_add" json:"auth_role_add,omitempty"`
|
||||
Alarm *AlarmRequest `protobuf:"bytes,15,opt,name=alarm" json:"alarm,omitempty"`
|
||||
AuthRoleGrant *AuthRoleGrantRequest `protobuf:"bytes,15,opt,name=auth_role_grant" json:"auth_role_grant,omitempty"`
|
||||
Alarm *AlarmRequest `protobuf:"bytes,16,opt,name=alarm" json:"alarm,omitempty"`
|
||||
}
|
||||
|
||||
func (m *InternalRaftRequest) Reset() { *m = InternalRaftRequest{} }
|
||||
@ -204,16 +205,28 @@ func (m *InternalRaftRequest) MarshalTo(data []byte) (int, error) {
|
||||
}
|
||||
i += n13
|
||||
}
|
||||
if m.Alarm != nil {
|
||||
if m.AuthRoleGrant != nil {
|
||||
data[i] = 0x7a
|
||||
i++
|
||||
i = encodeVarintRaftInternal(data, i, uint64(m.Alarm.Size()))
|
||||
n14, err := m.Alarm.MarshalTo(data[i:])
|
||||
i = encodeVarintRaftInternal(data, i, uint64(m.AuthRoleGrant.Size()))
|
||||
n14, err := m.AuthRoleGrant.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n14
|
||||
}
|
||||
if m.Alarm != nil {
|
||||
data[i] = 0x82
|
||||
i++
|
||||
data[i] = 0x1
|
||||
i++
|
||||
i = encodeVarintRaftInternal(data, i, uint64(m.Alarm.Size()))
|
||||
n15, err := m.Alarm.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n15
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@ -320,9 +333,13 @@ func (m *InternalRaftRequest) Size() (n int) {
|
||||
l = m.AuthRoleAdd.Size()
|
||||
n += 1 + l + sovRaftInternal(uint64(l))
|
||||
}
|
||||
if m.AuthRoleGrant != nil {
|
||||
l = m.AuthRoleGrant.Size()
|
||||
n += 1 + l + sovRaftInternal(uint64(l))
|
||||
}
|
||||
if m.Alarm != nil {
|
||||
l = m.Alarm.Size()
|
||||
n += 1 + l + sovRaftInternal(uint64(l))
|
||||
n += 2 + l + sovRaftInternal(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
@ -824,6 +841,39 @@ func (m *InternalRaftRequest) Unmarshal(data []byte) error {
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 15:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AuthRoleGrant", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRaftInternal
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthRaftInternal
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.AuthRoleGrant == nil {
|
||||
m.AuthRoleGrant = &AuthRoleGrantRequest{}
|
||||
}
|
||||
if err := m.AuthRoleGrant.Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 16:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Alarm", wireType)
|
||||
}
|
||||
|
@ -30,8 +30,9 @@ message InternalRaftRequest {
|
||||
AuthUserDeleteRequest auth_user_delete = 12;
|
||||
AuthUserChangePasswordRequest auth_user_change_password = 13;
|
||||
AuthRoleAddRequest auth_role_add = 14;
|
||||
AuthRoleGrantRequest auth_role_grant = 15;
|
||||
|
||||
AlarmRequest alarm = 15;
|
||||
AlarmRequest alarm = 16;
|
||||
}
|
||||
|
||||
message EmptyResponse {
|
||||
|
@ -11,14 +11,17 @@ import (
|
||||
|
||||
math "math"
|
||||
|
||||
context "golang.org/x/net/context"
|
||||
authpb "github.com/coreos/etcd/auth/authpb"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
io "io"
|
||||
)
|
||||
|
||||
import storagepb "github.com/coreos/etcd/storage/storagepb"
|
||||
|
||||
import io "io"
|
||||
import (
|
||||
context "golang.org/x/net/context"
|
||||
grpc "google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
@ -1362,12 +1365,21 @@ func (m *AuthRoleDeleteRequest) String() string { return proto.CompactTextString
|
||||
func (*AuthRoleDeleteRequest) ProtoMessage() {}
|
||||
|
||||
type AuthRoleGrantRequest struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Perm *authpb.Permission `protobuf:"bytes,2,opt,name=perm" json:"perm,omitempty"`
|
||||
}
|
||||
|
||||
func (m *AuthRoleGrantRequest) Reset() { *m = AuthRoleGrantRequest{} }
|
||||
func (m *AuthRoleGrantRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*AuthRoleGrantRequest) ProtoMessage() {}
|
||||
|
||||
func (m *AuthRoleGrantRequest) GetPerm() *authpb.Permission {
|
||||
if m != nil {
|
||||
return m.Perm
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AuthRoleRevokeRequest struct {
|
||||
}
|
||||
|
||||
@ -4724,6 +4736,22 @@ func (m *AuthRoleGrantRequest) MarshalTo(data []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Name) > 0 {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(len(m.Name)))
|
||||
i += copy(data[i:], m.Name)
|
||||
}
|
||||
if m.Perm != nil {
|
||||
data[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Perm.Size()))
|
||||
n31, err := m.Perm.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n31
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@ -4764,11 +4792,11 @@ func (m *AuthEnableResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n31, err := m.Header.MarshalTo(data[i:])
|
||||
n32, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n31
|
||||
i += n32
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4792,11 +4820,11 @@ func (m *AuthDisableResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n32, err := m.Header.MarshalTo(data[i:])
|
||||
n33, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n32
|
||||
i += n33
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4820,11 +4848,11 @@ func (m *AuthenticateResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n33, err := m.Header.MarshalTo(data[i:])
|
||||
n34, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n33
|
||||
i += n34
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4848,11 +4876,11 @@ func (m *AuthUserAddResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n34, err := m.Header.MarshalTo(data[i:])
|
||||
n35, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n34
|
||||
i += n35
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4876,11 +4904,11 @@ func (m *AuthUserGetResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n35, err := m.Header.MarshalTo(data[i:])
|
||||
n36, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n35
|
||||
i += n36
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4904,11 +4932,11 @@ func (m *AuthUserDeleteResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n36, err := m.Header.MarshalTo(data[i:])
|
||||
n37, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n36
|
||||
i += n37
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4932,11 +4960,11 @@ func (m *AuthUserChangePasswordResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n37, err := m.Header.MarshalTo(data[i:])
|
||||
n38, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n37
|
||||
i += n38
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4960,11 +4988,11 @@ func (m *AuthUserGrantResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n38, err := m.Header.MarshalTo(data[i:])
|
||||
n39, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n38
|
||||
i += n39
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -4988,11 +5016,11 @@ func (m *AuthUserRevokeResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n39, err := m.Header.MarshalTo(data[i:])
|
||||
n40, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n39
|
||||
i += n40
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5016,11 +5044,11 @@ func (m *AuthRoleAddResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n40, err := m.Header.MarshalTo(data[i:])
|
||||
n41, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n40
|
||||
i += n41
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5044,11 +5072,11 @@ func (m *AuthRoleGetResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n41, err := m.Header.MarshalTo(data[i:])
|
||||
n42, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n41
|
||||
i += n42
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5072,11 +5100,11 @@ func (m *AuthRoleDeleteResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n42, err := m.Header.MarshalTo(data[i:])
|
||||
n43, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n42
|
||||
i += n43
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5100,11 +5128,11 @@ func (m *AuthRoleGrantResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n43, err := m.Header.MarshalTo(data[i:])
|
||||
n44, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n43
|
||||
i += n44
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5128,11 +5156,11 @@ func (m *AuthRoleRevokeResponse) MarshalTo(data []byte) (int, error) {
|
||||
data[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintRpc(data, i, uint64(m.Header.Size()))
|
||||
n44, err := m.Header.MarshalTo(data[i:])
|
||||
n45, err := m.Header.MarshalTo(data[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n44
|
||||
i += n45
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@ -5962,6 +5990,14 @@ func (m *AuthRoleDeleteRequest) Size() (n int) {
|
||||
func (m *AuthRoleGrantRequest) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRpc(uint64(l))
|
||||
}
|
||||
if m.Perm != nil {
|
||||
l = m.Perm.Size()
|
||||
n += 1 + l + sovRpc(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@ -11503,6 +11539,68 @@ func (m *AuthRoleGrantRequest) Unmarshal(data []byte) error {
|
||||
return fmt.Errorf("proto: AuthRoleGrantRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRpc
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRpc
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(data[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Perm", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRpc
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := data[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthRpc
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Perm == nil {
|
||||
m.Perm = &authpb.Permission{}
|
||||
}
|
||||
if err := m.Perm.Unmarshal(data[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRpc(data[iNdEx:])
|
||||
|
@ -3,6 +3,7 @@ package etcdserverpb;
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "etcd/storage/storagepb/kv.proto";
|
||||
import "etcd/auth/authpb/auth.proto";
|
||||
|
||||
option (gogoproto.marshaler_all) = true;
|
||||
option (gogoproto.unmarshaler_all) = true;
|
||||
@ -525,6 +526,8 @@ message AuthRoleDeleteRequest {
|
||||
}
|
||||
|
||||
message AuthRoleGrantRequest {
|
||||
string name = 1;
|
||||
authpb.Permission perm = 2;
|
||||
}
|
||||
|
||||
message AuthRoleRevokeRequest {
|
||||
|
@ -57,6 +57,7 @@ type Authenticator interface {
|
||||
UserDelete(ctx context.Context, r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error)
|
||||
UserChangePassword(ctx context.Context, r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error)
|
||||
RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error)
|
||||
RoleGrant(ctx context.Context, r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error)
|
||||
}
|
||||
|
||||
func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeResponse, error) {
|
||||
@ -242,6 +243,14 @@ func (s *EtcdServer) RoleAdd(ctx context.Context, r *pb.AuthRoleAddRequest) (*pb
|
||||
return result.resp.(*pb.AuthRoleAddResponse), result.err
|
||||
}
|
||||
|
||||
func (s *EtcdServer) RoleGrant(ctx context.Context, r *pb.AuthRoleGrantRequest) (*pb.AuthRoleGrantResponse, error) {
|
||||
result, err := s.processInternalRaftRequest(ctx, pb.InternalRaftRequest{AuthRoleGrant: r})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.resp.(*pb.AuthRoleGrantResponse), result.err
|
||||
}
|
||||
|
||||
func (s *EtcdServer) processInternalRaftRequest(ctx context.Context, r pb.InternalRaftRequest) (*applyResult, error) {
|
||||
r.ID = s.reqIDGen.Next()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user