From 365b4a4bed56bed3c852bbbf6a0bea93fab8faee Mon Sep 17 00:00:00 2001 From: Marcus Hines Date: Mon, 6 Jan 2025 18:18:38 +0000 Subject: [PATCH] Add ACL Policy for Debug service. This will enable the support of per user per command ACL for the service. this will allow the service to act as a grpc based replacement for ssh access that was previously acl'ed via username to tacacs --- debug/debug.pb.go | 176 +++++++++++++++++++++++++++++++++++++++++----- debug/debug.proto | 17 +++++ 2 files changed, 174 insertions(+), 19 deletions(-) diff --git a/debug/debug.pb.go b/debug/debug.pb.go index d5063da..5dfe279 100644 --- a/debug/debug.pb.go +++ b/debug/debug.pb.go @@ -308,6 +308,108 @@ func (x *DebugStatus) GetDetails() []*anypb.Any { return nil } +type Policy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Terms []*Term `protobuf:"bytes,1,rep,name=terms,proto3" json:"terms,omitempty"` +} + +func (x *Policy) Reset() { + *x = Policy{} + if protoimpl.UnsafeEnabled { + mi := &file_debug_debug_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy) ProtoMessage() {} + +func (x *Policy) ProtoReflect() protoreflect.Message { + mi := &file_debug_debug_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Policy.ProtoReflect.Descriptor instead. +func (*Policy) Descriptor() ([]byte, []int) { + return file_debug_debug_proto_rawDescGZIP(), []int{3} +} + +func (x *Policy) GetTerms() []*Term { + if x != nil { + return x.Terms + } + return nil +} + +type Term struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Users []string `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + Requests []*DebugRequest `protobuf:"bytes,2,rep,name=requests,proto3" json:"requests,omitempty"` +} + +func (x *Term) Reset() { + *x = Term{} + if protoimpl.UnsafeEnabled { + mi := &file_debug_debug_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Term) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Term) ProtoMessage() {} + +func (x *Term) ProtoReflect() protoreflect.Message { + mi := &file_debug_debug_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Term.ProtoReflect.Descriptor instead. +func (*Term) Descriptor() ([]byte, []int) { + return file_debug_debug_proto_rawDescGZIP(), []int{4} +} + +func (x *Term) GetUsers() []string { + if x != nil { + return x.Users + } + return nil +} + +func (x *Term) GetRequests() []*DebugRequest { + if x != nil { + return x.Requests + } + return nil +} + var File_debug_debug_proto protoreflect.FileDescriptor var file_debug_debug_proto_rawDesc = []byte{ @@ -349,15 +451,23 @@ var file_debug_debug_proto_rawDesc = []byte{ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, - 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x32, 0x47, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, - 0x67, 0x12, 0x3e, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x18, 0x2e, 0x67, 0x6e, 0x6f, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x30, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x26, 0x0a, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6e, 0x6f, 0x69, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x54, + 0x65, 0x72, 0x6d, 0x52, 0x05, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x22, 0x52, 0x0a, 0x04, 0x54, 0x65, + 0x72, 0x6d, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x6e, 0x6f, 0x69, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6e, 0x6f, 0x69, 0x2e, 0x64, 0x65, 0x62, 0x75, - 0x67, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, - 0x01, 0x42, 0x2a, 0xd2, 0x3e, 0x05, 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x5a, 0x20, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6f, 0x69, 0x2f, 0x64, 0x65, 0x62, 0x75, 0x67, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x65, 0x73, 0x74, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x73, 0x32, 0x47, + 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x3e, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, 0x67, + 0x12, 0x18, 0x2e, 0x67, 0x6e, 0x6f, 0x69, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x44, 0x65, + 0x62, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x6e, 0x6f, + 0x69, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0x2a, 0xd2, 0x3e, 0x05, 0x30, 0x2e, 0x31, 0x2e, + 0x30, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, + 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6f, 0x69, 0x2f, 0x64, 0x65, + 0x62, 0x75, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -373,26 +483,30 @@ func file_debug_debug_proto_rawDescGZIP() []byte { } var file_debug_debug_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_debug_debug_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_debug_debug_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_debug_debug_proto_goTypes = []interface{}{ (DebugRequest_Mode)(0), // 0: gnoi.debug.DebugRequest.Mode (*DebugRequest)(nil), // 1: gnoi.debug.DebugRequest (*DebugResponse)(nil), // 2: gnoi.debug.DebugResponse (*DebugStatus)(nil), // 3: gnoi.debug.DebugStatus - (*anypb.Any)(nil), // 4: google.protobuf.Any + (*Policy)(nil), // 4: gnoi.debug.Policy + (*Term)(nil), // 5: gnoi.debug.Term + (*anypb.Any)(nil), // 6: google.protobuf.Any } var file_debug_debug_proto_depIdxs = []int32{ 0, // 0: gnoi.debug.DebugRequest.mode:type_name -> gnoi.debug.DebugRequest.Mode 1, // 1: gnoi.debug.DebugResponse.request:type_name -> gnoi.debug.DebugRequest 3, // 2: gnoi.debug.DebugResponse.status:type_name -> gnoi.debug.DebugStatus - 4, // 3: gnoi.debug.DebugStatus.details:type_name -> google.protobuf.Any - 1, // 4: gnoi.debug.Debug.Debug:input_type -> gnoi.debug.DebugRequest - 2, // 5: gnoi.debug.Debug.Debug:output_type -> gnoi.debug.DebugResponse - 5, // [5:6] is the sub-list for method output_type - 4, // [4:5] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 6, // 3: gnoi.debug.DebugStatus.details:type_name -> google.protobuf.Any + 5, // 4: gnoi.debug.Policy.terms:type_name -> gnoi.debug.Term + 1, // 5: gnoi.debug.Term.requests:type_name -> gnoi.debug.DebugRequest + 1, // 6: gnoi.debug.Debug.Debug:input_type -> gnoi.debug.DebugRequest + 2, // 7: gnoi.debug.Debug.Debug:output_type -> gnoi.debug.DebugResponse + 7, // [7:8] is the sub-list for method output_type + 6, // [6:7] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_debug_debug_proto_init() } @@ -437,6 +551,30 @@ func file_debug_debug_proto_init() { return nil } } + file_debug_debug_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_debug_debug_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Term); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_debug_debug_proto_msgTypes[1].OneofWrappers = []interface{}{ (*DebugResponse_Request)(nil), @@ -449,7 +587,7 @@ func file_debug_debug_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_debug_debug_proto_rawDesc, NumEnums: 1, - NumMessages: 3, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/debug/debug.proto b/debug/debug.proto index 17e08be..4b49fac 100644 --- a/debug/debug.proto +++ b/debug/debug.proto @@ -75,3 +75,20 @@ message DebugStatus { // A list of messages that carry the error details. repeated google.protobuf.Any details = 3; } + +// Policy defines a set of commands a list of users are allowed to execute +// on the device. +// There can only be a single policy defined for the service. +message Policy { + repeated Term terms = 1; +} + +// Term defines a term in the policy for allowing access to commands by users. +message Term { + // Users are the allowed spiffe id's allowed to use the particular debug + // requests. + repeated string users = 1; + // The only fields in the request that are matched is mode / command + // role_account. + repeated DebugRequest requests = 2; +}