diff --git a/api/client/events.go b/api/client/events.go index 6b9d9240a723a..0267933f0d3d2 100644 --- a/api/client/events.go +++ b/api/client/events.go @@ -19,6 +19,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" "github.com/gravitational/teleport/api/types" @@ -66,6 +67,12 @@ func EventToGRPC(in types.Event) (*proto.Event, error) { out.Resource = &proto.Event_CrownJewel{ CrownJewel: r, } + case *clusterconfigpb.AccessGraphSettings: + out.Resource = &proto.Event_AccessGraphSettings{ + AccessGraphSettings: r, + } + default: + return nil, trace.BadParameter("resource type %T is not supported", r) } case *types.ResourceHeader: out.Resource = &proto.Event_ResourceHeader{ @@ -486,6 +493,9 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) { } else if r := in.GetCrownJewel(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil + } else if r := in.GetAccessGraphSettings(); r != nil { + out.Resource = types.Resource153ToLegacy(r) + return &out, nil } else { return nil, trace.BadParameter("received unsupported resource %T", in.Resource) } diff --git a/api/client/proto/event.pb.go b/api/client/proto/event.pb.go index 7518486cf92db..7720e03072e57 100644 --- a/api/client/proto/event.pb.go +++ b/api/client/proto/event.pb.go @@ -23,6 +23,7 @@ package proto import ( v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1" v15 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + v17 "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" v16 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" v12 "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1" v14 "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" @@ -161,6 +162,7 @@ type Event struct { // *Event_KubernetesWaitingContainer // *Event_AccessMonitoringRule // *Event_CrownJewel + // *Event_AccessGraphSettings Resource isEvent_Resource `protobuf_oneof:"Resource"` } @@ -581,6 +583,13 @@ func (x *Event) GetCrownJewel() *v16.CrownJewel { return nil } +func (x *Event) GetAccessGraphSettings() *v17.AccessGraphSettings { + if x, ok := x.GetResource().(*Event_AccessGraphSettings); ok { + return x.AccessGraphSettings + } + return nil +} + type isEvent_Resource interface { isEvent_Resource() } @@ -853,6 +862,11 @@ type Event_CrownJewel struct { CrownJewel *v16.CrownJewel `protobuf:"bytes,58,opt,name=CrownJewel,proto3,oneof"` } +type Event_AccessGraphSettings struct { + // AccessGraphSettings is a resource for access graph settings. + AccessGraphSettings *v17.AccessGraphSettings `protobuf:"bytes,61,opt,name=AccessGraphSettings,proto3,oneof"` +} + func (*Event_ResourceHeader) isEvent_Resource() {} func (*Event_CertAuthority) isEvent_Resource() {} @@ -959,6 +973,8 @@ func (*Event_AccessMonitoringRule) isEvent_Resource() {} func (*Event_CrownJewel) isEvent_Resource() {} +func (*Event_AccessGraphSettings) isEvent_Resource() {} + var File_teleport_legacy_client_proto_event_proto protoreflect.FileDescriptor var file_teleport_legacy_client_proto_event_proto_rawDesc = []byte{ @@ -971,259 +987,269 @@ var file_teleport_legacy_client_proto_event_proto_rawDesc = []byte{ 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, - 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, - 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, - 0x31, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, - 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, - 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, - 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x6c, - 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, - 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xbe, 0x1c, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x54, - 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x48, 0x00, 0x52, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x56, 0x32, 0x48, - 0x00, 0x52, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, - 0x41, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x32, - 0x48, 0x00, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, - 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, - 0x55, 0x73, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x23, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, - 0x52, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x48, 0x00, 0x52, 0x09, 0x4e, - 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x06, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, - 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, - 0x56, 0x32, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, - 0x6e, 0x65, 0x6c, 0x12, 0x47, 0x0a, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x10, 0x54, 0x75, 0x6e, 0x6e, - 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0a, - 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, - 0x00, 0x52, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, - 0x08, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x56, 0x33, 0x48, 0x00, 0x52, 0x08, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5c, - 0x0a, 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, - 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x16, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, - 0x16, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, - 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x41, 0x75, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x43, 0x6c, + 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x35, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x72, 0x6f, + 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x6f, 0x77, 0x6e, + 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, + 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x76, 0x31, + 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa2, 0x1d, 0x0a, 0x05, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x43, 0x65, 0x72, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0d, 0x43, 0x65, 0x72, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0c, 0x53, 0x74, 0x61, + 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, + 0x48, 0x00, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, + 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, 0x52, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x30, 0x0a, + 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x48, 0x00, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, + 0x29, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, + 0x48, 0x00, 0x52, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, + 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, + 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x76, + 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x47, 0x0a, 0x10, 0x54, 0x75, + 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x6e, + 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, + 0x00, 0x52, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0a, + 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x44, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x35, 0x0a, + 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x08, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, + 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x33, 0x48, 0x00, 0x52, 0x08, 0x57, 0x65, 0x62, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5c, 0x0a, 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x17, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x16, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, + 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x48, + 0x00, 0x52, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x12, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x12, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x6f, 0x63, - 0x6b, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x50, - 0x0a, 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, - 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x34, 0x48, 0x00, 0x52, 0x13, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x56, 0x0a, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, - 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, - 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x33, 0x48, - 0x00, 0x52, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, - 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x57, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, - 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x57, 0x69, 0x6e, - 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x56, 0x33, - 0x48, 0x00, 0x52, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, - 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x09, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x12, 0x20, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x03, 0x41, - 0x70, 0x70, 0x12, 0x41, 0x0a, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x10, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x10, 0x4b, 0x75, - 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x4a, - 0x0a, 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, - 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x56, - 0x31, 0x48, 0x00, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x44, - 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, - 0x31, 0x48, 0x00, 0x52, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x24, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x41, 0x4d, - 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x56, 0x31, 0x48, 0x00, 0x52, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, - 0x3d, 0x0a, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, - 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, - 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x26, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x27, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x49, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x48, 0x00, 0x52, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, - 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, - 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, - 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, - 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, - 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0b, 0x49, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x56, 0x31, 0x48, 0x00, - 0x52, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x57, 0x0a, - 0x16, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, - 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, - 0x52, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x0e, - 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x2e, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x58, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x12, 0x38, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x48, 0x00, 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x47, 0x0a, 0x0b, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, - 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x48, 0x00, 0x52, - 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x12, 0x7e, 0x0a, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, - 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, - 0x37, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, - 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x48, 0x00, 0x52, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, - 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x12, 0x6d, 0x0a, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, - 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x14, 0x41, 0x63, 0x63, 0x65, + 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x48, 0x00, 0x52, + 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x19, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x34, + 0x48, 0x00, 0x52, 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x56, 0x0a, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, + 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x56, 0x33, 0x48, 0x00, 0x52, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, + 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x41, 0x0a, 0x0e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, + 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, + 0x48, 0x00, 0x52, 0x0e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, + 0x6f, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x1c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x56, 0x33, 0x48, 0x00, 0x52, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, + 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x09, 0x41, 0x70, + 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x18, 0x1e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, + 0x56, 0x33, 0x48, 0x00, 0x52, 0x03, 0x41, 0x70, 0x70, 0x12, 0x41, 0x0a, 0x10, 0x53, 0x6e, 0x6f, + 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x10, 0x53, 0x6e, 0x6f, 0x77, + 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x10, + 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, + 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, + 0x33, 0x48, 0x00, 0x52, 0x10, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x11, + 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x22, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x56, 0x31, 0x48, 0x00, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, + 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0f, 0x44, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x16, 0x53, + 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x56, 0x31, 0x48, 0x00, 0x52, 0x16, + 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, + 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x09, + 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x55, 0x49, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x48, 0x00, + 0x52, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, + 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x28, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x49, + 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, + 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x41, 0x0a, + 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, + 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, + 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x31, 0x48, 0x00, + 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x38, 0x0a, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, 0x49, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x57, 0x0a, 0x16, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x2f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x58, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, + 0x52, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x75, 0x64, + 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x38, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x12, 0x47, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x35, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x48, 0x00, 0x52, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x7e, 0x0a, 0x1a, 0x4b, 0x75, 0x62, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x37, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, + 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x48, 0x00, 0x52, 0x1a, 0x4b, 0x75, + 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x6d, 0x0a, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, - 0x12, 0x44, 0x0a, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x18, 0x3a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x0a, 0x43, 0x72, 0x6f, 0x77, - 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x31, 0x10, 0x32, 0x52, 0x12, - 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x75, 0x64, - 0x69, 0x74, 0x2a, 0x2a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, - 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x42, 0x34, - 0x5a, 0x32, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x48, + 0x00, 0x52, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, + 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, + 0x00, 0x52, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x12, 0x62, 0x0a, + 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x18, 0x3d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x48, 0x00, 0x52, 0x13, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x42, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4a, 0x04, 0x08, + 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x31, 0x10, 0x32, 0x52, 0x12, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x75, 0x64, 0x69, 0x74, 0x2a, 0x2a, 0x0a, + 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, + 0x49, 0x54, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, + 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1293,6 +1319,7 @@ var file_teleport_legacy_client_proto_event_proto_goTypes = []interface{}{ (*v14.KubernetesWaitingContainer)(nil), // 49: teleport.kubewaitingcontainer.v1.KubernetesWaitingContainer (*v15.AccessMonitoringRule)(nil), // 50: teleport.accessmonitoringrules.v1.AccessMonitoringRule (*v16.CrownJewel)(nil), // 51: teleport.crownjewel.v1.CrownJewel + (*v17.AccessGraphSettings)(nil), // 52: teleport.clusterconfig.v1.AccessGraphSettings } var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 0, // 0: proto.Event.Type:type_name -> proto.Operation @@ -1349,11 +1376,12 @@ var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 49, // 51: proto.Event.KubernetesWaitingContainer:type_name -> teleport.kubewaitingcontainer.v1.KubernetesWaitingContainer 50, // 52: proto.Event.AccessMonitoringRule:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule 51, // 53: proto.Event.CrownJewel:type_name -> teleport.crownjewel.v1.CrownJewel - 54, // [54:54] is the sub-list for method output_type - 54, // [54:54] is the sub-list for method input_type - 54, // [54:54] is the sub-list for extension type_name - 54, // [54:54] is the sub-list for extension extendee - 0, // [0:54] is the sub-list for field type_name + 52, // 54: proto.Event.AccessGraphSettings:type_name -> teleport.clusterconfig.v1.AccessGraphSettings + 55, // [55:55] is the sub-list for method output_type + 55, // [55:55] is the sub-list for method input_type + 55, // [55:55] is the sub-list for extension type_name + 55, // [55:55] is the sub-list for extension extendee + 0, // [0:55] is the sub-list for field type_name } func init() { file_teleport_legacy_client_proto_event_proto_init() } @@ -1429,6 +1457,7 @@ func file_teleport_legacy_client_proto_event_proto_init() { (*Event_KubernetesWaitingContainer)(nil), (*Event_AccessMonitoringRule)(nil), (*Event_CrownJewel)(nil), + (*Event_AccessGraphSettings)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/api/gen/proto/go/teleport/accessgraph/v1/authorized_key.pb.go b/api/gen/proto/go/teleport/accessgraph/v1/authorized_key.pb.go new file mode 100644 index 0000000000000..11a3a967d6dbc --- /dev/null +++ b/api/gen/proto/go/teleport/accessgraph/v1/authorized_key.pb.go @@ -0,0 +1,331 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/access_graph/v1/authorized_key.proto + +package accessgraphv1 + +import ( + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The `AuthorizedKey` message represents an authorized key entry for a specific local user. +// These authorized keys are generated by the server when a particular SSH AuthorizedKey is granted access to a user on the node. +type AuthorizedKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // metadata is the AuthorizedKey's metadata. + Metadata *v1.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + // kind is a resource kind. + Kind string `protobuf:"bytes,2,opt,name=kind,proto3" json:"kind,omitempty"` + // sub_kind is an optional resource sub kind, used in some resources. + SubKind string `protobuf:"bytes,3,opt,name=sub_kind,json=subKind,proto3" json:"sub_kind,omitempty"` + // version is version. + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + // Spec is an AuthorizedKey specification. + Spec *AuthorizedKeySpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` +} + +func (x *AuthorizedKey) Reset() { + *x = AuthorizedKey{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_authorized_key_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthorizedKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthorizedKey) ProtoMessage() {} + +func (x *AuthorizedKey) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_authorized_key_proto_msgTypes[0] + 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 AuthorizedKey.ProtoReflect.Descriptor instead. +func (*AuthorizedKey) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_authorized_key_proto_rawDescGZIP(), []int{0} +} + +func (x *AuthorizedKey) GetMetadata() *v1.Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *AuthorizedKey) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *AuthorizedKey) GetSubKind() string { + if x != nil { + return x.SubKind + } + return "" +} + +func (x *AuthorizedKey) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *AuthorizedKey) GetSpec() *AuthorizedKeySpec { + if x != nil { + return x.Spec + } + return nil +} + +// AuthorizedKeySpec is the authorized key spec. +type AuthorizedKeySpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // host_id is the node identifier and must match the credentials used. + HostId string `protobuf:"bytes,1,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty"` + // key_fingerprint is the SHA256 SSH public key fingerprint. + KeyFingerprint string `protobuf:"bytes,2,opt,name=key_fingerprint,json=keyFingerprint,proto3" json:"key_fingerprint,omitempty"` + // host_user is the user who can be accessed using the fingerprint above. + HostUser string `protobuf:"bytes,3,opt,name=host_user,json=hostUser,proto3" json:"host_user,omitempty"` + // key_comment is the authorized key's comment. + // Authorized keys consist of the following space-separated fields: + // options, keytype, base64-encoded key, comment. The options field is optional. + KeyComment string `protobuf:"bytes,4,opt,name=key_comment,json=keyComment,proto3" json:"key_comment,omitempty"` + // key_type is the ssh's key type. + KeyType string `protobuf:"bytes,5,opt,name=key_type,json=keyType,proto3" json:"key_type,omitempty"` +} + +func (x *AuthorizedKeySpec) Reset() { + *x = AuthorizedKeySpec{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_authorized_key_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthorizedKeySpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthorizedKeySpec) ProtoMessage() {} + +func (x *AuthorizedKeySpec) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_authorized_key_proto_msgTypes[1] + 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 AuthorizedKeySpec.ProtoReflect.Descriptor instead. +func (*AuthorizedKeySpec) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_authorized_key_proto_rawDescGZIP(), []int{1} +} + +func (x *AuthorizedKeySpec) GetHostId() string { + if x != nil { + return x.HostId + } + return "" +} + +func (x *AuthorizedKeySpec) GetKeyFingerprint() string { + if x != nil { + return x.KeyFingerprint + } + return "" +} + +func (x *AuthorizedKeySpec) GetHostUser() string { + if x != nil { + return x.HostUser + } + return "" +} + +func (x *AuthorizedKeySpec) GetKeyComment() string { + if x != nil { + return x.KeyComment + } + return "" +} + +func (x *AuthorizedKeySpec) GetKeyType() string { + if x != nil { + return x.KeyType + } + return "" +} + +var File_teleport_access_graph_v1_authorized_key_proto protoreflect.FileDescriptor + +var file_teleport_access_graph_v1_authorized_key_proto_rawDesc = []byte{ + 0x0a, 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x18, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd3, 0x01, 0x0a, + 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x12, 0x38, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x75, 0x62, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x73, 0x75, 0x62, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x3f, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, + 0x65, 0x63, 0x22, 0xae, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, + 0x64, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, + 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6b, 0x65, 0x79, 0x46, + 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x6f, + 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, + 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x6b, 0x65, 0x79, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6b, 0x65, + 0x79, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x54, + 0x79, 0x70, 0x65, 0x42, 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, + 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_teleport_access_graph_v1_authorized_key_proto_rawDescOnce sync.Once + file_teleport_access_graph_v1_authorized_key_proto_rawDescData = file_teleport_access_graph_v1_authorized_key_proto_rawDesc +) + +func file_teleport_access_graph_v1_authorized_key_proto_rawDescGZIP() []byte { + file_teleport_access_graph_v1_authorized_key_proto_rawDescOnce.Do(func() { + file_teleport_access_graph_v1_authorized_key_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_access_graph_v1_authorized_key_proto_rawDescData) + }) + return file_teleport_access_graph_v1_authorized_key_proto_rawDescData +} + +var file_teleport_access_graph_v1_authorized_key_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_teleport_access_graph_v1_authorized_key_proto_goTypes = []interface{}{ + (*AuthorizedKey)(nil), // 0: teleport.access_graph.v1.AuthorizedKey + (*AuthorizedKeySpec)(nil), // 1: teleport.access_graph.v1.AuthorizedKeySpec + (*v1.Metadata)(nil), // 2: teleport.header.v1.Metadata +} +var file_teleport_access_graph_v1_authorized_key_proto_depIdxs = []int32{ + 2, // 0: teleport.access_graph.v1.AuthorizedKey.metadata:type_name -> teleport.header.v1.Metadata + 1, // 1: teleport.access_graph.v1.AuthorizedKey.spec:type_name -> teleport.access_graph.v1.AuthorizedKeySpec + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_teleport_access_graph_v1_authorized_key_proto_init() } +func file_teleport_access_graph_v1_authorized_key_proto_init() { + if File_teleport_access_graph_v1_authorized_key_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_teleport_access_graph_v1_authorized_key_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthorizedKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_authorized_key_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthorizedKeySpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_access_graph_v1_authorized_key_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_teleport_access_graph_v1_authorized_key_proto_goTypes, + DependencyIndexes: file_teleport_access_graph_v1_authorized_key_proto_depIdxs, + MessageInfos: file_teleport_access_graph_v1_authorized_key_proto_msgTypes, + }.Build() + File_teleport_access_graph_v1_authorized_key_proto = out.File + file_teleport_access_graph_v1_authorized_key_proto_rawDesc = nil + file_teleport_access_graph_v1_authorized_key_proto_goTypes = nil + file_teleport_access_graph_v1_authorized_key_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/accessgraph/v1/private_key.pb.go b/api/gen/proto/go/teleport/accessgraph/v1/private_key.pb.go new file mode 100644 index 0000000000000..e2d33a704c7e0 --- /dev/null +++ b/api/gen/proto/go/teleport/accessgraph/v1/private_key.pb.go @@ -0,0 +1,390 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/access_graph/v1/private_key.proto + +package accessgraphv1 + +import ( + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// PublicKeyMode is the mode of the public key. +// The public key can be derived from the private key, stored in a separate file, or the private key was password protected +// and we could not extract the public key from it or from the file. +type PublicKeyMode int32 + +const ( + // PUBLIC_KEY_MODE_UNSPECIFIED is an invalid state. + PublicKeyMode_PUBLIC_KEY_MODE_UNSPECIFIED PublicKeyMode = 0 + // PUBLIC_KEY_MODE_DERIVED is the state where the public key is derived from the private key. + PublicKeyMode_PUBLIC_KEY_MODE_DERIVED PublicKeyMode = 1 + // PUBLIC_KEY_MODE_PUB_FILE is a state where the public key is stored in a separate file from the private key. + // The private key is password protected and we could not extract the public key from it. + // This mode is used when the private key is password protected and there is a .pub file next to the private key + // that contains the public key. + PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE PublicKeyMode = 2 + // PUBLIC_KEY_MODE_PROTECTED is a state where the private key is password protected and we could not extract the public key from it + // or from the .pub file. + PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED PublicKeyMode = 3 +) + +// Enum value maps for PublicKeyMode. +var ( + PublicKeyMode_name = map[int32]string{ + 0: "PUBLIC_KEY_MODE_UNSPECIFIED", + 1: "PUBLIC_KEY_MODE_DERIVED", + 2: "PUBLIC_KEY_MODE_PUB_FILE", + 3: "PUBLIC_KEY_MODE_PROTECTED", + } + PublicKeyMode_value = map[string]int32{ + "PUBLIC_KEY_MODE_UNSPECIFIED": 0, + "PUBLIC_KEY_MODE_DERIVED": 1, + "PUBLIC_KEY_MODE_PUB_FILE": 2, + "PUBLIC_KEY_MODE_PROTECTED": 3, + } +) + +func (x PublicKeyMode) Enum() *PublicKeyMode { + p := new(PublicKeyMode) + *p = x + return p +} + +func (x PublicKeyMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PublicKeyMode) Descriptor() protoreflect.EnumDescriptor { + return file_teleport_access_graph_v1_private_key_proto_enumTypes[0].Descriptor() +} + +func (PublicKeyMode) Type() protoreflect.EnumType { + return &file_teleport_access_graph_v1_private_key_proto_enumTypes[0] +} + +func (x PublicKeyMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PublicKeyMode.Descriptor instead. +func (PublicKeyMode) EnumDescriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_private_key_proto_rawDescGZIP(), []int{0} +} + +// The `PrivateKey` message represents a private key entry for a specific local user. +// It serves as a reference to a private key located on a user's laptop. Note that it *NEVER* contains the private key itself. +// Instead, it stores metadata related to the key, including the fingerprint of the public key, the device trust identifier, and the public key mode. +// The Teleport Access Graph uses this metadata to assess whether a particular private key is authorized to access a user on the node without using Teleport. +type PrivateKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // metadata is the PrivateKey's metadata. + Metadata *v1.Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` + // kind is a resource kind. + Kind string `protobuf:"bytes,2,opt,name=kind,proto3" json:"kind,omitempty"` + // sub_kind is an optional resource sub kind, used in some resources. + SubKind string `protobuf:"bytes,3,opt,name=sub_kind,json=subKind,proto3" json:"sub_kind,omitempty"` + // version is version. + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` + // Spec is a PrivateKey specification. + Spec *PrivateKeySpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` +} + +func (x *PrivateKey) Reset() { + *x = PrivateKey{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_private_key_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PrivateKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrivateKey) ProtoMessage() {} + +func (x *PrivateKey) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_private_key_proto_msgTypes[0] + 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 PrivateKey.ProtoReflect.Descriptor instead. +func (*PrivateKey) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_private_key_proto_rawDescGZIP(), []int{0} +} + +func (x *PrivateKey) GetMetadata() *v1.Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *PrivateKey) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *PrivateKey) GetSubKind() string { + if x != nil { + return x.SubKind + } + return "" +} + +func (x *PrivateKey) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *PrivateKey) GetSpec() *PrivateKeySpec { + if x != nil { + return x.Spec + } + return nil +} + +// PrivateKeySpec is the private key spec. +type PrivateKeySpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // device_id is the device trust identifier of the device that owns the key. + DeviceId string `protobuf:"bytes,1,opt,name=device_id,json=deviceId,proto3" json:"device_id,omitempty"` + // public_key_fingerprint is the SHA256 of the SSH public key corresponding to + // the private key. + PublicKeyFingerprint string `protobuf:"bytes,2,opt,name=public_key_fingerprint,json=publicKeyFingerprint,proto3" json:"public_key_fingerprint,omitempty"` + // public_key_mode is the public key mode. + PublicKeyMode PublicKeyMode `protobuf:"varint,3,opt,name=public_key_mode,json=publicKeyMode,proto3,enum=teleport.access_graph.v1.PublicKeyMode" json:"public_key_mode,omitempty"` +} + +func (x *PrivateKeySpec) Reset() { + *x = PrivateKeySpec{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_private_key_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PrivateKeySpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PrivateKeySpec) ProtoMessage() {} + +func (x *PrivateKeySpec) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_private_key_proto_msgTypes[1] + 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 PrivateKeySpec.ProtoReflect.Descriptor instead. +func (*PrivateKeySpec) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_private_key_proto_rawDescGZIP(), []int{1} +} + +func (x *PrivateKeySpec) GetDeviceId() string { + if x != nil { + return x.DeviceId + } + return "" +} + +func (x *PrivateKeySpec) GetPublicKeyFingerprint() string { + if x != nil { + return x.PublicKeyFingerprint + } + return "" +} + +func (x *PrivateKeySpec) GetPublicKeyMode() PublicKeyMode { + if x != nil { + return x.PublicKeyMode + } + return PublicKeyMode_PUBLIC_KEY_MODE_UNSPECIFIED +} + +var File_teleport_access_graph_v1_private_key_proto protoreflect.FileDescriptor + +var file_teleport_access_graph_v1_private_key_proto_rawDesc = []byte{ + 0x0a, 0x2a, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xcd, 0x01, 0x0a, 0x0a, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x5f, 0x6b, 0x69, + 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x4b, 0x69, 0x6e, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x53, + 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0xb4, 0x01, 0x0a, 0x0e, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1b, 0x0a, 0x09, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, + 0x4f, 0x0a, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x4d, 0x6f, 0x64, 0x65, + 0x2a, 0x8a, 0x01, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, + 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, + 0x59, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x44, 0x45, 0x52, 0x49, 0x56, 0x45, 0x44, 0x10, 0x01, + 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4d, + 0x4f, 0x44, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x1d, + 0x0a, 0x19, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x4d, 0x4f, 0x44, + 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0x5a, 0x5a, + 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_teleport_access_graph_v1_private_key_proto_rawDescOnce sync.Once + file_teleport_access_graph_v1_private_key_proto_rawDescData = file_teleport_access_graph_v1_private_key_proto_rawDesc +) + +func file_teleport_access_graph_v1_private_key_proto_rawDescGZIP() []byte { + file_teleport_access_graph_v1_private_key_proto_rawDescOnce.Do(func() { + file_teleport_access_graph_v1_private_key_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_access_graph_v1_private_key_proto_rawDescData) + }) + return file_teleport_access_graph_v1_private_key_proto_rawDescData +} + +var file_teleport_access_graph_v1_private_key_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_teleport_access_graph_v1_private_key_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_teleport_access_graph_v1_private_key_proto_goTypes = []interface{}{ + (PublicKeyMode)(0), // 0: teleport.access_graph.v1.PublicKeyMode + (*PrivateKey)(nil), // 1: teleport.access_graph.v1.PrivateKey + (*PrivateKeySpec)(nil), // 2: teleport.access_graph.v1.PrivateKeySpec + (*v1.Metadata)(nil), // 3: teleport.header.v1.Metadata +} +var file_teleport_access_graph_v1_private_key_proto_depIdxs = []int32{ + 3, // 0: teleport.access_graph.v1.PrivateKey.metadata:type_name -> teleport.header.v1.Metadata + 2, // 1: teleport.access_graph.v1.PrivateKey.spec:type_name -> teleport.access_graph.v1.PrivateKeySpec + 0, // 2: teleport.access_graph.v1.PrivateKeySpec.public_key_mode:type_name -> teleport.access_graph.v1.PublicKeyMode + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_teleport_access_graph_v1_private_key_proto_init() } +func file_teleport_access_graph_v1_private_key_proto_init() { + if File_teleport_access_graph_v1_private_key_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_teleport_access_graph_v1_private_key_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PrivateKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_private_key_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PrivateKeySpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_access_graph_v1_private_key_proto_rawDesc, + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_teleport_access_graph_v1_private_key_proto_goTypes, + DependencyIndexes: file_teleport_access_graph_v1_private_key_proto_depIdxs, + EnumInfos: file_teleport_access_graph_v1_private_key_proto_enumTypes, + MessageInfos: file_teleport_access_graph_v1_private_key_proto_msgTypes, + }.Build() + File_teleport_access_graph_v1_private_key_proto = out.File + file_teleport_access_graph_v1_private_key_proto_rawDesc = nil + file_teleport_access_graph_v1_private_key_proto_goTypes = nil + file_teleport_access_graph_v1_private_key_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/accessgraph/v1/secrets_service.pb.go b/api/gen/proto/go/teleport/accessgraph/v1/secrets_service.pb.go new file mode 100644 index 0000000000000..954ea18e6d5af --- /dev/null +++ b/api/gen/proto/go/teleport/accessgraph/v1/secrets_service.pb.go @@ -0,0 +1,626 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/access_graph/v1/secrets_service.proto + +package accessgraphv1 + +import ( + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// OperationType is an enum that indicates the operation that the client wants to perform. +type OperationType int32 + +const ( + // OPERATION_TYPE_UNSPECIFIED is an unknown operation. + OperationType_OPERATION_TYPE_UNSPECIFIED OperationType = 0 + // OPERATION_TYPE_ADD is an operation that indicates that the client wants to add keys to the list. + OperationType_OPERATION_TYPE_ADD OperationType = 1 + // OPERATION_TYPE_SYNC is an operation that indicates that the client has sent all the keys and + // the server can proceed with the analysis. + OperationType_OPERATION_TYPE_SYNC OperationType = 2 +) + +// Enum value maps for OperationType. +var ( + OperationType_name = map[int32]string{ + 0: "OPERATION_TYPE_UNSPECIFIED", + 1: "OPERATION_TYPE_ADD", + 2: "OPERATION_TYPE_SYNC", + } + OperationType_value = map[string]int32{ + "OPERATION_TYPE_UNSPECIFIED": 0, + "OPERATION_TYPE_ADD": 1, + "OPERATION_TYPE_SYNC": 2, + } +) + +func (x OperationType) Enum() *OperationType { + p := new(OperationType) + *p = x + return p +} + +func (x OperationType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (OperationType) Descriptor() protoreflect.EnumDescriptor { + return file_teleport_access_graph_v1_secrets_service_proto_enumTypes[0].Descriptor() +} + +func (OperationType) Type() protoreflect.EnumType { + return &file_teleport_access_graph_v1_secrets_service_proto_enumTypes[0] +} + +func (x OperationType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use OperationType.Descriptor instead. +func (OperationType) EnumDescriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{0} +} + +// ReportAuthorizedKeysRequest is used by Teleport nodes to report authorized keys +// that could be used to bypass Teleport. +type ReportAuthorizedKeysRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // keys is a list of authorized keys that could be used to bypass Teleport. + Keys []*AuthorizedKey `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` + // operation indicates the operation that the client wants to perform. + Operation OperationType `protobuf:"varint,2,opt,name=operation,proto3,enum=teleport.access_graph.v1.OperationType" json:"operation,omitempty"` +} + +func (x *ReportAuthorizedKeysRequest) Reset() { + *x = ReportAuthorizedKeysRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportAuthorizedKeysRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportAuthorizedKeysRequest) ProtoMessage() {} + +func (x *ReportAuthorizedKeysRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[0] + 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 ReportAuthorizedKeysRequest.ProtoReflect.Descriptor instead. +func (*ReportAuthorizedKeysRequest) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{0} +} + +func (x *ReportAuthorizedKeysRequest) GetKeys() []*AuthorizedKey { + if x != nil { + return x.Keys + } + return nil +} + +func (x *ReportAuthorizedKeysRequest) GetOperation() OperationType { + if x != nil { + return x.Operation + } + return OperationType_OPERATION_TYPE_UNSPECIFIED +} + +// ReportAuthorizedKeysResponse is the response from ReportAuthorizedKeys +// RPC method. +type ReportAuthorizedKeysResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ReportAuthorizedKeysResponse) Reset() { + *x = ReportAuthorizedKeysResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportAuthorizedKeysResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportAuthorizedKeysResponse) ProtoMessage() {} + +func (x *ReportAuthorizedKeysResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[1] + 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 ReportAuthorizedKeysResponse.ProtoReflect.Descriptor instead. +func (*ReportAuthorizedKeysResponse) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{1} +} + +// ReportSecretsRequest is used by trusted devices to report secrets found on the host +// that could be used to bypass Teleport. +type ReportSecretsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ReportSecretsRequest_DeviceAssertion + // *ReportSecretsRequest_PrivateKeys + Payload isReportSecretsRequest_Payload `protobuf_oneof:"payload"` +} + +func (x *ReportSecretsRequest) Reset() { + *x = ReportSecretsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportSecretsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportSecretsRequest) ProtoMessage() {} + +func (x *ReportSecretsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[2] + 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 ReportSecretsRequest.ProtoReflect.Descriptor instead. +func (*ReportSecretsRequest) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{2} +} + +func (m *ReportSecretsRequest) GetPayload() isReportSecretsRequest_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ReportSecretsRequest) GetDeviceAssertion() *v1.AssertDeviceRequest { + if x, ok := x.GetPayload().(*ReportSecretsRequest_DeviceAssertion); ok { + return x.DeviceAssertion + } + return nil +} + +func (x *ReportSecretsRequest) GetPrivateKeys() *ReportPrivateKeys { + if x, ok := x.GetPayload().(*ReportSecretsRequest_PrivateKeys); ok { + return x.PrivateKeys + } + return nil +} + +type isReportSecretsRequest_Payload interface { + isReportSecretsRequest_Payload() +} + +type ReportSecretsRequest_DeviceAssertion struct { + // The device should initiate the device assertion ceremony by sending the + // AssertDeviceRequest. Please refer to the [teleport.devicetrust.v1.AssertDeviceRequest] + // message for more details. + DeviceAssertion *v1.AssertDeviceRequest `protobuf:"bytes,1,opt,name=device_assertion,json=deviceAssertion,proto3,oneof"` +} + +type ReportSecretsRequest_PrivateKeys struct { + // private_keys is a list of private keys that were found on the device. + PrivateKeys *ReportPrivateKeys `protobuf:"bytes,4,opt,name=private_keys,json=privateKeys,proto3,oneof"` +} + +func (*ReportSecretsRequest_DeviceAssertion) isReportSecretsRequest_Payload() {} + +func (*ReportSecretsRequest_PrivateKeys) isReportSecretsRequest_Payload() {} + +// ReportPrivateKeys is used by trusted devices to report private keys found on the host +// that could be used to bypass Teleport. +type ReportPrivateKeys struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // keys is a list of private keys that could be used to bypass Teleport. + Keys []*PrivateKey `protobuf:"bytes,1,rep,name=keys,proto3" json:"keys,omitempty"` +} + +func (x *ReportPrivateKeys) Reset() { + *x = ReportPrivateKeys{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportPrivateKeys) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportPrivateKeys) ProtoMessage() {} + +func (x *ReportPrivateKeys) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_secrets_service_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 ReportPrivateKeys.ProtoReflect.Descriptor instead. +func (*ReportPrivateKeys) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{3} +} + +func (x *ReportPrivateKeys) GetKeys() []*PrivateKey { + if x != nil { + return x.Keys + } + return nil +} + +// ReportSecretsResponse is the response from the ReportSecrets +// RPC method. +type ReportSecretsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ReportSecretsResponse_DeviceAssertion + Payload isReportSecretsResponse_Payload `protobuf_oneof:"payload"` +} + +func (x *ReportSecretsResponse) Reset() { + *x = ReportSecretsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_access_graph_v1_secrets_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReportSecretsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReportSecretsResponse) ProtoMessage() {} + +func (x *ReportSecretsResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_access_graph_v1_secrets_service_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 ReportSecretsResponse.ProtoReflect.Descriptor instead. +func (*ReportSecretsResponse) Descriptor() ([]byte, []int) { + return file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP(), []int{4} +} + +func (m *ReportSecretsResponse) GetPayload() isReportSecretsResponse_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ReportSecretsResponse) GetDeviceAssertion() *v1.AssertDeviceResponse { + if x, ok := x.GetPayload().(*ReportSecretsResponse_DeviceAssertion); ok { + return x.DeviceAssertion + } + return nil +} + +type isReportSecretsResponse_Payload interface { + isReportSecretsResponse_Payload() +} + +type ReportSecretsResponse_DeviceAssertion struct { + // device_assertion is the response from the device assertion ceremony. + // Please refer to the [teleport.devicetrust.v1.AssertDeviceResponse] + // message for more details + DeviceAssertion *v1.AssertDeviceResponse `protobuf:"bytes,1,opt,name=device_assertion,json=deviceAssertion,proto3,oneof"` +} + +func (*ReportSecretsResponse_DeviceAssertion) isReportSecretsResponse_Payload() {} + +var File_teleport_access_graph_v1_secrets_service_proto protoreflect.FileDescriptor + +var file_teleport_access_graph_v1_secrets_service_proto_rawDesc = []byte{ + 0x0a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x73, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x18, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x1a, 0x2d, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, + 0x73, 0x73, 0x65, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x01, 0x0a, 0x1b, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x6b, + 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, + 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x45, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, + 0x1e, 0x0a, 0x1c, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xce, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x10, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, + 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x48, 0x00, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, + 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x48, 0x00, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x22, 0x4d, 0x0a, 0x11, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, + 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x38, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, + 0x7e, 0x0a, 0x15, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x10, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, + 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x72, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2a, + 0x60, 0x0a, 0x0d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1e, 0x0a, 0x1a, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x16, 0x0a, 0x12, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, + 0x50, 0x45, 0x5f, 0x41, 0x44, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4f, 0x50, 0x45, 0x52, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, + 0x02, 0x32, 0x9d, 0x02, 0x0a, 0x15, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x8b, 0x01, 0x0a, 0x14, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, + 0x4b, 0x65, 0x79, 0x73, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, + 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x76, 0x0a, 0x0d, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, + 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, + 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, + 0x01, 0x42, 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x3b, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_teleport_access_graph_v1_secrets_service_proto_rawDescOnce sync.Once + file_teleport_access_graph_v1_secrets_service_proto_rawDescData = file_teleport_access_graph_v1_secrets_service_proto_rawDesc +) + +func file_teleport_access_graph_v1_secrets_service_proto_rawDescGZIP() []byte { + file_teleport_access_graph_v1_secrets_service_proto_rawDescOnce.Do(func() { + file_teleport_access_graph_v1_secrets_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_access_graph_v1_secrets_service_proto_rawDescData) + }) + return file_teleport_access_graph_v1_secrets_service_proto_rawDescData +} + +var file_teleport_access_graph_v1_secrets_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_teleport_access_graph_v1_secrets_service_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_teleport_access_graph_v1_secrets_service_proto_goTypes = []interface{}{ + (OperationType)(0), // 0: teleport.access_graph.v1.OperationType + (*ReportAuthorizedKeysRequest)(nil), // 1: teleport.access_graph.v1.ReportAuthorizedKeysRequest + (*ReportAuthorizedKeysResponse)(nil), // 2: teleport.access_graph.v1.ReportAuthorizedKeysResponse + (*ReportSecretsRequest)(nil), // 3: teleport.access_graph.v1.ReportSecretsRequest + (*ReportPrivateKeys)(nil), // 4: teleport.access_graph.v1.ReportPrivateKeys + (*ReportSecretsResponse)(nil), // 5: teleport.access_graph.v1.ReportSecretsResponse + (*AuthorizedKey)(nil), // 6: teleport.access_graph.v1.AuthorizedKey + (*v1.AssertDeviceRequest)(nil), // 7: teleport.devicetrust.v1.AssertDeviceRequest + (*PrivateKey)(nil), // 8: teleport.access_graph.v1.PrivateKey + (*v1.AssertDeviceResponse)(nil), // 9: teleport.devicetrust.v1.AssertDeviceResponse +} +var file_teleport_access_graph_v1_secrets_service_proto_depIdxs = []int32{ + 6, // 0: teleport.access_graph.v1.ReportAuthorizedKeysRequest.keys:type_name -> teleport.access_graph.v1.AuthorizedKey + 0, // 1: teleport.access_graph.v1.ReportAuthorizedKeysRequest.operation:type_name -> teleport.access_graph.v1.OperationType + 7, // 2: teleport.access_graph.v1.ReportSecretsRequest.device_assertion:type_name -> teleport.devicetrust.v1.AssertDeviceRequest + 4, // 3: teleport.access_graph.v1.ReportSecretsRequest.private_keys:type_name -> teleport.access_graph.v1.ReportPrivateKeys + 8, // 4: teleport.access_graph.v1.ReportPrivateKeys.keys:type_name -> teleport.access_graph.v1.PrivateKey + 9, // 5: teleport.access_graph.v1.ReportSecretsResponse.device_assertion:type_name -> teleport.devicetrust.v1.AssertDeviceResponse + 1, // 6: teleport.access_graph.v1.SecretsScannerService.ReportAuthorizedKeys:input_type -> teleport.access_graph.v1.ReportAuthorizedKeysRequest + 3, // 7: teleport.access_graph.v1.SecretsScannerService.ReportSecrets:input_type -> teleport.access_graph.v1.ReportSecretsRequest + 2, // 8: teleport.access_graph.v1.SecretsScannerService.ReportAuthorizedKeys:output_type -> teleport.access_graph.v1.ReportAuthorizedKeysResponse + 5, // 9: teleport.access_graph.v1.SecretsScannerService.ReportSecrets:output_type -> teleport.access_graph.v1.ReportSecretsResponse + 8, // [8:10] is the sub-list for method output_type + 6, // [6:8] 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_teleport_access_graph_v1_secrets_service_proto_init() } +func file_teleport_access_graph_v1_secrets_service_proto_init() { + if File_teleport_access_graph_v1_secrets_service_proto != nil { + return + } + file_teleport_access_graph_v1_authorized_key_proto_init() + file_teleport_access_graph_v1_private_key_proto_init() + if !protoimpl.UnsafeEnabled { + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportAuthorizedKeysRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportAuthorizedKeysResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportSecretsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportPrivateKeys); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReportSecretsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[2].OneofWrappers = []interface{}{ + (*ReportSecretsRequest_DeviceAssertion)(nil), + (*ReportSecretsRequest_PrivateKeys)(nil), + } + file_teleport_access_graph_v1_secrets_service_proto_msgTypes[4].OneofWrappers = []interface{}{ + (*ReportSecretsResponse_DeviceAssertion)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_access_graph_v1_secrets_service_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_teleport_access_graph_v1_secrets_service_proto_goTypes, + DependencyIndexes: file_teleport_access_graph_v1_secrets_service_proto_depIdxs, + EnumInfos: file_teleport_access_graph_v1_secrets_service_proto_enumTypes, + MessageInfos: file_teleport_access_graph_v1_secrets_service_proto_msgTypes, + }.Build() + File_teleport_access_graph_v1_secrets_service_proto = out.File + file_teleport_access_graph_v1_secrets_service_proto_rawDesc = nil + file_teleport_access_graph_v1_secrets_service_proto_goTypes = nil + file_teleport_access_graph_v1_secrets_service_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/accessgraph/v1/secrets_service_grpc.pb.go b/api/gen/proto/go/teleport/accessgraph/v1/secrets_service_grpc.pb.go new file mode 100644 index 0000000000000..f93b2d48d0bda --- /dev/null +++ b/api/gen/proto/go/teleport/accessgraph/v1/secrets_service_grpc.pb.go @@ -0,0 +1,256 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc (unknown) +// source: teleport/access_graph/v1/secrets_service.proto + +package accessgraphv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +const ( + SecretsScannerService_ReportAuthorizedKeys_FullMethodName = "/teleport.access_graph.v1.SecretsScannerService/ReportAuthorizedKeys" + SecretsScannerService_ReportSecrets_FullMethodName = "/teleport.access_graph.v1.SecretsScannerService/ReportSecrets" +) + +// SecretsScannerServiceClient is the client API for SecretsScannerService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type SecretsScannerServiceClient interface { + // ReportAuthorizedKeys is used by Teleport SSH nodes to report authorized keys + // that could be used to bypass Teleport. + // The client (Teleport SSH Node) should authenticate using the certificate-key pair signed by Teleport HostCA. + ReportAuthorizedKeys(ctx context.Context, opts ...grpc.CallOption) (SecretsScannerService_ReportAuthorizedKeysClient, error) + // ReportSecrets is used by trusted devices to report secrets found on the host that could be used to bypass Teleport. + // The client (device) should first authenticate using the [ReportSecretsRequest.device_assertion] flow. Please refer to + // the [teleport.devicetrust.v1.AssertDeviceRequest] and [teleport.devicetrust.v1.AssertDeviceResponse] messages for more details. + // + // Once the device is asserted, the client can send the secrets using the [ReportSecretsRequest.private_keys] field + // and then close the client side of the stream. + // + // -> ReportSecrets (client) [1 or more] + // -> CloseStream (client) + // <- TerminateStream (server) + // + // Any failure in the assertion ceremony will result in the stream being terminated by the server. All secrets + // reported by the client before the assertion terminates will be ignored and result in the stream being terminated. + ReportSecrets(ctx context.Context, opts ...grpc.CallOption) (SecretsScannerService_ReportSecretsClient, error) +} + +type secretsScannerServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewSecretsScannerServiceClient(cc grpc.ClientConnInterface) SecretsScannerServiceClient { + return &secretsScannerServiceClient{cc} +} + +func (c *secretsScannerServiceClient) ReportAuthorizedKeys(ctx context.Context, opts ...grpc.CallOption) (SecretsScannerService_ReportAuthorizedKeysClient, error) { + stream, err := c.cc.NewStream(ctx, &SecretsScannerService_ServiceDesc.Streams[0], SecretsScannerService_ReportAuthorizedKeys_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &secretsScannerServiceReportAuthorizedKeysClient{stream} + return x, nil +} + +type SecretsScannerService_ReportAuthorizedKeysClient interface { + Send(*ReportAuthorizedKeysRequest) error + Recv() (*ReportAuthorizedKeysResponse, error) + grpc.ClientStream +} + +type secretsScannerServiceReportAuthorizedKeysClient struct { + grpc.ClientStream +} + +func (x *secretsScannerServiceReportAuthorizedKeysClient) Send(m *ReportAuthorizedKeysRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *secretsScannerServiceReportAuthorizedKeysClient) Recv() (*ReportAuthorizedKeysResponse, error) { + m := new(ReportAuthorizedKeysResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *secretsScannerServiceClient) ReportSecrets(ctx context.Context, opts ...grpc.CallOption) (SecretsScannerService_ReportSecretsClient, error) { + stream, err := c.cc.NewStream(ctx, &SecretsScannerService_ServiceDesc.Streams[1], SecretsScannerService_ReportSecrets_FullMethodName, opts...) + if err != nil { + return nil, err + } + x := &secretsScannerServiceReportSecretsClient{stream} + return x, nil +} + +type SecretsScannerService_ReportSecretsClient interface { + Send(*ReportSecretsRequest) error + Recv() (*ReportSecretsResponse, error) + grpc.ClientStream +} + +type secretsScannerServiceReportSecretsClient struct { + grpc.ClientStream +} + +func (x *secretsScannerServiceReportSecretsClient) Send(m *ReportSecretsRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *secretsScannerServiceReportSecretsClient) Recv() (*ReportSecretsResponse, error) { + m := new(ReportSecretsResponse) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// SecretsScannerServiceServer is the server API for SecretsScannerService service. +// All implementations must embed UnimplementedSecretsScannerServiceServer +// for forward compatibility +type SecretsScannerServiceServer interface { + // ReportAuthorizedKeys is used by Teleport SSH nodes to report authorized keys + // that could be used to bypass Teleport. + // The client (Teleport SSH Node) should authenticate using the certificate-key pair signed by Teleport HostCA. + ReportAuthorizedKeys(SecretsScannerService_ReportAuthorizedKeysServer) error + // ReportSecrets is used by trusted devices to report secrets found on the host that could be used to bypass Teleport. + // The client (device) should first authenticate using the [ReportSecretsRequest.device_assertion] flow. Please refer to + // the [teleport.devicetrust.v1.AssertDeviceRequest] and [teleport.devicetrust.v1.AssertDeviceResponse] messages for more details. + // + // Once the device is asserted, the client can send the secrets using the [ReportSecretsRequest.private_keys] field + // and then close the client side of the stream. + // + // -> ReportSecrets (client) [1 or more] + // -> CloseStream (client) + // <- TerminateStream (server) + // + // Any failure in the assertion ceremony will result in the stream being terminated by the server. All secrets + // reported by the client before the assertion terminates will be ignored and result in the stream being terminated. + ReportSecrets(SecretsScannerService_ReportSecretsServer) error + mustEmbedUnimplementedSecretsScannerServiceServer() +} + +// UnimplementedSecretsScannerServiceServer must be embedded to have forward compatible implementations. +type UnimplementedSecretsScannerServiceServer struct { +} + +func (UnimplementedSecretsScannerServiceServer) ReportAuthorizedKeys(SecretsScannerService_ReportAuthorizedKeysServer) error { + return status.Errorf(codes.Unimplemented, "method ReportAuthorizedKeys not implemented") +} +func (UnimplementedSecretsScannerServiceServer) ReportSecrets(SecretsScannerService_ReportSecretsServer) error { + return status.Errorf(codes.Unimplemented, "method ReportSecrets not implemented") +} +func (UnimplementedSecretsScannerServiceServer) mustEmbedUnimplementedSecretsScannerServiceServer() {} + +// UnsafeSecretsScannerServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to SecretsScannerServiceServer will +// result in compilation errors. +type UnsafeSecretsScannerServiceServer interface { + mustEmbedUnimplementedSecretsScannerServiceServer() +} + +func RegisterSecretsScannerServiceServer(s grpc.ServiceRegistrar, srv SecretsScannerServiceServer) { + s.RegisterService(&SecretsScannerService_ServiceDesc, srv) +} + +func _SecretsScannerService_ReportAuthorizedKeys_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SecretsScannerServiceServer).ReportAuthorizedKeys(&secretsScannerServiceReportAuthorizedKeysServer{stream}) +} + +type SecretsScannerService_ReportAuthorizedKeysServer interface { + Send(*ReportAuthorizedKeysResponse) error + Recv() (*ReportAuthorizedKeysRequest, error) + grpc.ServerStream +} + +type secretsScannerServiceReportAuthorizedKeysServer struct { + grpc.ServerStream +} + +func (x *secretsScannerServiceReportAuthorizedKeysServer) Send(m *ReportAuthorizedKeysResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *secretsScannerServiceReportAuthorizedKeysServer) Recv() (*ReportAuthorizedKeysRequest, error) { + m := new(ReportAuthorizedKeysRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _SecretsScannerService_ReportSecrets_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(SecretsScannerServiceServer).ReportSecrets(&secretsScannerServiceReportSecretsServer{stream}) +} + +type SecretsScannerService_ReportSecretsServer interface { + Send(*ReportSecretsResponse) error + Recv() (*ReportSecretsRequest, error) + grpc.ServerStream +} + +type secretsScannerServiceReportSecretsServer struct { + grpc.ServerStream +} + +func (x *secretsScannerServiceReportSecretsServer) Send(m *ReportSecretsResponse) error { + return x.ServerStream.SendMsg(m) +} + +func (x *secretsScannerServiceReportSecretsServer) Recv() (*ReportSecretsRequest, error) { + m := new(ReportSecretsRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// SecretsScannerService_ServiceDesc is the grpc.ServiceDesc for SecretsScannerService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var SecretsScannerService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "teleport.access_graph.v1.SecretsScannerService", + HandlerType: (*SecretsScannerServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ReportAuthorizedKeys", + Handler: _SecretsScannerService_ReportAuthorizedKeys_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "ReportSecrets", + Handler: _SecretsScannerService_ReportSecrets_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "teleport/access_graph/v1/secrets_service.proto", +} diff --git a/api/gen/proto/go/teleport/clusterconfig/v1/access_graph.pb.go b/api/gen/proto/go/teleport/clusterconfig/v1/access_graph.pb.go index e3eaae3aaa046..263c852cdf155 100644 --- a/api/gen/proto/go/teleport/clusterconfig/v1/access_graph.pb.go +++ b/api/gen/proto/go/teleport/clusterconfig/v1/access_graph.pb.go @@ -50,6 +50,8 @@ type AccessGraphConfig struct { // insecure is a flag that indicates whether the access graph service should // skip verifying the server's certificate chain and host name. Insecure bool `protobuf:"varint,4,opt,name=insecure,proto3" json:"insecure,omitempty"` + // secrets_scan_config is used to configure the parameters for the secrets scanning functionality. + SecretsScanConfig *AccessGraphSecretsScanConfiguration `protobuf:"bytes,5,opt,name=secrets_scan_config,json=secretsScanConfig,proto3" json:"secrets_scan_config,omitempty"` } func (x *AccessGraphConfig) Reset() { @@ -112,6 +114,62 @@ func (x *AccessGraphConfig) GetInsecure() bool { return false } +func (x *AccessGraphConfig) GetSecretsScanConfig() *AccessGraphSecretsScanConfiguration { + if x != nil { + return x.SecretsScanConfig + } + return nil +} + +// AccessGraphSecretsScanConfiguration controls the secrets scanning service parameters. +type AccessGraphSecretsScanConfiguration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ssh_scan_enabled indicates if the SSH scan feature is enabled for the cluster. + SshScanEnabled bool `protobuf:"varint,1,opt,name=ssh_scan_enabled,json=sshScanEnabled,proto3" json:"ssh_scan_enabled,omitempty"` +} + +func (x *AccessGraphSecretsScanConfiguration) Reset() { + *x = AccessGraphSecretsScanConfiguration{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_access_graph_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AccessGraphSecretsScanConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccessGraphSecretsScanConfiguration) ProtoMessage() {} + +func (x *AccessGraphSecretsScanConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_access_graph_proto_msgTypes[1] + 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 AccessGraphSecretsScanConfiguration.ProtoReflect.Descriptor instead. +func (*AccessGraphSecretsScanConfiguration) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_access_graph_proto_rawDescGZIP(), []int{1} +} + +func (x *AccessGraphSecretsScanConfiguration) GetSshScanEnabled() bool { + if x != nil { + return x.SshScanEnabled + } + return false +} + var File_teleport_clusterconfig_v1_access_graph_proto protoreflect.FileDescriptor var file_teleport_clusterconfig_v1_access_graph_proto_rawDesc = []byte{ @@ -119,21 +177,33 @@ var file_teleport_clusterconfig_v1_access_graph_proto_rawDesc = []byte{ 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x22, 0x73, 0x0a, 0x11, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, - 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, - 0x63, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x42, 0x5e, - 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x22, 0xe3, 0x01, 0x0a, 0x11, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x63, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x02, 0x63, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, + 0x6e, 0x0a, 0x13, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x5f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x73, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, + 0x4f, 0x0a, 0x23, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, + 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x73, 0x68, 0x5f, 0x73, 0x63, + 0x61, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x73, 0x73, 0x68, 0x53, 0x63, 0x61, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, + 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, + 0x3b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -148,16 +218,18 @@ func file_teleport_clusterconfig_v1_access_graph_proto_rawDescGZIP() []byte { return file_teleport_clusterconfig_v1_access_graph_proto_rawDescData } -var file_teleport_clusterconfig_v1_access_graph_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_teleport_clusterconfig_v1_access_graph_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_teleport_clusterconfig_v1_access_graph_proto_goTypes = []interface{}{ - (*AccessGraphConfig)(nil), // 0: teleport.clusterconfig.v1.AccessGraphConfig + (*AccessGraphConfig)(nil), // 0: teleport.clusterconfig.v1.AccessGraphConfig + (*AccessGraphSecretsScanConfiguration)(nil), // 1: teleport.clusterconfig.v1.AccessGraphSecretsScanConfiguration } var file_teleport_clusterconfig_v1_access_graph_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 1, // 0: teleport.clusterconfig.v1.AccessGraphConfig.secrets_scan_config:type_name -> teleport.clusterconfig.v1.AccessGraphSecretsScanConfiguration + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_teleport_clusterconfig_v1_access_graph_proto_init() } @@ -178,6 +250,18 @@ func file_teleport_clusterconfig_v1_access_graph_proto_init() { return nil } } + file_teleport_clusterconfig_v1_access_graph_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AccessGraphSecretsScanConfiguration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -185,7 +269,7 @@ func file_teleport_clusterconfig_v1_access_graph_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_clusterconfig_v1_access_graph_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/api/gen/proto/go/teleport/clusterconfig/v1/access_graph_settings.pb.go b/api/gen/proto/go/teleport/clusterconfig/v1/access_graph_settings.pb.go new file mode 100644 index 0000000000000..93c3141620969 --- /dev/null +++ b/api/gen/proto/go/teleport/clusterconfig/v1/access_graph_settings.pb.go @@ -0,0 +1,359 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/clusterconfig/v1/access_graph_settings.proto + +package clusterconfigv1 + +import ( + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// AccessGraphSecretsScanConfig is used to configure the parameters for the secrets scanning functionality. +type AccessGraphSecretsScanConfig int32 + +const ( + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED is an unknown secrets scan configuration. + AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED AccessGraphSecretsScanConfig = 0 + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED is a disabled secrets scan configuration. + AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED AccessGraphSecretsScanConfig = 1 + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED is an enabled secrets scan configuration. + AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED AccessGraphSecretsScanConfig = 2 +) + +// Enum value maps for AccessGraphSecretsScanConfig. +var ( + AccessGraphSecretsScanConfig_name = map[int32]string{ + 0: "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED", + 1: "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED", + 2: "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED", + } + AccessGraphSecretsScanConfig_value = map[string]int32{ + "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED": 0, + "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED": 1, + "ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED": 2, + } +) + +func (x AccessGraphSecretsScanConfig) Enum() *AccessGraphSecretsScanConfig { + p := new(AccessGraphSecretsScanConfig) + *p = x + return p +} + +func (x AccessGraphSecretsScanConfig) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (AccessGraphSecretsScanConfig) Descriptor() protoreflect.EnumDescriptor { + return file_teleport_clusterconfig_v1_access_graph_settings_proto_enumTypes[0].Descriptor() +} + +func (AccessGraphSecretsScanConfig) Type() protoreflect.EnumType { + return &file_teleport_clusterconfig_v1_access_graph_settings_proto_enumTypes[0] +} + +func (x AccessGraphSecretsScanConfig) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use AccessGraphSecretsScanConfig.Descriptor instead. +func (AccessGraphSecretsScanConfig) EnumDescriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescGZIP(), []int{0} +} + +// AccessGraphSettings holds dynamic configuration settings for the Access Graph service. +type AccessGraphSettings struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // kind is the kind of the resource. + Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"` + // sub_kind is the sub kind of the resource. + SubKind string `protobuf:"bytes,2,opt,name=sub_kind,json=subKind,proto3" json:"sub_kind,omitempty"` + // version is the version of the resource. + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + // metadata is the metadata of the resource. + Metadata *v1.Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // spec is the spec of the resource. + Spec *AccessGraphSettingsSpec `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` +} + +func (x *AccessGraphSettings) Reset() { + *x = AccessGraphSettings{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AccessGraphSettings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccessGraphSettings) ProtoMessage() {} + +func (x *AccessGraphSettings) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[0] + 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 AccessGraphSettings.ProtoReflect.Descriptor instead. +func (*AccessGraphSettings) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescGZIP(), []int{0} +} + +func (x *AccessGraphSettings) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *AccessGraphSettings) GetSubKind() string { + if x != nil { + return x.SubKind + } + return "" +} + +func (x *AccessGraphSettings) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *AccessGraphSettings) GetMetadata() *v1.Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *AccessGraphSettings) GetSpec() *AccessGraphSettingsSpec { + if x != nil { + return x.Spec + } + return nil +} + +// AccessGraphSettingsSpec is the spec for the Access Graph service configuration settings. +type AccessGraphSettingsSpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // secrets_scan_config is used to configure the parameters for the secrets scanning functionality. + SecretsScanConfig AccessGraphSecretsScanConfig `protobuf:"varint,1,opt,name=secrets_scan_config,json=secretsScanConfig,proto3,enum=teleport.clusterconfig.v1.AccessGraphSecretsScanConfig" json:"secrets_scan_config,omitempty"` +} + +func (x *AccessGraphSettingsSpec) Reset() { + *x = AccessGraphSettingsSpec{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AccessGraphSettingsSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccessGraphSettingsSpec) ProtoMessage() {} + +func (x *AccessGraphSettingsSpec) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[1] + 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 AccessGraphSettingsSpec.ProtoReflect.Descriptor instead. +func (*AccessGraphSettingsSpec) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescGZIP(), []int{1} +} + +func (x *AccessGraphSettingsSpec) GetSecretsScanConfig() AccessGraphSecretsScanConfig { + if x != nil { + return x.SecretsScanConfig + } + return AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED +} + +var File_teleport_clusterconfig_v1_access_graph_settings_proto protoreflect.FileDescriptor + +var file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDesc = []byte{ + 0x0a, 0x35, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x76, 0x31, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x01, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6b, 0x69, 0x6e, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x75, 0x62, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x46, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x70, + 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x82, 0x01, 0x0a, 0x17, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x53, 0x70, 0x65, 0x63, 0x12, 0x67, 0x0a, 0x13, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x5f, + 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, + 0x53, 0x63, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x73, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2a, 0xad, 0x01, + 0x0a, 0x1c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, + 0x0a, 0x2c, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, 0x53, + 0x45, 0x43, 0x52, 0x45, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, 0x46, + 0x49, 0x47, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x2d, 0x0a, 0x29, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, + 0x5f, 0x53, 0x45, 0x43, 0x52, 0x45, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x43, 0x4f, + 0x4e, 0x46, 0x49, 0x47, 0x5f, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, + 0x2c, 0x0a, 0x28, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x47, 0x52, 0x41, 0x50, 0x48, 0x5f, + 0x53, 0x45, 0x43, 0x52, 0x45, 0x54, 0x53, 0x5f, 0x53, 0x43, 0x41, 0x4e, 0x5f, 0x43, 0x4f, 0x4e, + 0x46, 0x49, 0x47, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x02, 0x42, 0x5e, 0x5a, + 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescOnce sync.Once + file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescData = file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDesc +) + +func file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescGZIP() []byte { + file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescOnce.Do(func() { + file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescData) + }) + return file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDescData +} + +var file_teleport_clusterconfig_v1_access_graph_settings_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_teleport_clusterconfig_v1_access_graph_settings_proto_goTypes = []interface{}{ + (AccessGraphSecretsScanConfig)(0), // 0: teleport.clusterconfig.v1.AccessGraphSecretsScanConfig + (*AccessGraphSettings)(nil), // 1: teleport.clusterconfig.v1.AccessGraphSettings + (*AccessGraphSettingsSpec)(nil), // 2: teleport.clusterconfig.v1.AccessGraphSettingsSpec + (*v1.Metadata)(nil), // 3: teleport.header.v1.Metadata +} +var file_teleport_clusterconfig_v1_access_graph_settings_proto_depIdxs = []int32{ + 3, // 0: teleport.clusterconfig.v1.AccessGraphSettings.metadata:type_name -> teleport.header.v1.Metadata + 2, // 1: teleport.clusterconfig.v1.AccessGraphSettings.spec:type_name -> teleport.clusterconfig.v1.AccessGraphSettingsSpec + 0, // 2: teleport.clusterconfig.v1.AccessGraphSettingsSpec.secrets_scan_config:type_name -> teleport.clusterconfig.v1.AccessGraphSecretsScanConfig + 3, // [3:3] is the sub-list for method output_type + 3, // [3:3] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_teleport_clusterconfig_v1_access_graph_settings_proto_init() } +func file_teleport_clusterconfig_v1_access_graph_settings_proto_init() { + if File_teleport_clusterconfig_v1_access_graph_settings_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AccessGraphSettings); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AccessGraphSettingsSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDesc, + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_teleport_clusterconfig_v1_access_graph_settings_proto_goTypes, + DependencyIndexes: file_teleport_clusterconfig_v1_access_graph_settings_proto_depIdxs, + EnumInfos: file_teleport_clusterconfig_v1_access_graph_settings_proto_enumTypes, + MessageInfos: file_teleport_clusterconfig_v1_access_graph_settings_proto_msgTypes, + }.Build() + File_teleport_clusterconfig_v1_access_graph_settings_proto = out.File + file_teleport_clusterconfig_v1_access_graph_settings_proto_rawDesc = nil + file_teleport_clusterconfig_v1_access_graph_settings_proto_goTypes = nil + file_teleport_clusterconfig_v1_access_graph_settings_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service.pb.go b/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service.pb.go index 5800164fee0e4..16fd98fa757f8 100644 --- a/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service.pb.go +++ b/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service.pb.go @@ -684,6 +684,228 @@ func (x *GetClusterAccessGraphConfigResponse) GetAccessGraph() *AccessGraphConfi return nil } +// Request for GetAccessGraphSettings +type GetAccessGraphSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetAccessGraphSettingsRequest) Reset() { + *x = GetAccessGraphSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetAccessGraphSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAccessGraphSettingsRequest) ProtoMessage() {} + +func (x *GetAccessGraphSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[15] + 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 GetAccessGraphSettingsRequest.ProtoReflect.Descriptor instead. +func (*GetAccessGraphSettingsRequest) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP(), []int{15} +} + +// Request for CreateAccessGraphSettings +type CreateAccessGraphSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccessGraphSettings *AccessGraphSettings `protobuf:"bytes,1,opt,name=access_graph_settings,json=accessGraphSettings,proto3" json:"access_graph_settings,omitempty"` +} + +func (x *CreateAccessGraphSettingsRequest) Reset() { + *x = CreateAccessGraphSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateAccessGraphSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateAccessGraphSettingsRequest) ProtoMessage() {} + +func (x *CreateAccessGraphSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[16] + 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 CreateAccessGraphSettingsRequest.ProtoReflect.Descriptor instead. +func (*CreateAccessGraphSettingsRequest) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP(), []int{16} +} + +func (x *CreateAccessGraphSettingsRequest) GetAccessGraphSettings() *AccessGraphSettings { + if x != nil { + return x.AccessGraphSettings + } + return nil +} + +// Request for UpdateAccessGraphSettings +type UpdateAccessGraphSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccessGraphSettings *AccessGraphSettings `protobuf:"bytes,1,opt,name=access_graph_settings,json=accessGraphSettings,proto3" json:"access_graph_settings,omitempty"` +} + +func (x *UpdateAccessGraphSettingsRequest) Reset() { + *x = UpdateAccessGraphSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateAccessGraphSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateAccessGraphSettingsRequest) ProtoMessage() {} + +func (x *UpdateAccessGraphSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[17] + 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 UpdateAccessGraphSettingsRequest.ProtoReflect.Descriptor instead. +func (*UpdateAccessGraphSettingsRequest) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP(), []int{17} +} + +func (x *UpdateAccessGraphSettingsRequest) GetAccessGraphSettings() *AccessGraphSettings { + if x != nil { + return x.AccessGraphSettings + } + return nil +} + +// Request for UpsertAccessGraphSettings +type UpsertAccessGraphSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AccessGraphSettings *AccessGraphSettings `protobuf:"bytes,1,opt,name=access_graph_settings,json=accessGraphSettings,proto3" json:"access_graph_settings,omitempty"` +} + +func (x *UpsertAccessGraphSettingsRequest) Reset() { + *x = UpsertAccessGraphSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpsertAccessGraphSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpsertAccessGraphSettingsRequest) ProtoMessage() {} + +func (x *UpsertAccessGraphSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[18] + 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 UpsertAccessGraphSettingsRequest.ProtoReflect.Descriptor instead. +func (*UpsertAccessGraphSettingsRequest) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP(), []int{18} +} + +func (x *UpsertAccessGraphSettingsRequest) GetAccessGraphSettings() *AccessGraphSettings { + if x != nil { + return x.AccessGraphSettings + } + return nil +} + +// Request for ResetAccessGraphSettings +type ResetAccessGraphSettingsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ResetAccessGraphSettingsRequest) Reset() { + *x = ResetAccessGraphSettingsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetAccessGraphSettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetAccessGraphSettingsRequest) ProtoMessage() {} + +func (x *ResetAccessGraphSettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[19] + 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 ResetAccessGraphSettingsRequest.ProtoReflect.Descriptor instead. +func (*ResetAccessGraphSettingsRequest) Descriptor() ([]byte, []int) { + return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP(), []int{19} +} + var File_teleport_clusterconfig_v1_clusterconfig_service_proto protoreflect.FileDescriptor var file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDesc = []byte{ @@ -695,193 +917,269 @@ var file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDesc = []byte{ 0x76, 0x31, 0x1a, 0x2c, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, - 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x23, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x7e, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x56, 0x0a, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x56, 0x32, 0x52, 0x14, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x7e, 0x0a, 0x24, 0x55, 0x70, 0x73, 0x65, - 0x72, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x56, 0x0a, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x56, 0x32, 0x52, 0x14, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x25, 0x0a, 0x23, 0x52, 0x65, 0x73, 0x65, + 0x1a, 0x35, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x23, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x22, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x22, 0x80, 0x01, 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x18, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x52, 0x16, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x80, 0x01, 0x0a, 0x23, 0x55, 0x70, 0x73, 0x65, 0x72, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, - 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, - 0x32, 0x52, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x24, 0x0a, 0x22, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x5f, 0x0a, 0x1b, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x52, 0x0e, 0x61, 0x75, - 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x5f, 0x0a, 0x1b, - 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x61, - 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, - 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x52, 0x0e, 0x61, - 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x22, 0x1c, 0x0a, - 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x24, 0x0a, 0x22, 0x47, - 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x76, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, + 0x7e, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x56, 0x0a, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x52, 0x14, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, + 0x7e, 0x0a, 0x24, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x56, 0x0a, 0x16, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x52, 0x14, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, + 0x25, 0x0a, 0x23, 0x52, 0x65, 0x73, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x22, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x80, 0x01, 0x0a, 0x23, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, + 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x59, 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x56, 0x32, 0x52, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x80, 0x01, + 0x0a, 0x23, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x59, 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x52, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x22, 0x24, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x5f, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, + 0x65, 0x56, 0x32, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x22, 0x5f, 0x0a, 0x1b, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x56, 0x32, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x22, 0x1c, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x1e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x24, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x76, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4f, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x22, 0x1f, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0x86, 0x01, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x62, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x20, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x62, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x32, 0xc7, 0x0d, 0x0a, 0x14, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x7c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x13, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x22, 0x86, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x62, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x21, 0x0a, 0x1f, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, + 0xf6, 0x12, 0x0a, 0x14, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x82, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x82, 0x01, 0x0a, 0x1d, + 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, - 0x12, 0x82, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x3f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x82, 0x01, 0x0a, 0x1d, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x12, 0x80, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x73, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x80, 0x01, 0x0a, 0x1c, 0x52, - 0x65, 0x73, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x79, 0x0a, - 0x19, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x67, 0x12, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x56, 0x32, 0x12, 0x79, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x12, 0x3b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x7f, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x7f, 0x0a, 0x1c, 0x55, 0x70, 0x73, - 0x65, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, - 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x7d, 0x0a, 0x1b, 0x52, 0x65, - 0x73, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x61, 0x0a, 0x11, 0x47, 0x65, 0x74, - 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x33, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, + 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x7f, + 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x67, 0x0a, 0x14, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, + 0x7f, 0x0a, 0x1c, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, + 0x12, 0x7d, 0x0a, 0x1b, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x3d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, + 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, + 0x61, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x12, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x67, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, - 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, - 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x65, - 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, - 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x6d, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x56, 0x32, 0x12, 0x67, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x67, 0x0a, 0x14, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x12, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x56, 0x32, 0x12, 0x65, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x12, 0x6d, 0x0a, 0x15, 0x47, + 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x47, + 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x16, 0x47, 0x65, + 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x38, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x56, 0x32, 0x12, 0x9c, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x88, + 0x01, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3b, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x19, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x3b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, + 0x86, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x5e, 0x5a, 0x5c, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -896,7 +1194,7 @@ func file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescGZIP() [] return file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDescData } -var file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_teleport_clusterconfig_v1_clusterconfig_service_proto_goTypes = []interface{}{ (*GetClusterNetworkingConfigRequest)(nil), // 0: teleport.clusterconfig.v1.GetClusterNetworkingConfigRequest (*UpdateClusterNetworkingConfigRequest)(nil), // 1: teleport.clusterconfig.v1.UpdateClusterNetworkingConfigRequest @@ -913,53 +1211,72 @@ var file_teleport_clusterconfig_v1_clusterconfig_service_proto_goTypes = []inter (*GetClusterAuditConfigRequest)(nil), // 12: teleport.clusterconfig.v1.GetClusterAuditConfigRequest (*GetClusterAccessGraphConfigRequest)(nil), // 13: teleport.clusterconfig.v1.GetClusterAccessGraphConfigRequest (*GetClusterAccessGraphConfigResponse)(nil), // 14: teleport.clusterconfig.v1.GetClusterAccessGraphConfigResponse - (*types.ClusterNetworkingConfigV2)(nil), // 15: types.ClusterNetworkingConfigV2 - (*types.SessionRecordingConfigV2)(nil), // 16: types.SessionRecordingConfigV2 - (*types.AuthPreferenceV2)(nil), // 17: types.AuthPreferenceV2 - (*AccessGraphConfig)(nil), // 18: teleport.clusterconfig.v1.AccessGraphConfig - (*types.ClusterAuditConfigV2)(nil), // 19: types.ClusterAuditConfigV2 + (*GetAccessGraphSettingsRequest)(nil), // 15: teleport.clusterconfig.v1.GetAccessGraphSettingsRequest + (*CreateAccessGraphSettingsRequest)(nil), // 16: teleport.clusterconfig.v1.CreateAccessGraphSettingsRequest + (*UpdateAccessGraphSettingsRequest)(nil), // 17: teleport.clusterconfig.v1.UpdateAccessGraphSettingsRequest + (*UpsertAccessGraphSettingsRequest)(nil), // 18: teleport.clusterconfig.v1.UpsertAccessGraphSettingsRequest + (*ResetAccessGraphSettingsRequest)(nil), // 19: teleport.clusterconfig.v1.ResetAccessGraphSettingsRequest + (*types.ClusterNetworkingConfigV2)(nil), // 20: types.ClusterNetworkingConfigV2 + (*types.SessionRecordingConfigV2)(nil), // 21: types.SessionRecordingConfigV2 + (*types.AuthPreferenceV2)(nil), // 22: types.AuthPreferenceV2 + (*AccessGraphConfig)(nil), // 23: teleport.clusterconfig.v1.AccessGraphConfig + (*AccessGraphSettings)(nil), // 24: teleport.clusterconfig.v1.AccessGraphSettings + (*types.ClusterAuditConfigV2)(nil), // 25: types.ClusterAuditConfigV2 } var file_teleport_clusterconfig_v1_clusterconfig_service_proto_depIdxs = []int32{ - 15, // 0: teleport.clusterconfig.v1.UpdateClusterNetworkingConfigRequest.cluster_network_config:type_name -> types.ClusterNetworkingConfigV2 - 15, // 1: teleport.clusterconfig.v1.UpsertClusterNetworkingConfigRequest.cluster_network_config:type_name -> types.ClusterNetworkingConfigV2 - 16, // 2: teleport.clusterconfig.v1.UpdateSessionRecordingConfigRequest.session_recording_config:type_name -> types.SessionRecordingConfigV2 - 16, // 3: teleport.clusterconfig.v1.UpsertSessionRecordingConfigRequest.session_recording_config:type_name -> types.SessionRecordingConfigV2 - 17, // 4: teleport.clusterconfig.v1.UpdateAuthPreferenceRequest.auth_preference:type_name -> types.AuthPreferenceV2 - 17, // 5: teleport.clusterconfig.v1.UpsertAuthPreferenceRequest.auth_preference:type_name -> types.AuthPreferenceV2 - 18, // 6: teleport.clusterconfig.v1.GetClusterAccessGraphConfigResponse.access_graph:type_name -> teleport.clusterconfig.v1.AccessGraphConfig - 0, // 7: teleport.clusterconfig.v1.ClusterConfigService.GetClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.GetClusterNetworkingConfigRequest - 1, // 8: teleport.clusterconfig.v1.ClusterConfigService.UpdateClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.UpdateClusterNetworkingConfigRequest - 2, // 9: teleport.clusterconfig.v1.ClusterConfigService.UpsertClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.UpsertClusterNetworkingConfigRequest - 3, // 10: teleport.clusterconfig.v1.ClusterConfigService.ResetClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.ResetClusterNetworkingConfigRequest - 4, // 11: teleport.clusterconfig.v1.ClusterConfigService.GetSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.GetSessionRecordingConfigRequest - 5, // 12: teleport.clusterconfig.v1.ClusterConfigService.UpdateSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.UpdateSessionRecordingConfigRequest - 6, // 13: teleport.clusterconfig.v1.ClusterConfigService.UpsertSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.UpsertSessionRecordingConfigRequest - 7, // 14: teleport.clusterconfig.v1.ClusterConfigService.ResetSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.ResetSessionRecordingConfigRequest - 8, // 15: teleport.clusterconfig.v1.ClusterConfigService.GetAuthPreference:input_type -> teleport.clusterconfig.v1.GetAuthPreferenceRequest - 9, // 16: teleport.clusterconfig.v1.ClusterConfigService.UpdateAuthPreference:input_type -> teleport.clusterconfig.v1.UpdateAuthPreferenceRequest - 10, // 17: teleport.clusterconfig.v1.ClusterConfigService.UpsertAuthPreference:input_type -> teleport.clusterconfig.v1.UpsertAuthPreferenceRequest - 11, // 18: teleport.clusterconfig.v1.ClusterConfigService.ResetAuthPreference:input_type -> teleport.clusterconfig.v1.ResetAuthPreferenceRequest - 12, // 19: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAuditConfig:input_type -> teleport.clusterconfig.v1.GetClusterAuditConfigRequest - 13, // 20: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAccessGraphConfig:input_type -> teleport.clusterconfig.v1.GetClusterAccessGraphConfigRequest - 15, // 21: teleport.clusterconfig.v1.ClusterConfigService.GetClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 - 15, // 22: teleport.clusterconfig.v1.ClusterConfigService.UpdateClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 - 15, // 23: teleport.clusterconfig.v1.ClusterConfigService.UpsertClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 - 15, // 24: teleport.clusterconfig.v1.ClusterConfigService.ResetClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 - 16, // 25: teleport.clusterconfig.v1.ClusterConfigService.GetSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 - 16, // 26: teleport.clusterconfig.v1.ClusterConfigService.UpdateSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 - 16, // 27: teleport.clusterconfig.v1.ClusterConfigService.UpsertSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 - 16, // 28: teleport.clusterconfig.v1.ClusterConfigService.ResetSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 - 17, // 29: teleport.clusterconfig.v1.ClusterConfigService.GetAuthPreference:output_type -> types.AuthPreferenceV2 - 17, // 30: teleport.clusterconfig.v1.ClusterConfigService.UpdateAuthPreference:output_type -> types.AuthPreferenceV2 - 17, // 31: teleport.clusterconfig.v1.ClusterConfigService.UpsertAuthPreference:output_type -> types.AuthPreferenceV2 - 17, // 32: teleport.clusterconfig.v1.ClusterConfigService.ResetAuthPreference:output_type -> types.AuthPreferenceV2 - 19, // 33: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAuditConfig:output_type -> types.ClusterAuditConfigV2 - 14, // 34: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAccessGraphConfig:output_type -> teleport.clusterconfig.v1.GetClusterAccessGraphConfigResponse - 21, // [21:35] is the sub-list for method output_type - 7, // [7:21] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 20, // 0: teleport.clusterconfig.v1.UpdateClusterNetworkingConfigRequest.cluster_network_config:type_name -> types.ClusterNetworkingConfigV2 + 20, // 1: teleport.clusterconfig.v1.UpsertClusterNetworkingConfigRequest.cluster_network_config:type_name -> types.ClusterNetworkingConfigV2 + 21, // 2: teleport.clusterconfig.v1.UpdateSessionRecordingConfigRequest.session_recording_config:type_name -> types.SessionRecordingConfigV2 + 21, // 3: teleport.clusterconfig.v1.UpsertSessionRecordingConfigRequest.session_recording_config:type_name -> types.SessionRecordingConfigV2 + 22, // 4: teleport.clusterconfig.v1.UpdateAuthPreferenceRequest.auth_preference:type_name -> types.AuthPreferenceV2 + 22, // 5: teleport.clusterconfig.v1.UpsertAuthPreferenceRequest.auth_preference:type_name -> types.AuthPreferenceV2 + 23, // 6: teleport.clusterconfig.v1.GetClusterAccessGraphConfigResponse.access_graph:type_name -> teleport.clusterconfig.v1.AccessGraphConfig + 24, // 7: teleport.clusterconfig.v1.CreateAccessGraphSettingsRequest.access_graph_settings:type_name -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 8: teleport.clusterconfig.v1.UpdateAccessGraphSettingsRequest.access_graph_settings:type_name -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 9: teleport.clusterconfig.v1.UpsertAccessGraphSettingsRequest.access_graph_settings:type_name -> teleport.clusterconfig.v1.AccessGraphSettings + 0, // 10: teleport.clusterconfig.v1.ClusterConfigService.GetClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.GetClusterNetworkingConfigRequest + 1, // 11: teleport.clusterconfig.v1.ClusterConfigService.UpdateClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.UpdateClusterNetworkingConfigRequest + 2, // 12: teleport.clusterconfig.v1.ClusterConfigService.UpsertClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.UpsertClusterNetworkingConfigRequest + 3, // 13: teleport.clusterconfig.v1.ClusterConfigService.ResetClusterNetworkingConfig:input_type -> teleport.clusterconfig.v1.ResetClusterNetworkingConfigRequest + 4, // 14: teleport.clusterconfig.v1.ClusterConfigService.GetSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.GetSessionRecordingConfigRequest + 5, // 15: teleport.clusterconfig.v1.ClusterConfigService.UpdateSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.UpdateSessionRecordingConfigRequest + 6, // 16: teleport.clusterconfig.v1.ClusterConfigService.UpsertSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.UpsertSessionRecordingConfigRequest + 7, // 17: teleport.clusterconfig.v1.ClusterConfigService.ResetSessionRecordingConfig:input_type -> teleport.clusterconfig.v1.ResetSessionRecordingConfigRequest + 8, // 18: teleport.clusterconfig.v1.ClusterConfigService.GetAuthPreference:input_type -> teleport.clusterconfig.v1.GetAuthPreferenceRequest + 9, // 19: teleport.clusterconfig.v1.ClusterConfigService.UpdateAuthPreference:input_type -> teleport.clusterconfig.v1.UpdateAuthPreferenceRequest + 10, // 20: teleport.clusterconfig.v1.ClusterConfigService.UpsertAuthPreference:input_type -> teleport.clusterconfig.v1.UpsertAuthPreferenceRequest + 11, // 21: teleport.clusterconfig.v1.ClusterConfigService.ResetAuthPreference:input_type -> teleport.clusterconfig.v1.ResetAuthPreferenceRequest + 12, // 22: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAuditConfig:input_type -> teleport.clusterconfig.v1.GetClusterAuditConfigRequest + 13, // 23: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAccessGraphConfig:input_type -> teleport.clusterconfig.v1.GetClusterAccessGraphConfigRequest + 15, // 24: teleport.clusterconfig.v1.ClusterConfigService.GetAccessGraphSettings:input_type -> teleport.clusterconfig.v1.GetAccessGraphSettingsRequest + 16, // 25: teleport.clusterconfig.v1.ClusterConfigService.CreateAccessGraphSettings:input_type -> teleport.clusterconfig.v1.CreateAccessGraphSettingsRequest + 17, // 26: teleport.clusterconfig.v1.ClusterConfigService.UpdateAccessGraphSettings:input_type -> teleport.clusterconfig.v1.UpdateAccessGraphSettingsRequest + 18, // 27: teleport.clusterconfig.v1.ClusterConfigService.UpsertAccessGraphSettings:input_type -> teleport.clusterconfig.v1.UpsertAccessGraphSettingsRequest + 19, // 28: teleport.clusterconfig.v1.ClusterConfigService.ResetAccessGraphSettings:input_type -> teleport.clusterconfig.v1.ResetAccessGraphSettingsRequest + 20, // 29: teleport.clusterconfig.v1.ClusterConfigService.GetClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 + 20, // 30: teleport.clusterconfig.v1.ClusterConfigService.UpdateClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 + 20, // 31: teleport.clusterconfig.v1.ClusterConfigService.UpsertClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 + 20, // 32: teleport.clusterconfig.v1.ClusterConfigService.ResetClusterNetworkingConfig:output_type -> types.ClusterNetworkingConfigV2 + 21, // 33: teleport.clusterconfig.v1.ClusterConfigService.GetSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 + 21, // 34: teleport.clusterconfig.v1.ClusterConfigService.UpdateSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 + 21, // 35: teleport.clusterconfig.v1.ClusterConfigService.UpsertSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 + 21, // 36: teleport.clusterconfig.v1.ClusterConfigService.ResetSessionRecordingConfig:output_type -> types.SessionRecordingConfigV2 + 22, // 37: teleport.clusterconfig.v1.ClusterConfigService.GetAuthPreference:output_type -> types.AuthPreferenceV2 + 22, // 38: teleport.clusterconfig.v1.ClusterConfigService.UpdateAuthPreference:output_type -> types.AuthPreferenceV2 + 22, // 39: teleport.clusterconfig.v1.ClusterConfigService.UpsertAuthPreference:output_type -> types.AuthPreferenceV2 + 22, // 40: teleport.clusterconfig.v1.ClusterConfigService.ResetAuthPreference:output_type -> types.AuthPreferenceV2 + 25, // 41: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAuditConfig:output_type -> types.ClusterAuditConfigV2 + 14, // 42: teleport.clusterconfig.v1.ClusterConfigService.GetClusterAccessGraphConfig:output_type -> teleport.clusterconfig.v1.GetClusterAccessGraphConfigResponse + 24, // 43: teleport.clusterconfig.v1.ClusterConfigService.GetAccessGraphSettings:output_type -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 44: teleport.clusterconfig.v1.ClusterConfigService.CreateAccessGraphSettings:output_type -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 45: teleport.clusterconfig.v1.ClusterConfigService.UpdateAccessGraphSettings:output_type -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 46: teleport.clusterconfig.v1.ClusterConfigService.UpsertAccessGraphSettings:output_type -> teleport.clusterconfig.v1.AccessGraphSettings + 24, // 47: teleport.clusterconfig.v1.ClusterConfigService.ResetAccessGraphSettings:output_type -> teleport.clusterconfig.v1.AccessGraphSettings + 29, // [29:48] is the sub-list for method output_type + 10, // [10:29] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_teleport_clusterconfig_v1_clusterconfig_service_proto_init() } @@ -968,6 +1285,7 @@ func file_teleport_clusterconfig_v1_clusterconfig_service_proto_init() { return } file_teleport_clusterconfig_v1_access_graph_proto_init() + file_teleport_clusterconfig_v1_access_graph_settings_proto_init() if !protoimpl.UnsafeEnabled { file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetClusterNetworkingConfigRequest); i { @@ -1149,6 +1467,66 @@ func file_teleport_clusterconfig_v1_clusterconfig_service_proto_init() { return nil } } + file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetAccessGraphSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateAccessGraphSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateAccessGraphSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpsertAccessGraphSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_clusterconfig_v1_clusterconfig_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResetAccessGraphSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1156,7 +1534,7 @@ func file_teleport_clusterconfig_v1_clusterconfig_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_clusterconfig_v1_clusterconfig_service_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 20, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service_grpc.pb.go b/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service_grpc.pb.go index 00dc46d7dbfca..be97e6e13f93e 100644 --- a/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/clusterconfig/v1/clusterconfig_service_grpc.pb.go @@ -48,6 +48,11 @@ const ( ClusterConfigService_ResetAuthPreference_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/ResetAuthPreference" ClusterConfigService_GetClusterAuditConfig_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/GetClusterAuditConfig" ClusterConfigService_GetClusterAccessGraphConfig_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/GetClusterAccessGraphConfig" + ClusterConfigService_GetAccessGraphSettings_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/GetAccessGraphSettings" + ClusterConfigService_CreateAccessGraphSettings_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/CreateAccessGraphSettings" + ClusterConfigService_UpdateAccessGraphSettings_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/UpdateAccessGraphSettings" + ClusterConfigService_UpsertAccessGraphSettings_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/UpsertAccessGraphSettings" + ClusterConfigService_ResetAccessGraphSettings_FullMethodName = "/teleport.clusterconfig.v1.ClusterConfigService/ResetAccessGraphSettings" ) // ClusterConfigServiceClient is the client API for ClusterConfigService service. @@ -80,8 +85,18 @@ type ClusterConfigServiceClient interface { ResetAuthPreference(ctx context.Context, in *ResetAuthPreferenceRequest, opts ...grpc.CallOption) (*types.AuthPreferenceV2, error) // GetClusterAuditConfig retrieves the active cluster audit configuration. GetClusterAuditConfig(ctx context.Context, in *GetClusterAuditConfigRequest, opts ...grpc.CallOption) (*types.ClusterAuditConfigV2, error) - // GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server. + // GetClusterAccessGraphConfig retrieves the cluster Access Graph configuration from Auth server. GetClusterAccessGraphConfig(ctx context.Context, in *GetClusterAccessGraphConfigRequest, opts ...grpc.CallOption) (*GetClusterAccessGraphConfigResponse, error) + // GetAccessGraphSettings updates the cluster Access Graph configuration. + GetAccessGraphSettings(ctx context.Context, in *GetAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) + // CreateAccessGraphSettings creates the cluster Access Graph configuration. + CreateAccessGraphSettings(ctx context.Context, in *CreateAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) + // UpdateAccessGraphSettings updates the cluster Access Graph configuration. + UpdateAccessGraphSettings(ctx context.Context, in *UpdateAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) + // UpsertAccessGraphSettings overwrites the active cluster Access Graph configuration. + UpsertAccessGraphSettings(ctx context.Context, in *UpsertAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) + // ResetAccessGraphSettings restores the active cluster Access Graph to default settings. + ResetAccessGraphSettings(ctx context.Context, in *ResetAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) } type clusterConfigServiceClient struct { @@ -218,6 +233,51 @@ func (c *clusterConfigServiceClient) GetClusterAccessGraphConfig(ctx context.Con return out, nil } +func (c *clusterConfigServiceClient) GetAccessGraphSettings(ctx context.Context, in *GetAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) { + out := new(AccessGraphSettings) + err := c.cc.Invoke(ctx, ClusterConfigService_GetAccessGraphSettings_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *clusterConfigServiceClient) CreateAccessGraphSettings(ctx context.Context, in *CreateAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) { + out := new(AccessGraphSettings) + err := c.cc.Invoke(ctx, ClusterConfigService_CreateAccessGraphSettings_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *clusterConfigServiceClient) UpdateAccessGraphSettings(ctx context.Context, in *UpdateAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) { + out := new(AccessGraphSettings) + err := c.cc.Invoke(ctx, ClusterConfigService_UpdateAccessGraphSettings_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *clusterConfigServiceClient) UpsertAccessGraphSettings(ctx context.Context, in *UpsertAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) { + out := new(AccessGraphSettings) + err := c.cc.Invoke(ctx, ClusterConfigService_UpsertAccessGraphSettings_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *clusterConfigServiceClient) ResetAccessGraphSettings(ctx context.Context, in *ResetAccessGraphSettingsRequest, opts ...grpc.CallOption) (*AccessGraphSettings, error) { + out := new(AccessGraphSettings) + err := c.cc.Invoke(ctx, ClusterConfigService_ResetAccessGraphSettings_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ClusterConfigServiceServer is the server API for ClusterConfigService service. // All implementations must embed UnimplementedClusterConfigServiceServer // for forward compatibility @@ -248,8 +308,18 @@ type ClusterConfigServiceServer interface { ResetAuthPreference(context.Context, *ResetAuthPreferenceRequest) (*types.AuthPreferenceV2, error) // GetClusterAuditConfig retrieves the active cluster audit configuration. GetClusterAuditConfig(context.Context, *GetClusterAuditConfigRequest) (*types.ClusterAuditConfigV2, error) - // GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server. + // GetClusterAccessGraphConfig retrieves the cluster Access Graph configuration from Auth server. GetClusterAccessGraphConfig(context.Context, *GetClusterAccessGraphConfigRequest) (*GetClusterAccessGraphConfigResponse, error) + // GetAccessGraphSettings updates the cluster Access Graph configuration. + GetAccessGraphSettings(context.Context, *GetAccessGraphSettingsRequest) (*AccessGraphSettings, error) + // CreateAccessGraphSettings creates the cluster Access Graph configuration. + CreateAccessGraphSettings(context.Context, *CreateAccessGraphSettingsRequest) (*AccessGraphSettings, error) + // UpdateAccessGraphSettings updates the cluster Access Graph configuration. + UpdateAccessGraphSettings(context.Context, *UpdateAccessGraphSettingsRequest) (*AccessGraphSettings, error) + // UpsertAccessGraphSettings overwrites the active cluster Access Graph configuration. + UpsertAccessGraphSettings(context.Context, *UpsertAccessGraphSettingsRequest) (*AccessGraphSettings, error) + // ResetAccessGraphSettings restores the active cluster Access Graph to default settings. + ResetAccessGraphSettings(context.Context, *ResetAccessGraphSettingsRequest) (*AccessGraphSettings, error) mustEmbedUnimplementedClusterConfigServiceServer() } @@ -299,6 +369,21 @@ func (UnimplementedClusterConfigServiceServer) GetClusterAuditConfig(context.Con func (UnimplementedClusterConfigServiceServer) GetClusterAccessGraphConfig(context.Context, *GetClusterAccessGraphConfigRequest) (*GetClusterAccessGraphConfigResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetClusterAccessGraphConfig not implemented") } +func (UnimplementedClusterConfigServiceServer) GetAccessGraphSettings(context.Context, *GetAccessGraphSettingsRequest) (*AccessGraphSettings, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAccessGraphSettings not implemented") +} +func (UnimplementedClusterConfigServiceServer) CreateAccessGraphSettings(context.Context, *CreateAccessGraphSettingsRequest) (*AccessGraphSettings, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateAccessGraphSettings not implemented") +} +func (UnimplementedClusterConfigServiceServer) UpdateAccessGraphSettings(context.Context, *UpdateAccessGraphSettingsRequest) (*AccessGraphSettings, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateAccessGraphSettings not implemented") +} +func (UnimplementedClusterConfigServiceServer) UpsertAccessGraphSettings(context.Context, *UpsertAccessGraphSettingsRequest) (*AccessGraphSettings, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpsertAccessGraphSettings not implemented") +} +func (UnimplementedClusterConfigServiceServer) ResetAccessGraphSettings(context.Context, *ResetAccessGraphSettingsRequest) (*AccessGraphSettings, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResetAccessGraphSettings not implemented") +} func (UnimplementedClusterConfigServiceServer) mustEmbedUnimplementedClusterConfigServiceServer() {} // UnsafeClusterConfigServiceServer may be embedded to opt out of forward compatibility for this service. @@ -564,6 +649,96 @@ func _ClusterConfigService_GetClusterAccessGraphConfig_Handler(srv interface{}, return interceptor(ctx, in, info, handler) } +func _ClusterConfigService_GetAccessGraphSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAccessGraphSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterConfigServiceServer).GetAccessGraphSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterConfigService_GetAccessGraphSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterConfigServiceServer).GetAccessGraphSettings(ctx, req.(*GetAccessGraphSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ClusterConfigService_CreateAccessGraphSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateAccessGraphSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterConfigServiceServer).CreateAccessGraphSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterConfigService_CreateAccessGraphSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterConfigServiceServer).CreateAccessGraphSettings(ctx, req.(*CreateAccessGraphSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ClusterConfigService_UpdateAccessGraphSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateAccessGraphSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterConfigServiceServer).UpdateAccessGraphSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterConfigService_UpdateAccessGraphSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterConfigServiceServer).UpdateAccessGraphSettings(ctx, req.(*UpdateAccessGraphSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ClusterConfigService_UpsertAccessGraphSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertAccessGraphSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterConfigServiceServer).UpsertAccessGraphSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterConfigService_UpsertAccessGraphSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterConfigServiceServer).UpsertAccessGraphSettings(ctx, req.(*UpsertAccessGraphSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ClusterConfigService_ResetAccessGraphSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResetAccessGraphSettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ClusterConfigServiceServer).ResetAccessGraphSettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ClusterConfigService_ResetAccessGraphSettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ClusterConfigServiceServer).ResetAccessGraphSettings(ctx, req.(*ResetAccessGraphSettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ClusterConfigService_ServiceDesc is the grpc.ServiceDesc for ClusterConfigService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -627,6 +802,26 @@ var ClusterConfigService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetClusterAccessGraphConfig", Handler: _ClusterConfigService_GetClusterAccessGraphConfig_Handler, }, + { + MethodName: "GetAccessGraphSettings", + Handler: _ClusterConfigService_GetAccessGraphSettings_Handler, + }, + { + MethodName: "CreateAccessGraphSettings", + Handler: _ClusterConfigService_CreateAccessGraphSettings_Handler, + }, + { + MethodName: "UpdateAccessGraphSettings", + Handler: _ClusterConfigService_UpdateAccessGraphSettings_Handler, + }, + { + MethodName: "UpsertAccessGraphSettings", + Handler: _ClusterConfigService_UpsertAccessGraphSettings_Handler, + }, + { + MethodName: "ResetAccessGraphSettings", + Handler: _ClusterConfigService_ResetAccessGraphSettings_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "teleport/clusterconfig/v1/clusterconfig_service.proto", diff --git a/api/gen/proto/go/teleport/devicetrust/v1/assert.pb.go b/api/gen/proto/go/teleport/devicetrust/v1/assert.pb.go new file mode 100644 index 0000000000000..0efdc20200dfc --- /dev/null +++ b/api/gen/proto/go/teleport/devicetrust/v1/assert.pb.go @@ -0,0 +1,544 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/devicetrust/v1/assert.proto + +package devicetrustv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Request to assert an enrolled device. Assertion authenticates the device, +// regardless of the user driving the assertion. +// +// Assertion messages are meant to be included by other requests and responses, +// either streams or multi-stage RPCs. The ceremony is resolved by a co-located +// DeviceTrustService. +// +// See the lib/devicetrust/assert (client) and lib/devicetrust/assertserver +// (server) packages. +// +// Assertion ceremony flow: +// -> AssertDeviceInit (client) +// <- AssertDeviceChallenge (server) +// -> AssertDeviceChallengeResponse (client) +// <- DeviceAsserted (server) +// +// A successful ceremony signifies that the device is registered, enrolled and +// passed the authentication challenge. +type AssertDeviceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *AssertDeviceRequest_Init + // *AssertDeviceRequest_ChallengeResponse + // *AssertDeviceRequest_TpmChallengeResponse + Payload isAssertDeviceRequest_Payload `protobuf_oneof:"payload"` +} + +func (x *AssertDeviceRequest) Reset() { + *x = AssertDeviceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssertDeviceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssertDeviceRequest) ProtoMessage() {} + +func (x *AssertDeviceRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[0] + 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 AssertDeviceRequest.ProtoReflect.Descriptor instead. +func (*AssertDeviceRequest) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_assert_proto_rawDescGZIP(), []int{0} +} + +func (m *AssertDeviceRequest) GetPayload() isAssertDeviceRequest_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *AssertDeviceRequest) GetInit() *AssertDeviceInit { + if x, ok := x.GetPayload().(*AssertDeviceRequest_Init); ok { + return x.Init + } + return nil +} + +func (x *AssertDeviceRequest) GetChallengeResponse() *AuthenticateDeviceChallengeResponse { + if x, ok := x.GetPayload().(*AssertDeviceRequest_ChallengeResponse); ok { + return x.ChallengeResponse + } + return nil +} + +func (x *AssertDeviceRequest) GetTpmChallengeResponse() *TPMAuthenticateDeviceChallengeResponse { + if x, ok := x.GetPayload().(*AssertDeviceRequest_TpmChallengeResponse); ok { + return x.TpmChallengeResponse + } + return nil +} + +type isAssertDeviceRequest_Payload interface { + isAssertDeviceRequest_Payload() +} + +type AssertDeviceRequest_Init struct { + Init *AssertDeviceInit `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type AssertDeviceRequest_ChallengeResponse struct { + ChallengeResponse *AuthenticateDeviceChallengeResponse `protobuf:"bytes,2,opt,name=challenge_response,json=challengeResponse,proto3,oneof"` +} + +type AssertDeviceRequest_TpmChallengeResponse struct { + TpmChallengeResponse *TPMAuthenticateDeviceChallengeResponse `protobuf:"bytes,3,opt,name=tpm_challenge_response,json=tpmChallengeResponse,proto3,oneof"` +} + +func (*AssertDeviceRequest_Init) isAssertDeviceRequest_Payload() {} + +func (*AssertDeviceRequest_ChallengeResponse) isAssertDeviceRequest_Payload() {} + +func (*AssertDeviceRequest_TpmChallengeResponse) isAssertDeviceRequest_Payload() {} + +// Response of the device assertion ceremony. +// See [AssertDeviceRequest]. +type AssertDeviceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *AssertDeviceResponse_Challenge + // *AssertDeviceResponse_TpmChallenge + // *AssertDeviceResponse_DeviceAsserted + Payload isAssertDeviceResponse_Payload `protobuf_oneof:"payload"` +} + +func (x *AssertDeviceResponse) Reset() { + *x = AssertDeviceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssertDeviceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssertDeviceResponse) ProtoMessage() {} + +func (x *AssertDeviceResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[1] + 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 AssertDeviceResponse.ProtoReflect.Descriptor instead. +func (*AssertDeviceResponse) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_assert_proto_rawDescGZIP(), []int{1} +} + +func (m *AssertDeviceResponse) GetPayload() isAssertDeviceResponse_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *AssertDeviceResponse) GetChallenge() *AuthenticateDeviceChallenge { + if x, ok := x.GetPayload().(*AssertDeviceResponse_Challenge); ok { + return x.Challenge + } + return nil +} + +func (x *AssertDeviceResponse) GetTpmChallenge() *TPMAuthenticateDeviceChallenge { + if x, ok := x.GetPayload().(*AssertDeviceResponse_TpmChallenge); ok { + return x.TpmChallenge + } + return nil +} + +func (x *AssertDeviceResponse) GetDeviceAsserted() *DeviceAsserted { + if x, ok := x.GetPayload().(*AssertDeviceResponse_DeviceAsserted); ok { + return x.DeviceAsserted + } + return nil +} + +type isAssertDeviceResponse_Payload interface { + isAssertDeviceResponse_Payload() +} + +type AssertDeviceResponse_Challenge struct { + Challenge *AuthenticateDeviceChallenge `protobuf:"bytes,1,opt,name=challenge,proto3,oneof"` +} + +type AssertDeviceResponse_TpmChallenge struct { + TpmChallenge *TPMAuthenticateDeviceChallenge `protobuf:"bytes,2,opt,name=tpm_challenge,json=tpmChallenge,proto3,oneof"` +} + +type AssertDeviceResponse_DeviceAsserted struct { + DeviceAsserted *DeviceAsserted `protobuf:"bytes,3,opt,name=device_asserted,json=deviceAsserted,proto3,oneof"` +} + +func (*AssertDeviceResponse_Challenge) isAssertDeviceResponse_Payload() {} + +func (*AssertDeviceResponse_TpmChallenge) isAssertDeviceResponse_Payload() {} + +func (*AssertDeviceResponse_DeviceAsserted) isAssertDeviceResponse_Payload() {} + +// AssertDeviceInit initiates the device assertion ceremony. +// See [AssertDeviceRequest]. +type AssertDeviceInit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the enrolled device credential. + CredentialId string `protobuf:"bytes,1,opt,name=credential_id,json=credentialId,proto3" json:"credential_id,omitempty"` + // Device collected data. + // Matched against the device registration information and any previously + // collected data. + DeviceData *DeviceCollectedData `protobuf:"bytes,2,opt,name=device_data,json=deviceData,proto3" json:"device_data,omitempty"` +} + +func (x *AssertDeviceInit) Reset() { + *x = AssertDeviceInit{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssertDeviceInit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssertDeviceInit) ProtoMessage() {} + +func (x *AssertDeviceInit) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[2] + 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 AssertDeviceInit.ProtoReflect.Descriptor instead. +func (*AssertDeviceInit) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_assert_proto_rawDescGZIP(), []int{2} +} + +func (x *AssertDeviceInit) GetCredentialId() string { + if x != nil { + return x.CredentialId + } + return "" +} + +func (x *AssertDeviceInit) GetDeviceData() *DeviceCollectedData { + if x != nil { + return x.DeviceData + } + return nil +} + +// DeviceAsserted marks a successful device assertion ceremony. +// See [AssertDeviceRequest]. +type DeviceAsserted struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeviceAsserted) Reset() { + *x = DeviceAsserted{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_assert_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeviceAsserted) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeviceAsserted) ProtoMessage() {} + +func (x *DeviceAsserted) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_assert_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 DeviceAsserted.ProtoReflect.Descriptor instead. +func (*DeviceAsserted) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_assert_proto_rawDescGZIP(), []int{3} +} + +var File_teleport_devicetrust_v1_assert_proto protoreflect.FileDescriptor + +var file_teleport_devicetrust_v1_assert_proto_rawDesc = []byte{ + 0x0a, 0x24, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x1a, + 0x34, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x02, 0x0a, 0x13, 0x41, + 0x73, 0x73, 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x72, + 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, + 0x6e, 0x69, 0x74, 0x12, 0x6d, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, + 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, + 0x11, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, + 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x14, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, + 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xab, 0x02, 0x0a, 0x14, 0x41, 0x73, 0x73, 0x65, 0x72, + 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x54, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, + 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x5e, 0x0a, 0x0d, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, + 0x73, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x86, 0x01, 0x0a, 0x10, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x4d, + 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0x10, 0x0a, + 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x42, + 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_teleport_devicetrust_v1_assert_proto_rawDescOnce sync.Once + file_teleport_devicetrust_v1_assert_proto_rawDescData = file_teleport_devicetrust_v1_assert_proto_rawDesc +) + +func file_teleport_devicetrust_v1_assert_proto_rawDescGZIP() []byte { + file_teleport_devicetrust_v1_assert_proto_rawDescOnce.Do(func() { + file_teleport_devicetrust_v1_assert_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_devicetrust_v1_assert_proto_rawDescData) + }) + return file_teleport_devicetrust_v1_assert_proto_rawDescData +} + +var file_teleport_devicetrust_v1_assert_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_teleport_devicetrust_v1_assert_proto_goTypes = []interface{}{ + (*AssertDeviceRequest)(nil), // 0: teleport.devicetrust.v1.AssertDeviceRequest + (*AssertDeviceResponse)(nil), // 1: teleport.devicetrust.v1.AssertDeviceResponse + (*AssertDeviceInit)(nil), // 2: teleport.devicetrust.v1.AssertDeviceInit + (*DeviceAsserted)(nil), // 3: teleport.devicetrust.v1.DeviceAsserted + (*AuthenticateDeviceChallengeResponse)(nil), // 4: teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse + (*TPMAuthenticateDeviceChallengeResponse)(nil), // 5: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse + (*AuthenticateDeviceChallenge)(nil), // 6: teleport.devicetrust.v1.AuthenticateDeviceChallenge + (*TPMAuthenticateDeviceChallenge)(nil), // 7: teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge + (*DeviceCollectedData)(nil), // 8: teleport.devicetrust.v1.DeviceCollectedData +} +var file_teleport_devicetrust_v1_assert_proto_depIdxs = []int32{ + 2, // 0: teleport.devicetrust.v1.AssertDeviceRequest.init:type_name -> teleport.devicetrust.v1.AssertDeviceInit + 4, // 1: teleport.devicetrust.v1.AssertDeviceRequest.challenge_response:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse + 5, // 2: teleport.devicetrust.v1.AssertDeviceRequest.tpm_challenge_response:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse + 6, // 3: teleport.devicetrust.v1.AssertDeviceResponse.challenge:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallenge + 7, // 4: teleport.devicetrust.v1.AssertDeviceResponse.tpm_challenge:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge + 3, // 5: teleport.devicetrust.v1.AssertDeviceResponse.device_asserted:type_name -> teleport.devicetrust.v1.DeviceAsserted + 8, // 6: teleport.devicetrust.v1.AssertDeviceInit.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_teleport_devicetrust_v1_assert_proto_init() } +func file_teleport_devicetrust_v1_assert_proto_init() { + if File_teleport_devicetrust_v1_assert_proto != nil { + return + } + file_teleport_devicetrust_v1_authenticate_challenge_proto_init() + file_teleport_devicetrust_v1_device_collected_data_proto_init() + if !protoimpl.UnsafeEnabled { + file_teleport_devicetrust_v1_assert_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssertDeviceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_assert_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssertDeviceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_assert_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssertDeviceInit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_assert_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeviceAsserted); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_teleport_devicetrust_v1_assert_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*AssertDeviceRequest_Init)(nil), + (*AssertDeviceRequest_ChallengeResponse)(nil), + (*AssertDeviceRequest_TpmChallengeResponse)(nil), + } + file_teleport_devicetrust_v1_assert_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*AssertDeviceResponse_Challenge)(nil), + (*AssertDeviceResponse_TpmChallenge)(nil), + (*AssertDeviceResponse_DeviceAsserted)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_devicetrust_v1_assert_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_teleport_devicetrust_v1_assert_proto_goTypes, + DependencyIndexes: file_teleport_devicetrust_v1_assert_proto_depIdxs, + MessageInfos: file_teleport_devicetrust_v1_assert_proto_msgTypes, + }.Build() + File_teleport_devicetrust_v1_assert_proto = out.File + file_teleport_devicetrust_v1_assert_proto_rawDesc = nil + file_teleport_devicetrust_v1_assert_proto_goTypes = nil + file_teleport_devicetrust_v1_assert_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/devicetrust/v1/authenticate_challenge.pb.go b/api/gen/proto/go/teleport/devicetrust/v1/authenticate_challenge.pb.go new file mode 100644 index 0000000000000..087fc953bf867 --- /dev/null +++ b/api/gen/proto/go/teleport/devicetrust/v1/authenticate_challenge.pb.go @@ -0,0 +1,382 @@ +// Copyright 2022 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.0 +// protoc (unknown) +// source: teleport/devicetrust/v1/authenticate_challenge.proto + +package devicetrustv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// AuthenticateDeviceChallenge carries the authentication challenge. +type AuthenticateDeviceChallenge struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Randomly-generated, opaque challenge to be signed using the device key. + Challenge []byte `protobuf:"bytes,1,opt,name=challenge,proto3" json:"challenge,omitempty"` +} + +func (x *AuthenticateDeviceChallenge) Reset() { + *x = AuthenticateDeviceChallenge{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthenticateDeviceChallenge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthenticateDeviceChallenge) ProtoMessage() {} + +func (x *AuthenticateDeviceChallenge) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[0] + 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 AuthenticateDeviceChallenge.ProtoReflect.Descriptor instead. +func (*AuthenticateDeviceChallenge) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescGZIP(), []int{0} +} + +func (x *AuthenticateDeviceChallenge) GetChallenge() []byte { + if x != nil { + return x.Challenge + } + return nil +} + +// AuthenticateDeviceChallengeResponse carries the authentication challenge +// response. +type AuthenticateDeviceChallengeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Signature over the challenge, using the device key. + Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AuthenticateDeviceChallengeResponse) Reset() { + *x = AuthenticateDeviceChallengeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthenticateDeviceChallengeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthenticateDeviceChallengeResponse) ProtoMessage() {} + +func (x *AuthenticateDeviceChallengeResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[1] + 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 AuthenticateDeviceChallengeResponse.ProtoReflect.Descriptor instead. +func (*AuthenticateDeviceChallengeResponse) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescGZIP(), []int{1} +} + +func (x *AuthenticateDeviceChallengeResponse) GetSignature() []byte { + if x != nil { + return x.Signature + } + return nil +} + +// TPMAuthenticateDeviceChallenge carries the authentication challenge +// specific to TPMs. +type TPMAuthenticateDeviceChallenge struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Randomly-generated nonce to be used during platform attestation by the + // TPM. + AttestationNonce []byte `protobuf:"bytes,1,opt,name=attestation_nonce,json=attestationNonce,proto3" json:"attestation_nonce,omitempty"` +} + +func (x *TPMAuthenticateDeviceChallenge) Reset() { + *x = TPMAuthenticateDeviceChallenge{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TPMAuthenticateDeviceChallenge) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TPMAuthenticateDeviceChallenge) ProtoMessage() {} + +func (x *TPMAuthenticateDeviceChallenge) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[2] + 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 TPMAuthenticateDeviceChallenge.ProtoReflect.Descriptor instead. +func (*TPMAuthenticateDeviceChallenge) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescGZIP(), []int{2} +} + +func (x *TPMAuthenticateDeviceChallenge) GetAttestationNonce() []byte { + if x != nil { + return x.AttestationNonce + } + return nil +} + +// TPMAuthenticateDeviceChallengeResponse carries the authentication challenge +// response specific to TPMs. +type TPMAuthenticateDeviceChallengeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The result of the client's platform attestation with the nonce provided + // in `TPMAuthenticateDeviceChallenge`. + PlatformParameters *TPMPlatformParameters `protobuf:"bytes,1,opt,name=platform_parameters,json=platformParameters,proto3" json:"platform_parameters,omitempty"` +} + +func (x *TPMAuthenticateDeviceChallengeResponse) Reset() { + *x = TPMAuthenticateDeviceChallengeResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TPMAuthenticateDeviceChallengeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TPMAuthenticateDeviceChallengeResponse) ProtoMessage() {} + +func (x *TPMAuthenticateDeviceChallengeResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_devicetrust_v1_authenticate_challenge_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 TPMAuthenticateDeviceChallengeResponse.ProtoReflect.Descriptor instead. +func (*TPMAuthenticateDeviceChallengeResponse) Descriptor() ([]byte, []int) { + return file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescGZIP(), []int{3} +} + +func (x *TPMAuthenticateDeviceChallengeResponse) GetPlatformParameters() *TPMPlatformParameters { + if x != nil { + return x.PlatformParameters + } + return nil +} + +var File_teleport_devicetrust_v1_authenticate_challenge_proto protoreflect.FileDescriptor + +var file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDesc = []byte{ + 0x0a, 0x34, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x17, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x1a, + 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x70, 0x6d, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x3b, 0x0a, 0x1b, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x22, + 0x43, 0x0a, 0x23, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x22, 0x4d, 0x0a, 0x1e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, + 0x6e, 0x63, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x26, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, + 0x0a, 0x13, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x12, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x42, + 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescOnce sync.Once + file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescData = file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDesc +) + +func file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescGZIP() []byte { + file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescOnce.Do(func() { + file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescData = protoimpl.X.CompressGZIP(file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescData) + }) + return file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDescData +} + +var file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_teleport_devicetrust_v1_authenticate_challenge_proto_goTypes = []interface{}{ + (*AuthenticateDeviceChallenge)(nil), // 0: teleport.devicetrust.v1.AuthenticateDeviceChallenge + (*AuthenticateDeviceChallengeResponse)(nil), // 1: teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse + (*TPMAuthenticateDeviceChallenge)(nil), // 2: teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge + (*TPMAuthenticateDeviceChallengeResponse)(nil), // 3: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse + (*TPMPlatformParameters)(nil), // 4: teleport.devicetrust.v1.TPMPlatformParameters +} +var file_teleport_devicetrust_v1_authenticate_challenge_proto_depIdxs = []int32{ + 4, // 0: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse.platform_parameters:type_name -> teleport.devicetrust.v1.TPMPlatformParameters + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_teleport_devicetrust_v1_authenticate_challenge_proto_init() } +func file_teleport_devicetrust_v1_authenticate_challenge_proto_init() { + if File_teleport_devicetrust_v1_authenticate_challenge_proto != nil { + return + } + file_teleport_devicetrust_v1_tpm_proto_init() + if !protoimpl.UnsafeEnabled { + file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthenticateDeviceChallenge); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthenticateDeviceChallengeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TPMAuthenticateDeviceChallenge); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TPMAuthenticateDeviceChallengeResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDesc, + NumEnums: 0, + NumMessages: 4, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_teleport_devicetrust_v1_authenticate_challenge_proto_goTypes, + DependencyIndexes: file_teleport_devicetrust_v1_authenticate_challenge_proto_depIdxs, + MessageInfos: file_teleport_devicetrust_v1_authenticate_challenge_proto_msgTypes, + }.Build() + File_teleport_devicetrust_v1_authenticate_challenge_proto = out.File + file_teleport_devicetrust_v1_authenticate_challenge_proto_rawDesc = nil + file_teleport_devicetrust_v1_authenticate_challenge_proto_goTypes = nil + file_teleport_devicetrust_v1_authenticate_challenge_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/teleport/devicetrust/v1/devicetrust_service.pb.go b/api/gen/proto/go/teleport/devicetrust/v1/devicetrust_service.pb.go index 777dbfc3a3730..dda6636b39332 100644 --- a/api/gen/proto/go/teleport/devicetrust/v1/devicetrust_service.pb.go +++ b/api/gen/proto/go/teleport/devicetrust/v1/devicetrust_service.pb.go @@ -2001,207 +2001,6 @@ func (x *AuthenticateDeviceInit) GetDeviceData() *DeviceCollectedData { return nil } -// TPMAuthenticateDeviceChallenge carries the authentication challenge -// specific to TPMs. -type TPMAuthenticateDeviceChallenge struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Randomly-generated nonce to be used during platform attestation by the - // TPM. - AttestationNonce []byte `protobuf:"bytes,1,opt,name=attestation_nonce,json=attestationNonce,proto3" json:"attestation_nonce,omitempty"` -} - -func (x *TPMAuthenticateDeviceChallenge) Reset() { - *x = TPMAuthenticateDeviceChallenge{} - if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TPMAuthenticateDeviceChallenge) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TPMAuthenticateDeviceChallenge) ProtoMessage() {} - -func (x *TPMAuthenticateDeviceChallenge) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28] - 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 TPMAuthenticateDeviceChallenge.ProtoReflect.Descriptor instead. -func (*TPMAuthenticateDeviceChallenge) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{28} -} - -func (x *TPMAuthenticateDeviceChallenge) GetAttestationNonce() []byte { - if x != nil { - return x.AttestationNonce - } - return nil -} - -// TPMAuthenticateDeviceChallengeResponse carries the authentication challenge -// response specific to TPMs. -type TPMAuthenticateDeviceChallengeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The result of the client's platform attestation with the nonce provided - // in `TPMAuthenticateDeviceChallenge`. - PlatformParameters *TPMPlatformParameters `protobuf:"bytes,1,opt,name=platform_parameters,json=platformParameters,proto3" json:"platform_parameters,omitempty"` -} - -func (x *TPMAuthenticateDeviceChallengeResponse) Reset() { - *x = TPMAuthenticateDeviceChallengeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TPMAuthenticateDeviceChallengeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TPMAuthenticateDeviceChallengeResponse) ProtoMessage() {} - -func (x *TPMAuthenticateDeviceChallengeResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29] - 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 TPMAuthenticateDeviceChallengeResponse.ProtoReflect.Descriptor instead. -func (*TPMAuthenticateDeviceChallengeResponse) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{29} -} - -func (x *TPMAuthenticateDeviceChallengeResponse) GetPlatformParameters() *TPMPlatformParameters { - if x != nil { - return x.PlatformParameters - } - return nil -} - -// AuthenticateDeviceChallenge carries the authentication challenge. -type AuthenticateDeviceChallenge struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Randomly-generated, opaque challenge to be signed using the device key. - Challenge []byte `protobuf:"bytes,1,opt,name=challenge,proto3" json:"challenge,omitempty"` -} - -func (x *AuthenticateDeviceChallenge) Reset() { - *x = AuthenticateDeviceChallenge{} - if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AuthenticateDeviceChallenge) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AuthenticateDeviceChallenge) ProtoMessage() {} - -func (x *AuthenticateDeviceChallenge) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30] - 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 AuthenticateDeviceChallenge.ProtoReflect.Descriptor instead. -func (*AuthenticateDeviceChallenge) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{30} -} - -func (x *AuthenticateDeviceChallenge) GetChallenge() []byte { - if x != nil { - return x.Challenge - } - return nil -} - -// AuthenticateDeviceChallengeResponse carries the authentication challenge -// response. -type AuthenticateDeviceChallengeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Signature over the challenge, using the device key. - Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AuthenticateDeviceChallengeResponse) Reset() { - *x = AuthenticateDeviceChallengeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AuthenticateDeviceChallengeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AuthenticateDeviceChallengeResponse) ProtoMessage() {} - -func (x *AuthenticateDeviceChallengeResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31] - 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 AuthenticateDeviceChallengeResponse.ProtoReflect.Descriptor instead. -func (*AuthenticateDeviceChallengeResponse) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{31} -} - -func (x *AuthenticateDeviceChallengeResponse) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - // Request for SyncInventory. // // A typical message sequence is as follows: @@ -2235,7 +2034,7 @@ type SyncInventoryRequest struct { func (x *SyncInventoryRequest) Reset() { *x = SyncInventoryRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2248,7 +2047,7 @@ func (x *SyncInventoryRequest) String() string { func (*SyncInventoryRequest) ProtoMessage() {} func (x *SyncInventoryRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2261,7 +2060,7 @@ func (x *SyncInventoryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryRequest.ProtoReflect.Descriptor instead. func (*SyncInventoryRequest) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{32} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{28} } func (m *SyncInventoryRequest) GetPayload() isSyncInventoryRequest_Payload { @@ -2344,7 +2143,7 @@ type SyncInventoryResponse struct { func (x *SyncInventoryResponse) Reset() { *x = SyncInventoryResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2357,7 +2156,7 @@ func (x *SyncInventoryResponse) String() string { func (*SyncInventoryResponse) ProtoMessage() {} func (x *SyncInventoryResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2370,7 +2169,7 @@ func (x *SyncInventoryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryResponse.ProtoReflect.Descriptor instead. func (*SyncInventoryResponse) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{33} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{29} } func (m *SyncInventoryResponse) GetPayload() isSyncInventoryResponse_Payload { @@ -2444,7 +2243,7 @@ type SyncInventoryStart struct { func (x *SyncInventoryStart) Reset() { *x = SyncInventoryStart{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2457,7 +2256,7 @@ func (x *SyncInventoryStart) String() string { func (*SyncInventoryStart) ProtoMessage() {} func (x *SyncInventoryStart) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2470,7 +2269,7 @@ func (x *SyncInventoryStart) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryStart.ProtoReflect.Descriptor instead. func (*SyncInventoryStart) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{34} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{30} } func (x *SyncInventoryStart) GetSource() *DeviceSource { @@ -2498,7 +2297,7 @@ type SyncInventoryEnd struct { func (x *SyncInventoryEnd) Reset() { *x = SyncInventoryEnd{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2511,7 +2310,7 @@ func (x *SyncInventoryEnd) String() string { func (*SyncInventoryEnd) ProtoMessage() {} func (x *SyncInventoryEnd) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2524,7 +2323,7 @@ func (x *SyncInventoryEnd) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryEnd.ProtoReflect.Descriptor instead. func (*SyncInventoryEnd) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{35} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{31} } // SyncInventoryDevices transports devices to add/update/remove. @@ -2541,7 +2340,7 @@ type SyncInventoryDevices struct { func (x *SyncInventoryDevices) Reset() { *x = SyncInventoryDevices{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2554,7 +2353,7 @@ func (x *SyncInventoryDevices) String() string { func (*SyncInventoryDevices) ProtoMessage() {} func (x *SyncInventoryDevices) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2567,7 +2366,7 @@ func (x *SyncInventoryDevices) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryDevices.ProtoReflect.Descriptor instead. func (*SyncInventoryDevices) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{36} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{32} } func (x *SyncInventoryDevices) GetDevices() []*Device { @@ -2588,7 +2387,7 @@ type SyncInventoryAck struct { func (x *SyncInventoryAck) Reset() { *x = SyncInventoryAck{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[37] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2601,7 +2400,7 @@ func (x *SyncInventoryAck) String() string { func (*SyncInventoryAck) ProtoMessage() {} func (x *SyncInventoryAck) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[37] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2614,7 +2413,7 @@ func (x *SyncInventoryAck) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryAck.ProtoReflect.Descriptor instead. func (*SyncInventoryAck) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{37} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{33} } // SyncInventoryResult is the response for SyncInventoryDevices or @@ -2632,7 +2431,7 @@ type SyncInventoryResult struct { func (x *SyncInventoryResult) Reset() { *x = SyncInventoryResult{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[38] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2645,7 +2444,7 @@ func (x *SyncInventoryResult) String() string { func (*SyncInventoryResult) ProtoMessage() {} func (x *SyncInventoryResult) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[38] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2658,7 +2457,7 @@ func (x *SyncInventoryResult) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryResult.ProtoReflect.Descriptor instead. func (*SyncInventoryResult) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{38} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{34} } func (x *SyncInventoryResult) GetDevices() []*DeviceOrStatus { @@ -2690,7 +2489,7 @@ type SyncInventoryMissingDevices struct { func (x *SyncInventoryMissingDevices) Reset() { *x = SyncInventoryMissingDevices{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[39] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2703,7 +2502,7 @@ func (x *SyncInventoryMissingDevices) String() string { func (*SyncInventoryMissingDevices) ProtoMessage() {} func (x *SyncInventoryMissingDevices) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[39] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2716,7 +2515,7 @@ func (x *SyncInventoryMissingDevices) ProtoReflect() protoreflect.Message { // Deprecated: Use SyncInventoryMissingDevices.ProtoReflect.Descriptor instead. func (*SyncInventoryMissingDevices) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{39} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{35} } func (x *SyncInventoryMissingDevices) GetDevices() []*Device { @@ -2736,7 +2535,7 @@ type GetDevicesUsageRequest struct { func (x *GetDevicesUsageRequest) Reset() { *x = GetDevicesUsageRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[40] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2749,7 +2548,7 @@ func (x *GetDevicesUsageRequest) String() string { func (*GetDevicesUsageRequest) ProtoMessage() {} func (x *GetDevicesUsageRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[40] + mi := &file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2762,7 +2561,7 @@ func (x *GetDevicesUsageRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDevicesUsageRequest.ProtoReflect.Descriptor instead. func (*GetDevicesUsageRequest) Descriptor() ([]byte, []int) { - return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{40} + return file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP(), []int{36} } var File_teleport_devicetrust_v1_devicetrust_service_proto protoreflect.FileDescriptor @@ -2780,495 +2579,476 @@ var file_teleport_devicetrust_v1_devicetrust_service_proto_rawDesc = []byte{ 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x33, 0x74, 0x65, 0x6c, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x34, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x2b, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x70, 0x6d, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x61, - 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, - 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x81, 0x02, 0x0a, 0x13, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x53, 0x0a, 0x18, 0x65, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x15, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x01, - 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, - 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, - 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x7c, 0x0a, 0x13, 0x55, - 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x32, 0x0a, 0x13, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x30, 0x0a, - 0x12, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x64, 0x5f, 0x6f, 0x72, 0x5f, 0x74, 0x61, 0x67, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, 0x4f, 0x72, 0x54, 0x61, 0x67, 0x22, - 0x50, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x33, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2b, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, + 0x76, 0x31, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, + 0x74, 0x70, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x23, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, + 0x76, 0x31, 0x2f, 0x75, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x81, 0x02, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x2f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, - 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x0a, 0x04, 0x76, 0x69, 0x65, 0x77, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, 0x76, 0x69, 0x65, 0x77, 0x22, 0x78, - 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, - 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x42, 0x75, 0x6c, - 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x2e, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x5e, - 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x07, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x72, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x66, - 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, - 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xc9, 0x01, 0x0a, 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x53, + 0x0a, 0x18, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x15, 0x65, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, - 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x22, 0xc1, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x6e, - 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x71, 0x0a, 0x18, 0x6d, - 0x61, 0x63, 0x6f, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, - 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x43, 0x68, 0x61, - 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, - 0x0a, 0x16, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x14, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, - 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x99, 0x02, 0x0a, 0x14, 0x45, 0x6e, 0x72, 0x6f, 0x6c, - 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x48, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, - 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, - 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x58, 0x0a, 0x0f, 0x6d, 0x61, 0x63, - 0x6f, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, - 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, - 0x65, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, - 0x6e, 0x67, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, - 0x65, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, - 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x70, 0x6d, 0x43, 0x68, - 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x22, 0x9c, 0x02, 0x0a, 0x10, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, - 0x0d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x41, 0x0a, 0x05, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x4f, 0x53, - 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x05, 0x6d, - 0x61, 0x63, 0x6f, 0x73, 0x12, 0x3b, 0x0a, 0x03, 0x74, 0x70, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x03, 0x74, 0x70, - 0x6d, 0x22, 0x4e, 0x0a, 0x13, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, + 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, + 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, + 0x6b, 0x22, 0x7c, 0x0a, 0x13, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x22, 0x3a, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x44, 0x65, 0x72, 0x22, 0x34, 0x0a, - 0x14, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, - 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, - 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, - 0x6e, 0x67, 0x65, 0x22, 0x3c, 0x0a, 0x1c, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x10, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x19, 0x0a, 0x07, 0x65, 0x6b, 0x5f, 0x63, 0x65, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06, 0x65, 0x6b, 0x43, 0x65, 0x72, - 0x74, 0x12, 0x17, 0x0a, 0x06, 0x65, 0x6b, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x05, 0x65, 0x6b, 0x4b, 0x65, 0x79, 0x12, 0x68, 0x0a, 0x16, 0x61, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x15, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x42, 0x04, 0x0a, 0x02, 0x65, 0x6b, 0x22, 0xad, 0x01, 0x0a, 0x18, 0x54, - 0x50, 0x4d, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, - 0x1f, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, - 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x11, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xa5, 0x01, 0x0a, 0x12, 0x54, + 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, + 0x32, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x49, 0x64, 0x22, 0x30, 0x0a, 0x12, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x09, 0x69, 0x64, 0x5f, + 0x6f, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x64, + 0x4f, 0x72, 0x54, 0x61, 0x67, 0x22, 0x50, 0x0a, 0x13, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x0a, 0x04, 0x76, + 0x69, 0x65, 0x77, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x56, 0x69, 0x65, 0x77, 0x52, 0x04, + 0x76, 0x69, 0x65, 0x77, 0x22, 0x78, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x83, + 0x01, 0x0a, 0x18, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x5f, 0x61, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x22, 0x5e, 0x0a, 0x19, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x4f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x22, 0x66, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, + 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0xc9, 0x01, 0x0a, + 0x1e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x0b, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xc1, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x3f, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, + 0x74, 0x12, 0x71, 0x0a, 0x18, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, + 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x61, + 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x6d, 0x61, + 0x63, 0x6f, 0x73, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x16, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, + 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, - 0x65, 0x12, 0x62, 0x0a, 0x14, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x63, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x52, 0x13, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x6e, - 0x63, 0x65, 0x22, 0x59, 0x0a, 0x16, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x65, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x0f, - 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x22, 0x99, 0x01, - 0x0a, 0x1a, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, - 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, - 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x13, 0x70, 0x6c, 0x61, 0x74, - 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x54, 0x50, 0x4d, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x12, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x19, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x14, 0x74, 0x70, 0x6d, + 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x99, 0x02, 0x0a, + 0x14, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x48, 0x00, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, + 0x58, 0x0a, 0x0f, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, + 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x61, 0x63, 0x6f, 0x73, + 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x52, 0x0a, 0x0d, 0x74, 0x70, 0x6d, + 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, + 0x0c, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x42, 0x09, 0x0a, + 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x9c, 0x02, 0x0a, 0x10, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x05, 0x6d, 0x61, 0x63, 0x6f, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x52, 0x05, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x12, 0x3b, 0x0a, 0x03, 0x74, 0x70, + 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x52, 0x03, 0x74, 0x70, 0x6d, 0x22, 0x4e, 0x0a, 0x13, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x37, + 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x22, 0x3a, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x4f, 0x53, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x24, 0x0a, + 0x0e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x64, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, + 0x44, 0x65, 0x72, 0x22, 0x34, 0x0a, 0x14, 0x4d, 0x61, 0x63, 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, + 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, + 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x22, 0x3c, 0x0a, 0x1c, 0x4d, 0x61, 0x63, + 0x4f, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xb6, 0x01, 0x0a, 0x10, 0x54, 0x50, 0x4d, 0x45, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x19, 0x0a, 0x07, + 0x65, 0x6b, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, + 0x06, 0x65, 0x6b, 0x43, 0x65, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x06, 0x65, 0x6b, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x65, 0x6b, 0x4b, 0x65, 0x79, + 0x12, 0x68, 0x0a, 0x16, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x52, 0x15, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x42, 0x04, 0x0a, 0x02, 0x65, 0x6b, + 0x22, 0xad, 0x01, 0x0a, 0x18, 0x54, 0x50, 0x4d, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x5f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x11, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x22, 0xa5, 0x01, 0x0a, 0x12, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x68, + 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x62, 0x0a, 0x14, 0x65, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x6d, - 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x11, 0x63, 0x68, 0x61, 0x6c, - 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, - 0x16, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x43, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x13, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, + 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x2b, 0x0a, 0x11, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x22, 0x59, 0x0a, 0x16, 0x54, 0x50, 0x4d, 0x45, + 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x22, 0x99, 0x01, 0x0a, 0x1a, 0x54, 0x50, 0x4d, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, + 0x0a, 0x13, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x12, 0x70, 0x6c, 0x61, + 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, + 0xd5, 0x02, 0x0a, 0x19, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x45, 0x0a, + 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x48, 0x00, 0x52, 0x04, + 0x69, 0x6e, 0x69, 0x74, 0x12, 0x6d, 0x0a, 0x12, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, + 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, - 0x52, 0x14, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0xb7, 0x02, 0x0a, 0x1a, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x54, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, - 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x48, 0x00, 0x52, 0x10, - 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x12, 0x5e, 0x0a, 0x0d, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, - 0x48, 0x00, 0x52, 0x0c, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, - 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xe4, 0x01, 0x0a, 0x16, - 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x56, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, 0x10, 0x75, 0x73, - 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x23, - 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, - 0x74, 0x61, 0x22, 0x4d, 0x0a, 0x1e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, - 0x65, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x10, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, - 0x65, 0x22, 0x89, 0x01, 0x0a, 0x26, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, - 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x13, - 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x52, 0x11, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, + 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, + 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x14, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, 0x6c, 0x6c, + 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xb7, 0x02, 0x0a, 0x1a, 0x41, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, + 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x12, 0x70, 0x6c, 0x61, 0x74, 0x66, - 0x6f, 0x72, 0x6d, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x22, 0x3b, 0x0a, - 0x1b, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x22, 0x43, 0x0a, 0x23, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, - 0xdf, 0x02, 0x0a, 0x14, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, + 0x00, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x11, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3d, 0x0a, - 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, - 0x72, 0x79, 0x45, 0x6e, 0x64, 0x48, 0x00, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x5b, 0x0a, 0x11, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x70, 0x73, 0x65, 0x72, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x73, 0x48, 0x00, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x5e, 0x0a, 0x0d, 0x74, 0x70, 0x6d, 0x5f, 0x63, 0x68, + 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x50, 0x4d, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0c, 0x74, 0x70, 0x6d, 0x43, 0x68, 0x61, + 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x22, 0xe4, 0x01, 0x0a, 0x16, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x69, 0x74, 0x12, 0x56, 0x0a, 0x11, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x54, 0x6f, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x11, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0b, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x0a, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x74, 0x61, 0x22, 0xdf, 0x02, 0x0a, 0x14, 0x53, 0x79, 0x6e, + 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, + 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x48, 0x00, 0x52, + 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3d, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x64, 0x48, 0x00, + 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x5b, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x70, 0x73, 0x65, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, + 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, + 0x00, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x54, 0x6f, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x12, 0x5b, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x74, 0x6f, + 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, + 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0f, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x54, 0x6f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, + 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x15, 0x53, + 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x03, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x03, + 0x61, 0x63, 0x6b, 0x12, 0x46, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x5f, 0x0a, 0x0f, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x54, 0x6f, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x22, 0x8a, 0x02, 0x0a, 0x15, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x03, 0x61, - 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, - 0x41, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x12, 0x46, 0x0a, 0x06, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x12, 0x5f, 0x0a, 0x0f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, + 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, + 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x42, 0x09, 0x0a, 0x07, + 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xac, 0x01, 0x0a, 0x12, 0x53, 0x79, 0x6e, 0x63, + 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3d, + 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x32, 0x0a, + 0x15, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, + 0x61, 0x63, 0x6b, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x04, 0x6d, + 0x6f, 0x64, 0x65, 0x52, 0x11, 0x6f, 0x6e, 0x5f, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x10, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, + 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, + 0x52, 0x18, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, + 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x22, 0x51, 0x0a, 0x14, 0x53, 0x79, + 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x12, 0x0a, + 0x10, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x63, + 0x6b, 0x22, 0x58, 0x0a, 0x13, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x58, 0x0a, 0x1b, 0x53, + 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, + 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x48, 0x00, 0x52, 0x0e, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xac, - 0x01, 0x0a, 0x12, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x3d, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, - 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, - 0x08, 0x03, 0x10, 0x04, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x52, 0x11, 0x6f, 0x6e, 0x5f, 0x6d, - 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x32, 0x0a, - 0x10, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x6e, - 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x52, 0x18, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, - 0x6c, 0x22, 0x51, 0x0a, 0x14, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, - 0x72, 0x79, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, - 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x41, 0x63, 0x6b, 0x22, 0x58, 0x0a, 0x13, 0x53, 0x79, 0x6e, 0x63, - 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, - 0x41, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x4f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x58, 0x0a, 0x1b, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, - 0x6f, 0x72, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x12, 0x39, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, - 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, 0x59, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x56, 0x69, 0x65, 0x77, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x56, - 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, - 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x44, 0x45, 0x56, 0x49, 0x43, - 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, - 0x02, 0x32, 0x89, 0x0b, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x72, 0x75, 0x73, - 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2a, + 0x59, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x56, 0x69, 0x65, 0x77, 0x12, 0x1b, 0x0a, + 0x17, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x45, + 0x56, 0x49, 0x43, 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x01, + 0x12, 0x18, 0x0a, 0x14, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x5f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x10, 0x02, 0x32, 0x89, 0x0b, 0x0a, 0x12, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x5d, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x5d, 0x0a, 0x0c, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, + 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x68, 0x0a, 0x0b, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, + 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, + 0x0a, 0x09, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x29, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x68, 0x0a, 0x0b, 0x46, - 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x68, - 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x2b, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x11, 0x42, 0x75, 0x6c, 0x6b, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x31, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x6f, 0x0a, 0x0c, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, - 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x81, 0x01, 0x0a, 0x12, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x32, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x79, 0x6e, - 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7a, 0x0a, 0x11, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x6e, 0x0a, - 0x0f, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x75, 0x6c, 0x6b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, + 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, + 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x42, 0x5a, 0x5a, - 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, - 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x6f, 0x0a, + 0x0c, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x81, + 0x01, 0x0a, 0x12, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, + 0x30, 0x01, 0x12, 0x72, 0x0a, 0x0d, 0x53, 0x79, 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, + 0x6f, 0x72, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x49, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x6e, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x42, 0x5a, 0x5a, 0x58, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, + 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3284,7 +3064,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_rawDescGZIP() []byte } var file_teleport_devicetrust_v1_devicetrust_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes = make([]protoimpl.MessageInfo, 41) +var file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes = make([]protoimpl.MessageInfo, 37) var file_teleport_devicetrust_v1_devicetrust_service_proto_goTypes = []interface{}{ (DeviceView)(0), // 0: teleport.devicetrust.v1.DeviceView (*CreateDeviceRequest)(nil), // 1: teleport.devicetrust.v1.CreateDeviceRequest @@ -3315,109 +3095,108 @@ var file_teleport_devicetrust_v1_devicetrust_service_proto_goTypes = []interface (*AuthenticateDeviceRequest)(nil), // 26: teleport.devicetrust.v1.AuthenticateDeviceRequest (*AuthenticateDeviceResponse)(nil), // 27: teleport.devicetrust.v1.AuthenticateDeviceResponse (*AuthenticateDeviceInit)(nil), // 28: teleport.devicetrust.v1.AuthenticateDeviceInit - (*TPMAuthenticateDeviceChallenge)(nil), // 29: teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge - (*TPMAuthenticateDeviceChallengeResponse)(nil), // 30: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse - (*AuthenticateDeviceChallenge)(nil), // 31: teleport.devicetrust.v1.AuthenticateDeviceChallenge - (*AuthenticateDeviceChallengeResponse)(nil), // 32: teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse - (*SyncInventoryRequest)(nil), // 33: teleport.devicetrust.v1.SyncInventoryRequest - (*SyncInventoryResponse)(nil), // 34: teleport.devicetrust.v1.SyncInventoryResponse - (*SyncInventoryStart)(nil), // 35: teleport.devicetrust.v1.SyncInventoryStart - (*SyncInventoryEnd)(nil), // 36: teleport.devicetrust.v1.SyncInventoryEnd - (*SyncInventoryDevices)(nil), // 37: teleport.devicetrust.v1.SyncInventoryDevices - (*SyncInventoryAck)(nil), // 38: teleport.devicetrust.v1.SyncInventoryAck - (*SyncInventoryResult)(nil), // 39: teleport.devicetrust.v1.SyncInventoryResult - (*SyncInventoryMissingDevices)(nil), // 40: teleport.devicetrust.v1.SyncInventoryMissingDevices - (*GetDevicesUsageRequest)(nil), // 41: teleport.devicetrust.v1.GetDevicesUsageRequest - (*Device)(nil), // 42: teleport.devicetrust.v1.Device - (*timestamppb.Timestamp)(nil), // 43: google.protobuf.Timestamp - (*fieldmaskpb.FieldMask)(nil), // 44: google.protobuf.FieldMask - (*status.Status)(nil), // 45: google.rpc.Status - (*DeviceCollectedData)(nil), // 46: teleport.devicetrust.v1.DeviceCollectedData - (*TPMPlatformParameters)(nil), // 47: teleport.devicetrust.v1.TPMPlatformParameters - (*UserCertificates)(nil), // 48: teleport.devicetrust.v1.UserCertificates + (*SyncInventoryRequest)(nil), // 29: teleport.devicetrust.v1.SyncInventoryRequest + (*SyncInventoryResponse)(nil), // 30: teleport.devicetrust.v1.SyncInventoryResponse + (*SyncInventoryStart)(nil), // 31: teleport.devicetrust.v1.SyncInventoryStart + (*SyncInventoryEnd)(nil), // 32: teleport.devicetrust.v1.SyncInventoryEnd + (*SyncInventoryDevices)(nil), // 33: teleport.devicetrust.v1.SyncInventoryDevices + (*SyncInventoryAck)(nil), // 34: teleport.devicetrust.v1.SyncInventoryAck + (*SyncInventoryResult)(nil), // 35: teleport.devicetrust.v1.SyncInventoryResult + (*SyncInventoryMissingDevices)(nil), // 36: teleport.devicetrust.v1.SyncInventoryMissingDevices + (*GetDevicesUsageRequest)(nil), // 37: teleport.devicetrust.v1.GetDevicesUsageRequest + (*Device)(nil), // 38: teleport.devicetrust.v1.Device + (*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp + (*fieldmaskpb.FieldMask)(nil), // 40: google.protobuf.FieldMask + (*status.Status)(nil), // 41: google.rpc.Status + (*DeviceCollectedData)(nil), // 42: teleport.devicetrust.v1.DeviceCollectedData + (*TPMPlatformParameters)(nil), // 43: teleport.devicetrust.v1.TPMPlatformParameters + (*AuthenticateDeviceChallengeResponse)(nil), // 44: teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse + (*TPMAuthenticateDeviceChallengeResponse)(nil), // 45: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse + (*AuthenticateDeviceChallenge)(nil), // 46: teleport.devicetrust.v1.AuthenticateDeviceChallenge + (*UserCertificates)(nil), // 47: teleport.devicetrust.v1.UserCertificates + (*TPMAuthenticateDeviceChallenge)(nil), // 48: teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge (*DeviceSource)(nil), // 49: teleport.devicetrust.v1.DeviceSource (*emptypb.Empty)(nil), // 50: google.protobuf.Empty (*DeviceEnrollToken)(nil), // 51: teleport.devicetrust.v1.DeviceEnrollToken (*DevicesUsage)(nil), // 52: teleport.devicetrust.v1.DevicesUsage } var file_teleport_devicetrust_v1_devicetrust_service_proto_depIdxs = []int32{ - 42, // 0: teleport.devicetrust.v1.CreateDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device - 43, // 1: teleport.devicetrust.v1.CreateDeviceRequest.enroll_token_expire_time:type_name -> google.protobuf.Timestamp - 42, // 2: teleport.devicetrust.v1.UpdateDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device - 44, // 3: teleport.devicetrust.v1.UpdateDeviceRequest.update_mask:type_name -> google.protobuf.FieldMask - 42, // 4: teleport.devicetrust.v1.UpsertDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device - 42, // 5: teleport.devicetrust.v1.FindDevicesResponse.devices:type_name -> teleport.devicetrust.v1.Device + 38, // 0: teleport.devicetrust.v1.CreateDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device + 39, // 1: teleport.devicetrust.v1.CreateDeviceRequest.enroll_token_expire_time:type_name -> google.protobuf.Timestamp + 38, // 2: teleport.devicetrust.v1.UpdateDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device + 40, // 3: teleport.devicetrust.v1.UpdateDeviceRequest.update_mask:type_name -> google.protobuf.FieldMask + 38, // 4: teleport.devicetrust.v1.UpsertDeviceRequest.device:type_name -> teleport.devicetrust.v1.Device + 38, // 5: teleport.devicetrust.v1.FindDevicesResponse.devices:type_name -> teleport.devicetrust.v1.Device 0, // 6: teleport.devicetrust.v1.ListDevicesRequest.view:type_name -> teleport.devicetrust.v1.DeviceView - 42, // 7: teleport.devicetrust.v1.ListDevicesResponse.devices:type_name -> teleport.devicetrust.v1.Device - 42, // 8: teleport.devicetrust.v1.BulkCreateDevicesRequest.devices:type_name -> teleport.devicetrust.v1.Device + 38, // 7: teleport.devicetrust.v1.ListDevicesResponse.devices:type_name -> teleport.devicetrust.v1.Device + 38, // 8: teleport.devicetrust.v1.BulkCreateDevicesRequest.devices:type_name -> teleport.devicetrust.v1.Device 12, // 9: teleport.devicetrust.v1.BulkCreateDevicesResponse.devices:type_name -> teleport.devicetrust.v1.DeviceOrStatus - 45, // 10: teleport.devicetrust.v1.DeviceOrStatus.status:type_name -> google.rpc.Status - 46, // 11: teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData - 43, // 12: teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest.expire_time:type_name -> google.protobuf.Timestamp + 41, // 10: teleport.devicetrust.v1.DeviceOrStatus.status:type_name -> google.rpc.Status + 42, // 11: teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData + 39, // 12: teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest.expire_time:type_name -> google.protobuf.Timestamp 16, // 13: teleport.devicetrust.v1.EnrollDeviceRequest.init:type_name -> teleport.devicetrust.v1.EnrollDeviceInit 20, // 14: teleport.devicetrust.v1.EnrollDeviceRequest.macos_challenge_response:type_name -> teleport.devicetrust.v1.MacOSEnrollChallengeResponse 25, // 15: teleport.devicetrust.v1.EnrollDeviceRequest.tpm_challenge_response:type_name -> teleport.devicetrust.v1.TPMEnrollChallengeResponse 17, // 16: teleport.devicetrust.v1.EnrollDeviceResponse.success:type_name -> teleport.devicetrust.v1.EnrollDeviceSuccess 19, // 17: teleport.devicetrust.v1.EnrollDeviceResponse.macos_challenge:type_name -> teleport.devicetrust.v1.MacOSEnrollChallenge 23, // 18: teleport.devicetrust.v1.EnrollDeviceResponse.tpm_challenge:type_name -> teleport.devicetrust.v1.TPMEnrollChallenge - 46, // 19: teleport.devicetrust.v1.EnrollDeviceInit.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData + 42, // 19: teleport.devicetrust.v1.EnrollDeviceInit.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData 18, // 20: teleport.devicetrust.v1.EnrollDeviceInit.macos:type_name -> teleport.devicetrust.v1.MacOSEnrollPayload 21, // 21: teleport.devicetrust.v1.EnrollDeviceInit.tpm:type_name -> teleport.devicetrust.v1.TPMEnrollPayload - 42, // 22: teleport.devicetrust.v1.EnrollDeviceSuccess.device:type_name -> teleport.devicetrust.v1.Device + 38, // 22: teleport.devicetrust.v1.EnrollDeviceSuccess.device:type_name -> teleport.devicetrust.v1.Device 22, // 23: teleport.devicetrust.v1.TPMEnrollPayload.attestation_parameters:type_name -> teleport.devicetrust.v1.TPMAttestationParameters 24, // 24: teleport.devicetrust.v1.TPMEnrollChallenge.encrypted_credential:type_name -> teleport.devicetrust.v1.TPMEncryptedCredential - 47, // 25: teleport.devicetrust.v1.TPMEnrollChallengeResponse.platform_parameters:type_name -> teleport.devicetrust.v1.TPMPlatformParameters + 43, // 25: teleport.devicetrust.v1.TPMEnrollChallengeResponse.platform_parameters:type_name -> teleport.devicetrust.v1.TPMPlatformParameters 28, // 26: teleport.devicetrust.v1.AuthenticateDeviceRequest.init:type_name -> teleport.devicetrust.v1.AuthenticateDeviceInit - 32, // 27: teleport.devicetrust.v1.AuthenticateDeviceRequest.challenge_response:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse - 30, // 28: teleport.devicetrust.v1.AuthenticateDeviceRequest.tpm_challenge_response:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse - 31, // 29: teleport.devicetrust.v1.AuthenticateDeviceResponse.challenge:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallenge - 48, // 30: teleport.devicetrust.v1.AuthenticateDeviceResponse.user_certificates:type_name -> teleport.devicetrust.v1.UserCertificates - 29, // 31: teleport.devicetrust.v1.AuthenticateDeviceResponse.tpm_challenge:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge - 48, // 32: teleport.devicetrust.v1.AuthenticateDeviceInit.user_certificates:type_name -> teleport.devicetrust.v1.UserCertificates - 46, // 33: teleport.devicetrust.v1.AuthenticateDeviceInit.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData - 47, // 34: teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse.platform_parameters:type_name -> teleport.devicetrust.v1.TPMPlatformParameters - 35, // 35: teleport.devicetrust.v1.SyncInventoryRequest.start:type_name -> teleport.devicetrust.v1.SyncInventoryStart - 36, // 36: teleport.devicetrust.v1.SyncInventoryRequest.end:type_name -> teleport.devicetrust.v1.SyncInventoryEnd - 37, // 37: teleport.devicetrust.v1.SyncInventoryRequest.devices_to_upsert:type_name -> teleport.devicetrust.v1.SyncInventoryDevices - 37, // 38: teleport.devicetrust.v1.SyncInventoryRequest.devices_to_remove:type_name -> teleport.devicetrust.v1.SyncInventoryDevices - 38, // 39: teleport.devicetrust.v1.SyncInventoryResponse.ack:type_name -> teleport.devicetrust.v1.SyncInventoryAck - 39, // 40: teleport.devicetrust.v1.SyncInventoryResponse.result:type_name -> teleport.devicetrust.v1.SyncInventoryResult - 40, // 41: teleport.devicetrust.v1.SyncInventoryResponse.missing_devices:type_name -> teleport.devicetrust.v1.SyncInventoryMissingDevices - 49, // 42: teleport.devicetrust.v1.SyncInventoryStart.source:type_name -> teleport.devicetrust.v1.DeviceSource - 42, // 43: teleport.devicetrust.v1.SyncInventoryDevices.devices:type_name -> teleport.devicetrust.v1.Device - 12, // 44: teleport.devicetrust.v1.SyncInventoryResult.devices:type_name -> teleport.devicetrust.v1.DeviceOrStatus - 42, // 45: teleport.devicetrust.v1.SyncInventoryMissingDevices.devices:type_name -> teleport.devicetrust.v1.Device - 1, // 46: teleport.devicetrust.v1.DeviceTrustService.CreateDevice:input_type -> teleport.devicetrust.v1.CreateDeviceRequest - 2, // 47: teleport.devicetrust.v1.DeviceTrustService.UpdateDevice:input_type -> teleport.devicetrust.v1.UpdateDeviceRequest - 3, // 48: teleport.devicetrust.v1.DeviceTrustService.UpsertDevice:input_type -> teleport.devicetrust.v1.UpsertDeviceRequest - 4, // 49: teleport.devicetrust.v1.DeviceTrustService.DeleteDevice:input_type -> teleport.devicetrust.v1.DeleteDeviceRequest - 5, // 50: teleport.devicetrust.v1.DeviceTrustService.FindDevices:input_type -> teleport.devicetrust.v1.FindDevicesRequest - 7, // 51: teleport.devicetrust.v1.DeviceTrustService.GetDevice:input_type -> teleport.devicetrust.v1.GetDeviceRequest - 8, // 52: teleport.devicetrust.v1.DeviceTrustService.ListDevices:input_type -> teleport.devicetrust.v1.ListDevicesRequest - 10, // 53: teleport.devicetrust.v1.DeviceTrustService.BulkCreateDevices:input_type -> teleport.devicetrust.v1.BulkCreateDevicesRequest - 13, // 54: teleport.devicetrust.v1.DeviceTrustService.CreateDeviceEnrollToken:input_type -> teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest - 14, // 55: teleport.devicetrust.v1.DeviceTrustService.EnrollDevice:input_type -> teleport.devicetrust.v1.EnrollDeviceRequest - 26, // 56: teleport.devicetrust.v1.DeviceTrustService.AuthenticateDevice:input_type -> teleport.devicetrust.v1.AuthenticateDeviceRequest - 33, // 57: teleport.devicetrust.v1.DeviceTrustService.SyncInventory:input_type -> teleport.devicetrust.v1.SyncInventoryRequest - 41, // 58: teleport.devicetrust.v1.DeviceTrustService.GetDevicesUsage:input_type -> teleport.devicetrust.v1.GetDevicesUsageRequest - 42, // 59: teleport.devicetrust.v1.DeviceTrustService.CreateDevice:output_type -> teleport.devicetrust.v1.Device - 42, // 60: teleport.devicetrust.v1.DeviceTrustService.UpdateDevice:output_type -> teleport.devicetrust.v1.Device - 42, // 61: teleport.devicetrust.v1.DeviceTrustService.UpsertDevice:output_type -> teleport.devicetrust.v1.Device - 50, // 62: teleport.devicetrust.v1.DeviceTrustService.DeleteDevice:output_type -> google.protobuf.Empty - 6, // 63: teleport.devicetrust.v1.DeviceTrustService.FindDevices:output_type -> teleport.devicetrust.v1.FindDevicesResponse - 42, // 64: teleport.devicetrust.v1.DeviceTrustService.GetDevice:output_type -> teleport.devicetrust.v1.Device - 9, // 65: teleport.devicetrust.v1.DeviceTrustService.ListDevices:output_type -> teleport.devicetrust.v1.ListDevicesResponse - 11, // 66: teleport.devicetrust.v1.DeviceTrustService.BulkCreateDevices:output_type -> teleport.devicetrust.v1.BulkCreateDevicesResponse - 51, // 67: teleport.devicetrust.v1.DeviceTrustService.CreateDeviceEnrollToken:output_type -> teleport.devicetrust.v1.DeviceEnrollToken - 15, // 68: teleport.devicetrust.v1.DeviceTrustService.EnrollDevice:output_type -> teleport.devicetrust.v1.EnrollDeviceResponse - 27, // 69: teleport.devicetrust.v1.DeviceTrustService.AuthenticateDevice:output_type -> teleport.devicetrust.v1.AuthenticateDeviceResponse - 34, // 70: teleport.devicetrust.v1.DeviceTrustService.SyncInventory:output_type -> teleport.devicetrust.v1.SyncInventoryResponse - 52, // 71: teleport.devicetrust.v1.DeviceTrustService.GetDevicesUsage:output_type -> teleport.devicetrust.v1.DevicesUsage - 59, // [59:72] is the sub-list for method output_type - 46, // [46:59] is the sub-list for method input_type - 46, // [46:46] is the sub-list for extension type_name - 46, // [46:46] is the sub-list for extension extendee - 0, // [0:46] is the sub-list for field type_name + 44, // 27: teleport.devicetrust.v1.AuthenticateDeviceRequest.challenge_response:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallengeResponse + 45, // 28: teleport.devicetrust.v1.AuthenticateDeviceRequest.tpm_challenge_response:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallengeResponse + 46, // 29: teleport.devicetrust.v1.AuthenticateDeviceResponse.challenge:type_name -> teleport.devicetrust.v1.AuthenticateDeviceChallenge + 47, // 30: teleport.devicetrust.v1.AuthenticateDeviceResponse.user_certificates:type_name -> teleport.devicetrust.v1.UserCertificates + 48, // 31: teleport.devicetrust.v1.AuthenticateDeviceResponse.tpm_challenge:type_name -> teleport.devicetrust.v1.TPMAuthenticateDeviceChallenge + 47, // 32: teleport.devicetrust.v1.AuthenticateDeviceInit.user_certificates:type_name -> teleport.devicetrust.v1.UserCertificates + 42, // 33: teleport.devicetrust.v1.AuthenticateDeviceInit.device_data:type_name -> teleport.devicetrust.v1.DeviceCollectedData + 31, // 34: teleport.devicetrust.v1.SyncInventoryRequest.start:type_name -> teleport.devicetrust.v1.SyncInventoryStart + 32, // 35: teleport.devicetrust.v1.SyncInventoryRequest.end:type_name -> teleport.devicetrust.v1.SyncInventoryEnd + 33, // 36: teleport.devicetrust.v1.SyncInventoryRequest.devices_to_upsert:type_name -> teleport.devicetrust.v1.SyncInventoryDevices + 33, // 37: teleport.devicetrust.v1.SyncInventoryRequest.devices_to_remove:type_name -> teleport.devicetrust.v1.SyncInventoryDevices + 34, // 38: teleport.devicetrust.v1.SyncInventoryResponse.ack:type_name -> teleport.devicetrust.v1.SyncInventoryAck + 35, // 39: teleport.devicetrust.v1.SyncInventoryResponse.result:type_name -> teleport.devicetrust.v1.SyncInventoryResult + 36, // 40: teleport.devicetrust.v1.SyncInventoryResponse.missing_devices:type_name -> teleport.devicetrust.v1.SyncInventoryMissingDevices + 49, // 41: teleport.devicetrust.v1.SyncInventoryStart.source:type_name -> teleport.devicetrust.v1.DeviceSource + 38, // 42: teleport.devicetrust.v1.SyncInventoryDevices.devices:type_name -> teleport.devicetrust.v1.Device + 12, // 43: teleport.devicetrust.v1.SyncInventoryResult.devices:type_name -> teleport.devicetrust.v1.DeviceOrStatus + 38, // 44: teleport.devicetrust.v1.SyncInventoryMissingDevices.devices:type_name -> teleport.devicetrust.v1.Device + 1, // 45: teleport.devicetrust.v1.DeviceTrustService.CreateDevice:input_type -> teleport.devicetrust.v1.CreateDeviceRequest + 2, // 46: teleport.devicetrust.v1.DeviceTrustService.UpdateDevice:input_type -> teleport.devicetrust.v1.UpdateDeviceRequest + 3, // 47: teleport.devicetrust.v1.DeviceTrustService.UpsertDevice:input_type -> teleport.devicetrust.v1.UpsertDeviceRequest + 4, // 48: teleport.devicetrust.v1.DeviceTrustService.DeleteDevice:input_type -> teleport.devicetrust.v1.DeleteDeviceRequest + 5, // 49: teleport.devicetrust.v1.DeviceTrustService.FindDevices:input_type -> teleport.devicetrust.v1.FindDevicesRequest + 7, // 50: teleport.devicetrust.v1.DeviceTrustService.GetDevice:input_type -> teleport.devicetrust.v1.GetDeviceRequest + 8, // 51: teleport.devicetrust.v1.DeviceTrustService.ListDevices:input_type -> teleport.devicetrust.v1.ListDevicesRequest + 10, // 52: teleport.devicetrust.v1.DeviceTrustService.BulkCreateDevices:input_type -> teleport.devicetrust.v1.BulkCreateDevicesRequest + 13, // 53: teleport.devicetrust.v1.DeviceTrustService.CreateDeviceEnrollToken:input_type -> teleport.devicetrust.v1.CreateDeviceEnrollTokenRequest + 14, // 54: teleport.devicetrust.v1.DeviceTrustService.EnrollDevice:input_type -> teleport.devicetrust.v1.EnrollDeviceRequest + 26, // 55: teleport.devicetrust.v1.DeviceTrustService.AuthenticateDevice:input_type -> teleport.devicetrust.v1.AuthenticateDeviceRequest + 29, // 56: teleport.devicetrust.v1.DeviceTrustService.SyncInventory:input_type -> teleport.devicetrust.v1.SyncInventoryRequest + 37, // 57: teleport.devicetrust.v1.DeviceTrustService.GetDevicesUsage:input_type -> teleport.devicetrust.v1.GetDevicesUsageRequest + 38, // 58: teleport.devicetrust.v1.DeviceTrustService.CreateDevice:output_type -> teleport.devicetrust.v1.Device + 38, // 59: teleport.devicetrust.v1.DeviceTrustService.UpdateDevice:output_type -> teleport.devicetrust.v1.Device + 38, // 60: teleport.devicetrust.v1.DeviceTrustService.UpsertDevice:output_type -> teleport.devicetrust.v1.Device + 50, // 61: teleport.devicetrust.v1.DeviceTrustService.DeleteDevice:output_type -> google.protobuf.Empty + 6, // 62: teleport.devicetrust.v1.DeviceTrustService.FindDevices:output_type -> teleport.devicetrust.v1.FindDevicesResponse + 38, // 63: teleport.devicetrust.v1.DeviceTrustService.GetDevice:output_type -> teleport.devicetrust.v1.Device + 9, // 64: teleport.devicetrust.v1.DeviceTrustService.ListDevices:output_type -> teleport.devicetrust.v1.ListDevicesResponse + 11, // 65: teleport.devicetrust.v1.DeviceTrustService.BulkCreateDevices:output_type -> teleport.devicetrust.v1.BulkCreateDevicesResponse + 51, // 66: teleport.devicetrust.v1.DeviceTrustService.CreateDeviceEnrollToken:output_type -> teleport.devicetrust.v1.DeviceEnrollToken + 15, // 67: teleport.devicetrust.v1.DeviceTrustService.EnrollDevice:output_type -> teleport.devicetrust.v1.EnrollDeviceResponse + 27, // 68: teleport.devicetrust.v1.DeviceTrustService.AuthenticateDevice:output_type -> teleport.devicetrust.v1.AuthenticateDeviceResponse + 30, // 69: teleport.devicetrust.v1.DeviceTrustService.SyncInventory:output_type -> teleport.devicetrust.v1.SyncInventoryResponse + 52, // 70: teleport.devicetrust.v1.DeviceTrustService.GetDevicesUsage:output_type -> teleport.devicetrust.v1.DevicesUsage + 58, // [58:71] is the sub-list for method output_type + 45, // [45:58] is the sub-list for method input_type + 45, // [45:45] is the sub-list for extension type_name + 45, // [45:45] is the sub-list for extension extendee + 0, // [0:45] is the sub-list for field type_name } func init() { file_teleport_devicetrust_v1_devicetrust_service_proto_init() } @@ -3425,6 +3204,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { if File_teleport_devicetrust_v1_devicetrust_service_proto != nil { return } + file_teleport_devicetrust_v1_authenticate_challenge_proto_init() file_teleport_devicetrust_v1_device_proto_init() file_teleport_devicetrust_v1_device_collected_data_proto_init() file_teleport_devicetrust_v1_device_enroll_token_proto_init() @@ -3770,54 +3550,6 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { } } file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TPMAuthenticateDeviceChallenge); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TPMAuthenticateDeviceChallengeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthenticateDeviceChallenge); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthenticateDeviceChallengeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryRequest); i { case 0: return &v.state @@ -3829,7 +3561,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryResponse); i { case 0: return &v.state @@ -3841,7 +3573,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryStart); i { case 0: return &v.state @@ -3853,7 +3585,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryEnd); i { case 0: return &v.state @@ -3865,7 +3597,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryDevices); i { case 0: return &v.state @@ -3877,7 +3609,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryAck); i { case 0: return &v.state @@ -3889,7 +3621,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryResult); i { case 0: return &v.state @@ -3901,7 +3633,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SyncInventoryMissingDevices); i { case 0: return &v.state @@ -3913,7 +3645,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { return nil } } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetDevicesUsageRequest); i { case 0: return &v.state @@ -3950,13 +3682,13 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { (*AuthenticateDeviceResponse_UserCertificates)(nil), (*AuthenticateDeviceResponse_TpmChallenge)(nil), } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[32].OneofWrappers = []interface{}{ + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[28].OneofWrappers = []interface{}{ (*SyncInventoryRequest_Start)(nil), (*SyncInventoryRequest_End)(nil), (*SyncInventoryRequest_DevicesToUpsert)(nil), (*SyncInventoryRequest_DevicesToRemove)(nil), } - file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[33].OneofWrappers = []interface{}{ + file_teleport_devicetrust_v1_devicetrust_service_proto_msgTypes[29].OneofWrappers = []interface{}{ (*SyncInventoryResponse_Ack)(nil), (*SyncInventoryResponse_Result)(nil), (*SyncInventoryResponse_MissingDevices)(nil), @@ -3967,7 +3699,7 @@ func file_teleport_devicetrust_v1_devicetrust_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_devicetrust_v1_devicetrust_service_proto_rawDesc, NumEnums: 1, - NumMessages: 41, + NumMessages: 37, NumExtensions: 0, NumServices: 1, }, diff --git a/api/proto/teleport/access_graph/v1/authorized_key.proto b/api/proto/teleport/access_graph/v1/authorized_key.proto new file mode 100644 index 0000000000000..1795d7a415a58 --- /dev/null +++ b/api/proto/teleport/access_graph/v1/authorized_key.proto @@ -0,0 +1,52 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.access_graph.v1; + +import "teleport/header/v1/metadata.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1;accessgraphv1"; + +// The `AuthorizedKey` message represents an authorized key entry for a specific local user. +// These authorized keys are generated by the server when a particular SSH AuthorizedKey is granted access to a user on the node. +message AuthorizedKey { + // metadata is the AuthorizedKey's metadata. + teleport.header.v1.Metadata metadata = 1; + // kind is a resource kind. + string kind = 2; + // sub_kind is an optional resource sub kind, used in some resources. + string sub_kind = 3; + // version is version. + string version = 4; + // Spec is an AuthorizedKey specification. + AuthorizedKeySpec spec = 5; +} + +// AuthorizedKeySpec is the authorized key spec. +message AuthorizedKeySpec { + // host_id is the node identifier and must match the credentials used. + string host_id = 1; + // key_fingerprint is the SHA256 SSH public key fingerprint. + string key_fingerprint = 2; + // host_user is the user who can be accessed using the fingerprint above. + string host_user = 3; + // key_comment is the authorized key's comment. + // Authorized keys consist of the following space-separated fields: + // options, keytype, base64-encoded key, comment. The options field is optional. + string key_comment = 4; + // key_type is the ssh's key type. + string key_type = 5; +} diff --git a/api/proto/teleport/access_graph/v1/private_key.proto b/api/proto/teleport/access_graph/v1/private_key.proto new file mode 100644 index 0000000000000..239c515d89044 --- /dev/null +++ b/api/proto/teleport/access_graph/v1/private_key.proto @@ -0,0 +1,67 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.access_graph.v1; + +import "teleport/header/v1/metadata.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1;accessgraphv1"; + +// The `PrivateKey` message represents a private key entry for a specific local user. +// It serves as a reference to a private key located on a user's laptop. Note that it *NEVER* contains the private key itself. +// Instead, it stores metadata related to the key, including the fingerprint of the public key, the device trust identifier, and the public key mode. +// The Teleport Access Graph uses this metadata to assess whether a particular private key is authorized to access a user on the node without using Teleport. +message PrivateKey { + // metadata is the PrivateKey's metadata. + teleport.header.v1.Metadata metadata = 1; + // kind is a resource kind. + string kind = 2; + // sub_kind is an optional resource sub kind, used in some resources. + string sub_kind = 3; + // version is version. + string version = 4; + // Spec is a PrivateKey specification. + PrivateKeySpec spec = 5; +} + +// PrivateKeySpec is the private key spec. +message PrivateKeySpec { + // device_id is the device trust identifier of the device that owns the key. + string device_id = 1; + // public_key_fingerprint is the SHA256 of the SSH public key corresponding to + // the private key. + string public_key_fingerprint = 2; + // public_key_mode is the public key mode. + PublicKeyMode public_key_mode = 3; +} + +// PublicKeyMode is the mode of the public key. +// The public key can be derived from the private key, stored in a separate file, or the private key was password protected +// and we could not extract the public key from it or from the file. +enum PublicKeyMode { + // PUBLIC_KEY_MODE_UNSPECIFIED is an invalid state. + PUBLIC_KEY_MODE_UNSPECIFIED = 0; + // PUBLIC_KEY_MODE_DERIVED is the state where the public key is derived from the private key. + PUBLIC_KEY_MODE_DERIVED = 1; + // PUBLIC_KEY_MODE_PUB_FILE is a state where the public key is stored in a separate file from the private key. + // The private key is password protected and we could not extract the public key from it. + // This mode is used when the private key is password protected and there is a .pub file next to the private key + // that contains the public key. + PUBLIC_KEY_MODE_PUB_FILE = 2; + // PUBLIC_KEY_MODE_PROTECTED is a state where the private key is password protected and we could not extract the public key from it + // or from the .pub file. + PUBLIC_KEY_MODE_PROTECTED = 3; +} diff --git a/api/proto/teleport/access_graph/v1/secrets_service.proto b/api/proto/teleport/access_graph/v1/secrets_service.proto new file mode 100644 index 0000000000000..7c2b3d49e6e76 --- /dev/null +++ b/api/proto/teleport/access_graph/v1/secrets_service.proto @@ -0,0 +1,101 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.access_graph.v1; + +import "teleport/access_graph/v1/authorized_key.proto"; +import "teleport/access_graph/v1/private_key.proto"; +import "teleport/devicetrust/v1/assert.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1;accessgraphv1"; + +// SecretsScannerService provides methods for Access Graph Secret Scanner functionality. +service SecretsScannerService { + // ReportAuthorizedKeys is used by Teleport SSH nodes to report authorized keys + // that could be used to bypass Teleport. + // The client (Teleport SSH Node) should authenticate using the certificate-key pair signed by Teleport HostCA. + rpc ReportAuthorizedKeys(stream ReportAuthorizedKeysRequest) returns (stream ReportAuthorizedKeysResponse) {} + + // ReportSecrets is used by trusted devices to report secrets found on the host that could be used to bypass Teleport. + // The client (device) should first authenticate using the [ReportSecretsRequest.device_assertion] flow. Please refer to + // the [teleport.devicetrust.v1.AssertDeviceRequest] and [teleport.devicetrust.v1.AssertDeviceResponse] messages for more details. + // + // Once the device is asserted, the client can send the secrets using the [ReportSecretsRequest.private_keys] field + // and then close the client side of the stream. + // + // -> ReportSecrets (client) [1 or more] + // -> CloseStream (client) + // <- TerminateStream (server) + // + // Any failure in the assertion ceremony will result in the stream being terminated by the server. All secrets + // reported by the client before the assertion terminates will be ignored and result in the stream being terminated. + rpc ReportSecrets(stream ReportSecretsRequest) returns (stream ReportSecretsResponse) {} +} + +// ReportAuthorizedKeysRequest is used by Teleport nodes to report authorized keys +// that could be used to bypass Teleport. +message ReportAuthorizedKeysRequest { + // keys is a list of authorized keys that could be used to bypass Teleport. + repeated teleport.access_graph.v1.AuthorizedKey keys = 1; + // operation indicates the operation that the client wants to perform. + OperationType operation = 2; +} + +// ReportAuthorizedKeysResponse is the response from ReportAuthorizedKeys +// RPC method. +message ReportAuthorizedKeysResponse {} + +// ReportSecretsRequest is used by trusted devices to report secrets found on the host +// that could be used to bypass Teleport. +message ReportSecretsRequest { + oneof payload { + // The device should initiate the device assertion ceremony by sending the + // AssertDeviceRequest. Please refer to the [teleport.devicetrust.v1.AssertDeviceRequest] + // message for more details. + teleport.devicetrust.v1.AssertDeviceRequest device_assertion = 1; + // private_keys is a list of private keys that were found on the device. + ReportPrivateKeys private_keys = 4; + } +} + +// ReportPrivateKeys is used by trusted devices to report private keys found on the host +// that could be used to bypass Teleport. +message ReportPrivateKeys { + // keys is a list of private keys that could be used to bypass Teleport. + repeated teleport.access_graph.v1.PrivateKey keys = 1; +} + +// ReportSecretsResponse is the response from the ReportSecrets +// RPC method. +message ReportSecretsResponse { + oneof payload { + // device_assertion is the response from the device assertion ceremony. + // Please refer to the [teleport.devicetrust.v1.AssertDeviceResponse] + // message for more details + teleport.devicetrust.v1.AssertDeviceResponse device_assertion = 1; + } +} + +// OperationType is an enum that indicates the operation that the client wants to perform. +enum OperationType { + // OPERATION_TYPE_UNSPECIFIED is an unknown operation. + OPERATION_TYPE_UNSPECIFIED = 0; + // OPERATION_TYPE_ADD is an operation that indicates that the client wants to add keys to the list. + OPERATION_TYPE_ADD = 1; + // OPERATION_TYPE_SYNC is an operation that indicates that the client has sent all the keys and + // the server can proceed with the analysis. + OPERATION_TYPE_SYNC = 2; +} diff --git a/api/proto/teleport/clusterconfig/v1/access_graph.proto b/api/proto/teleport/clusterconfig/v1/access_graph.proto index 525f88d030bac..147aa9261a07b 100644 --- a/api/proto/teleport/clusterconfig/v1/access_graph.proto +++ b/api/proto/teleport/clusterconfig/v1/access_graph.proto @@ -30,4 +30,12 @@ message AccessGraphConfig { // insecure is a flag that indicates whether the access graph service should // skip verifying the server's certificate chain and host name. bool insecure = 4; + // secrets_scan_config is used to configure the parameters for the secrets scanning functionality. + AccessGraphSecretsScanConfiguration secrets_scan_config = 5; +} + +// AccessGraphSecretsScanConfiguration controls the secrets scanning service parameters. +message AccessGraphSecretsScanConfiguration { + // ssh_scan_enabled indicates if the SSH scan feature is enabled for the cluster. + bool ssh_scan_enabled = 1; } diff --git a/api/proto/teleport/clusterconfig/v1/access_graph_settings.proto b/api/proto/teleport/clusterconfig/v1/access_graph_settings.proto new file mode 100644 index 0000000000000..3f0e99639f51e --- /dev/null +++ b/api/proto/teleport/clusterconfig/v1/access_graph_settings.proto @@ -0,0 +1,51 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.clusterconfig.v1; + +import "teleport/header/v1/metadata.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1;clusterconfigv1"; + +// AccessGraphSettings holds dynamic configuration settings for the Access Graph service. +message AccessGraphSettings { + // kind is the kind of the resource. + string kind = 1; + // sub_kind is the sub kind of the resource. + string sub_kind = 2; + // version is the version of the resource. + string version = 3; + // metadata is the metadata of the resource. + teleport.header.v1.Metadata metadata = 4; + // spec is the spec of the resource. + AccessGraphSettingsSpec spec = 5; +} + +// AccessGraphSettingsSpec is the spec for the Access Graph service configuration settings. +message AccessGraphSettingsSpec { + // secrets_scan_config is used to configure the parameters for the secrets scanning functionality. + AccessGraphSecretsScanConfig secrets_scan_config = 1; +} + +// AccessGraphSecretsScanConfig is used to configure the parameters for the secrets scanning functionality. +enum AccessGraphSecretsScanConfig { + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED is an unknown secrets scan configuration. + ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED = 0; + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED is a disabled secrets scan configuration. + ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED = 1; + // ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED is an enabled secrets scan configuration. + ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED = 2; +} diff --git a/api/proto/teleport/clusterconfig/v1/clusterconfig_service.proto b/api/proto/teleport/clusterconfig/v1/clusterconfig_service.proto index f9f12fcbf8ecc..dbd23a636c81b 100644 --- a/api/proto/teleport/clusterconfig/v1/clusterconfig_service.proto +++ b/api/proto/teleport/clusterconfig/v1/clusterconfig_service.proto @@ -17,6 +17,7 @@ syntax = "proto3"; package teleport.clusterconfig.v1; import "teleport/clusterconfig/v1/access_graph.proto"; +import "teleport/clusterconfig/v1/access_graph_settings.proto"; import "teleport/legacy/types/types.proto"; option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1;clusterconfigv1"; @@ -53,8 +54,19 @@ service ClusterConfigService { // GetClusterAuditConfig retrieves the active cluster audit configuration. rpc GetClusterAuditConfig(GetClusterAuditConfigRequest) returns (types.ClusterAuditConfigV2); - // GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server. + // GetClusterAccessGraphConfig retrieves the cluster Access Graph configuration from Auth server. rpc GetClusterAccessGraphConfig(GetClusterAccessGraphConfigRequest) returns (GetClusterAccessGraphConfigResponse); + + // GetAccessGraphSettings updates the cluster Access Graph configuration. + rpc GetAccessGraphSettings(GetAccessGraphSettingsRequest) returns (teleport.clusterconfig.v1.AccessGraphSettings); + // CreateAccessGraphSettings creates the cluster Access Graph configuration. + rpc CreateAccessGraphSettings(CreateAccessGraphSettingsRequest) returns (teleport.clusterconfig.v1.AccessGraphSettings); + // UpdateAccessGraphSettings updates the cluster Access Graph configuration. + rpc UpdateAccessGraphSettings(UpdateAccessGraphSettingsRequest) returns (teleport.clusterconfig.v1.AccessGraphSettings); + // UpsertAccessGraphSettings overwrites the active cluster Access Graph configuration. + rpc UpsertAccessGraphSettings(UpsertAccessGraphSettingsRequest) returns (teleport.clusterconfig.v1.AccessGraphSettings); + // ResetAccessGraphSettings restores the active cluster Access Graph to default settings. + rpc ResetAccessGraphSettings(ResetAccessGraphSettingsRequest) returns (teleport.clusterconfig.v1.AccessGraphSettings); } // Request for GetClusterNetworkingConfig @@ -116,3 +128,24 @@ message GetClusterAccessGraphConfigResponse { // access_graph holds the information about Access Graph service. teleport.clusterconfig.v1.AccessGraphConfig access_graph = 1; } + +// Request for GetAccessGraphSettings +message GetAccessGraphSettingsRequest {} + +// Request for CreateAccessGraphSettings +message CreateAccessGraphSettingsRequest { + teleport.clusterconfig.v1.AccessGraphSettings access_graph_settings = 1; +} + +// Request for UpdateAccessGraphSettings +message UpdateAccessGraphSettingsRequest { + teleport.clusterconfig.v1.AccessGraphSettings access_graph_settings = 1; +} + +// Request for UpsertAccessGraphSettings +message UpsertAccessGraphSettingsRequest { + teleport.clusterconfig.v1.AccessGraphSettings access_graph_settings = 1; +} + +// Request for ResetAccessGraphSettings +message ResetAccessGraphSettingsRequest {} diff --git a/api/proto/teleport/devicetrust/v1/assert.proto b/api/proto/teleport/devicetrust/v1/assert.proto new file mode 100644 index 0000000000000..5841c0a5c0519 --- /dev/null +++ b/api/proto/teleport/devicetrust/v1/assert.proto @@ -0,0 +1,74 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.devicetrust.v1; + +import "teleport/devicetrust/v1/authenticate_challenge.proto"; +import "teleport/devicetrust/v1/device_collected_data.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1;devicetrustv1"; + +// Request to assert an enrolled device. Assertion authenticates the device, +// regardless of the user driving the assertion. +// +// Assertion messages are meant to be included by other requests and responses, +// either streams or multi-stage RPCs. The ceremony is resolved by a co-located +// DeviceTrustService. +// +// See the lib/devicetrust/assert (client) and lib/devicetrust/assertserver +// (server) packages. +// +// Assertion ceremony flow: +// -> AssertDeviceInit (client) +// <- AssertDeviceChallenge (server) +// -> AssertDeviceChallengeResponse (client) +// <- DeviceAsserted (server) +// +// A successful ceremony signifies that the device is registered, enrolled and +// passed the authentication challenge. +message AssertDeviceRequest { + oneof payload { + AssertDeviceInit init = 1; + AuthenticateDeviceChallengeResponse challenge_response = 2; + TPMAuthenticateDeviceChallengeResponse tpm_challenge_response = 3; + } +} + +// Response of the device assertion ceremony. +// See [AssertDeviceRequest]. +message AssertDeviceResponse { + oneof payload { + AuthenticateDeviceChallenge challenge = 1; + TPMAuthenticateDeviceChallenge tpm_challenge = 2; + DeviceAsserted device_asserted = 3; + } +} + +// AssertDeviceInit initiates the device assertion ceremony. +// See [AssertDeviceRequest]. +message AssertDeviceInit { + // ID of the enrolled device credential. + string credential_id = 1; + + // Device collected data. + // Matched against the device registration information and any previously + // collected data. + DeviceCollectedData device_data = 2; +} + +// DeviceAsserted marks a successful device assertion ceremony. +// See [AssertDeviceRequest]. +message DeviceAsserted {} diff --git a/api/proto/teleport/devicetrust/v1/authenticate_challenge.proto b/api/proto/teleport/devicetrust/v1/authenticate_challenge.proto new file mode 100644 index 0000000000000..9f91a9046cae5 --- /dev/null +++ b/api/proto/teleport/devicetrust/v1/authenticate_challenge.proto @@ -0,0 +1,50 @@ +// Copyright 2022 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package teleport.devicetrust.v1; + +import "teleport/devicetrust/v1/tpm.proto"; + +option go_package = "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1;devicetrustv1"; + +// AuthenticateDeviceChallenge carries the authentication challenge. +message AuthenticateDeviceChallenge { + // Randomly-generated, opaque challenge to be signed using the device key. + bytes challenge = 1; +} + +// AuthenticateDeviceChallengeResponse carries the authentication challenge +// response. +message AuthenticateDeviceChallengeResponse { + // Signature over the challenge, using the device key. + bytes signature = 1; +} + +// TPMAuthenticateDeviceChallenge carries the authentication challenge +// specific to TPMs. +message TPMAuthenticateDeviceChallenge { + // Randomly-generated nonce to be used during platform attestation by the + // TPM. + bytes attestation_nonce = 1; +} + +// TPMAuthenticateDeviceChallengeResponse carries the authentication challenge +// response specific to TPMs. +message TPMAuthenticateDeviceChallengeResponse { + // The result of the client's platform attestation with the nonce provided + // in `TPMAuthenticateDeviceChallenge`. + TPMPlatformParameters platform_parameters = 1; +} diff --git a/api/proto/teleport/devicetrust/v1/devicetrust_service.proto b/api/proto/teleport/devicetrust/v1/devicetrust_service.proto index a332175deebfa..df5cb2eefae62 100644 --- a/api/proto/teleport/devicetrust/v1/devicetrust_service.proto +++ b/api/proto/teleport/devicetrust/v1/devicetrust_service.proto @@ -20,6 +20,7 @@ import "google/protobuf/empty.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/timestamp.proto"; import "google/rpc/status.proto"; +import "teleport/devicetrust/v1/authenticate_challenge.proto"; import "teleport/devicetrust/v1/device.proto"; import "teleport/devicetrust/v1/device_collected_data.proto"; import "teleport/devicetrust/v1/device_enroll_token.proto"; @@ -499,35 +500,6 @@ message AuthenticateDeviceInit { DeviceCollectedData device_data = 3; } -// TPMAuthenticateDeviceChallenge carries the authentication challenge -// specific to TPMs. -message TPMAuthenticateDeviceChallenge { - // Randomly-generated nonce to be used during platform attestation by the - // TPM. - bytes attestation_nonce = 1; -} - -// TPMAuthenticateDeviceChallengeResponse carries the authentication challenge -// response specific to TPMs. -message TPMAuthenticateDeviceChallengeResponse { - // The result of the client's platform attestation with the nonce provided - // in `TPMAuthenticateDeviceChallenge`. - TPMPlatformParameters platform_parameters = 1; -} - -// AuthenticateDeviceChallenge carries the authentication challenge. -message AuthenticateDeviceChallenge { - // Randomly-generated, opaque challenge to be signed using the device key. - bytes challenge = 1; -} - -// AuthenticateDeviceChallengeResponse carries the authentication challenge -// response. -message AuthenticateDeviceChallengeResponse { - // Signature over the challenge, using the device key. - bytes signature = 1; -} - // Request for SyncInventory. // // A typical message sequence is as follows: diff --git a/api/proto/teleport/legacy/client/proto/event.proto b/api/proto/teleport/legacy/client/proto/event.proto index dd99ad53b7302..4a4e96e53726c 100644 --- a/api/proto/teleport/legacy/client/proto/event.proto +++ b/api/proto/teleport/legacy/client/proto/event.proto @@ -18,6 +18,7 @@ package proto; import "teleport/accesslist/v1/accesslist.proto"; import "teleport/accessmonitoringrules/v1/access_monitoring_rules.proto"; +import "teleport/clusterconfig/v1/access_graph_settings.proto"; import "teleport/crownjewel/v1/crownjewel.proto"; import "teleport/discoveryconfig/v1/discoveryconfig.proto"; import "teleport/kubewaitingcontainer/v1/kubewaitingcontainer.proto"; @@ -157,5 +158,7 @@ message Event { teleport.accessmonitoringrules.v1.AccessMonitoringRule AccessMonitoringRule = 54; // CrownJewel is a Crown Jewel resource. teleport.crownjewel.v1.CrownJewel CrownJewel = 58; + // AccessGraphSettings is a resource for access graph settings. + teleport.clusterconfig.v1.AccessGraphSettings AccessGraphSettings = 61; } } diff --git a/api/proto/teleport/legacy/types/events/events.proto b/api/proto/teleport/legacy/types/events/events.proto index e0921f30c6dec..6bbb4c404e1f8 100644 --- a/api/proto/teleport/legacy/types/events/events.proto +++ b/api/proto/teleport/legacy/types/events/events.proto @@ -4368,6 +4368,7 @@ message OneOf { events.DiscoveryConfigUpdate DiscoveryConfigUpdate = 161; events.DiscoveryConfigDelete DiscoveryConfigDelete = 162; events.DiscoveryConfigDeleteAll DiscoveryConfigDeleteAll = 163; + events.AccessGraphSettingsUpdate AccessGraphSettingsUpdate = 164; events.IntegrationCreate IntegrationCreate = 165; events.IntegrationUpdate IntegrationUpdate = 166; events.IntegrationDelete IntegrationDelete = 167; @@ -6506,6 +6507,37 @@ message SpannerRPC { ]; } +// AccessGraphSettingsUpdate is emitted when the Access Graph Settings config is updated. +message AccessGraphSettingsUpdate { + // Metadata is a common event metadata + Metadata Metadata = 1 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + + // Status indicates whether the update was successful. + Status Status = 2 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + + // User is a common user event metadata + UserMetadata User = 3 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; + + // ConnectionMetadata holds information about the connection + ConnectionMetadata Connection = 4 [ + (gogoproto.nullable) = false, + (gogoproto.embed) = true, + (gogoproto.jsontag) = "" + ]; +} + // SPIFFEFederationCreate is emitted when a SPIFFE federation is created. message SPIFFEFederationCreate { // Metadata is a common event metadata diff --git a/api/types/accessgraph/authorized_key.go b/api/types/accessgraph/authorized_key.go new file mode 100644 index 0000000000000..215583716be49 --- /dev/null +++ b/api/types/accessgraph/authorized_key.go @@ -0,0 +1,95 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package accessgraph + +import ( + "time" + + "github.com/gravitational/trace" + "google.golang.org/protobuf/types/known/timestamppb" + + accessgraphv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types" +) + +const ( + // AuthorizedKeyDefaultKeyTTL is the default TTL for an authorized key. + AuthorizedKeyDefaultKeyTTL = 8 * time.Hour +) + +// NewAuthorizedKey creates a new SSH authorized key resource. +func NewAuthorizedKey(spec *accessgraphv1pb.AuthorizedKeySpec) (*accessgraphv1pb.AuthorizedKey, error) { + name := authKeyHashNameKey(spec) + authKey := &accessgraphv1pb.AuthorizedKey{ + Kind: types.KindAccessGraphSecretAuthorizedKey, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: name, + Expires: timestamppb.New( + time.Now().Add(AuthorizedKeyDefaultKeyTTL), + ), + }, + Spec: spec, + } + if err := ValidateAuthorizedKey(authKey); err != nil { + return nil, trace.Wrap(err) + } + + return authKey, nil +} + +// ValidateAuthorizedKey checks that required parameters are set +// for the specified AuthorizedKey +func ValidateAuthorizedKey(k *accessgraphv1pb.AuthorizedKey) error { + if k == nil { + return trace.BadParameter("AuthorizedKey is nil") + } + if k.Metadata == nil { + return trace.BadParameter("Metadata is nil") + } + if k.Spec == nil { + return trace.BadParameter("Spec is nil") + } + + if k.Spec.HostId == "" { + return trace.BadParameter("HostId is unset") + } + if k.Spec.HostUser == "" { + return trace.BadParameter("HostUser is unset") + } + if k.Spec.KeyFingerprint == "" { + return trace.BadParameter("KeyFingerprint is unset") + } + + if k.Spec.KeyType == "" { + return trace.BadParameter("KeyType is unset") + } + + if k.Metadata.Name == "" { + return trace.BadParameter("Name is unset") + } + if k.Metadata.Name != authKeyHashNameKey(k.Spec) { + return trace.BadParameter("Name must be derived from the key fields") + } + + return nil +} + +func authKeyHashNameKey(k *accessgraphv1pb.AuthorizedKeySpec) string { + return hashComp(k.HostId, k.HostUser, k.KeyFingerprint) +} diff --git a/api/types/accessgraph/authorized_key_test.go b/api/types/accessgraph/authorized_key_test.go new file mode 100644 index 0000000000000..46c92cbd15a47 --- /dev/null +++ b/api/types/accessgraph/authorized_key_test.go @@ -0,0 +1,105 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package accessgraph + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + accessgraphv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" +) + +func TestAuthorizedKey(t *testing.T) { + tests := []struct { + name string + spec *accessgraphv1pb.AuthorizedKeySpec + errValidation require.ErrorAssertionFunc + }{ + { + name: "valid", + spec: &accessgraphv1pb.AuthorizedKeySpec{ + HostId: uuid.New().String(), + KeyFingerprint: "fingerprint", + HostUser: "user", + KeyType: "ssh-rsa", + }, + errValidation: require.NoError, + }, + { + name: "missing fingerprint", + spec: &accessgraphv1pb.AuthorizedKeySpec{ + HostId: uuid.New().String(), + KeyFingerprint: "", + HostUser: "user", + KeyType: "ssh-rsa", + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "KeyFingerprint is unset") + }, + }, + { + name: "missing user", + spec: &accessgraphv1pb.AuthorizedKeySpec{ + HostId: uuid.New().String(), + KeyFingerprint: "fingerprint", + HostUser: "", + KeyType: "ssh-rsa", + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "HostUser is unset") + }, + }, + { + name: "missing HostID", + spec: &accessgraphv1pb.AuthorizedKeySpec{ + KeyFingerprint: "fingerprint", + HostUser: "user", + KeyType: "ssh-rsa", + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "HostId is unset") + }, + }, + { + name: "missing HostID", + spec: &accessgraphv1pb.AuthorizedKeySpec{ + KeyFingerprint: "fingerprint", + HostUser: "user", + HostId: uuid.New().String(), + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "KeyType is unset") + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + privKey, err := NewAuthorizedKey(tt.spec) + tt.errValidation(t, err) + if err != nil { + return + } + require.NotEmpty(t, privKey.Metadata.Name) + require.Empty(t, cmp.Diff(tt.spec, privKey.Spec, protocmp.Transform())) + + }) + } +} diff --git a/api/types/accessgraph/private_key.go b/api/types/accessgraph/private_key.go new file mode 100644 index 0000000000000..a8730685f8d3c --- /dev/null +++ b/api/types/accessgraph/private_key.go @@ -0,0 +1,123 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package accessgraph + +import ( + "crypto/sha256" + "encoding/hex" + + "github.com/gravitational/trace" + + accessgraphv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types" +) + +// NewPrivateKey creates a new SSH Private key resource with a generated name based on the spec. +func NewPrivateKey(spec *accessgraphv1pb.PrivateKeySpec) (*accessgraphv1pb.PrivateKey, error) { + name := privKeyHashNameKey(spec) + v, err := NewPrivateKeyWithName(name, spec) + + return v, trace.Wrap(err) +} + +// NewPrivateKeyWithName creates a new SSH Private key resource. +func NewPrivateKeyWithName(name string, spec *accessgraphv1pb.PrivateKeySpec) (*accessgraphv1pb.PrivateKey, error) { + privKey := &accessgraphv1pb.PrivateKey{ + Kind: types.KindAccessGraphSecretPrivateKey, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: name, + }, + Spec: spec, + } + if err := ValidatePrivateKey(privKey); err != nil { + return nil, trace.Wrap(err) + } + + return privKey, nil +} + +// ValidatePrivateKey checks that required parameters are set +// for the specified PrivateKey +func ValidatePrivateKey(k *accessgraphv1pb.PrivateKey) error { + if k == nil { + return trace.BadParameter("PrivateKey is nil") + } + if k.Metadata == nil { + return trace.BadParameter("Metadata is nil") + } + if k.Spec == nil { + return trace.BadParameter("Spec is nil") + } + + if k.Kind != types.KindAccessGraphSecretPrivateKey { + return trace.BadParameter("Kind is invalid") + } + + if k.Version != types.V1 { + return trace.BadParameter("Version is invalid") + } + + switch k.Spec.PublicKeyMode { + case accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED, + accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE, + accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED: + default: + return trace.BadParameter("PublicKeyMode is invalid") + } + + if k.Spec.DeviceId == "" { + return trace.BadParameter("DeviceId is unset") + } + if k.Spec.PublicKeyFingerprint == "" && k.Spec.PublicKeyMode != accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED { + return trace.BadParameter("PublicKeyFingerprint is unset") + } + + if k.Metadata.Name == "" { + return trace.BadParameter("Name is unset") + } + + return nil +} + +func privKeyHashNameKey(k *accessgraphv1pb.PrivateKeySpec) string { + return hashComp(k.DeviceId, k.PublicKeyFingerprint) +} + +func hashComp(values ...string) string { + h := sha256.New() + for _, value := range values { + h.Write([]byte(value)) + } + return hex.EncodeToString(h.Sum(nil)) +} + +// DescribePublicKeyMode returns a human-readable description of the public key mode. +func DescribePublicKeyMode(mode accessgraphv1pb.PublicKeyMode) string { + switch mode { + case accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE: + return "used public key file" + case accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED: + return "protected private key" + case accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED: + return "derived from private key" + default: + return "unknown" + } + +} diff --git a/api/types/accessgraph/private_key_test.go b/api/types/accessgraph/private_key_test.go new file mode 100644 index 0000000000000..c1c38bd21c49f --- /dev/null +++ b/api/types/accessgraph/private_key_test.go @@ -0,0 +1,119 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package accessgraph + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + accessgraphv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" +) + +func TestPrivateKey(t *testing.T) { + tests := []struct { + name string + spec *accessgraphv1pb.PrivateKeySpec + errValidation require.ErrorAssertionFunc + }{ + { + name: "valid derived", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "fingerprint", + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + }, + errValidation: require.NoError, + }, + { + name: "valid file", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "fingerprint", + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE, + }, + errValidation: require.NoError, + }, + { + name: "missing fingerprint derived", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "", + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "PublicKeyFingerprint is unset") + }, + }, + { + name: "missing fingerprint file", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "", + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE, + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "PublicKeyFingerprint is unset") + }, + }, + { + name: "valid protected", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "", /* empty fingerprint */ + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED, + }, + errValidation: require.NoError, + }, + { + name: "invalid public key ode", + spec: &accessgraphv1pb.PrivateKeySpec{ + DeviceId: uuid.New().String(), + PublicKeyFingerprint: "fingerprint", + PublicKeyMode: 500, + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "PublicKeyMode is invalid") + }, + }, + { + name: "missing DeviceId", + spec: &accessgraphv1pb.PrivateKeySpec{ + PublicKeyFingerprint: "fingerprint", + PublicKeyMode: accessgraphv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED, + }, + errValidation: func(t require.TestingT, err error, i ...any) { + require.ErrorContains(t, err, "DeviceId is unset") + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + privKey, err := NewPrivateKey(tt.spec) + tt.errValidation(t, err) + if err != nil { + return + } + require.NotEmpty(t, privKey.Metadata.Name) + require.Empty(t, cmp.Diff(tt.spec, privKey.Spec, protocmp.Transform())) + + }) + } +} diff --git a/api/types/clusterconfig/access_graph_settings.go b/api/types/clusterconfig/access_graph_settings.go new file mode 100644 index 0000000000000..87721a88939e3 --- /dev/null +++ b/api/types/clusterconfig/access_graph_settings.go @@ -0,0 +1,79 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package clusterconfig + +import ( + "github.com/gravitational/trace" + + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types" +) + +// NewAccessGraphSettings creates a new AccessGraphSettings resource. +func NewAccessGraphSettings(spec *clusterconfigpb.AccessGraphSettingsSpec) (*clusterconfigpb.AccessGraphSettings, error) { + settings := &clusterconfigpb.AccessGraphSettings{ + Kind: types.KindAccessGraphSettings, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: spec, + } + if err := ValidateAccessGraphSettings(settings); err != nil { + return nil, trace.Wrap(err) + } + + return settings, nil + +} + +// ValidateAccessGraphSettings checks that required parameters are set +func ValidateAccessGraphSettings(s *clusterconfigpb.AccessGraphSettings) error { + if s == nil { + return trace.BadParameter("AccessGraphSettings is nil") + } + if s.Metadata == nil { + return trace.BadParameter("Metadata is nil") + } + if s.Spec == nil { + return trace.BadParameter("Spec is nil") + } + + if s.Metadata.Name == "" { + return trace.BadParameter("Name is unset") + } + + if s.Metadata.Name != types.MetaNameAccessGraphSettings { + return trace.BadParameter("Name is not %s", types.MetaNameAccessGraphSettings) + } + + if s.Kind != types.KindAccessGraphSettings { + return trace.BadParameter("Kind is not AccessGraphSettings") + } + if s.Version != types.V1 { + return trace.BadParameter("Version is not V1") + } + + switch s.Spec.GetSecretsScanConfig() { + case clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED: + default: + return trace.BadParameter("SecretsScanConfig is invalid") + } + + return nil +} diff --git a/api/types/clusterconfig/access_graph_settings_test.go b/api/types/clusterconfig/access_graph_settings_test.go new file mode 100644 index 0000000000000..82f7a4e6dc9d7 --- /dev/null +++ b/api/types/clusterconfig/access_graph_settings_test.go @@ -0,0 +1,93 @@ +/* +Copyright 2024 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package clusterconfig + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types" +) + +func TestNewAccessGraphSettings(t *testing.T) { + tests := []struct { + name string + spec *clusterconfigpb.AccessGraphSettingsSpec + want *clusterconfigpb.AccessGraphSettings + assertErr func(*testing.T, error, ...any) + }{ + { + name: "success disabled", + spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + assertErr: func(t *testing.T, err error, a ...any) { + require.NoError(t, err) + }, + want: &clusterconfigpb.AccessGraphSettings{ + Kind: types.KindAccessGraphSettings, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + }, + }, + { + name: "success enabled", + spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + assertErr: func(t *testing.T, err error, a ...any) { + require.NoError(t, err) + }, + want: &clusterconfigpb.AccessGraphSettings{ + Kind: types.KindAccessGraphSettings, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + }, + }, + { + name: "invalid", + spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: 10, + }, + assertErr: func(t *testing.T, err error, a ...any) { + require.ErrorContains(t, err, "SecretsScanConfig is invalid") + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewAccessGraphSettings(tt.spec) + tt.assertErr(t, err) + require.Empty(t, cmp.Diff(got, tt.want, protocmp.Transform())) + }) + } +} diff --git a/api/types/constants.go b/api/types/constants.go index c613c29449700..0c1980e75c965 100644 --- a/api/types/constants.go +++ b/api/types/constants.go @@ -523,6 +523,21 @@ const ( // KindUserNotificationState is a resource which tracks whether a user has clicked on or dismissed a notification. KindUserNotificationState = "user_notification_state" + // KindAccessGraphSecretAuthorizedKey is a authorized key entry found in + // a Teleport SSH node type. + KindAccessGraphSecretAuthorizedKey = "access_graph_authorized_key" + + // KindAccessGraphSecretPrivateKey is a private key entry found in + // a managed device. + KindAccessGraphSecretPrivateKey = "access_graph_private_key" + + // KindAccessGraphSettings is a resource which holds cluster-wide configuration for dynamic access graph settings. + KindAccessGraphSettings = "access_graph_settings" + + // MetaNameAccessGraphSettings is the exact name of the singleton resource holding + // access graph settings. + MetaNameAccessGraphSettings = "access-graph-settings" + // V7 is the seventh version of resources. V7 = "v7" diff --git a/api/types/events/events.pb.go b/api/types/events/events.pb.go index 279dfceed50d6..00f45fa58155c 100644 --- a/api/types/events/events.pb.go +++ b/api/types/events/events.pb.go @@ -7426,6 +7426,7 @@ type OneOf struct { // *OneOf_DiscoveryConfigUpdate // *OneOf_DiscoveryConfigDelete // *OneOf_DiscoveryConfigDeleteAll + // *OneOf_AccessGraphSettingsUpdate // *OneOf_IntegrationCreate // *OneOf_IntegrationUpdate // *OneOf_IntegrationDelete @@ -7956,6 +7957,9 @@ type OneOf_DiscoveryConfigDelete struct { type OneOf_DiscoveryConfigDeleteAll struct { DiscoveryConfigDeleteAll *DiscoveryConfigDeleteAll `protobuf:"bytes,163,opt,name=DiscoveryConfigDeleteAll,proto3,oneof" json:"DiscoveryConfigDeleteAll,omitempty"` } +type OneOf_AccessGraphSettingsUpdate struct { + AccessGraphSettingsUpdate *AccessGraphSettingsUpdate `protobuf:"bytes,164,opt,name=AccessGraphSettingsUpdate,proto3,oneof" json:"AccessGraphSettingsUpdate,omitempty"` +} type OneOf_IntegrationCreate struct { IntegrationCreate *IntegrationCreate `protobuf:"bytes,165,opt,name=IntegrationCreate,proto3,oneof" json:"IntegrationCreate,omitempty"` } @@ -8132,6 +8136,7 @@ func (*OneOf_DiscoveryConfigCreate) isOneOf_Event() {} func (*OneOf_DiscoveryConfigUpdate) isOneOf_Event() {} func (*OneOf_DiscoveryConfigDelete) isOneOf_Event() {} func (*OneOf_DiscoveryConfigDeleteAll) isOneOf_Event() {} +func (*OneOf_AccessGraphSettingsUpdate) isOneOf_Event() {} func (*OneOf_IntegrationCreate) isOneOf_Event() {} func (*OneOf_IntegrationUpdate) isOneOf_Event() {} func (*OneOf_IntegrationDelete) isOneOf_Event() {} @@ -9265,6 +9270,13 @@ func (m *OneOf) GetDiscoveryConfigDeleteAll() *DiscoveryConfigDeleteAll { return nil } +func (m *OneOf) GetAccessGraphSettingsUpdate() *AccessGraphSettingsUpdate { + if x, ok := m.GetEvent().(*OneOf_AccessGraphSettingsUpdate); ok { + return x.AccessGraphSettingsUpdate + } + return nil +} + func (m *OneOf) GetIntegrationCreate() *IntegrationCreate { if x, ok := m.GetEvent().(*OneOf_IntegrationCreate); ok { return x.IntegrationCreate @@ -9463,6 +9475,7 @@ func (*OneOf) XXX_OneofWrappers() []interface{} { (*OneOf_DiscoveryConfigUpdate)(nil), (*OneOf_DiscoveryConfigDelete)(nil), (*OneOf_DiscoveryConfigDeleteAll)(nil), + (*OneOf_AccessGraphSettingsUpdate)(nil), (*OneOf_IntegrationCreate)(nil), (*OneOf_IntegrationUpdate)(nil), (*OneOf_IntegrationDelete)(nil), @@ -13175,6 +13188,54 @@ func (m *SpannerRPC) XXX_DiscardUnknown() { var xxx_messageInfo_SpannerRPC proto.InternalMessageInfo +// AccessGraphSettingsUpdate is emitted when the Access Graph Settings config is updated. +type AccessGraphSettingsUpdate struct { + // Metadata is a common event metadata + Metadata `protobuf:"bytes,1,opt,name=Metadata,proto3,embedded=Metadata" json:""` + // Status indicates whether the update was successful. + Status `protobuf:"bytes,2,opt,name=Status,proto3,embedded=Status" json:""` + // User is a common user event metadata + UserMetadata `protobuf:"bytes,3,opt,name=User,proto3,embedded=User" json:""` + // ConnectionMetadata holds information about the connection + ConnectionMetadata `protobuf:"bytes,4,opt,name=Connection,proto3,embedded=Connection" json:""` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *AccessGraphSettingsUpdate) Reset() { *m = AccessGraphSettingsUpdate{} } +func (m *AccessGraphSettingsUpdate) String() string { return proto.CompactTextString(m) } +func (*AccessGraphSettingsUpdate) ProtoMessage() {} +func (*AccessGraphSettingsUpdate) Descriptor() ([]byte, []int) { + return fileDescriptor_007ba1c3d6266d56, []int{206} +} +func (m *AccessGraphSettingsUpdate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *AccessGraphSettingsUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_AccessGraphSettingsUpdate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *AccessGraphSettingsUpdate) XXX_Merge(src proto.Message) { + xxx_messageInfo_AccessGraphSettingsUpdate.Merge(m, src) +} +func (m *AccessGraphSettingsUpdate) XXX_Size() int { + return m.Size() +} +func (m *AccessGraphSettingsUpdate) XXX_DiscardUnknown() { + xxx_messageInfo_AccessGraphSettingsUpdate.DiscardUnknown(m) +} + +var xxx_messageInfo_AccessGraphSettingsUpdate proto.InternalMessageInfo + // SPIFFEFederationCreate is emitted when a SPIFFE federation is created. type SPIFFEFederationCreate struct { // Metadata is a common event metadata @@ -13194,7 +13255,7 @@ func (m *SPIFFEFederationCreate) Reset() { *m = SPIFFEFederationCreate{} func (m *SPIFFEFederationCreate) String() string { return proto.CompactTextString(m) } func (*SPIFFEFederationCreate) ProtoMessage() {} func (*SPIFFEFederationCreate) Descriptor() ([]byte, []int) { - return fileDescriptor_007ba1c3d6266d56, []int{206} + return fileDescriptor_007ba1c3d6266d56, []int{207} } func (m *SPIFFEFederationCreate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -13242,7 +13303,7 @@ func (m *SPIFFEFederationDelete) Reset() { *m = SPIFFEFederationDelete{} func (m *SPIFFEFederationDelete) String() string { return proto.CompactTextString(m) } func (*SPIFFEFederationDelete) ProtoMessage() {} func (*SPIFFEFederationDelete) Descriptor() ([]byte, []int) { - return fileDescriptor_007ba1c3d6266d56, []int{207} + return fileDescriptor_007ba1c3d6266d56, []int{208} } func (m *SPIFFEFederationDelete) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -13501,6 +13562,7 @@ func init() { proto.RegisterType((*SessionRecordingConfigUpdate)(nil), "events.SessionRecordingConfigUpdate") proto.RegisterType((*AccessPathChanged)(nil), "events.AccessPathChanged") proto.RegisterType((*SpannerRPC)(nil), "events.SpannerRPC") + proto.RegisterType((*AccessGraphSettingsUpdate)(nil), "events.AccessGraphSettingsUpdate") proto.RegisterType((*SPIFFEFederationCreate)(nil), "events.SPIFFEFederationCreate") proto.RegisterType((*SPIFFEFederationDelete)(nil), "events.SPIFFEFederationDelete") } @@ -13510,962 +13572,965 @@ func init() { } var fileDescriptor_007ba1c3d6266d56 = []byte{ - // 15275 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6d, 0x70, 0x24, 0xc7, - 0x75, 0x20, 0x88, 0xfe, 0x40, 0x03, 0x78, 0xf8, 0x18, 0x20, 0x67, 0x38, 0x53, 0x1c, 0x0e, 0xa7, - 0xc9, 0xa2, 0x38, 0x9a, 0xa1, 0x48, 0x8c, 0x38, 0x1c, 0x92, 0x22, 0x45, 0x8a, 0x6c, 0xa0, 0x81, - 0x41, 0x73, 0xf0, 0xc5, 0x6a, 0xcc, 0x8c, 0xa8, 0x0f, 0xb6, 0x0b, 0x5d, 0x09, 0xa0, 0x88, 0xee, - 0xaa, 0x56, 0x55, 0xf5, 0x60, 0xc0, 0xfb, 0xb2, 0x7c, 0xfe, 0x90, 0x7c, 0x92, 0x4e, 0x27, 0x9f, - 0xbf, 0x7d, 0x77, 0xb2, 0x1d, 0xbe, 0xb3, 0x1d, 0x3e, 0xfb, 0x7c, 0x77, 0x61, 0x5b, 0xf6, 0x29, - 0xce, 0x3e, 0xdd, 0xc5, 0xd1, 0x2b, 0x7b, 0xc3, 0xf6, 0xee, 0x3a, 0x1c, 0xbb, 0x5e, 0xc8, 0xab, - 0x5d, 0xef, 0x0f, 0xc4, 0x6e, 0x84, 0x77, 0x57, 0xb1, 0xf6, 0x7a, 0xbd, 0x1b, 0x1b, 0xf9, 0x32, - 0xab, 0x2a, 0xeb, 0xa3, 0x1b, 0x9f, 0x34, 0x08, 0x0e, 0xfe, 0xcc, 0xa0, 0xdf, 0x7b, 0xf9, 0x32, - 0xeb, 0xe5, 0xcb, 0xcc, 0x97, 0x99, 0x2f, 0xdf, 0x83, 0x2b, 0x1e, 0x6d, 0xd0, 0x96, 0xed, 0x78, - 0x57, 0x1b, 0x74, 0x55, 0xaf, 0x6f, 0x5e, 0xf5, 0x36, 0x5b, 0xd4, 0xbd, 0x4a, 0xef, 0x52, 0xcb, - 0xf3, 0xff, 0x1b, 0x6f, 0x39, 0xb6, 0x67, 0x93, 0x02, 0xff, 0x75, 0xfe, 0xcc, 0xaa, 0xbd, 0x6a, - 0x23, 0xe8, 0x2a, 0xfb, 0x8b, 0x63, 0xcf, 0x5f, 0x58, 0xb5, 0xed, 0xd5, 0x06, 0xbd, 0x8a, 0xbf, - 0x96, 0xdb, 0x2b, 0x57, 0x5d, 0xcf, 0x69, 0xd7, 0x3d, 0x81, 0x2d, 0xc6, 0xb1, 0x9e, 0xd9, 0xa4, - 0xae, 0xa7, 0x37, 0x5b, 0x82, 0xe0, 0x62, 0x9c, 0x60, 0xc3, 0xd1, 0x5b, 0x2d, 0xea, 0x88, 0xca, - 0xcf, 0x3f, 0x9a, 0xde, 0x4e, 0xfc, 0x57, 0x90, 0x3c, 0x95, 0x4e, 0xe2, 0x33, 0x8a, 0x71, 0x54, - 0xbf, 0x92, 0x85, 0xfe, 0x39, 0xea, 0xe9, 0x86, 0xee, 0xe9, 0xe4, 0x02, 0xf4, 0x56, 0x2c, 0x83, - 0xde, 0x53, 0x32, 0x8f, 0x64, 0x2e, 0xe7, 0x26, 0x0a, 0xdb, 0x5b, 0xc5, 0x2c, 0x35, 0x35, 0x0e, - 0x24, 0x0f, 0x43, 0x7e, 0x69, 0xb3, 0x45, 0x95, 0xec, 0x23, 0x99, 0xcb, 0x03, 0x13, 0x03, 0xdb, - 0x5b, 0xc5, 0x5e, 0x94, 0x85, 0x86, 0x60, 0xf2, 0x28, 0x64, 0x2b, 0x65, 0x25, 0x87, 0xc8, 0xb1, - 0xed, 0xad, 0xe2, 0x70, 0xdb, 0x34, 0x9e, 0xb4, 0x9b, 0xa6, 0x47, 0x9b, 0x2d, 0x6f, 0x53, 0xcb, - 0x56, 0xca, 0xe4, 0x12, 0xe4, 0x27, 0x6d, 0x83, 0x2a, 0x79, 0x24, 0x22, 0xdb, 0x5b, 0xc5, 0x91, - 0xba, 0x6d, 0x50, 0x89, 0x0a, 0xf1, 0xe4, 0x55, 0xc8, 0x2f, 0x99, 0x4d, 0xaa, 0xf4, 0x3e, 0x92, - 0xb9, 0x3c, 0x78, 0xed, 0xfc, 0x38, 0x97, 0xca, 0xb8, 0x2f, 0x95, 0xf1, 0x25, 0x5f, 0x6c, 0x13, - 0xa3, 0xef, 0x6c, 0x15, 0x7b, 0xb6, 0xb7, 0x8a, 0x79, 0x26, 0xc9, 0x2f, 0x7f, 0xab, 0x98, 0xd1, - 0xb0, 0x24, 0x79, 0x09, 0x06, 0x27, 0x1b, 0x6d, 0xd7, 0xa3, 0xce, 0xbc, 0xde, 0xa4, 0x4a, 0x01, - 0x2b, 0x3c, 0xbf, 0xbd, 0x55, 0x3c, 0x5b, 0xe7, 0xe0, 0x9a, 0xa5, 0x37, 0xe5, 0x8a, 0x65, 0x72, - 0xf5, 0x37, 0x32, 0x70, 0xaa, 0x4a, 0x5d, 0xd7, 0xb4, 0xad, 0x40, 0x36, 0x8f, 0xc3, 0x80, 0x00, - 0x55, 0xca, 0x28, 0x9f, 0x81, 0x89, 0xbe, 0xed, 0xad, 0x62, 0xce, 0x35, 0x0d, 0x2d, 0xc4, 0x90, - 0x0f, 0x43, 0xdf, 0x1d, 0xd3, 0x5b, 0x9b, 0x9b, 0x2e, 0x09, 0x39, 0x9d, 0xdd, 0xde, 0x2a, 0x92, - 0x0d, 0xd3, 0x5b, 0xab, 0x35, 0x57, 0x74, 0xa9, 0x42, 0x9f, 0x8c, 0xcc, 0xc2, 0xe8, 0xa2, 0x63, - 0xde, 0xd5, 0x3d, 0x7a, 0x93, 0x6e, 0x2e, 0xda, 0x0d, 0xb3, 0xbe, 0x29, 0xa4, 0xf8, 0xc8, 0xf6, - 0x56, 0xf1, 0x42, 0x8b, 0xe3, 0x6a, 0xeb, 0x74, 0xb3, 0xd6, 0x42, 0xac, 0xc4, 0x24, 0x51, 0x52, - 0xfd, 0x46, 0x2f, 0x0c, 0xdd, 0x72, 0xa9, 0x13, 0xb4, 0xfb, 0x12, 0xe4, 0xd9, 0x6f, 0xd1, 0x64, - 0x94, 0x79, 0xdb, 0xa5, 0x8e, 0x2c, 0x73, 0x86, 0x27, 0x57, 0xa0, 0x77, 0xd6, 0x5e, 0x35, 0x2d, - 0xd1, 0xec, 0xd3, 0xdb, 0x5b, 0xc5, 0x53, 0x0d, 0x06, 0x90, 0x28, 0x39, 0x05, 0xf9, 0x18, 0x0c, - 0x55, 0x9a, 0x4c, 0x87, 0x6c, 0x4b, 0xf7, 0x6c, 0x47, 0xb4, 0x16, 0xa5, 0x6b, 0x4a, 0x70, 0xa9, - 0x60, 0x84, 0x9e, 0xbc, 0x08, 0x50, 0xba, 0x53, 0xd5, 0xec, 0x06, 0x2d, 0x69, 0xf3, 0x42, 0x19, - 0xb0, 0xb4, 0xbe, 0xe1, 0xd6, 0x1c, 0xbb, 0x41, 0x6b, 0xba, 0x23, 0x57, 0x2b, 0x51, 0x93, 0x29, - 0x18, 0x29, 0xd5, 0xeb, 0xd4, 0x75, 0x35, 0xfa, 0x99, 0x36, 0x75, 0x3d, 0x57, 0xe9, 0x7d, 0x24, - 0x77, 0x79, 0x60, 0xe2, 0xe1, 0xed, 0xad, 0xe2, 0x83, 0x3a, 0x62, 0x6a, 0x8e, 0x40, 0x49, 0x2c, - 0x62, 0x85, 0xc8, 0x04, 0x0c, 0x97, 0xde, 0x6e, 0x3b, 0xb4, 0x62, 0x50, 0xcb, 0x33, 0xbd, 0x4d, - 0xa1, 0x21, 0x17, 0xb6, 0xb7, 0x8a, 0x8a, 0xce, 0x10, 0x35, 0x53, 0x60, 0x24, 0x26, 0xd1, 0x22, - 0x64, 0x01, 0xc6, 0x6e, 0x4c, 0x2e, 0x56, 0xa9, 0x73, 0xd7, 0xac, 0xd3, 0x52, 0xbd, 0x6e, 0xb7, - 0x2d, 0x4f, 0xe9, 0x43, 0x3e, 0x8f, 0x6e, 0x6f, 0x15, 0x1f, 0x5e, 0xad, 0xb7, 0x6a, 0x2e, 0xc7, - 0xd6, 0x74, 0x8e, 0x96, 0x98, 0x25, 0xcb, 0x92, 0x4f, 0xc0, 0xf0, 0x92, 0xc3, 0xb4, 0xd0, 0x28, - 0x53, 0x06, 0x57, 0xfa, 0x51, 0xff, 0xcf, 0x8e, 0x8b, 0x09, 0x88, 0x43, 0xfd, 0x9e, 0xe5, 0x8d, - 0xf5, 0x78, 0x81, 0x9a, 0x81, 0x38, 0xb9, 0xb1, 0x11, 0x56, 0x84, 0x82, 0xc2, 0x3e, 0xde, 0x74, - 0xa8, 0x91, 0xd0, 0xb6, 0x01, 0x6c, 0xf3, 0x95, 0xed, 0xad, 0xe2, 0xe3, 0x8e, 0xa0, 0xa9, 0x75, - 0x55, 0xbb, 0x8e, 0xac, 0xc8, 0x14, 0xf4, 0x33, 0x6d, 0xba, 0x69, 0x5a, 0x86, 0x02, 0x8f, 0x64, - 0x2e, 0x8f, 0x5c, 0x1b, 0xf5, 0x5b, 0xef, 0xc3, 0x27, 0xce, 0x6d, 0x6f, 0x15, 0x4f, 0x33, 0x1d, - 0xac, 0xad, 0x9b, 0x96, 0x3c, 0x45, 0x04, 0x45, 0xd5, 0xbf, 0xcc, 0xc3, 0x08, 0x13, 0x8e, 0xa4, - 0xc7, 0x25, 0x36, 0x24, 0x19, 0x84, 0x8d, 0x50, 0xb7, 0xa5, 0xd7, 0xa9, 0x50, 0x69, 0x64, 0x67, - 0xf9, 0x40, 0x89, 0x5d, 0x9c, 0x9e, 0x5c, 0x81, 0x7e, 0x0e, 0xaa, 0x94, 0x85, 0x96, 0x0f, 0x6f, - 0x6f, 0x15, 0x07, 0x5c, 0x84, 0xd5, 0x4c, 0x43, 0x0b, 0xd0, 0x4c, 0xcd, 0xf8, 0xdf, 0x33, 0xb6, - 0xeb, 0x31, 0xe6, 0x42, 0xc9, 0x51, 0xcd, 0x44, 0x81, 0x35, 0x81, 0x92, 0xd5, 0x2c, 0x5a, 0x88, - 0xbc, 0x00, 0xc0, 0x21, 0x25, 0xc3, 0x70, 0x84, 0xa6, 0x3f, 0xb8, 0xbd, 0x55, 0x7c, 0x40, 0xb0, - 0xd0, 0x0d, 0x43, 0x1e, 0x26, 0x12, 0x31, 0x69, 0xc2, 0x10, 0xff, 0x35, 0xab, 0x2f, 0xd3, 0x06, - 0x57, 0xf3, 0xc1, 0x6b, 0x97, 0x7d, 0x69, 0x46, 0xa5, 0x33, 0x2e, 0x93, 0x4e, 0x59, 0x9e, 0xb3, - 0x39, 0x51, 0x14, 0x33, 0xe3, 0x39, 0x51, 0x55, 0x03, 0x71, 0xf2, 0x98, 0x94, 0xcb, 0xb0, 0x09, - 0x73, 0xda, 0x76, 0x36, 0x74, 0xc7, 0xa0, 0xc6, 0xc4, 0xa6, 0x3c, 0x61, 0xae, 0xf8, 0xe0, 0xda, - 0xb2, 0xac, 0x03, 0x32, 0x39, 0x99, 0x84, 0x61, 0xce, 0xad, 0xda, 0x5e, 0xc6, 0xbe, 0xef, 0x4b, - 0x48, 0xcb, 0x6d, 0x2f, 0xc7, 0xfb, 0x3b, 0x5a, 0x86, 0x8d, 0x49, 0x0e, 0xb8, 0x4d, 0x1d, 0x36, - 0x9b, 0xa2, 0xfa, 0x8b, 0x31, 0x29, 0x98, 0xdc, 0xe5, 0x98, 0x24, 0x0f, 0x51, 0xe4, 0xfc, 0x2b, - 0x30, 0x96, 0x10, 0x05, 0x19, 0x85, 0xdc, 0x3a, 0xdd, 0xe4, 0xea, 0xa2, 0xb1, 0x3f, 0xc9, 0x19, - 0xe8, 0xbd, 0xab, 0x37, 0xda, 0x62, 0x2d, 0xd3, 0xf8, 0x8f, 0x17, 0xb3, 0x1f, 0xc9, 0xb0, 0xa9, - 0x9f, 0x4c, 0xda, 0x96, 0x45, 0xeb, 0x9e, 0x3c, 0xfb, 0x3f, 0x07, 0x03, 0xb3, 0x76, 0x5d, 0x6f, - 0x60, 0x3f, 0x72, 0xbd, 0x53, 0xb6, 0xb7, 0x8a, 0x67, 0x58, 0x07, 0x8e, 0x37, 0x18, 0x46, 0x6a, - 0x53, 0x48, 0xca, 0x14, 0x40, 0xa3, 0x4d, 0xdb, 0xa3, 0x58, 0x30, 0x1b, 0x2a, 0x00, 0x16, 0x74, - 0x10, 0x25, 0x2b, 0x40, 0x48, 0x4c, 0xae, 0x42, 0xff, 0x22, 0x5b, 0xf0, 0xea, 0x76, 0x43, 0x28, - 0x1f, 0xce, 0xc9, 0xb8, 0x08, 0xca, 0x83, 0xc6, 0x27, 0x52, 0x67, 0x60, 0x64, 0xb2, 0x61, 0x52, - 0xcb, 0x93, 0x5b, 0xcd, 0x86, 0x54, 0x69, 0x95, 0x5a, 0x9e, 0xdc, 0x6a, 0x1c, 0x7c, 0x3a, 0x83, - 0xca, 0xad, 0x0e, 0x48, 0xd5, 0xbf, 0x9b, 0x83, 0x07, 0x6f, 0xb6, 0x97, 0xa9, 0x63, 0x51, 0x8f, - 0xba, 0x62, 0x65, 0x0c, 0xb8, 0xce, 0xc3, 0x58, 0x02, 0x29, 0xb8, 0xe3, 0x8a, 0xb5, 0x1e, 0x20, - 0x6b, 0x62, 0xb1, 0x95, 0xa7, 0xbd, 0x44, 0x51, 0x32, 0x03, 0xa7, 0x42, 0x20, 0x6b, 0x84, 0xab, - 0x64, 0x71, 0x4e, 0xbf, 0xb8, 0xbd, 0x55, 0x3c, 0x2f, 0x71, 0x63, 0xcd, 0x96, 0x35, 0x38, 0x5e, - 0x8c, 0xdc, 0x84, 0xd1, 0x10, 0x74, 0xc3, 0xb1, 0xdb, 0x2d, 0x57, 0xc9, 0x21, 0xab, 0xe2, 0xf6, - 0x56, 0xf1, 0x21, 0x89, 0xd5, 0x2a, 0x22, 0xe5, 0x95, 0x34, 0x5e, 0x90, 0x7c, 0x6f, 0x46, 0xe6, - 0x26, 0x46, 0x61, 0x1e, 0x47, 0xe1, 0xf3, 0xfe, 0x28, 0xec, 0x28, 0xa4, 0xf1, 0x78, 0x49, 0x31, - 0x28, 0x63, 0xcd, 0x48, 0x0c, 0xca, 0x44, 0x8d, 0xe7, 0x27, 0xe1, 0x81, 0x54, 0x5e, 0x7b, 0xd2, - 0xea, 0x3f, 0xcf, 0xc9, 0x5c, 0x16, 0x6d, 0x23, 0xe8, 0xcc, 0x05, 0xb9, 0x33, 0x17, 0x6d, 0x03, - 0xcd, 0xa5, 0x4c, 0xb8, 0x88, 0x49, 0x8d, 0x6d, 0xd9, 0x46, 0xdc, 0x6a, 0x4a, 0x96, 0x25, 0x6f, - 0xc2, 0xd9, 0x04, 0x90, 0x4f, 0xd7, 0x5c, 0xfb, 0x2f, 0x6d, 0x6f, 0x15, 0xd5, 0x14, 0xae, 0xf1, - 0xd9, 0xbb, 0x03, 0x17, 0xa2, 0xc3, 0x39, 0x49, 0xea, 0xb6, 0xe5, 0xe9, 0xa6, 0x25, 0xac, 0x3c, - 0x3e, 0x4a, 0x3e, 0xb8, 0xbd, 0x55, 0x7c, 0x4c, 0xd6, 0x41, 0x9f, 0x26, 0xde, 0xf8, 0x4e, 0x7c, - 0x88, 0x01, 0x4a, 0x0a, 0xaa, 0xd2, 0xd4, 0x57, 0x7d, 0xd3, 0xf5, 0xf2, 0xf6, 0x56, 0xf1, 0x03, - 0xa9, 0x75, 0x98, 0x8c, 0x4a, 0x5e, 0x2a, 0x3b, 0x71, 0x22, 0x1a, 0x90, 0x10, 0x37, 0x6f, 0x1b, - 0x14, 0xbf, 0xa1, 0x17, 0xf9, 0xab, 0xdb, 0x5b, 0xc5, 0x8b, 0x12, 0x7f, 0xcb, 0x36, 0x68, 0xbc, - 0xf9, 0x29, 0xa5, 0xd5, 0xdf, 0xc8, 0xc1, 0xc5, 0x6a, 0x69, 0x6e, 0xb6, 0x62, 0xf8, 0xb6, 0xc5, - 0xa2, 0x63, 0xdf, 0x35, 0x0d, 0x69, 0xf4, 0x2e, 0xc3, 0xb9, 0x18, 0x6a, 0x0a, 0xcd, 0x99, 0xc0, - 0xaa, 0xc5, 0x6f, 0xf3, 0xed, 0x96, 0x96, 0xa0, 0xa9, 0x71, 0x9b, 0xa7, 0x16, 0x31, 0xe9, 0x3b, - 0x31, 0x62, 0x7d, 0x14, 0x43, 0x55, 0xd7, 0x6c, 0xc7, 0xab, 0xb7, 0x3d, 0xa1, 0x04, 0xd8, 0x47, - 0x89, 0x3a, 0x5c, 0x41, 0xd4, 0xa5, 0x0a, 0x9f, 0x0f, 0xf9, 0x7c, 0x06, 0x46, 0x4b, 0x9e, 0xe7, - 0x98, 0xcb, 0x6d, 0x8f, 0xce, 0xe9, 0xad, 0x96, 0x69, 0xad, 0xe2, 0x58, 0x1f, 0xbc, 0xf6, 0x52, - 0xb0, 0x46, 0x76, 0x95, 0xc4, 0x78, 0xbc, 0xb8, 0x34, 0x44, 0x75, 0x1f, 0x55, 0x6b, 0x72, 0x9c, - 0x3c, 0x44, 0xe3, 0xe5, 0xd8, 0x10, 0x4d, 0xe5, 0xb5, 0xa7, 0x21, 0xfa, 0x95, 0x1c, 0x5c, 0x58, - 0x58, 0xf7, 0x74, 0x8d, 0xba, 0x76, 0xdb, 0xa9, 0x53, 0xf7, 0x56, 0xcb, 0xd0, 0x3d, 0x1a, 0x8e, - 0xd4, 0x22, 0xf4, 0x96, 0x0c, 0x83, 0x1a, 0xc8, 0xae, 0x97, 0xef, 0xbf, 0x74, 0x06, 0xd0, 0x38, - 0x9c, 0x3c, 0x0e, 0x7d, 0xa2, 0x0c, 0x72, 0xef, 0x9d, 0x18, 0xdc, 0xde, 0x2a, 0xf6, 0xb5, 0x39, - 0x48, 0xf3, 0x71, 0x8c, 0xac, 0x4c, 0x1b, 0x94, 0x91, 0xe5, 0x42, 0x32, 0x83, 0x83, 0x34, 0x1f, - 0x47, 0x5e, 0x87, 0x11, 0x64, 0x1b, 0xb4, 0x47, 0xcc, 0x7d, 0x67, 0x7c, 0xe9, 0xca, 0x8d, 0xe5, - 0x4b, 0x13, 0xb6, 0xa6, 0xe6, 0xf8, 0x05, 0xb4, 0x18, 0x03, 0x72, 0x07, 0x46, 0x45, 0x23, 0x42, - 0xa6, 0xbd, 0x5d, 0x98, 0x3e, 0xb0, 0xbd, 0x55, 0x1c, 0x13, 0xed, 0x97, 0xd8, 0x26, 0x98, 0x30, - 0xc6, 0xa2, 0xd9, 0x21, 0xe3, 0xc2, 0x4e, 0x8c, 0xc5, 0x17, 0xcb, 0x8c, 0xe3, 0x4c, 0xd4, 0x37, - 0x60, 0x48, 0x2e, 0x48, 0xce, 0xe2, 0x1e, 0x97, 0x8f, 0x13, 0xdc, 0x1d, 0x9b, 0x06, 0x6e, 0x6c, - 0x9f, 0x86, 0xc1, 0x32, 0x75, 0xeb, 0x8e, 0xd9, 0x62, 0x56, 0x83, 0x50, 0xf2, 0x53, 0xdb, 0x5b, - 0xc5, 0x41, 0x23, 0x04, 0x6b, 0x32, 0x8d, 0xfa, 0x6f, 0x33, 0x70, 0x96, 0xf1, 0x2e, 0xb9, 0xae, - 0xb9, 0x6a, 0x35, 0xe5, 0x65, 0xfb, 0x49, 0x28, 0x54, 0xb1, 0x3e, 0x51, 0xd3, 0x99, 0xed, 0xad, - 0xe2, 0x28, 0x6f, 0x81, 0xa4, 0x87, 0x82, 0x26, 0xd8, 0xe0, 0x65, 0x77, 0xd8, 0xe0, 0x31, 0x93, - 0xd6, 0xd3, 0x1d, 0xcf, 0xb4, 0x56, 0xab, 0x9e, 0xee, 0xb5, 0xdd, 0x88, 0x49, 0x2b, 0x30, 0x35, - 0x17, 0x51, 0x11, 0x93, 0x36, 0x52, 0x88, 0xbc, 0x02, 0x43, 0x53, 0x96, 0x11, 0x32, 0xe1, 0x13, - 0xe2, 0x43, 0xcc, 0xd2, 0xa4, 0x08, 0x4f, 0xb2, 0x88, 0x14, 0x50, 0xff, 0xd7, 0x0c, 0x28, 0x7c, - 0x37, 0x36, 0x6b, 0xba, 0xde, 0x1c, 0x6d, 0x2e, 0x4b, 0xb3, 0xd3, 0xb4, 0xbf, 0xbd, 0x63, 0x38, - 0x69, 0x2d, 0x42, 0x53, 0x40, 0x6c, 0xef, 0x1a, 0xa6, 0xeb, 0xc5, 0x27, 0xc3, 0x58, 0x29, 0x52, - 0x81, 0x3e, 0xce, 0x99, 0xdb, 0x12, 0x83, 0xd7, 0x14, 0x5f, 0x11, 0xe2, 0x55, 0x73, 0x65, 0x68, - 0x72, 0x62, 0x79, 0x7f, 0x2e, 0xca, 0xab, 0xff, 0x5b, 0x16, 0x46, 0xe3, 0x85, 0xc8, 0x1d, 0xe8, - 0x7f, 0xcd, 0x36, 0x2d, 0x6a, 0x2c, 0x58, 0xd8, 0xc2, 0xee, 0xa7, 0x14, 0xbe, 0x2d, 0x7e, 0xfa, - 0x2d, 0x2c, 0x53, 0x93, 0x2d, 0x58, 0x3c, 0xb4, 0x08, 0x98, 0x91, 0x4f, 0xc0, 0x00, 0xb3, 0x01, - 0xef, 0x22, 0xe7, 0xec, 0x8e, 0x9c, 0x1f, 0x11, 0x9c, 0xcf, 0x38, 0xbc, 0x50, 0x92, 0x75, 0xc8, - 0x8e, 0xe9, 0x95, 0x46, 0x75, 0xd7, 0xb6, 0x44, 0xcf, 0xa3, 0x5e, 0x39, 0x08, 0x91, 0xf5, 0x8a, - 0xd3, 0x30, 0xd3, 0x95, 0x7f, 0x2c, 0x76, 0x83, 0xb4, 0x77, 0xe1, 0xb2, 0x8a, 0xf7, 0x80, 0x44, - 0xac, 0x7e, 0x7f, 0x16, 0x9e, 0x0a, 0x45, 0xa6, 0xd1, 0xbb, 0x26, 0xdd, 0x10, 0xe2, 0x5c, 0x33, - 0x5b, 0x62, 0xf3, 0xc8, 0x54, 0xde, 0x9d, 0x5c, 0xd3, 0xad, 0x55, 0x6a, 0x90, 0x2b, 0xd0, 0xcb, - 0x76, 0xf8, 0xae, 0x92, 0x41, 0x73, 0x0d, 0xa7, 0x13, 0x87, 0x01, 0xe4, 0xd3, 0x07, 0xa4, 0x20, - 0x36, 0x14, 0x96, 0x1c, 0xdd, 0xf4, 0xfc, 0x9e, 0x2d, 0x25, 0x7b, 0x76, 0x17, 0x35, 0x8e, 0x73, - 0x1e, 0x7c, 0xce, 0x47, 0x41, 0x78, 0x08, 0x90, 0x05, 0xc1, 0x49, 0xce, 0xbf, 0x00, 0x83, 0x12, - 0xf1, 0x9e, 0x26, 0xf5, 0xaf, 0xe5, 0x65, 0x5d, 0xf7, 0x9b, 0x25, 0x74, 0xfd, 0x2a, 0xd3, 0x51, - 0xd7, 0x65, 0x56, 0x05, 0x57, 0x72, 0xa1, 0x89, 0x08, 0x8a, 0x6a, 0x22, 0x82, 0xc8, 0x33, 0xd0, - 0xcf, 0x59, 0x04, 0xfb, 0x57, 0xdc, 0xfb, 0x3a, 0x08, 0x8b, 0x2e, 0xcd, 0x01, 0x21, 0xf9, 0xc5, - 0x0c, 0x3c, 0xdc, 0x55, 0x12, 0xa8, 0x0c, 0x83, 0xd7, 0x9e, 0xdd, 0x97, 0x18, 0x27, 0x9e, 0xda, - 0xde, 0x2a, 0x5e, 0x69, 0x06, 0x24, 0x35, 0x47, 0xa2, 0xa9, 0xd5, 0x39, 0x91, 0xd4, 0xae, 0xee, - 0x4d, 0x61, 0xc6, 0x23, 0xaf, 0x74, 0x1a, 0xcf, 0x70, 0xac, 0xfa, 0xa6, 0xdf, 0xc8, 0x7c, 0x68, - 0x3c, 0x8a, 0xef, 0x5d, 0xf1, 0x49, 0x52, 0xaa, 0xe9, 0xc0, 0x85, 0xd4, 0xe1, 0x1c, 0xc7, 0x94, - 0xf5, 0xcd, 0x85, 0x95, 0x39, 0xdb, 0xf2, 0xd6, 0xfc, 0x0a, 0x7a, 0xe5, 0x43, 0x10, 0xac, 0xc0, - 0xd0, 0x37, 0x6b, 0xf6, 0x4a, 0xad, 0xc9, 0xa8, 0x52, 0xea, 0xe8, 0xc4, 0x89, 0x4d, 0xb4, 0x62, - 0xcc, 0xf9, 0x53, 0x50, 0x21, 0x3c, 0xa2, 0xf2, 0xc7, 0x69, 0x72, 0xc2, 0x89, 0x15, 0x52, 0x2b, - 0x30, 0x34, 0x6b, 0xd7, 0xd7, 0x03, 0x75, 0x79, 0x01, 0x0a, 0x4b, 0xba, 0xb3, 0x4a, 0x3d, 0x94, - 0xc5, 0xe0, 0xb5, 0xb1, 0x71, 0x7e, 0xec, 0xcb, 0x88, 0x38, 0x62, 0x62, 0x44, 0xcc, 0x06, 0x05, - 0x0f, 0x7f, 0x6b, 0xa2, 0x80, 0xfa, 0xad, 0x5e, 0x18, 0x12, 0x47, 0x94, 0x38, 0x9b, 0x93, 0x17, - 0xc3, 0x43, 0x5f, 0x31, 0x7d, 0x05, 0xc7, 0x34, 0xc1, 0xf1, 0xd2, 0x10, 0x63, 0xf6, 0x07, 0x5b, - 0xc5, 0xcc, 0xf6, 0x56, 0xb1, 0x47, 0xeb, 0x97, 0x36, 0x95, 0xe1, 0x7a, 0x23, 0x2d, 0xb0, 0xf2, - 0xa1, 0x63, 0xac, 0x2c, 0x5f, 0x7f, 0x5e, 0x81, 0x3e, 0xd1, 0x06, 0xa1, 0x71, 0xe7, 0xc2, 0xb3, - 0x8c, 0xc8, 0x51, 0x6b, 0xac, 0xb4, 0x5f, 0x8a, 0xbc, 0x04, 0x05, 0xbe, 0xb7, 0x17, 0x02, 0x38, - 0x9b, 0x7e, 0x16, 0x12, 0x2b, 0x2e, 0xca, 0x90, 0x19, 0x80, 0x70, 0x5f, 0x1f, 0x9c, 0x2c, 0x0b, - 0x0e, 0xc9, 0x1d, 0x7f, 0x8c, 0x8b, 0x54, 0x96, 0x3c, 0x07, 0x43, 0x4b, 0xd4, 0x69, 0x9a, 0x96, - 0xde, 0xa8, 0x9a, 0x6f, 0xfb, 0x87, 0xcb, 0xb8, 0xf0, 0xba, 0xe6, 0xdb, 0xf2, 0xc8, 0x8d, 0xd0, - 0x91, 0x4f, 0xa7, 0xed, 0x9b, 0xfb, 0xb0, 0x21, 0x8f, 0xee, 0xb8, 0xa1, 0x8c, 0xb5, 0x27, 0x65, - 0x1b, 0xfd, 0x3a, 0x0c, 0x47, 0xb6, 0x4c, 0xe2, 0xf4, 0xf0, 0xe1, 0x24, 0x6b, 0x69, 0xff, 0x17, - 0x63, 0x1b, 0xe5, 0xc0, 0x34, 0xb9, 0x62, 0x99, 0x9e, 0xa9, 0x37, 0x26, 0xed, 0x66, 0x53, 0xb7, - 0x0c, 0x65, 0x20, 0xd4, 0x64, 0x93, 0x63, 0x6a, 0x75, 0x8e, 0x92, 0x35, 0x39, 0x5a, 0x88, 0x6d, - 0xcb, 0x45, 0x1f, 0x6a, 0xb4, 0x6e, 0x3b, 0xcc, 0x16, 0xc0, 0xc3, 0x41, 0xb1, 0x2d, 0x77, 0x39, - 0xae, 0xe6, 0xf8, 0x48, 0xd9, 0xd8, 0x8e, 0x17, 0x7c, 0x2d, 0xdf, 0x3f, 0x38, 0x3a, 0x14, 0x3f, - 0xcf, 0x55, 0x7f, 0x21, 0x07, 0x83, 0x82, 0x94, 0x2d, 0xa5, 0x27, 0x0a, 0x7e, 0x10, 0x05, 0x4f, - 0x55, 0xd4, 0xc2, 0x61, 0x29, 0xaa, 0xfa, 0x85, 0x6c, 0x30, 0x1b, 0x2d, 0x3a, 0xa6, 0x75, 0xb0, - 0xd9, 0xe8, 0x12, 0xc0, 0xe4, 0x5a, 0xdb, 0x5a, 0xe7, 0xf7, 0x56, 0xd9, 0xf0, 0xde, 0xaa, 0x6e, - 0x6a, 0x12, 0x86, 0x3c, 0x0c, 0xf9, 0x32, 0xe3, 0xcf, 0x7a, 0x66, 0x68, 0x62, 0xe0, 0x1d, 0xce, - 0x29, 0xf3, 0x94, 0x86, 0x60, 0xb6, 0xb9, 0x9a, 0xd8, 0xf4, 0x28, 0x37, 0x67, 0x73, 0x7c, 0x73, - 0xb5, 0xcc, 0x00, 0x1a, 0x87, 0x93, 0xeb, 0x30, 0x56, 0xa6, 0x0d, 0x7d, 0x73, 0xce, 0x6c, 0x34, - 0x4c, 0x97, 0xd6, 0x6d, 0xcb, 0x70, 0x51, 0xc8, 0xa2, 0xba, 0xa6, 0xab, 0x25, 0x09, 0x88, 0x0a, - 0x85, 0x85, 0x95, 0x15, 0x97, 0x7a, 0x28, 0xbe, 0xdc, 0x04, 0xb0, 0xc9, 0xd9, 0x46, 0x88, 0x26, - 0x30, 0xea, 0xaf, 0x64, 0xd8, 0xee, 0xc5, 0x5d, 0xf7, 0xec, 0x56, 0xa0, 0xe5, 0x07, 0x12, 0xc9, - 0x95, 0xd0, 0xae, 0xc8, 0xe2, 0xd7, 0x9e, 0x12, 0x5f, 0xdb, 0x27, 0x6c, 0x8b, 0xd0, 0xa2, 0x48, - 0xfd, 0xaa, 0xdc, 0x0e, 0x5f, 0xa5, 0xfe, 0x45, 0x16, 0xce, 0x89, 0x16, 0x4f, 0x36, 0xcc, 0xd6, - 0xb2, 0xad, 0x3b, 0x86, 0x46, 0xeb, 0xd4, 0xbc, 0x4b, 0x8f, 0xe7, 0xc0, 0x8b, 0x0e, 0x9d, 0xfc, - 0x01, 0x86, 0xce, 0x35, 0xdc, 0x08, 0x32, 0xc9, 0xe0, 0x81, 0x2f, 0x37, 0x2a, 0x46, 0xb7, 0xb7, - 0x8a, 0x43, 0x06, 0x07, 0xe3, 0x91, 0xbf, 0x26, 0x13, 0x31, 0x25, 0x99, 0xa5, 0xd6, 0xaa, 0xb7, - 0x86, 0x4a, 0xd2, 0xcb, 0x95, 0xa4, 0x81, 0x10, 0x4d, 0x60, 0xd4, 0x7f, 0x99, 0x85, 0x33, 0x71, - 0x91, 0x57, 0xa9, 0x65, 0x9c, 0xc8, 0xfb, 0xdd, 0x91, 0xf7, 0x77, 0x72, 0xf0, 0x90, 0x28, 0x53, - 0x5d, 0xd3, 0x1d, 0x6a, 0x94, 0x4d, 0x87, 0xd6, 0x3d, 0xdb, 0xd9, 0x3c, 0xc6, 0x06, 0xd4, 0xe1, - 0x89, 0xfd, 0x3a, 0x14, 0xc4, 0xf6, 0x9f, 0xaf, 0x33, 0x23, 0x41, 0x4b, 0x10, 0x9a, 0x58, 0xa1, - 0xf8, 0xd1, 0x41, 0xac, 0xb3, 0x0a, 0xbb, 0xe9, 0xac, 0x8f, 0xc0, 0x70, 0x20, 0x7a, 0xdc, 0x88, - 0xf6, 0x85, 0xd6, 0x96, 0xe1, 0x23, 0x70, 0x2f, 0xaa, 0x45, 0x09, 0xb1, 0x36, 0x1f, 0x50, 0x29, - 0xa3, 0x35, 0x34, 0x2c, 0x6a, 0x0b, 0xca, 0x99, 0x86, 0x26, 0x13, 0xa9, 0x5b, 0x79, 0x38, 0x9f, - 0xde, 0xed, 0x1a, 0xd5, 0x8d, 0x93, 0x5e, 0x7f, 0x5f, 0xf6, 0x3a, 0x79, 0x14, 0xf2, 0x8b, 0xba, - 0xb7, 0x26, 0xee, 0xc1, 0xf1, 0x4e, 0x78, 0xc5, 0x6c, 0xd0, 0x5a, 0x4b, 0xf7, 0xd6, 0x34, 0x44, - 0x49, 0x73, 0x06, 0x20, 0xc7, 0x94, 0x39, 0x43, 0x5a, 0xec, 0x07, 0x1f, 0xc9, 0x5c, 0xce, 0xa7, - 0x2e, 0xf6, 0xdf, 0xca, 0x77, 0x9a, 0x57, 0xee, 0x38, 0xa6, 0x47, 0x4f, 0x34, 0xec, 0x44, 0xc3, - 0x0e, 0xa8, 0x61, 0x7f, 0x94, 0x85, 0xe1, 0x60, 0xd3, 0xf4, 0x16, 0xad, 0x1f, 0xcd, 0x5a, 0x15, - 0x6e, 0x65, 0x72, 0x07, 0xde, 0xca, 0x1c, 0x44, 0xa1, 0xd4, 0xe0, 0xc8, 0x93, 0x9b, 0x06, 0x28, - 0x31, 0x7e, 0xe4, 0x19, 0x1c, 0x74, 0x3e, 0x0a, 0x7d, 0x73, 0xfa, 0x3d, 0xb3, 0xd9, 0x6e, 0x0a, - 0x2b, 0x1d, 0xfd, 0xba, 0x9a, 0xfa, 0x3d, 0xcd, 0x87, 0xab, 0x7f, 0x3f, 0x03, 0x23, 0x42, 0xa8, - 0x82, 0xf9, 0x81, 0xa4, 0x1a, 0x4a, 0x27, 0x7b, 0x60, 0xe9, 0xe4, 0xf6, 0x2f, 0x1d, 0xf5, 0xa7, - 0x72, 0xa0, 0x4c, 0x9b, 0x0d, 0xba, 0xe4, 0xe8, 0x96, 0xbb, 0x42, 0x1d, 0xb1, 0x9d, 0x9e, 0x62, - 0xac, 0x0e, 0xf4, 0x81, 0xd2, 0x94, 0x92, 0xdd, 0xd7, 0x94, 0xf2, 0x21, 0x18, 0x10, 0x8d, 0x09, - 0x7c, 0x0a, 0x71, 0xd4, 0x38, 0x3e, 0x50, 0x0b, 0xf1, 0x8c, 0xb8, 0xd4, 0x6a, 0x39, 0xf6, 0x5d, - 0xea, 0xf0, 0x5b, 0x2a, 0x41, 0xac, 0xfb, 0x40, 0x2d, 0xc4, 0x4b, 0x9c, 0xa9, 0x6f, 0x2f, 0xca, - 0x9c, 0xa9, 0xa3, 0x85, 0x78, 0x72, 0x19, 0xfa, 0x67, 0xed, 0xba, 0x8e, 0x82, 0xe6, 0xd3, 0xca, - 0xd0, 0xf6, 0x56, 0xb1, 0xbf, 0x21, 0x60, 0x5a, 0x80, 0x65, 0x94, 0x65, 0x7b, 0xc3, 0x6a, 0xd8, - 0x3a, 0x77, 0x7e, 0xe9, 0xe7, 0x94, 0x86, 0x80, 0x69, 0x01, 0x96, 0x51, 0x32, 0x99, 0xa3, 0x53, - 0x51, 0x7f, 0xc8, 0x73, 0x45, 0xc0, 0xb4, 0x00, 0xab, 0xfe, 0x4a, 0x9e, 0x69, 0xaf, 0x6b, 0xbe, - 0x7d, 0xdf, 0xaf, 0x0b, 0xe1, 0x80, 0xe9, 0xdd, 0xc7, 0x80, 0xb9, 0x6f, 0x0e, 0xec, 0xd4, 0xbf, - 0xec, 0x03, 0x10, 0xd2, 0x9f, 0x3a, 0xd9, 0x1c, 0x1e, 0x4c, 0x6b, 0xca, 0x30, 0x36, 0x65, 0xad, - 0xe9, 0x56, 0x9d, 0x1a, 0xe1, 0xb1, 0x65, 0x01, 0x87, 0x36, 0xfa, 0xf4, 0x52, 0x81, 0x0c, 0xcf, - 0x2d, 0xb5, 0x64, 0x01, 0xf2, 0x34, 0x0c, 0x56, 0x2c, 0x8f, 0x3a, 0x7a, 0xdd, 0x33, 0xef, 0x52, - 0x31, 0x35, 0xe0, 0xcd, 0xb0, 0x19, 0x82, 0x35, 0x99, 0x86, 0x5c, 0x87, 0xa1, 0x45, 0xdd, 0xf1, - 0xcc, 0xba, 0xd9, 0xd2, 0x2d, 0xcf, 0x55, 0xfa, 0x71, 0x46, 0x43, 0x0b, 0xa3, 0x25, 0xc1, 0xb5, - 0x08, 0x15, 0xf9, 0x34, 0x0c, 0xe0, 0xd6, 0x14, 0x1d, 0xa7, 0x07, 0x76, 0xbc, 0x38, 0x7c, 0x2c, - 0x74, 0x0f, 0xe4, 0xa7, 0xaf, 0x78, 0x03, 0x1c, 0xbf, 0x3b, 0x0c, 0x38, 0x92, 0x8f, 0x43, 0xdf, - 0x94, 0x65, 0x20, 0x73, 0xd8, 0x91, 0xb9, 0x2a, 0x98, 0x9f, 0x0d, 0x99, 0xdb, 0xad, 0x18, 0x6f, - 0x9f, 0x5d, 0xfa, 0x28, 0x1b, 0x7c, 0xf7, 0x46, 0xd9, 0xd0, 0xbb, 0x70, 0x2c, 0x3e, 0x7c, 0x58, - 0xc7, 0xe2, 0x23, 0xfb, 0x3c, 0x16, 0x57, 0xdf, 0x86, 0xc1, 0x89, 0xc5, 0xe9, 0x60, 0xf4, 0x3e, - 0x08, 0xb9, 0x45, 0xe1, 0xa9, 0x90, 0xe7, 0xf6, 0x4c, 0xcb, 0x34, 0x34, 0x06, 0x23, 0x57, 0xa0, - 0x7f, 0x12, 0xdd, 0xdf, 0xc4, 0x2d, 0x62, 0x9e, 0xaf, 0x7f, 0x75, 0x84, 0xa1, 0x17, 0xac, 0x8f, - 0x26, 0x8f, 0x43, 0xdf, 0xa2, 0x63, 0xaf, 0x3a, 0x7a, 0x53, 0xac, 0xc1, 0xe8, 0x2a, 0xd2, 0xe2, - 0x20, 0xcd, 0xc7, 0xa9, 0x3f, 0x94, 0xf1, 0xcd, 0x76, 0x56, 0xa2, 0xda, 0xc6, 0xa3, 0x79, 0xac, - 0xbb, 0x9f, 0x97, 0x70, 0x39, 0x48, 0xf3, 0x71, 0xe4, 0x0a, 0xf4, 0x4e, 0x39, 0x8e, 0xed, 0xc8, - 0xce, 0xe6, 0x94, 0x01, 0xe4, 0xeb, 0x5e, 0xa4, 0x20, 0xcf, 0xc3, 0x20, 0x9f, 0x73, 0xf8, 0x89, - 0x66, 0xae, 0xdb, 0x4d, 0xa9, 0x4c, 0xa9, 0x7e, 0x23, 0x27, 0xd9, 0x6c, 0x5c, 0xe2, 0xf7, 0xe1, - 0xad, 0xc0, 0x33, 0x90, 0x9b, 0x58, 0x9c, 0x16, 0x13, 0xe0, 0x69, 0xbf, 0xa8, 0xa4, 0x2a, 0xb1, - 0x72, 0x8c, 0x9a, 0x5c, 0x80, 0xfc, 0x22, 0x53, 0x9f, 0x02, 0xaa, 0x47, 0xff, 0xf6, 0x56, 0x31, - 0xdf, 0x62, 0xfa, 0x83, 0x50, 0xc4, 0xb2, 0xcd, 0x0c, 0xdf, 0x31, 0x71, 0x6c, 0xb8, 0x8f, 0xb9, - 0x00, 0xf9, 0x92, 0xb3, 0x7a, 0x57, 0xcc, 0x5a, 0x88, 0xd5, 0x9d, 0xd5, 0xbb, 0x1a, 0x42, 0xc9, - 0x55, 0x00, 0x8d, 0x7a, 0x6d, 0xc7, 0xc2, 0x77, 0x20, 0x03, 0x78, 0xfe, 0x86, 0xb3, 0xa1, 0x83, - 0xd0, 0x5a, 0xdd, 0x36, 0xa8, 0x26, 0x91, 0xa8, 0x3f, 0x17, 0x5e, 0xec, 0x94, 0x4d, 0x77, 0xfd, - 0xa4, 0x0b, 0xf7, 0xd0, 0x85, 0xba, 0x38, 0xe2, 0x4c, 0x76, 0x52, 0x11, 0x7a, 0xa7, 0x1b, 0xfa, - 0xaa, 0x8b, 0x7d, 0x28, 0x7c, 0xc9, 0x56, 0x18, 0x40, 0xe3, 0xf0, 0x58, 0x3f, 0xf5, 0xef, 0xdc, - 0x4f, 0x3f, 0xda, 0x1b, 0x8c, 0xb6, 0x79, 0xea, 0x6d, 0xd8, 0xce, 0x49, 0x57, 0xed, 0xb6, 0xab, - 0x2e, 0x41, 0x5f, 0xd5, 0xa9, 0x4b, 0x47, 0x17, 0xb8, 0x1f, 0x70, 0x9d, 0x3a, 0x3f, 0xb6, 0xf0, - 0x91, 0x8c, 0xae, 0xec, 0x7a, 0x48, 0xd7, 0x17, 0xd2, 0x19, 0xae, 0x27, 0xe8, 0x04, 0x52, 0xd0, - 0x2d, 0xda, 0x8e, 0x27, 0x3a, 0x2e, 0xa0, 0x6b, 0xd9, 0x8e, 0xa7, 0xf9, 0x48, 0xf2, 0x21, 0x80, - 0xa5, 0xc9, 0x45, 0xdf, 0xd9, 0x7e, 0x20, 0xf4, 0x05, 0x14, 0x5e, 0xf6, 0x9a, 0x84, 0x26, 0x4b, - 0x30, 0xb0, 0xd0, 0xa2, 0x0e, 0xdf, 0x0a, 0xf1, 0x97, 0x1d, 0x1f, 0x8c, 0x89, 0x56, 0xf4, 0xfb, - 0xb8, 0xf8, 0x3f, 0x20, 0xe7, 0xeb, 0x8b, 0xed, 0xff, 0xd4, 0x42, 0x46, 0xe4, 0x79, 0x28, 0x94, - 0xb8, 0x9d, 0x37, 0x88, 0x2c, 0x03, 0x91, 0xe1, 0x16, 0x94, 0xa3, 0xf8, 0x9e, 0x5d, 0xc7, 0xbf, - 0x35, 0x41, 0xae, 0x5e, 0x81, 0xd1, 0x78, 0x35, 0x64, 0x10, 0xfa, 0x26, 0x17, 0xe6, 0xe7, 0xa7, - 0x26, 0x97, 0x46, 0x7b, 0x48, 0x3f, 0xe4, 0xab, 0x53, 0xf3, 0xe5, 0xd1, 0x8c, 0xfa, 0x4b, 0xd2, - 0x0c, 0xc2, 0x54, 0xeb, 0xe4, 0x6a, 0xf8, 0x40, 0xf7, 0x2d, 0xa3, 0x78, 0x1f, 0x8a, 0x27, 0x06, - 0x4d, 0xd3, 0xf3, 0xa8, 0x21, 0x56, 0x09, 0xbc, 0x2f, 0xf4, 0xee, 0x69, 0x09, 0x3c, 0x79, 0x12, - 0x86, 0x11, 0x26, 0xae, 0x08, 0xf9, 0xfe, 0x58, 0x14, 0x70, 0xee, 0x69, 0x51, 0xa4, 0xfa, 0xcd, - 0xf0, 0x76, 0x78, 0x96, 0xea, 0xc7, 0xf5, 0x46, 0xf1, 0x3d, 0xd2, 0x5f, 0xea, 0xdf, 0xe4, 0xf9, - 0x13, 0x10, 0xfe, 0x70, 0xef, 0x28, 0x44, 0x19, 0x1e, 0xe9, 0xe6, 0xf6, 0x70, 0xa4, 0xfb, 0x24, - 0x14, 0xe6, 0xa8, 0xb7, 0x66, 0xfb, 0x8e, 0x5f, 0xe8, 0xa1, 0xd7, 0x44, 0x88, 0xec, 0xa1, 0xc7, - 0x69, 0xc8, 0x3a, 0x10, 0xff, 0x55, 0x5e, 0xe0, 0x88, 0xed, 0x1f, 0x21, 0x9f, 0x4b, 0xec, 0x53, - 0xaa, 0xf8, 0x24, 0x17, 0x7d, 0xec, 0xcf, 0x04, 0x8e, 0xde, 0x92, 0x27, 0xd6, 0x5f, 0x6f, 0x15, - 0x0b, 0x9c, 0x46, 0x4b, 0x61, 0x4b, 0x5e, 0x87, 0x81, 0xb9, 0xe9, 0x92, 0x78, 0xa1, 0xc7, 0xbd, - 0x22, 0x1e, 0x0c, 0xa4, 0xe8, 0x23, 0x02, 0x91, 0xe0, 0x7b, 0x9b, 0xe6, 0x8a, 0x9e, 0x7c, 0xa0, - 0x17, 0x72, 0x61, 0xda, 0xc2, 0x5f, 0xee, 0x88, 0xd3, 0x85, 0x40, 0x5b, 0xa2, 0xef, 0x79, 0xe2, - 0xb2, 0xe2, 0xd8, 0x98, 0xb6, 0xf4, 0x1f, 0x60, 0x74, 0x2f, 0xc0, 0x58, 0xa9, 0xd5, 0x6a, 0x98, - 0xd4, 0x40, 0x7d, 0xd1, 0xda, 0x0d, 0xea, 0x0a, 0x97, 0x1f, 0x7c, 0x0c, 0xa2, 0x73, 0x64, 0x0d, - 0xdf, 0x85, 0xd6, 0x9c, 0x76, 0xd4, 0x3f, 0x33, 0x59, 0x56, 0xfd, 0x91, 0x2c, 0x9c, 0x9d, 0x74, - 0xa8, 0xee, 0xd1, 0xb9, 0xe9, 0x52, 0xa9, 0x8d, 0x3e, 0x72, 0x8d, 0x06, 0xb5, 0x56, 0x8f, 0x66, - 0x58, 0x7f, 0x14, 0x46, 0x82, 0x06, 0x54, 0xeb, 0x76, 0x8b, 0xca, 0x0f, 0xab, 0xea, 0x3e, 0xa6, - 0xe6, 0x32, 0x94, 0x16, 0x23, 0x25, 0x37, 0xe1, 0x74, 0x00, 0x29, 0x35, 0x1a, 0xf6, 0x86, 0x46, - 0xdb, 0x2e, 0x77, 0x8c, 0xed, 0xe7, 0x8e, 0xb1, 0x21, 0x07, 0x9d, 0xe1, 0x6b, 0x0e, 0x23, 0xd0, - 0xd2, 0x4a, 0xa9, 0x5f, 0xcd, 0xc1, 0xb9, 0xdb, 0x7a, 0xc3, 0x34, 0x42, 0xd1, 0x68, 0xd4, 0x6d, - 0xd9, 0x96, 0x4b, 0x8f, 0xd1, 0x28, 0x8d, 0x0c, 0x85, 0xfc, 0xa1, 0x0c, 0x85, 0x64, 0x17, 0xf5, - 0x1e, 0xb8, 0x8b, 0x0a, 0xfb, 0xea, 0xa2, 0x7f, 0x91, 0x81, 0x51, 0xdf, 0xf1, 0x5f, 0x7e, 0x4d, - 0x2d, 0x79, 0xa5, 0xe3, 0x11, 0x62, 0xcc, 0x0f, 0x1a, 0xf1, 0xa4, 0x0a, 0x7d, 0x53, 0xf7, 0x5a, - 0xa6, 0x43, 0xdd, 0x5d, 0x38, 0x71, 0x3f, 0x2c, 0x8e, 0x4b, 0xc6, 0x28, 0x2f, 0x92, 0x38, 0x29, - 0xe1, 0x60, 0x7c, 0xce, 0xc7, 0x9f, 0x3e, 0x4c, 0xf8, 0x4f, 0xc4, 0xf9, 0x73, 0x3e, 0xf1, 0x44, - 0x22, 0xf2, 0x3e, 0x33, 0x24, 0x25, 0x8f, 0x41, 0x6e, 0x69, 0x69, 0x56, 0xcc, 0xa4, 0xf8, 0x34, - 0xdf, 0xf3, 0xe4, 0xf7, 0x8a, 0x0c, 0xab, 0xfe, 0x69, 0x16, 0x80, 0xa9, 0x02, 0x1f, 0xae, 0x47, - 0xa2, 0x84, 0x13, 0xd0, 0xef, 0x0b, 0x5c, 0xa8, 0x61, 0xe0, 0xb5, 0x1f, 0xef, 0x88, 0x78, 0xdd, - 0xc1, 0x0b, 0x8d, 0xa2, 0xef, 0x48, 0xce, 0xef, 0x01, 0x70, 0x67, 0x83, 0x8e, 0xe4, 0xbe, 0xfb, - 0xf8, 0x87, 0x60, 0x40, 0xcc, 0x78, 0x76, 0xe4, 0xfc, 0xbf, 0xee, 0x03, 0xb5, 0x10, 0x1f, 0x9b, - 0x5a, 0x0b, 0x07, 0x58, 0x88, 0x7d, 0xf1, 0xf2, 0x5e, 0x39, 0x11, 0xef, 0x21, 0x8b, 0xf7, 0x4b, - 0x42, 0xbc, 0xfc, 0x05, 0xcf, 0xb1, 0x15, 0xef, 0xa1, 0x9d, 0x7d, 0xab, 0x7f, 0x94, 0x01, 0xc2, - 0x9a, 0xb5, 0xa8, 0xbb, 0xee, 0x86, 0xed, 0x18, 0xdc, 0x39, 0xfd, 0x48, 0x04, 0x73, 0x78, 0xf7, - 0x95, 0xdf, 0xe8, 0x87, 0xd3, 0x11, 0xc7, 0xdf, 0x63, 0x3e, 0x59, 0x5d, 0x89, 0x8e, 0xa6, 0x6e, - 0xaf, 0x5e, 0x3e, 0x20, 0x5f, 0x88, 0xf6, 0x46, 0x1e, 0xa0, 0x49, 0x37, 0xa1, 0x4f, 0xc1, 0x90, - 0xf8, 0xc1, 0x56, 0x68, 0xff, 0xa6, 0x0b, 0x47, 0xa9, 0xcb, 0x00, 0x5a, 0x04, 0x4d, 0x9e, 0x85, - 0x01, 0x36, 0x60, 0x56, 0x31, 0x8a, 0x47, 0x5f, 0xf8, 0xa2, 0xc4, 0xf0, 0x81, 0xf2, 0x7a, 0x12, - 0x50, 0x4a, 0xef, 0x88, 0xfa, 0x77, 0xf1, 0x8e, 0xe8, 0x4d, 0x18, 0x2c, 0x59, 0x96, 0xed, 0xe1, - 0x26, 0xdd, 0x15, 0x57, 0x13, 0x1d, 0xad, 0xf2, 0xc7, 0xf0, 0x71, 0x7c, 0x48, 0x9f, 0x6a, 0x96, - 0xcb, 0x0c, 0xc9, 0x35, 0xff, 0x55, 0x0c, 0x75, 0x84, 0x57, 0x39, 0x5e, 0xcf, 0x38, 0x02, 0x96, - 0x7c, 0x14, 0x83, 0x9d, 0x37, 0xbc, 0xe8, 0xd8, 0x2d, 0xdb, 0xa5, 0x06, 0x17, 0xd4, 0x60, 0x18, - 0x6a, 0xa0, 0x25, 0x10, 0xf8, 0x8e, 0x2d, 0x12, 0x51, 0x23, 0x52, 0x84, 0xac, 0xc0, 0x19, 0xff, - 0xa2, 0x38, 0x78, 0x31, 0x58, 0x29, 0xbb, 0xca, 0x10, 0xbe, 0x4a, 0x22, 0x71, 0x65, 0xa8, 0x94, - 0x27, 0x2e, 0xfa, 0xd7, 0x22, 0xfe, 0x93, 0xc3, 0x9a, 0x69, 0xc8, 0x5d, 0x9d, 0xca, 0x8f, 0x7c, - 0x17, 0x0c, 0xce, 0xe9, 0xf7, 0xca, 0x6d, 0x71, 0xf6, 0x32, 0xbc, 0xfb, 0xdb, 0x97, 0xa6, 0x7e, - 0xaf, 0x66, 0x88, 0x72, 0x31, 0x9b, 0x42, 0x66, 0x49, 0x6a, 0x70, 0x76, 0xd1, 0xb1, 0x9b, 0xb6, - 0x47, 0x8d, 0xd8, 0xe3, 0xbb, 0x53, 0xe1, 0x6b, 0xdd, 0x96, 0xa0, 0xa8, 0x75, 0x79, 0x85, 0xd7, - 0x81, 0x0d, 0x69, 0xc2, 0xa9, 0x92, 0xeb, 0xb6, 0x9b, 0x34, 0xbc, 0xa1, 0x1a, 0xdd, 0xf1, 0x33, - 0x3e, 0x28, 0xbc, 0x96, 0x1f, 0xd2, 0xb1, 0x28, 0xbf, 0xa0, 0xaa, 0x79, 0xa6, 0x5c, 0x23, 0x7e, - 0x4b, 0x9c, 0xf7, 0x6b, 0xf9, 0xfe, 0x91, 0xd1, 0x53, 0xda, 0xb9, 0x64, 0x63, 0x96, 0x4c, 0xaf, - 0x41, 0xd5, 0xaf, 0x67, 0x00, 0x42, 0x01, 0x93, 0xa7, 0xa2, 0xa1, 0x82, 0x32, 0xe1, 0x45, 0x87, - 0x88, 0x5e, 0x10, 0x89, 0x0d, 0x44, 0x2e, 0x40, 0x1e, 0x23, 0x5c, 0x64, 0xc3, 0x83, 0xd5, 0x75, - 0xd3, 0x32, 0x34, 0x84, 0x32, 0xac, 0xf4, 0x14, 0x1d, 0xb1, 0x78, 0xa9, 0xcf, 0xad, 0xc2, 0x32, - 0x9c, 0xaa, 0xb6, 0x97, 0xfd, 0xba, 0xa5, 0x77, 0x75, 0x18, 0x68, 0xc3, 0x6d, 0x2f, 0x07, 0x8f, - 0x51, 0x23, 0x61, 0x4c, 0xa2, 0x45, 0xd4, 0x5f, 0xc9, 0xc4, 0x66, 0xc1, 0x23, 0x5c, 0xf4, 0x3e, - 0x90, 0xf4, 0xd3, 0x48, 0x4e, 0x4b, 0xea, 0xff, 0x94, 0x85, 0xc1, 0x45, 0xdb, 0xf1, 0x44, 0xc8, - 0x90, 0xe3, 0xbd, 0x0a, 0x49, 0x7b, 0xa5, 0xfc, 0x1e, 0xf6, 0x4a, 0x17, 0x20, 0x2f, 0xb9, 0x28, - 0xf3, 0x7b, 0x11, 0xc3, 0x70, 0x34, 0x84, 0xaa, 0xdf, 0x9d, 0x05, 0xf8, 0xf8, 0xd3, 0x4f, 0xdf, - 0xc7, 0x02, 0x52, 0x7f, 0x32, 0x03, 0xa7, 0xc4, 0x45, 0x9d, 0x14, 0x74, 0xab, 0xcf, 0xbf, 0x62, - 0x95, 0xc7, 0x25, 0x07, 0x69, 0x3e, 0x8e, 0x2d, 0x01, 0x53, 0xf7, 0x4c, 0x0f, 0xef, 0x2a, 0xa4, - 0xa8, 0x5b, 0x54, 0xc0, 0xe4, 0x25, 0xc0, 0xa7, 0x23, 0x4f, 0xf9, 0x57, 0x90, 0xb9, 0x70, 0xdd, - 0x63, 0x05, 0xa6, 0x52, 0xaf, 0x21, 0xd5, 0x5f, 0xcb, 0x43, 0x7e, 0xea, 0x1e, 0xad, 0x1f, 0xf3, - 0xae, 0x91, 0x0e, 0x36, 0xf3, 0x07, 0x3c, 0xd8, 0xdc, 0x8f, 0x4f, 0xc5, 0x2b, 0x61, 0x7f, 0x16, - 0xa2, 0xd5, 0xc7, 0x7a, 0x3e, 0x5e, 0xbd, 0xdf, 0xd3, 0xc7, 0xcf, 0x25, 0xe7, 0xff, 0xcb, 0x41, - 0xae, 0x3a, 0xb9, 0x78, 0xa2, 0x37, 0x47, 0xaa, 0x37, 0xdd, 0xef, 0xac, 0xd5, 0xe0, 0x1a, 0xaa, - 0x3f, 0xf4, 0x12, 0x8d, 0xdd, 0x38, 0x7d, 0x27, 0x07, 0x23, 0xd5, 0xe9, 0xa5, 0x45, 0xe9, 0x24, - 0xf8, 0x26, 0xf7, 0xe4, 0x43, 0x9f, 0x32, 0xde, 0xa5, 0x17, 0x12, 0xf6, 0xcc, 0xad, 0x8a, 0xe5, - 0x3d, 0x77, 0xfd, 0xb6, 0xde, 0x68, 0x53, 0x3c, 0x7a, 0xe1, 0x7e, 0xbf, 0xae, 0xf9, 0x36, 0xfd, - 0x2a, 0x3e, 0xfc, 0xf7, 0x19, 0x90, 0x8f, 0x42, 0xee, 0x96, 0xf0, 0xc8, 0xe8, 0xc4, 0xe7, 0x99, - 0x6b, 0x9c, 0x0f, 0x9b, 0x04, 0x73, 0x6d, 0xd3, 0x40, 0x0e, 0xac, 0x14, 0x2b, 0x7c, 0x43, 0x2c, - 0xc0, 0xbb, 0x2a, 0xbc, 0xea, 0x17, 0xbe, 0x51, 0x29, 0x93, 0x2a, 0x0c, 0x2e, 0x52, 0xa7, 0x69, - 0x62, 0x47, 0xf9, 0x73, 0x76, 0x77, 0x26, 0x6c, 0xa7, 0x32, 0xd8, 0x0a, 0x0b, 0x21, 0x33, 0x99, - 0x0b, 0x79, 0x03, 0x80, 0xdb, 0x28, 0xbb, 0x0c, 0xe4, 0xf8, 0x30, 0xda, 0xfd, 0xdc, 0xb4, 0x4c, - 0xb1, 0xf1, 0x24, 0x66, 0x64, 0x1d, 0x46, 0xe7, 0x6c, 0xc3, 0x5c, 0x31, 0xb9, 0xeb, 0x25, 0x56, - 0x50, 0xd8, 0xd9, 0xe1, 0x89, 0x99, 0x92, 0x4d, 0xa9, 0x5c, 0x5a, 0x35, 0x09, 0xc6, 0xea, 0xff, - 0xdd, 0x0b, 0x79, 0xd6, 0xed, 0x27, 0xe3, 0xf7, 0x20, 0xe3, 0xb7, 0x04, 0xa3, 0x77, 0x6c, 0x67, - 0xdd, 0xb4, 0x56, 0x03, 0xaf, 0x78, 0xb1, 0x37, 0x45, 0x4f, 0x9e, 0x0d, 0x8e, 0xab, 0x05, 0x0e, - 0xf4, 0x5a, 0x82, 0x7c, 0x87, 0x11, 0xfc, 0x02, 0x00, 0x7f, 0xeb, 0x8e, 0x34, 0xfd, 0x61, 0xb0, - 0x0a, 0xfe, 0x12, 0x1e, 0x1d, 0xed, 0xe5, 0x60, 0x15, 0x21, 0x31, 0xdb, 0x84, 0x73, 0x5f, 0x88, - 0x01, 0xf4, 0xbb, 0xc7, 0x4d, 0x38, 0xfa, 0x42, 0xc8, 0x46, 0x00, 0xf7, 0x8a, 0x58, 0x04, 0x90, - 0xee, 0x97, 0x20, 0x26, 0x88, 0xc8, 0xe4, 0x20, 0xc2, 0xc3, 0xa5, 0x5c, 0x2f, 0x69, 0x12, 0x0f, - 0xf2, 0x5c, 0xec, 0x02, 0x9c, 0x44, 0xb8, 0x75, 0xbc, 0xff, 0x0e, 0x1d, 0xa8, 0x86, 0x76, 0x72, - 0xa0, 0x52, 0xbf, 0x90, 0x85, 0x81, 0x6a, 0x7b, 0xd9, 0xdd, 0x74, 0x3d, 0xda, 0x3c, 0xe6, 0x6a, - 0xec, 0x6f, 0xaf, 0xf2, 0xa9, 0xdb, 0xab, 0xc7, 0x7c, 0xa1, 0x48, 0xe7, 0x8e, 0x81, 0x49, 0xe7, - 0x8b, 0xe3, 0x7f, 0xcf, 0xc2, 0x28, 0xbf, 0x38, 0x2b, 0x9b, 0x6e, 0xfd, 0x10, 0x9c, 0xf9, 0x8f, - 0x5e, 0x2a, 0x07, 0xbb, 0x6c, 0xde, 0xc5, 0x13, 0x09, 0xf5, 0xb3, 0x59, 0x18, 0x2c, 0xb5, 0xbd, - 0xb5, 0x92, 0x87, 0xba, 0x75, 0x5f, 0xee, 0x4f, 0x7e, 0x37, 0x03, 0xa7, 0x58, 0x43, 0x96, 0xec, - 0x75, 0x6a, 0x1d, 0xc2, 0xc1, 0xa3, 0x7c, 0x80, 0x98, 0xdd, 0xe7, 0x01, 0xa2, 0x2f, 0xcb, 0xdc, - 0xde, 0x64, 0x89, 0xc7, 0xe5, 0x9a, 0xdd, 0xa0, 0xc7, 0xfb, 0x33, 0x0e, 0xf1, 0xb8, 0xdc, 0x17, - 0xc8, 0x21, 0x5c, 0xcf, 0xbc, 0xbf, 0x04, 0x72, 0x08, 0x67, 0x4b, 0xef, 0x0f, 0x81, 0x7c, 0x23, - 0x03, 0x03, 0x13, 0xb6, 0x77, 0xcc, 0x07, 0xbe, 0xf8, 0x8a, 0xe3, 0xad, 0xe6, 0xfe, 0x57, 0x1c, - 0x6f, 0xdd, 0x54, 0x7f, 0x2c, 0x0b, 0x67, 0x44, 0x90, 0x6e, 0x71, 0xfe, 0x70, 0x32, 0x1d, 0x8b, - 0xc1, 0x96, 0x14, 0xcd, 0xc9, 0x3c, 0x24, 0x44, 0xf3, 0xf3, 0x39, 0x38, 0x83, 0xa1, 0x4c, 0xd9, - 0xb6, 0xec, 0x7d, 0x60, 0x8b, 0x90, 0x7a, 0xf4, 0x12, 0x74, 0x2e, 0xe5, 0x12, 0xf4, 0xaf, 0xb7, - 0x8a, 0xcf, 0xad, 0x9a, 0xde, 0x5a, 0x7b, 0x79, 0xbc, 0x6e, 0x37, 0xaf, 0xae, 0x3a, 0xfa, 0x5d, - 0x93, 0x5f, 0xff, 0xe9, 0x8d, 0xab, 0x41, 0xbe, 0x0b, 0xbd, 0x65, 0x8a, 0x4c, 0x18, 0x55, 0xdc, - 0xeb, 0x30, 0xae, 0xfe, 0xf5, 0xa9, 0x0b, 0xf0, 0x9a, 0x6d, 0x5a, 0xc2, 0xa7, 0x90, 0x1b, 0xba, - 0x55, 0xb6, 0x3f, 0x7c, 0xcb, 0x36, 0xad, 0x5a, 0xdc, 0xb1, 0x70, 0xaf, 0xf5, 0x85, 0xac, 0x35, - 0xa9, 0x1a, 0xf5, 0xef, 0x65, 0xe0, 0xc1, 0xa8, 0x16, 0xbf, 0x1f, 0x6c, 0xc7, 0x1f, 0xcf, 0xc2, - 0x03, 0x37, 0x50, 0x38, 0x81, 0x23, 0xc7, 0xc9, 0xbc, 0x25, 0x06, 0x67, 0x8a, 0x6c, 0x4e, 0x2c, - 0xca, 0xce, 0xb2, 0x39, 0x99, 0xd4, 0x85, 0x6c, 0x7e, 0x3f, 0x03, 0xa7, 0x17, 0x2a, 0xe5, 0xc9, - 0xf7, 0xc9, 0x88, 0x4a, 0x7e, 0xcf, 0x31, 0x37, 0x38, 0x13, 0xdf, 0x73, 0xcc, 0x4d, 0x4f, 0xf6, - 0x3d, 0xd5, 0xd2, 0xdc, 0xec, 0xfb, 0x49, 0xdf, 0x22, 0xdf, 0xf3, 0x3e, 0xd0, 0xb7, 0xc8, 0xf7, - 0x1c, 0x73, 0x7d, 0xfb, 0x7f, 0x0b, 0x30, 0x78, 0xb3, 0xbd, 0x4c, 0x85, 0x4b, 0xc8, 0x7d, 0x7d, - 0xde, 0x7a, 0x0d, 0x06, 0x85, 0x18, 0xf0, 0xae, 0x42, 0x0a, 0x59, 0x27, 0x42, 0x90, 0xf0, 0xa8, - 0x40, 0x32, 0x11, 0xb9, 0x00, 0xf9, 0xdb, 0xd4, 0x59, 0x96, 0x5f, 0x73, 0xde, 0xa5, 0xce, 0xb2, - 0x86, 0x50, 0x32, 0x1b, 0x3a, 0xaa, 0x97, 0x16, 0x2b, 0x98, 0xbe, 0x44, 0x5c, 0x93, 0x60, 0x3e, - 0x96, 0xc0, 0xdb, 0x4c, 0x6f, 0x99, 0x3c, 0xf1, 0x89, 0xfc, 0x92, 0x3c, 0x5e, 0x92, 0xcc, 0xc3, - 0x98, 0xec, 0x6e, 0xc4, 0x73, 0x77, 0xf4, 0xa7, 0xb0, 0x4b, 0xcb, 0xda, 0x91, 0x2c, 0x4a, 0x5e, - 0x81, 0x21, 0x1f, 0x88, 0x8e, 0x53, 0x03, 0x61, 0xc0, 0xf8, 0x80, 0x55, 0x2c, 0x31, 0x50, 0xa4, - 0x80, 0xcc, 0x00, 0x0f, 0xff, 0x21, 0x85, 0x41, 0xcc, 0x11, 0x2d, 0x52, 0x80, 0x3c, 0x8b, 0x0c, - 0xf0, 0x71, 0x05, 0xba, 0x88, 0x0c, 0xe2, 0x53, 0x47, 0x74, 0x84, 0x77, 0x04, 0x9c, 0x3f, 0x68, - 0x8d, 0x90, 0x91, 0x05, 0x80, 0xf0, 0x2a, 0x5f, 0x84, 0x0d, 0xd8, 0xb3, 0x93, 0x81, 0xc4, 0x42, - 0xbe, 0x84, 0x1b, 0xde, 0xcf, 0x25, 0x9c, 0xfa, 0x87, 0x59, 0x18, 0x2c, 0xb5, 0x5a, 0xc1, 0x50, - 0x78, 0x0a, 0x0a, 0xa5, 0x56, 0xeb, 0x96, 0x56, 0x91, 0x03, 0x88, 0xeb, 0xad, 0x56, 0xad, 0xed, - 0x98, 0xb2, 0x27, 0x26, 0x27, 0x22, 0x93, 0x30, 0x5c, 0x6a, 0xb5, 0x16, 0xdb, 0xcb, 0x0d, 0xb3, - 0x2e, 0xe5, 0x23, 0xe2, 0xa9, 0xd3, 0x5a, 0xad, 0x5a, 0x0b, 0x31, 0xf1, 0xa4, 0x54, 0xd1, 0x32, - 0xe4, 0x4d, 0x0c, 0xb6, 0x23, 0xd2, 0xe1, 0xf0, 0x84, 0x1b, 0x6a, 0x10, 0x3a, 0x3c, 0x6c, 0xdb, - 0x78, 0x40, 0xc4, 0x43, 0xac, 0x5f, 0xf0, 0x03, 0xd5, 0xb3, 0x8a, 0x12, 0x69, 0x6f, 0x42, 0x96, - 0xe4, 0xc3, 0xd0, 0x57, 0x6a, 0xb5, 0xa4, 0x5b, 0x1e, 0x74, 0xe5, 0x61, 0xa5, 0x62, 0x7d, 0xec, - 0x93, 0x9d, 0x7f, 0x09, 0x46, 0xa2, 0x95, 0xed, 0x29, 0x44, 0xfb, 0x5f, 0x65, 0xf0, 0x83, 0x8e, - 0xb9, 0x27, 0xf1, 0x33, 0x90, 0x2b, 0xb5, 0x5a, 0x62, 0x3e, 0x3a, 0x9d, 0xd2, 0x1f, 0xf1, 0x87, - 0xc7, 0xa5, 0x56, 0xcb, 0xff, 0xf4, 0x63, 0xfe, 0x24, 0x61, 0x5f, 0x9f, 0xfe, 0x0d, 0xfe, 0xe9, - 0xc7, 0xfb, 0xb9, 0x80, 0xfa, 0x6b, 0x39, 0x38, 0x55, 0x6a, 0xb5, 0x4e, 0x42, 0xbb, 0x1f, 0xd6, - 0xf3, 0xe6, 0xa7, 0x01, 0xa4, 0xe9, 0xb1, 0x2f, 0x78, 0x30, 0x35, 0x28, 0x4d, 0x8d, 0x4a, 0x46, - 0x93, 0x88, 0x7c, 0xf5, 0xeb, 0xdf, 0x93, 0xfa, 0x7d, 0x36, 0x87, 0x53, 0xf1, 0x71, 0x0f, 0xd5, - 0xf4, 0x5e, 0xe9, 0x36, 0xd1, 0x07, 0x85, 0x3d, 0xf5, 0xc1, 0xef, 0x44, 0x06, 0x0f, 0x86, 0x0a, - 0x3f, 0xe9, 0x85, 0xde, 0x03, 0x99, 0xc5, 0x23, 0xb2, 0x30, 0x45, 0xfc, 0x18, 0x3f, 0x7d, 0x91, - 0x88, 0x66, 0x54, 0x67, 0xa8, 0x9a, 0x69, 0x68, 0x31, 0x5a, 0xbf, 0x0f, 0xfb, 0xf6, 0xd4, 0x87, - 0x5b, 0x59, 0x7c, 0xb1, 0x1c, 0x44, 0x43, 0x3a, 0xf8, 0xee, 0xe2, 0x2a, 0x00, 0xbf, 0xef, 0x0f, - 0x9c, 0x89, 0x87, 0x79, 0xe0, 0x13, 0x9e, 0xd5, 0x48, 0x04, 0x3e, 0x09, 0x49, 0x02, 0xbf, 0xa4, - 0x5c, 0xaa, 0x5f, 0xd2, 0x15, 0xe8, 0xd7, 0xf4, 0x8d, 0xd7, 0xdb, 0xd4, 0xd9, 0x14, 0xe6, 0x0c, - 0x0f, 0x36, 0xa8, 0x6f, 0xd4, 0x3e, 0xc3, 0x80, 0x5a, 0x80, 0x26, 0x6a, 0xf0, 0xe4, 0x5d, 0xf2, - 0xc3, 0xe0, 0x27, 0xd3, 0xc1, 0x43, 0xf7, 0xfd, 0x28, 0x3a, 0x79, 0x11, 0x72, 0xa5, 0x3b, 0x55, - 0x21, 0xd9, 0xa0, 0x6b, 0x4b, 0x77, 0xaa, 0x42, 0x5e, 0x1d, 0xcb, 0xde, 0xa9, 0xaa, 0x9f, 0xcd, - 0x02, 0x49, 0x52, 0x92, 0xe7, 0x60, 0x00, 0xa1, 0xab, 0x4c, 0x67, 0xe4, 0x74, 0x98, 0x1b, 0x6e, - 0xcd, 0x41, 0x68, 0xc4, 0xb8, 0xf3, 0x49, 0xc9, 0x0b, 0x98, 0xf9, 0x57, 0x24, 0x64, 0x8b, 0xa4, - 0xc3, 0xdc, 0x70, 0xfd, 0x5c, 0xb9, 0xb1, 0xc4, 0xbf, 0x82, 0x18, 0xed, 0xc2, 0x3b, 0xd5, 0x19, - 0xdb, 0xf5, 0x84, 0xa8, 0xb9, 0x5d, 0xb8, 0xe1, 0x62, 0x1e, 0xd6, 0x88, 0x5d, 0xc8, 0xc9, 0x30, - 0x97, 0xd4, 0x9d, 0x2a, 0x7f, 0x1c, 0x62, 0x68, 0x76, 0xc3, 0x37, 0x28, 0x79, 0x2e, 0xa9, 0x0d, - 0xb7, 0xc6, 0x1f, 0x96, 0x18, 0x98, 0x72, 0x38, 0x92, 0x4b, 0x2a, 0x52, 0x4a, 0xfd, 0x62, 0x3f, - 0x8c, 0x96, 0x75, 0x4f, 0x5f, 0xd6, 0x5d, 0x2a, 0xed, 0xa6, 0x4f, 0xf9, 0x30, 0xff, 0x73, 0x24, - 0x39, 0x18, 0xcb, 0x29, 0x5f, 0x13, 0x2f, 0x40, 0x3e, 0x1a, 0xf2, 0x0d, 0x32, 0x7d, 0xca, 0xa9, - 0xc3, 0x96, 0x6b, 0x2d, 0x01, 0xd6, 0x12, 0x84, 0xe4, 0x49, 0x18, 0xf4, 0x61, 0x6c, 0x03, 0x90, - 0x0b, 0x75, 0xc6, 0x58, 0x66, 0xf6, 0xbf, 0x26, 0xa3, 0xc9, 0x0b, 0x30, 0xe4, 0xff, 0x94, 0x4c, - 0x6b, 0x9e, 0x07, 0x6d, 0x39, 0xb1, 0x7b, 0x92, 0x49, 0xe5, 0xa2, 0x38, 0xbf, 0xf5, 0x46, 0x8a, - 0xc6, 0x52, 0x8d, 0x45, 0x48, 0xc9, 0x67, 0x60, 0xc4, 0xff, 0x2d, 0x36, 0x0c, 0x3c, 0x2b, 0xdb, - 0x93, 0x41, 0x46, 0xe3, 0x98, 0x58, 0xc7, 0xa3, 0xe4, 0x7c, 0xeb, 0xf0, 0x90, 0x9f, 0x3d, 0xcb, - 0x58, 0x4e, 0xee, 0x1c, 0x62, 0x15, 0x90, 0x0a, 0x8c, 0xf9, 0x90, 0x50, 0x43, 0xfb, 0xc2, 0x1d, - 0xa3, 0xb1, 0x5c, 0x4b, 0x55, 0xd2, 0x64, 0x29, 0xd2, 0x80, 0x0b, 0x11, 0xa0, 0xe1, 0xae, 0x99, - 0x2b, 0x9e, 0xd8, 0xee, 0x89, 0xc8, 0xbf, 0x22, 0x5d, 0x62, 0xc0, 0x95, 0xd3, 0xf8, 0x79, 0x4f, - 0xa3, 0x39, 0x99, 0xba, 0x72, 0x23, 0x55, 0x38, 0xe3, 0xe3, 0x6f, 0x4c, 0x2e, 0x2e, 0x3a, 0xf6, - 0x5b, 0xb4, 0xee, 0x55, 0xca, 0x62, 0xbb, 0x8c, 0x11, 0xe1, 0x8c, 0xe5, 0xda, 0x6a, 0xbd, 0xc5, - 0x94, 0x82, 0xe1, 0xa2, 0xcc, 0x53, 0x0b, 0x93, 0xdb, 0xf0, 0x80, 0x04, 0xaf, 0x58, 0xae, 0xa7, - 0x5b, 0x75, 0x5a, 0x29, 0x8b, 0x3d, 0x34, 0xee, 0xe7, 0x05, 0x57, 0x53, 0x20, 0xa3, 0x6c, 0xd3, - 0x8b, 0x93, 0x97, 0x60, 0xd8, 0x47, 0xf0, 0xbb, 0xbb, 0x41, 0xbc, 0xbb, 0xc3, 0x21, 0x69, 0x2c, - 0xd7, 0xe2, 0x6f, 0x18, 0xa3, 0xc4, 0xb2, 0x46, 0x61, 0x42, 0xf9, 0xa1, 0x88, 0x46, 0x79, 0x9b, - 0xad, 0x54, 0x65, 0xc4, 0x24, 0xf3, 0xaf, 0x84, 0x1a, 0xb5, 0xe0, 0x98, 0xab, 0x26, 0xdf, 0x49, - 0xfb, 0xcf, 0x16, 0x97, 0x6b, 0x36, 0x02, 0xd3, 0xf4, 0x83, 0x93, 0x9f, 0x2f, 0xc1, 0xe9, 0x14, - 0x1d, 0xdb, 0xd3, 0x8e, 0xf1, 0x0b, 0xd9, 0xb0, 0x11, 0xc7, 0x7c, 0xdb, 0x38, 0x01, 0xfd, 0xfe, - 0x97, 0x08, 0xe3, 0x41, 0xe9, 0x34, 0x34, 0xe3, 0x3c, 0x7c, 0x7c, 0x44, 0x1c, 0xc7, 0x7c, 0x2b, - 0x79, 0x18, 0xe2, 0x78, 0x27, 0x13, 0x8a, 0xe3, 0x98, 0x6f, 0x2f, 0x7f, 0x3f, 0x17, 0xce, 0x49, - 0x27, 0x7b, 0xcc, 0xc3, 0x32, 0x93, 0x43, 0xef, 0xd3, 0xc2, 0x1e, 0x9e, 0x0f, 0xca, 0xaa, 0xd9, - 0xb7, 0x4f, 0xd5, 0xfc, 0xe3, 0x64, 0x7f, 0x72, 0xd3, 0xf3, 0x58, 0xf6, 0xe7, 0x21, 0x0c, 0x56, - 0x72, 0x2d, 0x5c, 0xc7, 0xb8, 0x8d, 0xde, 0x2b, 0x05, 0xd6, 0x5b, 0x16, 0x26, 0x7a, 0x94, 0x84, - 0x7c, 0x12, 0xce, 0x45, 0x00, 0x8b, 0xba, 0xa3, 0x37, 0xa9, 0x17, 0xe6, 0xf9, 0xc3, 0x50, 0x49, - 0x7e, 0xe9, 0x5a, 0x2b, 0x40, 0xcb, 0xb9, 0x03, 0x3b, 0x70, 0x90, 0x94, 0xa3, 0x6f, 0x0f, 0xae, - 0xc9, 0x7f, 0x92, 0x07, 0x25, 0x30, 0x10, 0x83, 0x47, 0x38, 0x47, 0x38, 0x19, 0xbf, 0x27, 0x3a, - 0xd7, 0x84, 0xb1, 0x50, 0x18, 0xd5, 0x76, 0xb3, 0xa9, 0x63, 0x07, 0x33, 0x03, 0xb4, 0x18, 0x67, - 0x16, 0x12, 0x72, 0x9b, 0xf3, 0xbc, 0xb0, 0x39, 0x49, 0xf8, 0xc8, 0xa9, 0xe6, 0x72, 0x16, 0x5a, - 0x92, 0x2b, 0xf9, 0x52, 0x06, 0xce, 0x94, 0x56, 0x56, 0x68, 0xdd, 0xa3, 0xc6, 0xc2, 0x32, 0x33, - 0xbe, 0x26, 0xed, 0xb6, 0xe5, 0xf9, 0xf6, 0xee, 0x8b, 0x9d, 0xab, 0xe3, 0x9d, 0x34, 0x9e, 0x56, - 0x98, 0xb7, 0x24, 0x08, 0x1a, 0xa0, 0x0b, 0x92, 0x9a, 0x8d, 0x34, 0xb5, 0x3a, 0x12, 0x69, 0xa9, - 0xf5, 0x9e, 0xbf, 0x01, 0x0f, 0x76, 0x64, 0xb9, 0x93, 0xb1, 0xd3, 0x2b, 0x1b, 0x3b, 0xff, 0x20, - 0x13, 0xaa, 0x7b, 0x4c, 0x48, 0x64, 0x1c, 0x20, 0x04, 0x89, 0xed, 0xcf, 0xc8, 0xf6, 0x56, 0x11, - 0x42, 0xa1, 0x69, 0x12, 0x05, 0x59, 0x80, 0x82, 0x10, 0x0b, 0xcf, 0xdc, 0xfa, 0xa1, 0x1d, 0x7a, - 0x61, 0x5c, 0x96, 0x03, 0x6e, 0x6d, 0xc4, 0x37, 0x0b, 0x36, 0xe7, 0x5f, 0x80, 0xc1, 0xfd, 0x7e, - 0xd7, 0x97, 0x72, 0x40, 0xe4, 0xbd, 0xca, 0x11, 0x1a, 0x72, 0xef, 0x89, 0xc1, 0xb2, 0xbf, 0xcc, - 0x2b, 0x97, 0xa1, 0x9f, 0x7d, 0x02, 0xe6, 0x32, 0x90, 0x62, 0x97, 0xb6, 0x05, 0x4c, 0x0b, 0xb0, - 0x61, 0xe0, 0xa0, 0xbe, 0xf4, 0xc0, 0x41, 0xea, 0x0f, 0xe7, 0xe0, 0xac, 0xdc, 0x21, 0x65, 0x8a, - 0xe1, 0xd0, 0x4f, 0x3a, 0xe5, 0x5d, 0xec, 0x14, 0x15, 0x0a, 0xdc, 0x44, 0x15, 0x71, 0xe9, 0xf9, - 0xf1, 0x01, 0x42, 0x34, 0x81, 0x51, 0xff, 0x69, 0x16, 0x86, 0x17, 0x6d, 0xd7, 0x5b, 0x75, 0xa8, - 0xbb, 0xa8, 0x3b, 0xee, 0x7d, 0xdc, 0x1d, 0x1f, 0x81, 0x61, 0x0c, 0xfd, 0xd2, 0xa4, 0x16, 0x0f, - 0x8f, 0xd2, 0x2b, 0x25, 0x92, 0xf0, 0x11, 0x22, 0x67, 0x50, 0x84, 0x90, 0x69, 0x3f, 0xb7, 0x2f, - 0xa4, 0x80, 0x3c, 0xdc, 0xb8, 0xe0, 0x70, 0xf5, 0x67, 0x72, 0x30, 0xe4, 0x4b, 0x79, 0xc2, 0x3c, - 0xae, 0xf7, 0x01, 0x47, 0x2b, 0xe4, 0xab, 0x00, 0x8b, 0xb6, 0xe3, 0xe9, 0x8d, 0xf9, 0x50, 0xf3, - 0xf1, 0x20, 0xad, 0x85, 0x50, 0x5e, 0x46, 0x22, 0xc1, 0xf5, 0x2b, 0x34, 0xde, 0xf8, 0xc4, 0xc4, - 0xd7, 0xaf, 0x00, 0xaa, 0x49, 0x14, 0xea, 0x6f, 0x65, 0xe1, 0x94, 0xdf, 0x49, 0x53, 0xf7, 0x68, - 0xbd, 0x7d, 0x3f, 0xcf, 0x4d, 0x51, 0x69, 0xf7, 0xee, 0x28, 0x6d, 0xf5, 0xdf, 0x48, 0x13, 0xc9, - 0x64, 0xc3, 0x3e, 0x99, 0x48, 0xfe, 0x36, 0x74, 0x5c, 0xfd, 0xde, 0x1c, 0x9c, 0xf1, 0xa5, 0x3e, - 0xdd, 0xb6, 0x70, 0x0b, 0x3a, 0xa9, 0x37, 0x1a, 0xf7, 0xf3, 0x9e, 0x6f, 0xd0, 0x17, 0xc4, 0x82, - 0x88, 0xa5, 0x26, 0xf2, 0xb7, 0xad, 0x08, 0x70, 0xcd, 0x36, 0x0d, 0x4d, 0x26, 0x22, 0xaf, 0xc0, - 0x90, 0xff, 0xb3, 0xe4, 0xac, 0xfa, 0x1b, 0x3d, 0x3c, 0x50, 0x0e, 0x0a, 0xe9, 0x4e, 0xe4, 0xc9, - 0x78, 0xa4, 0x80, 0xfa, 0xcf, 0x0b, 0x70, 0xfe, 0x8e, 0x69, 0x19, 0xf6, 0x86, 0xeb, 0xa7, 0xff, - 0x3b, 0xf6, 0x07, 0x2a, 0x47, 0x9d, 0xf6, 0xef, 0x75, 0x78, 0x20, 0x2e, 0x52, 0x27, 0x08, 0xca, - 0x2c, 0x7a, 0x67, 0x83, 0x13, 0xd4, 0xfc, 0x44, 0x80, 0xe2, 0x56, 0x46, 0x4b, 0x2f, 0x19, 0xcf, - 0x24, 0xd8, 0xb7, 0x9b, 0x4c, 0x82, 0x4f, 0x40, 0xa1, 0x6c, 0x37, 0x75, 0xd3, 0x0f, 0x1e, 0x82, - 0xa3, 0x38, 0xa8, 0x17, 0x31, 0x9a, 0xa0, 0x60, 0xfc, 0x45, 0xc5, 0xd8, 0x65, 0x03, 0x21, 0x7f, - 0xbf, 0x00, 0xb3, 0xd2, 0x34, 0x99, 0x88, 0xd8, 0x30, 0x2c, 0xaa, 0x13, 0x77, 0x28, 0x80, 0x9b, - 0xa7, 0x67, 0x7d, 0x19, 0x75, 0x56, 0xab, 0xf1, 0x48, 0x39, 0xbe, 0x8d, 0xe2, 0x09, 0x0e, 0xc5, - 0xc7, 0xf0, 0xdb, 0x14, 0x2d, 0xca, 0x5f, 0x12, 0x02, 0x4e, 0x32, 0x83, 0x49, 0x21, 0xe0, 0x2c, - 0x23, 0x13, 0x91, 0x29, 0x18, 0xc3, 0xd0, 0xb9, 0xc1, 0x56, 0x8a, 0xa9, 0xc4, 0x10, 0x1a, 0x95, - 0x78, 0x34, 0xcf, 0xa3, 0xed, 0xb2, 0x8f, 0xab, 0xd5, 0x05, 0x5a, 0x4b, 0x96, 0x38, 0xff, 0x2a, - 0x90, 0x64, 0x9b, 0xf7, 0x74, 0x38, 0xff, 0xc5, 0x6c, 0xb8, 0xaf, 0x3b, 0xee, 0xee, 0x15, 0x87, - 0x71, 0x1c, 0xfd, 0xcb, 0x19, 0x18, 0x4b, 0x84, 0x62, 0x26, 0xcf, 0x00, 0x70, 0x88, 0x14, 0xf2, - 0x0e, 0x63, 0x48, 0x84, 0xe1, 0x99, 0xc5, 0x52, 0x12, 0x92, 0x91, 0xab, 0xd0, 0xcf, 0x7f, 0x89, - 0x30, 0x35, 0xc9, 0x22, 0xed, 0xb6, 0x69, 0x68, 0x01, 0x51, 0x58, 0x0b, 0xde, 0xf2, 0xe4, 0x52, - 0x8b, 0x78, 0x9b, 0xad, 0xa0, 0x16, 0x46, 0xc6, 0x3a, 0x70, 0x28, 0x68, 0x70, 0xc9, 0x38, 0xaa, - 0xae, 0x2b, 0x88, 0xa8, 0xd6, 0xb9, 0x9d, 0xa2, 0x5a, 0xc7, 0xe6, 0x26, 0x11, 0xc6, 0xfa, 0xf0, - 0x9e, 0x86, 0x7c, 0x39, 0x0b, 0xa7, 0x82, 0x5a, 0x8f, 0xf0, 0x42, 0xe1, 0x3d, 0x24, 0x92, 0x2f, - 0x65, 0x40, 0x99, 0x30, 0x1b, 0x0d, 0xd3, 0x5a, 0xad, 0x58, 0x2b, 0xb6, 0xd3, 0xc4, 0xc9, 0xe3, - 0xe8, 0x8e, 0x3b, 0xd5, 0x1f, 0xc8, 0xc0, 0x98, 0x68, 0xd0, 0xa4, 0xee, 0x18, 0x47, 0x77, 0x96, - 0x14, 0x6f, 0xc9, 0xd1, 0xe9, 0x8b, 0xfa, 0xb5, 0x2c, 0xc0, 0xac, 0x5d, 0x5f, 0x3f, 0xe6, 0x6f, - 0x03, 0x3f, 0x0a, 0x05, 0x1e, 0x2b, 0x48, 0x68, 0xec, 0xd8, 0x38, 0x7f, 0xf2, 0xc9, 0x3e, 0x8d, - 0x23, 0x26, 0x46, 0xc5, 0x09, 0x6d, 0x81, 0xc7, 0x1a, 0x52, 0x32, 0x9a, 0x28, 0xc2, 0x2a, 0x65, - 0x74, 0xc2, 0xaa, 0x09, 0x2a, 0x65, 0xb0, 0x68, 0xa5, 0xdb, 0x5b, 0xc5, 0x7c, 0xc3, 0xae, 0xaf, - 0x6b, 0x48, 0xaf, 0xfe, 0x4d, 0x86, 0xcb, 0xee, 0x98, 0xbf, 0x8f, 0xf3, 0x3f, 0x3f, 0xbf, 0xc7, - 0xcf, 0xff, 0xc1, 0x0c, 0x9c, 0xd1, 0x68, 0xdd, 0xbe, 0x4b, 0x9d, 0xcd, 0x49, 0xdb, 0xa0, 0x37, - 0xa8, 0x45, 0x9d, 0xa3, 0x1a, 0x51, 0xff, 0x17, 0xa6, 0x01, 0x08, 0x1b, 0x73, 0xcb, 0xa5, 0xc6, - 0xf1, 0x49, 0xd1, 0xa0, 0xfe, 0x9f, 0x7d, 0xa0, 0xa4, 0x5a, 0x88, 0xc7, 0xd6, 0x2a, 0xea, 0x68, - 0xf6, 0xe7, 0x0f, 0xcb, 0xec, 0xef, 0xdd, 0x9b, 0xd9, 0x5f, 0xd8, 0xab, 0xd9, 0xdf, 0xb7, 0x1b, - 0xb3, 0xbf, 0x19, 0x37, 0xfb, 0xfb, 0xd1, 0xec, 0x7f, 0xa6, 0xab, 0xd9, 0x3f, 0x65, 0x19, 0xfb, - 0x34, 0xfa, 0x8f, 0x6d, 0xfa, 0xd0, 0xfd, 0xec, 0x56, 0x2e, 0xb3, 0x49, 0xb1, 0x6e, 0x3b, 0x06, - 0x35, 0xc4, 0x26, 0x05, 0x4f, 0xc8, 0x1d, 0x01, 0xd3, 0x02, 0x6c, 0x22, 0x17, 0xeb, 0xf0, 0x6e, - 0x72, 0xb1, 0x1e, 0xc2, 0x36, 0xe6, 0x0b, 0x59, 0x18, 0x9b, 0xa4, 0x8e, 0xc7, 0x83, 0x11, 0x1e, - 0x86, 0x9b, 0x51, 0x09, 0x4e, 0x49, 0x0c, 0xd1, 0x22, 0xcf, 0x86, 0xae, 0x53, 0x75, 0xea, 0x78, - 0x71, 0xcf, 0xab, 0x38, 0x3d, 0xab, 0xde, 0xcf, 0x87, 0x24, 0xc6, 0x6e, 0x50, 0xbd, 0x0f, 0xe7, - 0x82, 0x34, 0xc5, 0x2f, 0x2d, 0xa0, 0x97, 0x52, 0x1c, 0xe5, 0xf7, 0x9e, 0xe2, 0x48, 0xfd, 0xa5, - 0x0c, 0x5c, 0xd2, 0xa8, 0x45, 0x37, 0xf4, 0xe5, 0x06, 0x95, 0x9a, 0x25, 0x56, 0x06, 0x36, 0x6b, - 0x98, 0x6e, 0x53, 0xf7, 0xea, 0x6b, 0x07, 0x92, 0xd1, 0x34, 0x0c, 0xc9, 0xf3, 0xd7, 0x1e, 0xe6, - 0xb6, 0x48, 0x39, 0xf5, 0x37, 0x73, 0xd0, 0x37, 0x61, 0x7b, 0xaf, 0xd9, 0x07, 0xcc, 0xb9, 0x15, - 0x4e, 0xf9, 0xd9, 0x3d, 0x9c, 0x8b, 0x7c, 0x18, 0x2b, 0x97, 0xc2, 0x90, 0xa3, 0x5b, 0xde, 0xb2, - 0x9d, 0x08, 0xd7, 0xee, 0x93, 0xed, 0x31, 0xdb, 0xd6, 0x73, 0x30, 0x80, 0x71, 0x2c, 0xa4, 0x93, - 0x4b, 0x74, 0x7a, 0xf5, 0x18, 0x30, 0x5e, 0x47, 0x48, 0x4a, 0x3e, 0x19, 0x89, 0x9e, 0x58, 0x38, - 0x78, 0x76, 0x2e, 0x39, 0x90, 0xe2, 0xa1, 0x25, 0xc1, 0x52, 0xbf, 0x93, 0x87, 0x21, 0xdf, 0xd5, - 0xf1, 0x88, 0x7a, 0xf0, 0x29, 0x28, 0xcc, 0xd8, 0x52, 0x48, 0x75, 0x74, 0x8d, 0x5c, 0xb3, 0xdd, - 0x98, 0xcf, 0xa7, 0x20, 0x22, 0xcf, 0x40, 0xff, 0xbc, 0x6d, 0xc8, 0x8e, 0xbd, 0x38, 0xa6, 0x2d, - 0xdb, 0x48, 0x3c, 0x8c, 0x0c, 0x08, 0xc9, 0x25, 0xc8, 0xa3, 0x4f, 0xb4, 0x74, 0xf4, 0x1c, 0xf3, - 0x83, 0x46, 0xbc, 0xa4, 0x1b, 0x85, 0xbd, 0xea, 0x46, 0xdf, 0x7e, 0x75, 0xa3, 0xff, 0x70, 0x75, - 0xe3, 0x0d, 0x18, 0xc2, 0x9a, 0xfc, 0x8c, 0x4c, 0x3b, 0x2f, 0x6f, 0x0f, 0x8a, 0x15, 0x68, 0x98, - 0xb7, 0x5b, 0xe4, 0x65, 0xc2, 0x85, 0x27, 0xc2, 0x2a, 0xa6, 0x76, 0x70, 0x00, 0xb5, 0xfb, 0xe3, - 0x0c, 0xf4, 0xdd, 0xb2, 0xd6, 0x2d, 0x7b, 0xe3, 0x60, 0x1a, 0xf7, 0x0c, 0x0c, 0x0a, 0x36, 0xd2, - 0x1c, 0x8f, 0x6f, 0x5d, 0xdb, 0x1c, 0x5c, 0x43, 0x4e, 0x9a, 0x4c, 0x45, 0x5e, 0x0a, 0x0a, 0xe1, - 0xb3, 0x87, 0x5c, 0x98, 0x94, 0xc0, 0x2f, 0x54, 0x8f, 0xc6, 0x51, 0x97, 0xc9, 0xc9, 0x05, 0xc8, - 0x97, 0x59, 0x53, 0xa5, 0xa8, 0x9c, 0xac, 0x29, 0x1a, 0x42, 0xd5, 0xdf, 0xcb, 0xc2, 0x48, 0xec, - 0xf8, 0xe9, 0x09, 0x18, 0x10, 0xc7, 0x3f, 0xa6, 0x1f, 0xd8, 0x1d, 0x9f, 0x45, 0x04, 0x40, 0xad, - 0x9f, 0xff, 0x59, 0x31, 0xc8, 0xc7, 0xa0, 0xcf, 0x76, 0x71, 0x69, 0xc2, 0x6f, 0x19, 0x09, 0x87, - 0xd0, 0x42, 0x95, 0xb5, 0x9d, 0x0f, 0x0e, 0x41, 0x22, 0x6b, 0xa4, 0xed, 0xe2, 0xa7, 0x5d, 0x87, - 0x01, 0xdd, 0x75, 0xa9, 0x57, 0xf3, 0xf4, 0x55, 0x39, 0xd6, 0x7b, 0x00, 0x94, 0x47, 0x07, 0x02, - 0x97, 0xf4, 0x55, 0xf2, 0x2a, 0x0c, 0xd7, 0x1d, 0x8a, 0x8b, 0x97, 0xde, 0x60, 0xad, 0x94, 0x8c, - 0xcb, 0x08, 0x42, 0x3e, 0xf1, 0x0f, 0x11, 0x15, 0x83, 0xdc, 0x86, 0x61, 0xf1, 0x39, 0xdc, 0x27, - 0x19, 0x07, 0xda, 0x48, 0xb8, 0x98, 0x70, 0x91, 0x70, 0xaf, 0x64, 0xe1, 0x9a, 0x2e, 0x93, 0xcb, - 0x7c, 0x0d, 0x89, 0x54, 0xfd, 0x66, 0x86, 0x19, 0x3c, 0x0c, 0x80, 0x39, 0x52, 0x99, 0xae, 0x34, - 0xf7, 0xa8, 0x2b, 0xcd, 0x30, 0x9b, 0x59, 0xc1, 0xed, 0x32, 0x3b, 0x69, 0x02, 0x4b, 0xc6, 0xa1, - 0x60, 0xc8, 0x67, 0x3f, 0x67, 0xa3, 0x1f, 0xe1, 0xd7, 0xa3, 0x09, 0x2a, 0x72, 0x19, 0xf2, 0xcc, - 0xa0, 0x8d, 0x6f, 0xfc, 0xe4, 0x35, 0x52, 0x43, 0x0a, 0xf5, 0xbb, 0xb3, 0x30, 0x24, 0x7d, 0xcd, - 0xb5, 0x03, 0x7d, 0xce, 0x8b, 0xbb, 0x6b, 0xa6, 0xef, 0xe6, 0x80, 0x3b, 0x02, 0xbf, 0xc9, 0xd7, - 0x03, 0x51, 0xec, 0xea, 0x0a, 0x42, 0x08, 0xe6, 0x39, 0xf1, 0xa1, 0x85, 0xdd, 0x6f, 0x82, 0x18, - 0xfd, 0x6b, 0xf9, 0xfe, 0xec, 0x68, 0xee, 0xb5, 0x7c, 0x7f, 0x7e, 0xb4, 0x17, 0xe3, 0xe2, 0x60, - 0x28, 0x5a, 0xbe, 0xc3, 0xb4, 0x56, 0xcc, 0xd5, 0x63, 0xee, 0x55, 0x7e, 0xb8, 0x31, 0x83, 0x62, - 0xb2, 0x39, 0xe6, 0x2e, 0xe6, 0xef, 0xaa, 0x6c, 0x4e, 0xb2, 0x9f, 0x09, 0xd9, 0xfc, 0x49, 0x06, - 0x94, 0x54, 0xd9, 0x94, 0x8e, 0xe8, 0xe6, 0xfb, 0xf0, 0x72, 0xa0, 0x7d, 0x3b, 0x0b, 0x63, 0x15, - 0xcb, 0xa3, 0xab, 0x7c, 0xdf, 0x73, 0xcc, 0xa7, 0x8a, 0x9b, 0x30, 0x28, 0x7d, 0x8c, 0xe8, 0xf3, - 0x87, 0x82, 0x5d, 0x65, 0x88, 0xea, 0xc0, 0x49, 0x2e, 0x7d, 0x88, 0x69, 0x93, 0x63, 0x42, 0x3e, - 0xe6, 0x73, 0xce, 0xf1, 0x10, 0xf2, 0x31, 0x9f, 0xbc, 0xde, 0xa3, 0x42, 0xfe, 0x57, 0x19, 0x38, - 0x9d, 0x52, 0x39, 0xb9, 0x04, 0x7d, 0xd5, 0xf6, 0x32, 0x06, 0xe4, 0xc9, 0x84, 0x3e, 0xa2, 0x6e, - 0x7b, 0x19, 0x63, 0xf1, 0x68, 0x3e, 0x92, 0x2c, 0xe1, 0xb3, 0xdb, 0x85, 0x4a, 0x79, 0x52, 0x48, - 0x55, 0x95, 0x1e, 0x10, 0x33, 0x70, 0xda, 0x97, 0x05, 0x4f, 0x73, 0x6d, 0xd3, 0xa8, 0xc7, 0x9e, - 0xe6, 0xb2, 0x32, 0xe4, 0x53, 0x30, 0x50, 0x7a, 0xbb, 0xed, 0x50, 0xe4, 0xcb, 0x25, 0xfe, 0x81, - 0x80, 0xaf, 0x8f, 0x48, 0xe3, 0xcc, 0x5f, 0x19, 0x33, 0x8a, 0x38, 0xef, 0x90, 0xa1, 0xfa, 0xc5, - 0x0c, 0x9c, 0xef, 0xdc, 0x3a, 0xf2, 0x61, 0xe8, 0x63, 0x3b, 0xdb, 0x92, 0x36, 0x2f, 0x3e, 0x9d, - 0xe7, 0x0b, 0xb4, 0x1b, 0xb4, 0xa6, 0x3b, 0xb2, 0xe1, 0xed, 0x93, 0x91, 0x97, 0x61, 0xb0, 0xe2, - 0xba, 0x6d, 0xea, 0x54, 0x9f, 0xb9, 0xa5, 0x55, 0xc4, 0x9e, 0x0a, 0x6d, 0x76, 0x13, 0xc1, 0x35, - 0xf7, 0x99, 0x58, 0xc8, 0x1d, 0x99, 0x5e, 0xfd, 0x5c, 0x06, 0x2e, 0x74, 0xfb, 0x2a, 0xb6, 0x81, - 0x5f, 0xa2, 0x96, 0x6e, 0xb1, 0x1d, 0x7f, 0x26, 0xdc, 0xa2, 0x78, 0x08, 0x8b, 0x6e, 0x32, 0x02, - 0x42, 0x56, 0x88, 0x9f, 0x8e, 0x05, 0xd7, 0xf1, 0xfc, 0x24, 0x0f, 0x61, 0xb1, 0x42, 0x3e, 0xa1, - 0xfa, 0x7b, 0x3a, 0xf4, 0x2e, 0x58, 0x74, 0x61, 0x85, 0x3c, 0x2d, 0x25, 0x86, 0x17, 0x03, 0x6d, - 0x4c, 0x1e, 0x30, 0x88, 0x98, 0xe9, 0xd1, 0xa4, 0xf4, 0xf1, 0xd7, 0xe5, 0x0c, 0xc1, 0x42, 0x1d, - 0x88, 0x5c, 0x86, 0x63, 0x66, 0x7a, 0x34, 0x39, 0x93, 0xf0, 0x75, 0x39, 0x33, 0xab, 0xe8, 0xec, - 0x48, 0x29, 0x8e, 0xf1, 0x4b, 0x89, 0x69, 0x60, 0x36, 0x2d, 0x7d, 0x69, 0xdc, 0x26, 0x48, 0x52, - 0xcc, 0xf4, 0x68, 0xe9, 0x69, 0x4f, 0x87, 0x64, 0xc7, 0x98, 0xf8, 0x85, 0x9c, 0x8c, 0x9b, 0xe9, - 0xd1, 0x22, 0xb4, 0xe4, 0x79, 0x18, 0x14, 0xbf, 0x5f, 0xb3, 0x4d, 0x2b, 0xfe, 0xf6, 0x5e, 0x42, - 0xcd, 0xf4, 0x68, 0x32, 0xa5, 0x54, 0xe9, 0xa2, 0x63, 0x06, 0xb9, 0xdd, 0xe3, 0x95, 0x22, 0x4e, - 0xaa, 0x14, 0x7f, 0x93, 0x97, 0x61, 0x38, 0x08, 0x6a, 0xf0, 0x16, 0xad, 0x7b, 0xe2, 0x48, 0xe4, - 0x81, 0x58, 0x61, 0x8e, 0x9c, 0xe9, 0xd1, 0xa2, 0xd4, 0xe4, 0x32, 0x14, 0x34, 0xea, 0x9a, 0x6f, - 0xfb, 0x47, 0xf9, 0x23, 0xd2, 0x74, 0x66, 0xbe, 0xcd, 0xa4, 0x24, 0xf0, 0xac, 0x77, 0xc2, 0xbb, - 0x03, 0x71, 0x80, 0x41, 0x62, 0xb5, 0x4c, 0x59, 0x06, 0xeb, 0x1d, 0xe9, 0xe2, 0xe8, 0xd5, 0x30, - 0xd4, 0x83, 0x48, 0xcb, 0x34, 0x18, 0x7f, 0x53, 0x27, 0x63, 0x67, 0x7a, 0xb4, 0x18, 0xbd, 0x24, - 0xd5, 0xb2, 0xe9, 0xae, 0x8b, 0xe8, 0x5a, 0x71, 0xa9, 0x32, 0x94, 0x24, 0x55, 0xf6, 0x53, 0xaa, - 0x7a, 0x9e, 0x7a, 0x1b, 0xb6, 0xb3, 0x2e, 0x62, 0x69, 0xc5, 0xab, 0x16, 0x58, 0xa9, 0x6a, 0x01, - 0x91, 0xab, 0x66, 0x8b, 0xcc, 0x48, 0x7a, 0xd5, 0xba, 0xa7, 0xcb, 0x55, 0xf3, 0xfd, 0xa5, 0xdf, - 0x49, 0xb3, 0x54, 0xbf, 0xcb, 0xb3, 0x63, 0x26, 0x3b, 0x14, 0x71, 0x52, 0x87, 0xe2, 0x6f, 0x56, - 0xa9, 0x94, 0x01, 0x51, 0xa4, 0xbf, 0x0c, 0x2a, 0x95, 0x50, 0xac, 0x52, 0x39, 0x57, 0xe2, 0x75, - 0x39, 0x31, 0xa0, 0x32, 0x16, 0xed, 0xa0, 0x10, 0xc3, 0x3a, 0x48, 0x4a, 0x20, 0x58, 0xc4, 0xa4, - 0x63, 0x0a, 0x41, 0xf2, 0xc1, 0xa0, 0x85, 0x93, 0x8b, 0x33, 0x3d, 0x1a, 0xa6, 0x23, 0x53, 0x79, - 0x3a, 0x3b, 0xe5, 0x34, 0x52, 0x0c, 0xf9, 0x14, 0x0c, 0x36, 0xd3, 0xa3, 0xf1, 0x54, 0x77, 0x4f, - 0x4b, 0x89, 0x63, 0x94, 0x33, 0xd1, 0x29, 0x22, 0x40, 0xb0, 0x29, 0x22, 0x4c, 0x2f, 0x33, 0x9d, - 0x4c, 0xae, 0xa2, 0x3c, 0x10, 0x5d, 0x51, 0xe3, 0xf8, 0x99, 0x1e, 0x2d, 0x99, 0x90, 0xe5, 0xf9, - 0x48, 0xbe, 0x11, 0xe5, 0x6c, 0x2c, 0xe0, 0x45, 0x88, 0x62, 0xe2, 0x92, 0x33, 0x93, 0x2c, 0xa4, - 0x66, 0x08, 0x56, 0xce, 0x45, 0x97, 0xe3, 0x14, 0x92, 0x99, 0x1e, 0x2d, 0x35, 0xb7, 0xf0, 0x64, - 0x22, 0xeb, 0x87, 0xa2, 0x44, 0xef, 0x2d, 0x63, 0xe8, 0x99, 0x1e, 0x2d, 0x91, 0x27, 0xe4, 0xba, - 0x9c, 0x6e, 0x43, 0x79, 0x30, 0xda, 0x89, 0x21, 0x86, 0x75, 0xa2, 0x94, 0x96, 0xe3, 0xba, 0x9c, - 0x82, 0x41, 0x39, 0x9f, 0x2c, 0x15, 0xce, 0x9c, 0x52, 0xaa, 0x06, 0x2d, 0x3d, 0xaa, 0xbc, 0xf2, - 0x90, 0xc8, 0xeb, 0x25, 0xca, 0xa7, 0xd1, 0xcc, 0xf4, 0x68, 0xe9, 0x11, 0xe9, 0xb5, 0xf4, 0x70, - 0xec, 0xca, 0x85, 0x6e, 0x3c, 0x83, 0xd6, 0xa5, 0x87, 0x72, 0xd7, 0xbb, 0x04, 0xc7, 0x56, 0x1e, - 0x8e, 0x46, 0xdb, 0xeb, 0x48, 0x38, 0xd3, 0xa3, 0x75, 0x09, 0xb1, 0x7d, 0xab, 0x43, 0xa4, 0x6a, - 0xe5, 0x62, 0x34, 0xad, 0x5f, 0x2a, 0xd1, 0x4c, 0x8f, 0xd6, 0x21, 0xce, 0xf5, 0xad, 0x0e, 0x81, - 0x8c, 0x95, 0x62, 0x57, 0xb6, 0x81, 0x3c, 0x3a, 0x84, 0x41, 0x5e, 0x48, 0x8d, 0x01, 0xac, 0x3c, - 0x12, 0x55, 0xdd, 0x14, 0x12, 0xa6, 0xba, 0x69, 0xd1, 0x83, 0x17, 0x52, 0x83, 0xd6, 0x2a, 0x8f, - 0x76, 0x61, 0x18, 0xb4, 0x31, 0x35, 0xdc, 0xed, 0x42, 0x6a, 0xd4, 0x58, 0x45, 0x8d, 0x32, 0x4c, - 0x21, 0x61, 0x0c, 0xd3, 0xe2, 0xcd, 0x2e, 0xa4, 0x86, 0x39, 0x55, 0x1e, 0xeb, 0xc2, 0x30, 0x6c, - 0x61, 0x5a, 0x80, 0xd4, 0xe7, 0x23, 0x71, 0x46, 0x95, 0x0f, 0x44, 0xe7, 0x0d, 0x09, 0xc5, 0xe6, - 0x0d, 0x39, 0x22, 0xe9, 0x64, 0x22, 0x92, 0x9a, 0xf2, 0x78, 0x74, 0x98, 0xc7, 0xd0, 0x6c, 0x98, - 0xc7, 0x63, 0xaf, 0x4d, 0x26, 0x22, 0x4a, 0x29, 0x97, 0x3a, 0x31, 0x41, 0x74, 0x94, 0x09, 0x8f, - 0x41, 0x55, 0x49, 0x09, 0x69, 0xa4, 0x7c, 0x30, 0xea, 0x73, 0x97, 0x20, 0x98, 0xe9, 0xd1, 0x52, - 0x02, 0x21, 0x69, 0xe9, 0xef, 0xf7, 0x95, 0xcb, 0xd1, 0x61, 0x9b, 0x46, 0xc3, 0x86, 0x6d, 0xea, - 0xdb, 0xff, 0xd9, 0x34, 0xff, 0x5a, 0xe5, 0x4a, 0xd4, 0x30, 0x4b, 0x52, 0x30, 0xc3, 0x2c, 0xc5, - 0x2f, 0x57, 0x4b, 0x7f, 0x91, 0xae, 0x3c, 0xd1, 0xb5, 0x85, 0x48, 0x93, 0xd2, 0x42, 0xfe, 0x40, - 0x3b, 0xb4, 0x9d, 0x6e, 0xb5, 0x1a, 0xb6, 0x6e, 0x28, 0x1f, 0x4a, 0xb5, 0x9d, 0x38, 0x52, 0xb2, - 0x9d, 0x38, 0x80, 0xad, 0xf2, 0xb2, 0xff, 0xa9, 0xf2, 0x64, 0x74, 0x95, 0x97, 0x71, 0x6c, 0x95, - 0x8f, 0xf8, 0xaa, 0x4e, 0x26, 0x7c, 0x35, 0x95, 0xa7, 0xa2, 0x0a, 0x10, 0x43, 0x33, 0x05, 0x88, - 0x7b, 0x77, 0xbe, 0xd9, 0xd9, 0xbb, 0x51, 0x19, 0x47, 0x6e, 0x8f, 0xf8, 0xdc, 0x3a, 0xd1, 0xcd, - 0xf4, 0x68, 0x9d, 0x3d, 0x24, 0x2b, 0x29, 0xce, 0x8a, 0xca, 0xd5, 0xa8, 0x82, 0x25, 0x08, 0x98, - 0x82, 0x25, 0x5d, 0x1c, 0x2b, 0x29, 0xde, 0x86, 0xca, 0x87, 0x3b, 0xb2, 0x0a, 0xbe, 0x39, 0xc5, - 0x47, 0xf1, 0xba, 0xec, 0x2e, 0xa8, 0x3c, 0x1d, 0x5d, 0xec, 0x42, 0x0c, 0x5b, 0xec, 0x24, 0xb7, - 0xc2, 0xeb, 0xb2, 0xa3, 0x9c, 0x72, 0x2d, 0x59, 0x2a, 0x5c, 0x22, 0x25, 0x87, 0x3a, 0x2d, 0xdd, - 0xbf, 0x4c, 0x79, 0x26, 0xaa, 0x75, 0x69, 0x34, 0x4c, 0xeb, 0x52, 0x7d, 0xd3, 0xa6, 0x93, 0x6e, - 0x62, 0xca, 0xf5, 0xf8, 0x59, 0x42, 0x14, 0xcf, 0x2c, 0x9f, 0x84, 0x6b, 0xd9, 0xab, 0xf1, 0xe0, - 0x32, 0xca, 0xb3, 0xb1, 0xcb, 0x8c, 0x08, 0x96, 0xd9, 0xb7, 0xb1, 0x60, 0x34, 0xaf, 0xc6, 0xe3, - 0xb1, 0x28, 0xcf, 0xa5, 0x73, 0x08, 0x74, 0x25, 0x1e, 0xbf, 0xe5, 0xd5, 0x78, 0x08, 0x13, 0xe5, - 0xf9, 0x74, 0x0e, 0x81, 0x74, 0xe3, 0x21, 0x4f, 0x9e, 0x96, 0x82, 0xaa, 0x2a, 0x1f, 0x89, 0x9a, - 0x8e, 0x01, 0x82, 0x99, 0x8e, 0x61, 0xe8, 0xd5, 0xa7, 0xa5, 0x60, 0xa4, 0xca, 0x0b, 0x89, 0x22, - 0x41, 0x63, 0xa5, 0x90, 0xa5, 0x4f, 0x4b, 0x41, 0x3c, 0x95, 0x17, 0x13, 0x45, 0x82, 0xd6, 0x49, - 0xa1, 0x3e, 0x8d, 0x6e, 0xef, 0x70, 0x94, 0x8f, 0x46, 0x8f, 0x38, 0x3a, 0x53, 0xce, 0xf4, 0x68, - 0xdd, 0xde, 0xf3, 0xbc, 0xd9, 0xd9, 0xe9, 0x4e, 0x79, 0x29, 0x3a, 0x84, 0x3b, 0xd1, 0xb1, 0x21, - 0xdc, 0xd1, 0x71, 0xef, 0xe5, 0xd8, 0x9b, 0x5c, 0xe5, 0xe5, 0xe8, 0x14, 0x17, 0x41, 0xb2, 0x29, - 0x2e, 0xfe, 0x82, 0x37, 0xf2, 0xd8, 0x54, 0xf9, 0x58, 0x74, 0x8a, 0x93, 0x71, 0x6c, 0x8a, 0x8b, - 0x3c, 0x4c, 0x9d, 0x4c, 0xbc, 0x81, 0x54, 0x5e, 0x89, 0x4e, 0x71, 0x31, 0x34, 0x9b, 0xe2, 0xe2, - 0xaf, 0x26, 0x5f, 0x8e, 0x3d, 0x05, 0x54, 0x5e, 0x4d, 0x6f, 0x3f, 0x22, 0xe5, 0xf6, 0xf3, 0x87, - 0x83, 0x5a, 0xfa, 0x9b, 0x36, 0xa5, 0x14, 0x1d, 0xbf, 0x69, 0x34, 0x6c, 0xfc, 0xa6, 0xbe, 0x87, - 0x5b, 0x48, 0x4d, 0xaa, 0xaf, 0x4c, 0x74, 0xd9, 0x38, 0x84, 0xa6, 0x48, 0x5a, 0x3a, 0x7e, 0x79, - 0x8f, 0xcc, 0x37, 0x42, 0x93, 0x1d, 0xf6, 0xc8, 0xfe, 0x36, 0x28, 0x46, 0xcf, 0x66, 0xd7, 0x84, - 0x0f, 0x98, 0x52, 0x8e, 0xce, 0xae, 0x09, 0x02, 0x36, 0xbb, 0x26, 0x3d, 0xc7, 0xa6, 0x61, 0x54, - 0x68, 0x11, 0x77, 0x6d, 0x33, 0xad, 0x55, 0x65, 0x2a, 0xf6, 0xa4, 0x24, 0x86, 0x67, 0xb3, 0x53, - 0x1c, 0x86, 0xeb, 0x35, 0x87, 0x4d, 0x36, 0xcc, 0xd6, 0xb2, 0xad, 0x3b, 0x46, 0x95, 0x5a, 0x86, - 0x32, 0x1d, 0x5b, 0xaf, 0x53, 0x68, 0x70, 0xbd, 0x4e, 0x81, 0x63, 0x40, 0x95, 0x18, 0x5c, 0xa3, - 0x75, 0x6a, 0xde, 0xa5, 0xca, 0x0d, 0x64, 0x5b, 0xec, 0xc4, 0x56, 0x90, 0xcd, 0xf4, 0x68, 0x9d, - 0x38, 0x30, 0x5b, 0x7d, 0x6e, 0xb3, 0xfa, 0xfa, 0x6c, 0xf0, 0x8c, 0x72, 0xd1, 0xa1, 0x2d, 0xdd, - 0xa1, 0xca, 0x4c, 0xd4, 0x56, 0x4f, 0x25, 0x62, 0xb6, 0x7a, 0x2a, 0x22, 0xc9, 0xd6, 0x1f, 0x0b, - 0x95, 0x6e, 0x6c, 0xc3, 0x11, 0x91, 0x5e, 0x9a, 0xcd, 0x4e, 0x51, 0x04, 0x13, 0xd0, 0xac, 0x6d, - 0xad, 0xe2, 0x49, 0xc5, 0x6b, 0xd1, 0xd9, 0xa9, 0x33, 0x25, 0x9b, 0x9d, 0x3a, 0x63, 0x99, 0xaa, - 0x47, 0xb1, 0x7c, 0x0c, 0xde, 0x8c, 0xaa, 0x7a, 0x0a, 0x09, 0x53, 0xf5, 0x14, 0x70, 0x92, 0xa1, - 0x46, 0x5d, 0xea, 0x29, 0xb3, 0xdd, 0x18, 0x22, 0x49, 0x92, 0x21, 0x82, 0x93, 0x0c, 0xa7, 0xa9, - 0x57, 0x5f, 0x53, 0xe6, 0xba, 0x31, 0x44, 0x92, 0x24, 0x43, 0x04, 0xb3, 0xcd, 0x66, 0x14, 0x3c, - 0xd1, 0x6e, 0xac, 0xfb, 0x7d, 0x36, 0x1f, 0xdd, 0x6c, 0x76, 0x24, 0x64, 0x9b, 0xcd, 0x8e, 0x48, - 0xf2, 0xb9, 0x5d, 0xfb, 0x28, 0x2a, 0x0b, 0x58, 0xe1, 0x78, 0x68, 0x17, 0xec, 0xa6, 0xd4, 0x4c, - 0x8f, 0xb6, 0x5b, 0x1f, 0xc8, 0x0f, 0x05, 0xae, 0x44, 0xca, 0x22, 0x56, 0x75, 0x2a, 0x38, 0xab, - 0xe0, 0xe0, 0x99, 0x1e, 0x2d, 0x70, 0x36, 0x7a, 0x1e, 0x06, 0xf1, 0xa3, 0x2a, 0x96, 0xe9, 0x95, - 0x27, 0x94, 0xd7, 0xa3, 0x5b, 0x26, 0x09, 0xc5, 0xb6, 0x4c, 0xd2, 0x4f, 0x36, 0x89, 0xe3, 0x4f, - 0x3e, 0xc5, 0x94, 0x27, 0x14, 0x2d, 0x3a, 0x89, 0x47, 0x90, 0x6c, 0x12, 0x8f, 0x00, 0x82, 0x7a, - 0xcb, 0x8e, 0xdd, 0x2a, 0x4f, 0x28, 0xd5, 0x94, 0x7a, 0x39, 0x2a, 0xa8, 0x97, 0xff, 0x0c, 0xea, - 0xad, 0xae, 0xb5, 0xbd, 0x32, 0xfb, 0xc6, 0xa5, 0x94, 0x7a, 0x7d, 0x64, 0x50, 0xaf, 0x0f, 0x60, - 0x53, 0x21, 0x02, 0x16, 0x1d, 0x9b, 0x4d, 0xda, 0x37, 0xcd, 0x46, 0x43, 0xb9, 0x15, 0x9d, 0x0a, - 0xe3, 0x78, 0x36, 0x15, 0xc6, 0x61, 0xcc, 0xf4, 0xe4, 0xad, 0xa2, 0xcb, 0xed, 0x55, 0xe5, 0x76, - 0xd4, 0xf4, 0x0c, 0x31, 0xcc, 0xf4, 0x0c, 0x7f, 0xe1, 0xee, 0x82, 0xfd, 0xd2, 0xe8, 0x8a, 0x43, - 0xdd, 0x35, 0xe5, 0x4e, 0x6c, 0x77, 0x21, 0xe1, 0x70, 0x77, 0x21, 0xfd, 0x26, 0xab, 0xf0, 0x50, - 0x64, 0xa1, 0xf1, 0xef, 0x9e, 0xaa, 0x54, 0x77, 0xea, 0x6b, 0xca, 0xc7, 0x91, 0xd5, 0x63, 0xa9, - 0x4b, 0x55, 0x94, 0x74, 0xa6, 0x47, 0xeb, 0xc6, 0x09, 0xb7, 0xe5, 0xaf, 0xcf, 0xf2, 0xc8, 0x67, - 0xda, 0xe2, 0xa4, 0xbf, 0x09, 0x7d, 0x23, 0xb6, 0x2d, 0x4f, 0x92, 0xe0, 0xb6, 0x3c, 0x09, 0x26, - 0x2d, 0xb8, 0x18, 0xdb, 0xaa, 0xcd, 0xe9, 0x0d, 0xb6, 0x2f, 0xa1, 0xc6, 0xa2, 0x5e, 0x5f, 0xa7, - 0x9e, 0xf2, 0x09, 0xe4, 0x7d, 0xa9, 0xc3, 0x86, 0x2f, 0x46, 0x3d, 0xd3, 0xa3, 0xed, 0xc0, 0x8f, - 0xa8, 0x3c, 0x6d, 0xbb, 0xf2, 0xc9, 0xe8, 0xf9, 0x26, 0x83, 0xcd, 0xf4, 0x68, 0x3c, 0xa5, 0xfb, - 0x9b, 0xa0, 0xdc, 0x6a, 0xad, 0x3a, 0xba, 0x41, 0xb9, 0xa1, 0x85, 0xb6, 0x9b, 0x30, 0x40, 0x3f, - 0x15, 0xb5, 0xd2, 0x3a, 0xd1, 0x31, 0x2b, 0xad, 0x13, 0x8e, 0x29, 0x6a, 0x24, 0xc8, 0xb7, 0xf2, - 0xe9, 0xa8, 0xa2, 0x46, 0x90, 0x4c, 0x51, 0xa3, 0x21, 0xc1, 0x3f, 0x0e, 0x67, 0x83, 0xfd, 0xbc, - 0x58, 0x7f, 0x79, 0xa7, 0x29, 0x6f, 0x22, 0x9f, 0x8b, 0x89, 0xcb, 0x80, 0x08, 0xd5, 0x4c, 0x8f, - 0xd6, 0xa1, 0x3c, 0x5b, 0x71, 0x13, 0xf9, 0x2b, 0x84, 0x79, 0xf1, 0x5d, 0xd1, 0x15, 0xb7, 0x03, - 0x19, 0x5b, 0x71, 0x3b, 0xa0, 0x52, 0x99, 0x0b, 0xa1, 0xea, 0x3b, 0x30, 0x0f, 0x64, 0xda, 0x89, - 0x43, 0x2a, 0x73, 0x61, 0xa9, 0x2d, 0xef, 0xc0, 0x3c, 0xb0, 0xd6, 0x3a, 0x71, 0x20, 0x97, 0xa1, - 0x50, 0xad, 0xce, 0x69, 0x6d, 0x4b, 0xa9, 0xc7, 0x7c, 0xc0, 0x10, 0x3a, 0xd3, 0xa3, 0x09, 0x3c, - 0x33, 0x83, 0xa6, 0x1a, 0xba, 0xeb, 0x99, 0x75, 0x17, 0x47, 0x8c, 0x3f, 0x42, 0x8c, 0xa8, 0x19, - 0x94, 0x46, 0xc3, 0xcc, 0xa0, 0x34, 0x38, 0xb3, 0x17, 0x27, 0x75, 0xd7, 0xd5, 0x2d, 0xc3, 0xd1, - 0x27, 0x70, 0x99, 0xa0, 0x31, 0x4f, 0xf9, 0x08, 0x96, 0xd9, 0x8b, 0x51, 0x08, 0x1e, 0xbe, 0xfb, - 0x10, 0xdf, 0xcc, 0x59, 0x89, 0x1d, 0xbe, 0xc7, 0xf0, 0x78, 0xf8, 0x1e, 0x83, 0xa1, 0xdd, 0xe9, - 0xc3, 0x34, 0xba, 0x6a, 0x32, 0x11, 0x29, 0xab, 0x31, 0xbb, 0x33, 0x4e, 0x80, 0x76, 0x67, 0x1c, - 0x18, 0x69, 0x92, 0xbf, 0xdc, 0xae, 0x75, 0x68, 0x52, 0xb8, 0xca, 0x26, 0xca, 0xb0, 0xf5, 0x3b, - 0x1c, 0x1c, 0xe5, 0x4d, 0x4b, 0x6f, 0xda, 0xe5, 0x09, 0x5f, 0xea, 0x66, 0x74, 0xfd, 0xee, 0x48, - 0xc8, 0xd6, 0xef, 0x8e, 0x48, 0x36, 0xbb, 0xfa, 0x1b, 0xad, 0x35, 0xdd, 0xa1, 0x46, 0xd9, 0x74, - 0xf0, 0x64, 0x71, 0x93, 0x6f, 0x0d, 0xdf, 0x8a, 0xce, 0xae, 0x5d, 0x48, 0xd9, 0xec, 0xda, 0x05, - 0xcd, 0x8c, 0xbc, 0x74, 0xb4, 0x46, 0x75, 0x43, 0x59, 0x8f, 0x1a, 0x79, 0x9d, 0x29, 0x99, 0x91, - 0xd7, 0x19, 0xdb, 0xf9, 0x73, 0xee, 0x38, 0xa6, 0x47, 0x95, 0xc6, 0x6e, 0x3e, 0x07, 0x49, 0x3b, - 0x7f, 0x0e, 0xa2, 0xd9, 0x86, 0x30, 0xde, 0x21, 0xcd, 0xe8, 0x86, 0x30, 0xd9, 0x0d, 0xf1, 0x12, - 0xcc, 0x62, 0x11, 0x0f, 0x26, 0x14, 0x2b, 0x6a, 0xb1, 0x08, 0x30, 0xb3, 0x58, 0xc2, 0x27, 0x15, - 0x11, 0x07, 0x7d, 0xc5, 0x8e, 0xae, 0xa1, 0x32, 0x8e, 0xad, 0xa1, 0x11, 0x67, 0xfe, 0xe7, 0x23, - 0xde, 0xb3, 0x4a, 0x2b, 0x6a, 0x75, 0x48, 0x28, 0x66, 0x75, 0xc8, 0x7e, 0xb6, 0x93, 0x70, 0x0a, - 0x6f, 0xc1, 0xb5, 0x76, 0x70, 0x8f, 0xf3, 0x99, 0xe8, 0x67, 0xc6, 0xd0, 0xec, 0x33, 0x63, 0xa0, - 0x08, 0x13, 0x31, 0x6d, 0x39, 0x1d, 0x98, 0x84, 0xe7, 0x83, 0x31, 0x10, 0x99, 0x05, 0x52, 0x2d, - 0xcd, 0xcd, 0x56, 0x8c, 0x45, 0xf9, 0x8a, 0xcc, 0x8d, 0x9e, 0xc0, 0x26, 0x29, 0x66, 0x7a, 0xb4, - 0x94, 0x72, 0xe4, 0x2d, 0xb8, 0x20, 0xa0, 0xe2, 0x35, 0x1c, 0x26, 0x97, 0x35, 0x82, 0x05, 0xc1, - 0x8b, 0x7a, 0x67, 0x74, 0xa3, 0x9d, 0xe9, 0xd1, 0xba, 0xf2, 0xea, 0x5c, 0x97, 0x58, 0x1f, 0xda, - 0xbb, 0xa9, 0x2b, 0x58, 0x24, 0xba, 0xf2, 0xea, 0x5c, 0x97, 0x90, 0xfb, 0xdd, 0xdd, 0xd4, 0x15, - 0x74, 0x42, 0x57, 0x5e, 0xc4, 0x85, 0x62, 0x37, 0x7c, 0xa9, 0xd1, 0x50, 0x36, 0xb0, 0xba, 0x0f, - 0xee, 0xa6, 0xba, 0x12, 0x1a, 0x9c, 0x3b, 0x71, 0x64, 0xb3, 0xf4, 0x42, 0x8b, 0x5a, 0xd5, 0xc8, - 0x02, 0x74, 0x2f, 0x3a, 0x4b, 0x27, 0x08, 0xd8, 0x2c, 0x9d, 0x00, 0xb2, 0x01, 0x25, 0x3b, 0x61, - 0x2b, 0x9b, 0xd1, 0x01, 0x25, 0xe3, 0xd8, 0x80, 0x8a, 0x38, 0x6c, 0x2f, 0xc0, 0xe9, 0x85, 0x75, - 0x4f, 0xf7, 0x2d, 0x48, 0x57, 0x74, 0xe5, 0xdb, 0xb1, 0x4b, 0xa6, 0x24, 0x09, 0x5e, 0x32, 0x25, - 0xc1, 0x6c, 0x8c, 0x30, 0x70, 0x75, 0xd3, 0xaa, 0x4f, 0xeb, 0x66, 0xa3, 0xed, 0x50, 0xe5, 0x3f, - 0x8b, 0x8e, 0x91, 0x18, 0x9a, 0x8d, 0x91, 0x18, 0x88, 0x2d, 0xd0, 0x0c, 0x54, 0x72, 0x5d, 0x73, - 0xd5, 0x12, 0xfb, 0xca, 0x76, 0xc3, 0x53, 0xfe, 0xf3, 0xe8, 0x02, 0x9d, 0x46, 0xc3, 0x16, 0xe8, - 0x34, 0x38, 0x9e, 0x3a, 0xa5, 0x24, 0x5e, 0x56, 0xfe, 0x8b, 0xd8, 0xa9, 0x53, 0x0a, 0x0d, 0x9e, - 0x3a, 0xa5, 0x25, 0x6d, 0x9e, 0x86, 0x51, 0x6e, 0x93, 0xcd, 0x9a, 0xc1, 0x5d, 0xf5, 0x7f, 0x19, - 0x5d, 0x1f, 0xe3, 0x78, 0xb6, 0x3e, 0xc6, 0x61, 0x51, 0x3e, 0xa2, 0x0b, 0xfe, 0xab, 0x4e, 0x7c, - 0x02, 0xf9, 0x27, 0xca, 0x90, 0x1b, 0x32, 0x1f, 0x31, 0x52, 0xbe, 0x3b, 0xd3, 0x89, 0x51, 0x30, - 0x3c, 0x12, 0x85, 0xa2, 0x8c, 0x34, 0x7a, 0xd7, 0xa4, 0x1b, 0xca, 0x67, 0x3b, 0x32, 0xe2, 0x04, - 0x51, 0x46, 0x1c, 0x46, 0xde, 0x80, 0xb3, 0x21, 0x6c, 0x8e, 0x36, 0x97, 0x83, 0x99, 0xe9, 0x7b, - 0x32, 0x51, 0x33, 0x38, 0x9d, 0x8c, 0x99, 0xc1, 0xe9, 0x98, 0x34, 0xd6, 0x42, 0x74, 0xff, 0xf5, - 0x0e, 0xac, 0x03, 0x09, 0x76, 0x60, 0x90, 0xc6, 0x5a, 0x48, 0xf3, 0x7b, 0x77, 0x60, 0x1d, 0xc8, - 0xb4, 0x03, 0x03, 0xf2, 0xf9, 0x0c, 0x5c, 0x4a, 0x47, 0x95, 0x1a, 0x8d, 0x69, 0xdb, 0x09, 0x71, - 0xca, 0xf7, 0x65, 0xa2, 0x07, 0x0d, 0xbb, 0x2b, 0x36, 0xd3, 0xa3, 0xed, 0xb2, 0x02, 0xf2, 0x31, - 0x18, 0x2e, 0xb5, 0x0d, 0xd3, 0xc3, 0x8b, 0x37, 0x66, 0x38, 0x7f, 0x7f, 0x26, 0xb6, 0xc5, 0x91, - 0xb1, 0xb8, 0xc5, 0x91, 0x01, 0xe4, 0x35, 0x18, 0xab, 0xd2, 0x7a, 0xdb, 0x31, 0xbd, 0x4d, 0x0d, - 0x93, 0x6a, 0x33, 0x1e, 0x3f, 0x90, 0x89, 0x4e, 0x62, 0x09, 0x0a, 0x36, 0x89, 0x25, 0x80, 0xe4, - 0x76, 0x87, 0xd4, 0xcb, 0xca, 0xe7, 0x32, 0x5d, 0xaf, 0xe5, 0x83, 0xbe, 0xec, 0x90, 0xb9, 0x79, - 0x31, 0x35, 0x95, 0xad, 0xf2, 0xf9, 0x4c, 0x97, 0x6b, 0x74, 0x69, 0x86, 0x4b, 0xc9, 0x82, 0xbb, - 0x98, 0x9a, 0xac, 0x54, 0xf9, 0xc1, 0x4c, 0x97, 0x6b, 0xef, 0x90, 0x63, 0x5a, 0x9e, 0xd3, 0x67, - 0xb9, 0xa7, 0x88, 0x60, 0xf4, 0xdf, 0x64, 0x92, 0xae, 0x22, 0x41, 0x79, 0x89, 0x90, 0x15, 0xbb, - 0xe5, 0x06, 0x4a, 0xff, 0x85, 0x4c, 0xd2, 0x37, 0x2f, 0x2c, 0x16, 0xfe, 0x22, 0x14, 0xce, 0x4f, - 0xdd, 0xf3, 0xa8, 0x63, 0xe9, 0x0d, 0xec, 0xce, 0xaa, 0x67, 0x3b, 0xfa, 0x2a, 0x9d, 0xb2, 0xf4, - 0xe5, 0x06, 0x55, 0xbe, 0x98, 0x89, 0x5a, 0xb0, 0x9d, 0x49, 0x99, 0x05, 0xdb, 0x19, 0x4b, 0xd6, - 0xe0, 0xa1, 0x34, 0x6c, 0xd9, 0x74, 0xb1, 0x9e, 0x2f, 0x65, 0xa2, 0x26, 0x6c, 0x17, 0x5a, 0x66, - 0xc2, 0x76, 0x41, 0x93, 0x6b, 0x30, 0x30, 0x61, 0xfb, 0xd3, 0xef, 0x7f, 0x1b, 0x73, 0x86, 0x0c, - 0x30, 0x33, 0x3d, 0x5a, 0x48, 0x26, 0xca, 0x88, 0x41, 0xfd, 0xe5, 0x64, 0x99, 0xf0, 0xf2, 0x29, - 0xf8, 0x21, 0xca, 0x08, 0x71, 0xff, 0x77, 0xc9, 0x32, 0xe1, 0x1d, 0x57, 0xf0, 0x83, 0xcd, 0x24, - 0xbc, 0xc6, 0xb9, 0xe9, 0x12, 0xb3, 0xdb, 0x26, 0xd7, 0xf4, 0x46, 0x83, 0x5a, 0xab, 0x54, 0xf9, - 0x4a, 0x6c, 0x26, 0x49, 0x27, 0x63, 0x33, 0x49, 0x3a, 0x86, 0x7c, 0x0a, 0xce, 0xdd, 0xd6, 0x1b, - 0xa6, 0x11, 0xe2, 0xfc, 0xfc, 0x97, 0xca, 0x0f, 0x65, 0xa2, 0xbb, 0xe9, 0x0e, 0x74, 0x6c, 0x37, - 0xdd, 0x01, 0x45, 0xe6, 0x80, 0xe0, 0x32, 0x1a, 0xcc, 0x16, 0x6c, 0x7d, 0x56, 0xfe, 0xfb, 0x4c, - 0xd4, 0x4e, 0x4d, 0x92, 0x30, 0x3b, 0x35, 0x09, 0x25, 0xb5, 0xce, 0x21, 0xce, 0x95, 0x1f, 0xce, - 0x44, 0x4f, 0x6b, 0x3a, 0x11, 0xce, 0xf4, 0x68, 0x9d, 0xe3, 0xa4, 0xdf, 0x80, 0xd1, 0xea, 0x62, - 0x65, 0x7a, 0x7a, 0xaa, 0x7a, 0xbb, 0x52, 0x46, 0xf7, 0x5d, 0x43, 0xf9, 0x91, 0xd8, 0x8a, 0x15, - 0x27, 0x60, 0x2b, 0x56, 0x1c, 0x46, 0xaa, 0x70, 0x86, 0x09, 0x62, 0xd1, 0xa1, 0x2b, 0xd4, 0xa1, - 0x56, 0xdd, 0x1f, 0x96, 0x3f, 0x96, 0x89, 0x1a, 0x0a, 0x69, 0x44, 0xcc, 0x50, 0x48, 0x83, 0x93, - 0x75, 0xb8, 0x10, 0x3f, 0xcc, 0x91, 0xdf, 0x43, 0x29, 0x3f, 0x9e, 0x89, 0xd9, 0xb3, 0x5d, 0x88, - 0xd1, 0x9e, 0xed, 0x82, 0x27, 0x16, 0x3c, 0x2c, 0x4e, 0x46, 0x84, 0xcf, 0x64, 0xbc, 0xb6, 0x9f, - 0xe0, 0xb5, 0x3d, 0x1e, 0xfa, 0xf4, 0x75, 0xa1, 0x9e, 0xe9, 0xd1, 0xba, 0xb3, 0x63, 0xaa, 0x92, - 0x8c, 0xc5, 0xad, 0xfc, 0x64, 0x26, 0xdd, 0xa9, 0x24, 0xe2, 0x69, 0x9c, 0x16, 0xc4, 0xfb, 0x8d, - 0x4e, 0x91, 0xa4, 0x95, 0x9f, 0x8a, 0x0d, 0x99, 0x74, 0x32, 0x36, 0x64, 0x3a, 0x84, 0xa2, 0x7e, - 0x0d, 0xc6, 0xb8, 0x5e, 0x2e, 0xea, 0x38, 0x92, 0xac, 0x55, 0x6a, 0x28, 0xff, 0x43, 0x6c, 0xc1, - 0x4a, 0x50, 0xa0, 0x77, 0x4e, 0x1c, 0xc8, 0x66, 0xdf, 0x6a, 0x4b, 0xb7, 0x2c, 0x3c, 0x29, 0x55, - 0xfe, 0xc7, 0xd8, 0xec, 0x1b, 0xa2, 0xd0, 0xf7, 0x36, 0xf8, 0x85, 0x39, 0x7d, 0xd2, 0x9e, 0x0b, - 0x2a, 0x5f, 0x8d, 0xad, 0x73, 0xa9, 0x54, 0x6c, 0x9d, 0x4b, 0x7f, 0x6d, 0x78, 0xbb, 0xc3, 0x53, - 0x3b, 0xe5, 0xa7, 0xbb, 0xf3, 0x0d, 0xd7, 0xcf, 0xf4, 0x97, 0x7a, 0xb7, 0x3b, 0x3c, 0x53, 0x53, - 0x7e, 0xa6, 0x3b, 0xdf, 0xd0, 0x5d, 0x2e, 0xfd, 0x95, 0x5b, 0xad, 0xf3, 0x13, 0x2f, 0xe5, 0x67, - 0xe3, 0x13, 0x42, 0x07, 0x42, 0x9c, 0x10, 0x3a, 0xbd, 0x13, 0x7b, 0x2d, 0xe5, 0xa1, 0x95, 0xf2, - 0x73, 0xb1, 0xbe, 0x4e, 0x50, 0xb0, 0xbe, 0x4e, 0xbe, 0xcf, 0x7a, 0x2d, 0xe5, 0x3d, 0x91, 0xf2, - 0x3f, 0x77, 0xe6, 0x15, 0x08, 0x35, 0xe5, 0x19, 0xd2, 0x6b, 0x29, 0xcf, 0x66, 0x94, 0xff, 0xa5, - 0x33, 0xaf, 0xd0, 0xeb, 0x26, 0xf9, 0xda, 0xe6, 0x0d, 0x38, 0xcb, 0xe7, 0xaf, 0x69, 0x6a, 0xd0, - 0xc8, 0x87, 0xfe, 0x7c, 0x6c, 0xa8, 0xa4, 0x93, 0xe1, 0x21, 0x73, 0x2a, 0x26, 0x8d, 0xb5, 0x68, - 0xeb, 0x2f, 0xec, 0xc0, 0x3a, 0x34, 0x81, 0xd3, 0x31, 0x13, 0x7d, 0xd0, 0x8b, 0xbb, 0x4f, 0xf5, - 0xab, 0x19, 0x18, 0xaa, 0x7a, 0x0e, 0xd5, 0x9b, 0x22, 0x72, 0xc2, 0x79, 0xe8, 0xe7, 0x6e, 0x5c, - 0xfe, 0x4b, 0x0a, 0x2d, 0xf8, 0x4d, 0x2e, 0xc1, 0xc8, 0xac, 0xee, 0x7a, 0x58, 0xb2, 0x62, 0x19, - 0xf4, 0x1e, 0x3e, 0x61, 0xc8, 0x69, 0x31, 0x28, 0x99, 0xe5, 0x74, 0xbc, 0x1c, 0x86, 0xac, 0xc9, - 0xed, 0x18, 0x30, 0xa0, 0xff, 0x9d, 0xad, 0x62, 0x0f, 0xc6, 0x07, 0x88, 0x95, 0x55, 0xbf, 0x99, - 0x81, 0x84, 0x83, 0xd9, 0xfe, 0x5f, 0x38, 0x2d, 0xc0, 0xa9, 0x58, 0x98, 0x24, 0xf1, 0x0e, 0x63, - 0x97, 0x51, 0x94, 0xe2, 0xa5, 0xc9, 0x07, 0x03, 0xff, 0xff, 0x5b, 0xda, 0xac, 0x08, 0x06, 0xd1, - 0xb7, 0xbd, 0x55, 0xcc, 0xb5, 0x9d, 0x86, 0x26, 0xa1, 0xc4, 0x63, 0xe5, 0xff, 0x63, 0x34, 0x8c, - 0x01, 0x43, 0x2e, 0x89, 0xe7, 0x56, 0x99, 0x30, 0x84, 0x44, 0x2c, 0x1d, 0x1c, 0x7f, 0x5e, 0xf5, - 0x31, 0x18, 0xaa, 0x34, 0x5b, 0xd4, 0x71, 0x6d, 0x4b, 0xf7, 0x6c, 0x3f, 0xed, 0x34, 0x86, 0x17, - 0x30, 0x25, 0xb8, 0xfc, 0xe4, 0x5d, 0xa6, 0x27, 0x57, 0xfc, 0xdc, 0x01, 0x39, 0x8c, 0xbe, 0x83, - 0x21, 0x24, 0xe3, 0x29, 0xc6, 0x38, 0x05, 0x23, 0xbd, 0xe5, 0xea, 0xf8, 0x52, 0x24, 0x20, 0x6d, - 0x33, 0x80, 0x4c, 0x8a, 0x14, 0xe4, 0x49, 0x28, 0xe0, 0xc9, 0x9a, 0x8b, 0x39, 0x41, 0x44, 0x60, - 0x8b, 0x06, 0x42, 0xe4, 0x30, 0x02, 0x9c, 0x86, 0xdc, 0x84, 0xd1, 0xf0, 0xda, 0x00, 0x13, 0xa5, - 0xfb, 0x51, 0x80, 0x31, 0x35, 0xdb, 0x7a, 0x80, 0xe3, 0x19, 0xd6, 0x65, 0x16, 0x89, 0x82, 0x64, - 0x06, 0x4e, 0x85, 0x30, 0x26, 0x22, 0x3f, 0xfa, 0x38, 0xa6, 0x26, 0x94, 0x78, 0x31, 0x71, 0xca, - 0xac, 0xe2, 0xc5, 0x48, 0x05, 0xfa, 0xfc, 0xa8, 0x16, 0xfd, 0x3b, 0x2a, 0xe9, 0x69, 0x11, 0xd5, - 0xa2, 0x4f, 0x8e, 0x67, 0xe1, 0x97, 0x27, 0xd3, 0x30, 0xa2, 0xd9, 0x6d, 0x8f, 0x2e, 0xd9, 0x62, - 0xb1, 0x16, 0xe1, 0x69, 0xb1, 0x4d, 0x0e, 0xc3, 0xd4, 0x3c, 0xdb, 0xcf, 0x6c, 0x27, 0x67, 0x58, - 0x8b, 0x96, 0x22, 0xf3, 0x30, 0x96, 0xb8, 0x60, 0x91, 0xf3, 0xcd, 0x49, 0x9f, 0x97, 0x64, 0x96, - 0x2c, 0x4a, 0xbe, 0x3f, 0x03, 0x85, 0x25, 0x47, 0x37, 0x3d, 0x57, 0x3c, 0x32, 0x79, 0x60, 0x7c, - 0xc3, 0xd1, 0x5b, 0x4c, 0x3f, 0xc6, 0x31, 0xbc, 0xd2, 0x6d, 0xbd, 0xd1, 0xa6, 0xee, 0xc4, 0x1d, - 0xf6, 0x75, 0xff, 0x70, 0xab, 0xf8, 0xd1, 0x55, 0xdc, 0xc6, 0x8d, 0xd7, 0xed, 0xe6, 0xd5, 0x55, - 0x47, 0xbf, 0x6b, 0x7a, 0x38, 0x75, 0xe8, 0x8d, 0xab, 0x1e, 0x6d, 0xe0, 0x6e, 0xf1, 0xaa, 0xde, - 0x32, 0xaf, 0x62, 0x18, 0xbf, 0xab, 0x01, 0x27, 0x5e, 0x03, 0x53, 0x01, 0x0f, 0xff, 0x92, 0x55, - 0x80, 0xe3, 0xc8, 0x3c, 0xdb, 0x64, 0xe1, 0xa7, 0x96, 0x5a, 0x2d, 0xf1, 0x62, 0x45, 0xda, 0x63, - 0xf9, 0x18, 0xae, 0xd8, 0x81, 0xc0, 0xf4, 0x96, 0x9c, 0x6e, 0x5f, 0xe2, 0xc0, 0xb4, 0x60, 0x49, - 0xb4, 0xc8, 0x17, 0xd3, 0x70, 0x28, 0x71, 0xbf, 0xb1, 0x29, 0x42, 0x8a, 0x17, 0x23, 0xcb, 0x70, - 0x4a, 0xf0, 0x0d, 0xe2, 0xc5, 0x8e, 0x44, 0x67, 0x85, 0x18, 0x9a, 0x2b, 0x6d, 0xd0, 0x46, 0x43, - 0x80, 0xe5, 0x3a, 0x62, 0x25, 0xc8, 0x44, 0x98, 0x2a, 0x09, 0x73, 0xfb, 0x2b, 0xa7, 0x50, 0x63, - 0x2f, 0x6c, 0x6f, 0x15, 0x15, 0xbf, 0x3c, 0x06, 0x78, 0x49, 0x4d, 0xfc, 0x87, 0x45, 0x64, 0x1e, - 0x5c, 0xeb, 0x47, 0x53, 0x78, 0xc4, 0x75, 0x3e, 0x5a, 0x84, 0x4c, 0xc2, 0x70, 0xe0, 0x30, 0x7b, - 0xeb, 0x56, 0xa5, 0x8c, 0x4f, 0x62, 0x44, 0x12, 0xfb, 0x58, 0x28, 0x5a, 0x99, 0x49, 0xa4, 0x8c, - 0xf4, 0x76, 0x8e, 0xbf, 0x91, 0x89, 0xbd, 0x9d, 0x6b, 0xa5, 0xbc, 0x9d, 0x5b, 0x24, 0x2f, 0xc3, - 0x60, 0xe9, 0x4e, 0x55, 0xbc, 0x09, 0x74, 0x95, 0xd3, 0x61, 0x0c, 0x70, 0xcc, 0xfd, 0x28, 0xde, - 0x0f, 0xca, 0x4d, 0x97, 0xe9, 0xc9, 0x14, 0x8c, 0x44, 0xee, 0xdc, 0x5d, 0xe5, 0x0c, 0x72, 0xe0, - 0xe9, 0xf7, 0x11, 0x53, 0x73, 0x04, 0x2a, 0x92, 0x8d, 0x34, 0x52, 0x88, 0x69, 0x0d, 0xdb, 0xb6, - 0x36, 0x1a, 0xf6, 0x86, 0x46, 0xf1, 0xf9, 0x21, 0x3e, 0xb0, 0xe9, 0xe7, 0x5a, 0x63, 0x08, 0x54, - 0xcd, 0xe1, 0xb8, 0x48, 0xfa, 0xd1, 0x68, 0x31, 0xf2, 0x16, 0x10, 0x8c, 0xc0, 0x4c, 0x0d, 0xff, - 0x08, 0xb6, 0x52, 0x76, 0x95, 0xb3, 0x18, 0x66, 0x8e, 0xc4, 0xdf, 0xbf, 0x56, 0xca, 0x13, 0x97, + // 15313 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6d, 0x70, 0x24, 0x47, + 0x76, 0x20, 0x86, 0xfe, 0x40, 0x03, 0x78, 0xf8, 0x18, 0x20, 0x67, 0x38, 0x53, 0x1c, 0x0e, 0xa7, + 0xc9, 0xe2, 0x72, 0x76, 0x86, 0x4b, 0x62, 0x96, 0xc3, 0x21, 0xb9, 0xe4, 0x92, 0x4b, 0x36, 0xd0, + 0xc0, 0xa0, 0x39, 0xf8, 0x62, 0x35, 0x66, 0x66, 0xb9, 0x1f, 0x6c, 0x15, 0xba, 0x12, 0x40, 0x11, + 0xdd, 0x55, 0xbd, 0x55, 0xd5, 0x83, 0x01, 0xfd, 0xa5, 0x95, 0xf5, 0xb1, 0x2b, 0xef, 0xae, 0xd6, + 0x2b, 0xeb, 0x5b, 0xb6, 0x57, 0x92, 0x65, 0x4b, 0x0a, 0x59, 0x1f, 0xb6, 0x43, 0xd2, 0x4a, 0xde, + 0xb0, 0xe4, 0xb5, 0xc3, 0x94, 0xd7, 0x72, 0x48, 0xb2, 0x4f, 0xa1, 0xb8, 0xd3, 0x61, 0x75, 0x7b, + 0xa7, 0xfb, 0x81, 0xb8, 0x8b, 0xd0, 0xdd, 0x6d, 0x9c, 0x74, 0x3a, 0xdd, 0xc5, 0x45, 0xbe, 0xcc, + 0xaa, 0xca, 0xfa, 0xe8, 0xc6, 0x27, 0x05, 0x82, 0x83, 0x3f, 0x33, 0xe8, 0xf7, 0x5e, 0xbe, 0xcc, + 0x7a, 0xf9, 0x32, 0xf3, 0x65, 0xe6, 0xcb, 0xf7, 0xe0, 0x8a, 0x47, 0x1b, 0xb4, 0x65, 0x3b, 0xde, + 0xd5, 0x06, 0x5d, 0xd5, 0xeb, 0x9b, 0x57, 0xbd, 0xcd, 0x16, 0x75, 0xaf, 0xd2, 0xbb, 0xd4, 0xf2, + 0xfc, 0xff, 0xc6, 0x5b, 0x8e, 0xed, 0xd9, 0xa4, 0xc0, 0x7f, 0x9d, 0x3f, 0xb3, 0x6a, 0xaf, 0xda, + 0x08, 0xba, 0xca, 0xfe, 0xe2, 0xd8, 0xf3, 0x17, 0x56, 0x6d, 0x7b, 0xb5, 0x41, 0xaf, 0xe2, 0xaf, + 0xe5, 0xf6, 0xca, 0x55, 0xd7, 0x73, 0xda, 0x75, 0x4f, 0x60, 0x8b, 0x71, 0xac, 0x67, 0x36, 0xa9, + 0xeb, 0xe9, 0xcd, 0x96, 0x20, 0xb8, 0x18, 0x27, 0xd8, 0x70, 0xf4, 0x56, 0x8b, 0x3a, 0xa2, 0xf2, + 0xf3, 0x8f, 0xa6, 0xb7, 0x13, 0xff, 0x15, 0x24, 0x4f, 0xa5, 0x93, 0xf8, 0x8c, 0x62, 0x1c, 0xd5, + 0xaf, 0x64, 0xa1, 0x7f, 0x8e, 0x7a, 0xba, 0xa1, 0x7b, 0x3a, 0xb9, 0x00, 0xbd, 0x15, 0xcb, 0xa0, + 0xf7, 0x94, 0xcc, 0x23, 0x99, 0xcb, 0xb9, 0x89, 0xc2, 0xf6, 0x56, 0x31, 0x4b, 0x4d, 0x8d, 0x03, + 0xc9, 0xc3, 0x90, 0x5f, 0xda, 0x6c, 0x51, 0x25, 0xfb, 0x48, 0xe6, 0xf2, 0xc0, 0xc4, 0xc0, 0xf6, + 0x56, 0xb1, 0x17, 0x65, 0xa1, 0x21, 0x98, 0x3c, 0x0a, 0xd9, 0x4a, 0x59, 0xc9, 0x21, 0x72, 0x6c, + 0x7b, 0xab, 0x38, 0xdc, 0x36, 0x8d, 0x27, 0xed, 0xa6, 0xe9, 0xd1, 0x66, 0xcb, 0xdb, 0xd4, 0xb2, + 0x95, 0x32, 0xb9, 0x04, 0xf9, 0x49, 0xdb, 0xa0, 0x4a, 0x1e, 0x89, 0xc8, 0xf6, 0x56, 0x71, 0xa4, + 0x6e, 0x1b, 0x54, 0xa2, 0x42, 0x3c, 0x79, 0x15, 0xf2, 0x4b, 0x66, 0x93, 0x2a, 0xbd, 0x8f, 0x64, + 0x2e, 0x0f, 0x5e, 0x3b, 0x3f, 0xce, 0xa5, 0x32, 0xee, 0x4b, 0x65, 0x7c, 0xc9, 0x17, 0xdb, 0xc4, + 0xe8, 0x3b, 0x5b, 0xc5, 0x9e, 0xed, 0xad, 0x62, 0x9e, 0x49, 0xf2, 0xcb, 0xdf, 0x2a, 0x66, 0x34, + 0x2c, 0x49, 0x5e, 0x82, 0xc1, 0xc9, 0x46, 0xdb, 0xf5, 0xa8, 0x33, 0xaf, 0x37, 0xa9, 0x52, 0xc0, + 0x0a, 0xcf, 0x6f, 0x6f, 0x15, 0xcf, 0xd6, 0x39, 0xb8, 0x66, 0xe9, 0x4d, 0xb9, 0x62, 0x99, 0x5c, + 0xfd, 0xad, 0x0c, 0x9c, 0xaa, 0x52, 0xd7, 0x35, 0x6d, 0x2b, 0x90, 0xcd, 0xe3, 0x30, 0x20, 0x40, + 0x95, 0x32, 0xca, 0x67, 0x60, 0xa2, 0x6f, 0x7b, 0xab, 0x98, 0x73, 0x4d, 0x43, 0x0b, 0x31, 0xe4, + 0xc3, 0xd0, 0x77, 0xc7, 0xf4, 0xd6, 0xe6, 0xa6, 0x4b, 0x42, 0x4e, 0x67, 0xb7, 0xb7, 0x8a, 0x64, + 0xc3, 0xf4, 0xd6, 0x6a, 0xcd, 0x15, 0x5d, 0xaa, 0xd0, 0x27, 0x23, 0xb3, 0x30, 0xba, 0xe8, 0x98, + 0x77, 0x75, 0x8f, 0xde, 0xa4, 0x9b, 0x8b, 0x76, 0xc3, 0xac, 0x6f, 0x0a, 0x29, 0x3e, 0xb2, 0xbd, + 0x55, 0xbc, 0xd0, 0xe2, 0xb8, 0xda, 0x3a, 0xdd, 0xac, 0xb5, 0x10, 0x2b, 0x31, 0x49, 0x94, 0x54, + 0xbf, 0xd1, 0x0b, 0x43, 0xb7, 0x5c, 0xea, 0x04, 0xed, 0xbe, 0x04, 0x79, 0xf6, 0x5b, 0x34, 0x19, + 0x65, 0xde, 0x76, 0xa9, 0x23, 0xcb, 0x9c, 0xe1, 0xc9, 0x15, 0xe8, 0x9d, 0xb5, 0x57, 0x4d, 0x4b, + 0x34, 0xfb, 0xf4, 0xf6, 0x56, 0xf1, 0x54, 0x83, 0x01, 0x24, 0x4a, 0x4e, 0x41, 0x3e, 0x06, 0x43, + 0x95, 0x26, 0xd3, 0x21, 0xdb, 0xd2, 0x3d, 0xdb, 0x11, 0xad, 0x45, 0xe9, 0x9a, 0x12, 0x5c, 0x2a, + 0x18, 0xa1, 0x27, 0x2f, 0x02, 0x94, 0xee, 0x54, 0x35, 0xbb, 0x41, 0x4b, 0xda, 0xbc, 0x50, 0x06, + 0x2c, 0xad, 0x6f, 0xb8, 0x35, 0xc7, 0x6e, 0xd0, 0x9a, 0xee, 0xc8, 0xd5, 0x4a, 0xd4, 0x64, 0x0a, + 0x46, 0x4a, 0xf5, 0x3a, 0x75, 0x5d, 0x8d, 0x7e, 0xa6, 0x4d, 0x5d, 0xcf, 0x55, 0x7a, 0x1f, 0xc9, + 0x5d, 0x1e, 0x98, 0x78, 0x78, 0x7b, 0xab, 0xf8, 0xa0, 0x8e, 0x98, 0x9a, 0x23, 0x50, 0x12, 0x8b, + 0x58, 0x21, 0x32, 0x01, 0xc3, 0xa5, 0xb7, 0xdb, 0x0e, 0xad, 0x18, 0xd4, 0xf2, 0x4c, 0x6f, 0x53, + 0x68, 0xc8, 0x85, 0xed, 0xad, 0xa2, 0xa2, 0x33, 0x44, 0xcd, 0x14, 0x18, 0x89, 0x49, 0xb4, 0x08, + 0x59, 0x80, 0xb1, 0x1b, 0x93, 0x8b, 0x55, 0xea, 0xdc, 0x35, 0xeb, 0xb4, 0x54, 0xaf, 0xdb, 0x6d, + 0xcb, 0x53, 0xfa, 0x90, 0xcf, 0xa3, 0xdb, 0x5b, 0xc5, 0x87, 0x57, 0xeb, 0xad, 0x9a, 0xcb, 0xb1, + 0x35, 0x9d, 0xa3, 0x25, 0x66, 0xc9, 0xb2, 0xe4, 0x13, 0x30, 0xbc, 0xe4, 0x30, 0x2d, 0x34, 0xca, + 0x94, 0xc1, 0x95, 0x7e, 0xd4, 0xff, 0xb3, 0xe3, 0x62, 0x02, 0xe2, 0x50, 0xbf, 0x67, 0x79, 0x63, + 0x3d, 0x5e, 0xa0, 0x66, 0x20, 0x4e, 0x6e, 0x6c, 0x84, 0x15, 0xa1, 0xa0, 0xb0, 0x8f, 0x37, 0x1d, + 0x6a, 0x24, 0xb4, 0x6d, 0x00, 0xdb, 0x7c, 0x65, 0x7b, 0xab, 0xf8, 0xb8, 0x23, 0x68, 0x6a, 0x5d, + 0xd5, 0xae, 0x23, 0x2b, 0x32, 0x05, 0xfd, 0x4c, 0x9b, 0x6e, 0x9a, 0x96, 0xa1, 0xc0, 0x23, 0x99, + 0xcb, 0x23, 0xd7, 0x46, 0xfd, 0xd6, 0xfb, 0xf0, 0x89, 0x73, 0xdb, 0x5b, 0xc5, 0xd3, 0x4c, 0x07, + 0x6b, 0xeb, 0xa6, 0x25, 0x4f, 0x11, 0x41, 0x51, 0xf5, 0xaf, 0xf2, 0x30, 0xc2, 0x84, 0x23, 0xe9, + 0x71, 0x89, 0x0d, 0x49, 0x06, 0x61, 0x23, 0xd4, 0x6d, 0xe9, 0x75, 0x2a, 0x54, 0x1a, 0xd9, 0x59, + 0x3e, 0x50, 0x62, 0x17, 0xa7, 0x27, 0x57, 0xa0, 0x9f, 0x83, 0x2a, 0x65, 0xa1, 0xe5, 0xc3, 0xdb, + 0x5b, 0xc5, 0x01, 0x17, 0x61, 0x35, 0xd3, 0xd0, 0x02, 0x34, 0x53, 0x33, 0xfe, 0xf7, 0x8c, 0xed, + 0x7a, 0x8c, 0xb9, 0x50, 0x72, 0x54, 0x33, 0x51, 0x60, 0x4d, 0xa0, 0x64, 0x35, 0x8b, 0x16, 0x22, + 0x2f, 0x00, 0x70, 0x48, 0xc9, 0x30, 0x1c, 0xa1, 0xe9, 0x0f, 0x6e, 0x6f, 0x15, 0x1f, 0x10, 0x2c, + 0x74, 0xc3, 0x90, 0x87, 0x89, 0x44, 0x4c, 0x9a, 0x30, 0xc4, 0x7f, 0xcd, 0xea, 0xcb, 0xb4, 0xc1, + 0xd5, 0x7c, 0xf0, 0xda, 0x65, 0x5f, 0x9a, 0x51, 0xe9, 0x8c, 0xcb, 0xa4, 0x53, 0x96, 0xe7, 0x6c, + 0x4e, 0x14, 0xc5, 0xcc, 0x78, 0x4e, 0x54, 0xd5, 0x40, 0x9c, 0x3c, 0x26, 0xe5, 0x32, 0x6c, 0xc2, + 0x9c, 0xb6, 0x9d, 0x0d, 0xdd, 0x31, 0xa8, 0x31, 0xb1, 0x29, 0x4f, 0x98, 0x2b, 0x3e, 0xb8, 0xb6, + 0x2c, 0xeb, 0x80, 0x4c, 0x4e, 0x26, 0x61, 0x98, 0x73, 0xab, 0xb6, 0x97, 0xb1, 0xef, 0xfb, 0x12, + 0xd2, 0x72, 0xdb, 0xcb, 0xf1, 0xfe, 0x8e, 0x96, 0x61, 0x63, 0x92, 0x03, 0x6e, 0x53, 0x87, 0xcd, + 0xa6, 0xa8, 0xfe, 0x62, 0x4c, 0x0a, 0x26, 0x77, 0x39, 0x26, 0xc9, 0x43, 0x14, 0x39, 0xff, 0x0a, + 0x8c, 0x25, 0x44, 0x41, 0x46, 0x21, 0xb7, 0x4e, 0x37, 0xb9, 0xba, 0x68, 0xec, 0x4f, 0x72, 0x06, + 0x7a, 0xef, 0xea, 0x8d, 0xb6, 0x58, 0xcb, 0x34, 0xfe, 0xe3, 0xc5, 0xec, 0x47, 0x32, 0x6c, 0xea, + 0x27, 0x93, 0xb6, 0x65, 0xd1, 0xba, 0x27, 0xcf, 0xfe, 0xcf, 0xc1, 0xc0, 0xac, 0x5d, 0xd7, 0x1b, + 0xd8, 0x8f, 0x5c, 0xef, 0x94, 0xed, 0xad, 0xe2, 0x19, 0xd6, 0x81, 0xe3, 0x0d, 0x86, 0x91, 0xda, + 0x14, 0x92, 0x32, 0x05, 0xd0, 0x68, 0xd3, 0xf6, 0x28, 0x16, 0xcc, 0x86, 0x0a, 0x80, 0x05, 0x1d, + 0x44, 0xc9, 0x0a, 0x10, 0x12, 0x93, 0xab, 0xd0, 0xbf, 0xc8, 0x16, 0xbc, 0xba, 0xdd, 0x10, 0xca, + 0x87, 0x73, 0x32, 0x2e, 0x82, 0xf2, 0xa0, 0xf1, 0x89, 0xd4, 0x19, 0x18, 0x99, 0x6c, 0x98, 0xd4, + 0xf2, 0xe4, 0x56, 0xb3, 0x21, 0x55, 0x5a, 0xa5, 0x96, 0x27, 0xb7, 0x1a, 0x07, 0x9f, 0xce, 0xa0, + 0x72, 0xab, 0x03, 0x52, 0xf5, 0xff, 0xcd, 0xc1, 0x83, 0x37, 0xdb, 0xcb, 0xd4, 0xb1, 0xa8, 0x47, + 0x5d, 0xb1, 0x32, 0x06, 0x5c, 0xe7, 0x61, 0x2c, 0x81, 0x14, 0xdc, 0x71, 0xc5, 0x5a, 0x0f, 0x90, + 0x35, 0xb1, 0xd8, 0xca, 0xd3, 0x5e, 0xa2, 0x28, 0x99, 0x81, 0x53, 0x21, 0x90, 0x35, 0xc2, 0x55, + 0xb2, 0x38, 0xa7, 0x5f, 0xdc, 0xde, 0x2a, 0x9e, 0x97, 0xb8, 0xb1, 0x66, 0xcb, 0x1a, 0x1c, 0x2f, + 0x46, 0x6e, 0xc2, 0x68, 0x08, 0xba, 0xe1, 0xd8, 0xed, 0x96, 0xab, 0xe4, 0x90, 0x55, 0x71, 0x7b, + 0xab, 0xf8, 0x90, 0xc4, 0x6a, 0x15, 0x91, 0xf2, 0x4a, 0x1a, 0x2f, 0x48, 0xbe, 0x37, 0x23, 0x73, + 0x13, 0xa3, 0x30, 0x8f, 0xa3, 0xf0, 0x79, 0x7f, 0x14, 0x76, 0x14, 0xd2, 0x78, 0xbc, 0xa4, 0x18, + 0x94, 0xb1, 0x66, 0x24, 0x06, 0x65, 0xa2, 0xc6, 0xf3, 0x93, 0xf0, 0x40, 0x2a, 0xaf, 0x3d, 0x69, + 0xf5, 0x5f, 0xe4, 0x64, 0x2e, 0x8b, 0xb6, 0x11, 0x74, 0xe6, 0x82, 0xdc, 0x99, 0x8b, 0xb6, 0x81, + 0xe6, 0x52, 0x26, 0x5c, 0xc4, 0xa4, 0xc6, 0xb6, 0x6c, 0x23, 0x6e, 0x35, 0x25, 0xcb, 0x92, 0x37, + 0xe1, 0x6c, 0x02, 0xc8, 0xa7, 0x6b, 0xae, 0xfd, 0x97, 0xb6, 0xb7, 0x8a, 0x6a, 0x0a, 0xd7, 0xf8, + 0xec, 0xdd, 0x81, 0x0b, 0xd1, 0xe1, 0x9c, 0x24, 0x75, 0xdb, 0xf2, 0x74, 0xd3, 0x12, 0x56, 0x1e, + 0x1f, 0x25, 0x1f, 0xdc, 0xde, 0x2a, 0x3e, 0x26, 0xeb, 0xa0, 0x4f, 0x13, 0x6f, 0x7c, 0x27, 0x3e, + 0xc4, 0x00, 0x25, 0x05, 0x55, 0x69, 0xea, 0xab, 0xbe, 0xe9, 0x7a, 0x79, 0x7b, 0xab, 0xf8, 0x81, + 0xd4, 0x3a, 0x4c, 0x46, 0x25, 0x2f, 0x95, 0x9d, 0x38, 0x11, 0x0d, 0x48, 0x88, 0x9b, 0xb7, 0x0d, + 0x8a, 0xdf, 0xd0, 0x8b, 0xfc, 0xd5, 0xed, 0xad, 0xe2, 0x45, 0x89, 0xbf, 0x65, 0x1b, 0x34, 0xde, + 0xfc, 0x94, 0xd2, 0xea, 0x6f, 0xe5, 0xe0, 0x62, 0xb5, 0x34, 0x37, 0x5b, 0x31, 0x7c, 0xdb, 0x62, + 0xd1, 0xb1, 0xef, 0x9a, 0x86, 0x34, 0x7a, 0x97, 0xe1, 0x5c, 0x0c, 0x35, 0x85, 0xe6, 0x4c, 0x60, + 0xd5, 0xe2, 0xb7, 0xf9, 0x76, 0x4b, 0x4b, 0xd0, 0xd4, 0xb8, 0xcd, 0x53, 0x8b, 0x98, 0xf4, 0x9d, + 0x18, 0xb1, 0x3e, 0x8a, 0xa1, 0xaa, 0x6b, 0xb6, 0xe3, 0xd5, 0xdb, 0x9e, 0x50, 0x02, 0xec, 0xa3, + 0x44, 0x1d, 0xae, 0x20, 0xea, 0x52, 0x85, 0xcf, 0x87, 0x7c, 0x3e, 0x03, 0xa3, 0x25, 0xcf, 0x73, + 0xcc, 0xe5, 0xb6, 0x47, 0xe7, 0xf4, 0x56, 0xcb, 0xb4, 0x56, 0x71, 0xac, 0x0f, 0x5e, 0x7b, 0x29, + 0x58, 0x23, 0xbb, 0x4a, 0x62, 0x3c, 0x5e, 0x5c, 0x1a, 0xa2, 0xba, 0x8f, 0xaa, 0x35, 0x39, 0x4e, + 0x1e, 0xa2, 0xf1, 0x72, 0x6c, 0x88, 0xa6, 0xf2, 0xda, 0xd3, 0x10, 0xfd, 0x4a, 0x0e, 0x2e, 0x2c, + 0xac, 0x7b, 0xba, 0x46, 0x5d, 0xbb, 0xed, 0xd4, 0xa9, 0x7b, 0xab, 0x65, 0xe8, 0x1e, 0x0d, 0x47, + 0x6a, 0x11, 0x7a, 0x4b, 0x86, 0x41, 0x0d, 0x64, 0xd7, 0xcb, 0xf7, 0x5f, 0x3a, 0x03, 0x68, 0x1c, + 0x4e, 0x1e, 0x87, 0x3e, 0x51, 0x06, 0xb9, 0xf7, 0x4e, 0x0c, 0x6e, 0x6f, 0x15, 0xfb, 0xda, 0x1c, + 0xa4, 0xf9, 0x38, 0x46, 0x56, 0xa6, 0x0d, 0xca, 0xc8, 0x72, 0x21, 0x99, 0xc1, 0x41, 0x9a, 0x8f, + 0x23, 0xaf, 0xc3, 0x08, 0xb2, 0x0d, 0xda, 0x23, 0xe6, 0xbe, 0x33, 0xbe, 0x74, 0xe5, 0xc6, 0xf2, + 0xa5, 0x09, 0x5b, 0x53, 0x73, 0xfc, 0x02, 0x5a, 0x8c, 0x01, 0xb9, 0x03, 0xa3, 0xa2, 0x11, 0x21, + 0xd3, 0xde, 0x2e, 0x4c, 0x1f, 0xd8, 0xde, 0x2a, 0x8e, 0x89, 0xf6, 0x4b, 0x6c, 0x13, 0x4c, 0x18, + 0x63, 0xd1, 0xec, 0x90, 0x71, 0x61, 0x27, 0xc6, 0xe2, 0x8b, 0x65, 0xc6, 0x71, 0x26, 0xea, 0x1b, + 0x30, 0x24, 0x17, 0x24, 0x67, 0x71, 0x8f, 0xcb, 0xc7, 0x09, 0xee, 0x8e, 0x4d, 0x03, 0x37, 0xb6, + 0x4f, 0xc3, 0x60, 0x99, 0xba, 0x75, 0xc7, 0x6c, 0x31, 0xab, 0x41, 0x28, 0xf9, 0xa9, 0xed, 0xad, + 0xe2, 0xa0, 0x11, 0x82, 0x35, 0x99, 0x46, 0xfd, 0xd7, 0x19, 0x38, 0xcb, 0x78, 0x97, 0x5c, 0xd7, + 0x5c, 0xb5, 0x9a, 0xf2, 0xb2, 0xfd, 0x24, 0x14, 0xaa, 0x58, 0x9f, 0xa8, 0xe9, 0xcc, 0xf6, 0x56, + 0x71, 0x94, 0xb7, 0x40, 0xd2, 0x43, 0x41, 0x13, 0x6c, 0xf0, 0xb2, 0x3b, 0x6c, 0xf0, 0x98, 0x49, + 0xeb, 0xe9, 0x8e, 0x67, 0x5a, 0xab, 0x55, 0x4f, 0xf7, 0xda, 0x6e, 0xc4, 0xa4, 0x15, 0x98, 0x9a, + 0x8b, 0xa8, 0x88, 0x49, 0x1b, 0x29, 0x44, 0x5e, 0x81, 0xa1, 0x29, 0xcb, 0x08, 0x99, 0xf0, 0x09, + 0xf1, 0x21, 0x66, 0x69, 0x52, 0x84, 0x27, 0x59, 0x44, 0x0a, 0xa8, 0xff, 0x63, 0x06, 0x14, 0xbe, + 0x1b, 0x9b, 0x35, 0x5d, 0x6f, 0x8e, 0x36, 0x97, 0xa5, 0xd9, 0x69, 0xda, 0xdf, 0xde, 0x31, 0x9c, + 0xb4, 0x16, 0xa1, 0x29, 0x20, 0xb6, 0x77, 0x0d, 0xd3, 0xf5, 0xe2, 0x93, 0x61, 0xac, 0x14, 0xa9, + 0x40, 0x1f, 0xe7, 0xcc, 0x6d, 0x89, 0xc1, 0x6b, 0x8a, 0xaf, 0x08, 0xf1, 0xaa, 0xb9, 0x32, 0x34, + 0x39, 0xb1, 0xbc, 0x3f, 0x17, 0xe5, 0xd5, 0x5f, 0xcb, 0xc2, 0x68, 0xbc, 0x10, 0xb9, 0x03, 0xfd, + 0xaf, 0xd9, 0xa6, 0x45, 0x8d, 0x05, 0x0b, 0x5b, 0xd8, 0xfd, 0x94, 0xc2, 0xb7, 0xc5, 0x4f, 0xbf, + 0x85, 0x65, 0x6a, 0xb2, 0x05, 0x8b, 0x87, 0x16, 0x01, 0x33, 0xf2, 0x09, 0x18, 0x60, 0x36, 0xe0, + 0x5d, 0xe4, 0x9c, 0xdd, 0x91, 0xf3, 0x23, 0x82, 0xf3, 0x19, 0x87, 0x17, 0x4a, 0xb2, 0x0e, 0xd9, + 0x31, 0xbd, 0xd2, 0xa8, 0xee, 0xda, 0x96, 0xe8, 0x79, 0xd4, 0x2b, 0x07, 0x21, 0xb2, 0x5e, 0x71, + 0x1a, 0x66, 0xba, 0xf2, 0x8f, 0xc5, 0x6e, 0x90, 0xf6, 0x2e, 0x5c, 0x56, 0xf1, 0x1e, 0x90, 0x88, + 0xd5, 0xef, 0xcf, 0xc2, 0x53, 0xa1, 0xc8, 0x34, 0x7a, 0xd7, 0xa4, 0x1b, 0x42, 0x9c, 0x6b, 0x66, + 0x4b, 0x6c, 0x1e, 0x99, 0xca, 0xbb, 0x93, 0x6b, 0xba, 0xb5, 0x4a, 0x0d, 0x72, 0x05, 0x7a, 0xd9, + 0x0e, 0xdf, 0x55, 0x32, 0x68, 0xae, 0xe1, 0x74, 0xe2, 0x30, 0x80, 0x7c, 0xfa, 0x80, 0x14, 0xc4, + 0x86, 0xc2, 0x92, 0xa3, 0x9b, 0x9e, 0xdf, 0xb3, 0xa5, 0x64, 0xcf, 0xee, 0xa2, 0xc6, 0x71, 0xce, + 0x83, 0xcf, 0xf9, 0x28, 0x08, 0x0f, 0x01, 0xb2, 0x20, 0x38, 0xc9, 0xf9, 0x17, 0x60, 0x50, 0x22, + 0xde, 0xd3, 0xa4, 0xfe, 0xb5, 0xbc, 0xac, 0xeb, 0x7e, 0xb3, 0x84, 0xae, 0x5f, 0x65, 0x3a, 0xea, + 0xba, 0xcc, 0xaa, 0xe0, 0x4a, 0x2e, 0x34, 0x11, 0x41, 0x51, 0x4d, 0x44, 0x10, 0x79, 0x06, 0xfa, + 0x39, 0x8b, 0x60, 0xff, 0x8a, 0x7b, 0x5f, 0x07, 0x61, 0xd1, 0xa5, 0x39, 0x20, 0x24, 0xbf, 0x94, + 0x81, 0x87, 0xbb, 0x4a, 0x02, 0x95, 0x61, 0xf0, 0xda, 0xb3, 0xfb, 0x12, 0xe3, 0xc4, 0x53, 0xdb, + 0x5b, 0xc5, 0x2b, 0xcd, 0x80, 0xa4, 0xe6, 0x48, 0x34, 0xb5, 0x3a, 0x27, 0x92, 0xda, 0xd5, 0xbd, + 0x29, 0xcc, 0x78, 0xe4, 0x95, 0x4e, 0xe3, 0x19, 0x8e, 0x55, 0xdf, 0xf4, 0x1b, 0x99, 0x0f, 0x8d, + 0x47, 0xf1, 0xbd, 0x2b, 0x3e, 0x49, 0x4a, 0x35, 0x1d, 0xb8, 0x90, 0x3a, 0x9c, 0xe3, 0x98, 0xb2, + 0xbe, 0xb9, 0xb0, 0x32, 0x67, 0x5b, 0xde, 0x9a, 0x5f, 0x41, 0xaf, 0x7c, 0x08, 0x82, 0x15, 0x18, + 0xfa, 0x66, 0xcd, 0x5e, 0xa9, 0x35, 0x19, 0x55, 0x4a, 0x1d, 0x9d, 0x38, 0xb1, 0x89, 0x56, 0x8c, + 0x39, 0x7f, 0x0a, 0x2a, 0x84, 0x47, 0x54, 0xfe, 0x38, 0x4d, 0x4e, 0x38, 0xb1, 0x42, 0x6a, 0x05, + 0x86, 0x66, 0xed, 0xfa, 0x7a, 0xa0, 0x2e, 0x2f, 0x40, 0x61, 0x49, 0x77, 0x56, 0xa9, 0x87, 0xb2, + 0x18, 0xbc, 0x36, 0x36, 0xce, 0x8f, 0x7d, 0x19, 0x11, 0x47, 0x4c, 0x8c, 0x88, 0xd9, 0xa0, 0xe0, + 0xe1, 0x6f, 0x4d, 0x14, 0x50, 0xbf, 0xd5, 0x0b, 0x43, 0xe2, 0x88, 0x12, 0x67, 0x73, 0xf2, 0x62, + 0x78, 0xe8, 0x2b, 0xa6, 0xaf, 0xe0, 0x98, 0x26, 0x38, 0x5e, 0x1a, 0x62, 0xcc, 0xfe, 0x70, 0xab, + 0x98, 0xd9, 0xde, 0x2a, 0xf6, 0x68, 0xfd, 0xd2, 0xa6, 0x32, 0x5c, 0x6f, 0xa4, 0x05, 0x56, 0x3e, + 0x74, 0x8c, 0x95, 0xe5, 0xeb, 0xcf, 0x2b, 0xd0, 0x27, 0xda, 0x20, 0x34, 0xee, 0x5c, 0x78, 0x96, + 0x11, 0x39, 0x6a, 0x8d, 0x95, 0xf6, 0x4b, 0x91, 0x97, 0xa0, 0xc0, 0xf7, 0xf6, 0x42, 0x00, 0x67, + 0xd3, 0xcf, 0x42, 0x62, 0xc5, 0x45, 0x19, 0x32, 0x03, 0x10, 0xee, 0xeb, 0x83, 0x93, 0x65, 0xc1, + 0x21, 0xb9, 0xe3, 0x8f, 0x71, 0x91, 0xca, 0x92, 0xe7, 0x60, 0x68, 0x89, 0x3a, 0x4d, 0xd3, 0xd2, + 0x1b, 0x55, 0xf3, 0x6d, 0xff, 0x70, 0x19, 0x17, 0x5e, 0xd7, 0x7c, 0x5b, 0x1e, 0xb9, 0x11, 0x3a, + 0xf2, 0xe9, 0xb4, 0x7d, 0x73, 0x1f, 0x36, 0xe4, 0xd1, 0x1d, 0x37, 0x94, 0xb1, 0xf6, 0xa4, 0x6c, + 0xa3, 0x5f, 0x87, 0xe1, 0xc8, 0x96, 0x49, 0x9c, 0x1e, 0x3e, 0x9c, 0x64, 0x2d, 0xed, 0xff, 0x62, + 0x6c, 0xa3, 0x1c, 0x98, 0x26, 0x57, 0x2c, 0xd3, 0x33, 0xf5, 0xc6, 0xa4, 0xdd, 0x6c, 0xea, 0x96, + 0xa1, 0x0c, 0x84, 0x9a, 0x6c, 0x72, 0x4c, 0xad, 0xce, 0x51, 0xb2, 0x26, 0x47, 0x0b, 0xb1, 0x6d, + 0xb9, 0xe8, 0x43, 0x8d, 0xd6, 0x6d, 0x87, 0xd9, 0x02, 0x78, 0x38, 0x28, 0xb6, 0xe5, 0x2e, 0xc7, + 0xd5, 0x1c, 0x1f, 0x29, 0x1b, 0xdb, 0xf1, 0x82, 0xaf, 0xe5, 0xfb, 0x07, 0x47, 0x87, 0xe2, 0xe7, + 0xb9, 0xea, 0x2f, 0xe6, 0x60, 0x50, 0x90, 0xb2, 0xa5, 0xf4, 0x44, 0xc1, 0x0f, 0xa2, 0xe0, 0xa9, + 0x8a, 0x5a, 0x38, 0x2c, 0x45, 0x55, 0xbf, 0x90, 0x0d, 0x66, 0xa3, 0x45, 0xc7, 0xb4, 0x0e, 0x36, + 0x1b, 0x5d, 0x02, 0x98, 0x5c, 0x6b, 0x5b, 0xeb, 0xfc, 0xde, 0x2a, 0x1b, 0xde, 0x5b, 0xd5, 0x4d, + 0x4d, 0xc2, 0x90, 0x87, 0x21, 0x5f, 0x66, 0xfc, 0x59, 0xcf, 0x0c, 0x4d, 0x0c, 0xbc, 0xc3, 0x39, + 0x65, 0x9e, 0xd2, 0x10, 0xcc, 0x36, 0x57, 0x13, 0x9b, 0x1e, 0xe5, 0xe6, 0x6c, 0x8e, 0x6f, 0xae, + 0x96, 0x19, 0x40, 0xe3, 0x70, 0x72, 0x1d, 0xc6, 0xca, 0xb4, 0xa1, 0x6f, 0xce, 0x99, 0x8d, 0x86, + 0xe9, 0xd2, 0xba, 0x6d, 0x19, 0x2e, 0x0a, 0x59, 0x54, 0xd7, 0x74, 0xb5, 0x24, 0x01, 0x51, 0xa1, + 0xb0, 0xb0, 0xb2, 0xe2, 0x52, 0x0f, 0xc5, 0x97, 0x9b, 0x00, 0x36, 0x39, 0xdb, 0x08, 0xd1, 0x04, + 0x46, 0xfd, 0xd5, 0x0c, 0xdb, 0xbd, 0xb8, 0xeb, 0x9e, 0xdd, 0x0a, 0xb4, 0xfc, 0x40, 0x22, 0xb9, + 0x12, 0xda, 0x15, 0x59, 0xfc, 0xda, 0x53, 0xe2, 0x6b, 0xfb, 0x84, 0x6d, 0x11, 0x5a, 0x14, 0xa9, + 0x5f, 0x95, 0xdb, 0xe1, 0xab, 0xd4, 0xbf, 0xcc, 0xc2, 0x39, 0xd1, 0xe2, 0xc9, 0x86, 0xd9, 0x5a, + 0xb6, 0x75, 0xc7, 0xd0, 0x68, 0x9d, 0x9a, 0x77, 0xe9, 0xf1, 0x1c, 0x78, 0xd1, 0xa1, 0x93, 0x3f, + 0xc0, 0xd0, 0xb9, 0x86, 0x1b, 0x41, 0x26, 0x19, 0x3c, 0xf0, 0xe5, 0x46, 0xc5, 0xe8, 0xf6, 0x56, + 0x71, 0xc8, 0xe0, 0x60, 0x3c, 0xf2, 0xd7, 0x64, 0x22, 0xa6, 0x24, 0xb3, 0xd4, 0x5a, 0xf5, 0xd6, + 0x50, 0x49, 0x7a, 0xb9, 0x92, 0x34, 0x10, 0xa2, 0x09, 0x8c, 0xfa, 0xcf, 0xb3, 0x70, 0x26, 0x2e, + 0xf2, 0x2a, 0xb5, 0x8c, 0x13, 0x79, 0xbf, 0x3b, 0xf2, 0xfe, 0x4e, 0x0e, 0x1e, 0x12, 0x65, 0xaa, + 0x6b, 0xba, 0x43, 0x8d, 0xb2, 0xe9, 0xd0, 0xba, 0x67, 0x3b, 0x9b, 0xc7, 0xd8, 0x80, 0x3a, 0x3c, + 0xb1, 0x5f, 0x87, 0x82, 0xd8, 0xfe, 0xf3, 0x75, 0x66, 0x24, 0x68, 0x09, 0x42, 0x13, 0x2b, 0x14, + 0x3f, 0x3a, 0x88, 0x75, 0x56, 0x61, 0x37, 0x9d, 0xf5, 0x11, 0x18, 0x0e, 0x44, 0x8f, 0x1b, 0xd1, + 0xbe, 0xd0, 0xda, 0x32, 0x7c, 0x04, 0xee, 0x45, 0xb5, 0x28, 0x21, 0xd6, 0xe6, 0x03, 0x2a, 0x65, + 0xb4, 0x86, 0x86, 0x45, 0x6d, 0x41, 0x39, 0xd3, 0xd0, 0x64, 0x22, 0x75, 0x2b, 0x0f, 0xe7, 0xd3, + 0xbb, 0x5d, 0xa3, 0xba, 0x71, 0xd2, 0xeb, 0xef, 0xcb, 0x5e, 0x27, 0x8f, 0x42, 0x7e, 0x51, 0xf7, + 0xd6, 0xc4, 0x3d, 0x38, 0xde, 0x09, 0xaf, 0x98, 0x0d, 0x5a, 0x6b, 0xe9, 0xde, 0x9a, 0x86, 0x28, + 0x69, 0xce, 0x00, 0xe4, 0x98, 0x32, 0x67, 0x48, 0x8b, 0xfd, 0xe0, 0x23, 0x99, 0xcb, 0xf9, 0xd4, + 0xc5, 0xfe, 0x5b, 0xf9, 0x4e, 0xf3, 0xca, 0x1d, 0xc7, 0xf4, 0xe8, 0x89, 0x86, 0x9d, 0x68, 0xd8, + 0x01, 0x35, 0xec, 0x8f, 0xb3, 0x30, 0x1c, 0x6c, 0x9a, 0xde, 0xa2, 0xf5, 0xa3, 0x59, 0xab, 0xc2, + 0xad, 0x4c, 0xee, 0xc0, 0x5b, 0x99, 0x83, 0x28, 0x94, 0x1a, 0x1c, 0x79, 0x72, 0xd3, 0x00, 0x25, + 0xc6, 0x8f, 0x3c, 0x83, 0x83, 0xce, 0x47, 0xa1, 0x6f, 0x4e, 0xbf, 0x67, 0x36, 0xdb, 0x4d, 0x61, + 0xa5, 0xa3, 0x5f, 0x57, 0x53, 0xbf, 0xa7, 0xf9, 0x70, 0xf5, 0xff, 0xcf, 0xc0, 0x88, 0x10, 0xaa, + 0x60, 0x7e, 0x20, 0xa9, 0x86, 0xd2, 0xc9, 0x1e, 0x58, 0x3a, 0xb9, 0xfd, 0x4b, 0x47, 0xfd, 0xe9, + 0x1c, 0x28, 0xd3, 0x66, 0x83, 0x2e, 0x39, 0xba, 0xe5, 0xae, 0x50, 0x47, 0x6c, 0xa7, 0xa7, 0x18, + 0xab, 0x03, 0x7d, 0xa0, 0x34, 0xa5, 0x64, 0xf7, 0x35, 0xa5, 0x7c, 0x08, 0x06, 0x44, 0x63, 0x02, + 0x9f, 0x42, 0x1c, 0x35, 0x8e, 0x0f, 0xd4, 0x42, 0x3c, 0x23, 0x2e, 0xb5, 0x5a, 0x8e, 0x7d, 0x97, + 0x3a, 0xfc, 0x96, 0x4a, 0x10, 0xeb, 0x3e, 0x50, 0x0b, 0xf1, 0x12, 0x67, 0xea, 0xdb, 0x8b, 0x32, + 0x67, 0xea, 0x68, 0x21, 0x9e, 0x5c, 0x86, 0xfe, 0x59, 0xbb, 0xae, 0xa3, 0xa0, 0xf9, 0xb4, 0x32, + 0xb4, 0xbd, 0x55, 0xec, 0x6f, 0x08, 0x98, 0x16, 0x60, 0x19, 0x65, 0xd9, 0xde, 0xb0, 0x1a, 0xb6, + 0xce, 0x9d, 0x5f, 0xfa, 0x39, 0xa5, 0x21, 0x60, 0x5a, 0x80, 0x65, 0x94, 0x4c, 0xe6, 0xe8, 0x54, + 0xd4, 0x1f, 0xf2, 0x5c, 0x11, 0x30, 0x2d, 0xc0, 0xaa, 0xbf, 0x9a, 0x67, 0xda, 0xeb, 0x9a, 0x6f, + 0xdf, 0xf7, 0xeb, 0x42, 0x38, 0x60, 0x7a, 0xf7, 0x31, 0x60, 0xee, 0x9b, 0x03, 0x3b, 0xf5, 0xaf, + 0xfa, 0x00, 0x84, 0xf4, 0xa7, 0x4e, 0x36, 0x87, 0x07, 0xd3, 0x9a, 0x32, 0x8c, 0x4d, 0x59, 0x6b, + 0xba, 0x55, 0xa7, 0x46, 0x78, 0x6c, 0x59, 0xc0, 0xa1, 0x8d, 0x3e, 0xbd, 0x54, 0x20, 0xc3, 0x73, + 0x4b, 0x2d, 0x59, 0x80, 0x3c, 0x0d, 0x83, 0x15, 0xcb, 0xa3, 0x8e, 0x5e, 0xf7, 0xcc, 0xbb, 0x54, + 0x4c, 0x0d, 0x78, 0x33, 0x6c, 0x86, 0x60, 0x4d, 0xa6, 0x21, 0xd7, 0x61, 0x68, 0x51, 0x77, 0x3c, + 0xb3, 0x6e, 0xb6, 0x74, 0xcb, 0x73, 0x95, 0x7e, 0x9c, 0xd1, 0xd0, 0xc2, 0x68, 0x49, 0x70, 0x2d, + 0x42, 0x45, 0x3e, 0x0d, 0x03, 0xb8, 0x35, 0x45, 0xc7, 0xe9, 0x81, 0x1d, 0x2f, 0x0e, 0x1f, 0x0b, + 0xdd, 0x03, 0xf9, 0xe9, 0x2b, 0xde, 0x00, 0xc7, 0xef, 0x0e, 0x03, 0x8e, 0xe4, 0xe3, 0xd0, 0x37, + 0x65, 0x19, 0xc8, 0x1c, 0x76, 0x64, 0xae, 0x0a, 0xe6, 0x67, 0x43, 0xe6, 0x76, 0x2b, 0xc6, 0xdb, + 0x67, 0x97, 0x3e, 0xca, 0x06, 0xdf, 0xbd, 0x51, 0x36, 0xf4, 0x2e, 0x1c, 0x8b, 0x0f, 0x1f, 0xd6, + 0xb1, 0xf8, 0xc8, 0x3e, 0x8f, 0xc5, 0xd5, 0xb7, 0x61, 0x70, 0x62, 0x71, 0x3a, 0x18, 0xbd, 0x0f, + 0x42, 0x6e, 0x51, 0x78, 0x2a, 0xe4, 0xb9, 0x3d, 0xd3, 0x32, 0x0d, 0x8d, 0xc1, 0xc8, 0x15, 0xe8, + 0x9f, 0x44, 0xf7, 0x37, 0x71, 0x8b, 0x98, 0xe7, 0xeb, 0x5f, 0x1d, 0x61, 0xe8, 0x05, 0xeb, 0xa3, + 0xc9, 0xe3, 0xd0, 0xb7, 0xe8, 0xd8, 0xab, 0x8e, 0xde, 0x14, 0x6b, 0x30, 0xba, 0x8a, 0xb4, 0x38, + 0x48, 0xf3, 0x71, 0xea, 0x0f, 0x67, 0x7c, 0xb3, 0x9d, 0x95, 0xa8, 0xb6, 0xf1, 0x68, 0x1e, 0xeb, + 0xee, 0xe7, 0x25, 0x5c, 0x0e, 0xd2, 0x7c, 0x1c, 0xb9, 0x02, 0xbd, 0x53, 0x8e, 0x63, 0x3b, 0xb2, + 0xb3, 0x39, 0x65, 0x00, 0xf9, 0xba, 0x17, 0x29, 0xc8, 0xf3, 0x30, 0xc8, 0xe7, 0x1c, 0x7e, 0xa2, + 0x99, 0xeb, 0x76, 0x53, 0x2a, 0x53, 0xaa, 0xdf, 0xc8, 0x49, 0x36, 0x1b, 0x97, 0xf8, 0x7d, 0x78, + 0x2b, 0xf0, 0x0c, 0xe4, 0x26, 0x16, 0xa7, 0xc5, 0x04, 0x78, 0xda, 0x2f, 0x2a, 0xa9, 0x4a, 0xac, + 0x1c, 0xa3, 0x26, 0x17, 0x20, 0xbf, 0xc8, 0xd4, 0xa7, 0x80, 0xea, 0xd1, 0xbf, 0xbd, 0x55, 0xcc, + 0xb7, 0x98, 0xfe, 0x20, 0x14, 0xb1, 0x6c, 0x33, 0xc3, 0x77, 0x4c, 0x1c, 0x1b, 0xee, 0x63, 0x2e, + 0x40, 0xbe, 0xe4, 0xac, 0xde, 0x15, 0xb3, 0x16, 0x62, 0x75, 0x67, 0xf5, 0xae, 0x86, 0x50, 0x72, + 0x15, 0x40, 0xa3, 0x5e, 0xdb, 0xb1, 0xf0, 0x1d, 0xc8, 0x00, 0x9e, 0xbf, 0xe1, 0x6c, 0xe8, 0x20, + 0xb4, 0x56, 0xb7, 0x0d, 0xaa, 0x49, 0x24, 0xea, 0xcf, 0x87, 0x17, 0x3b, 0x65, 0xd3, 0x5d, 0x3f, + 0xe9, 0xc2, 0x3d, 0x74, 0xa1, 0x2e, 0x8e, 0x38, 0x93, 0x9d, 0x54, 0x84, 0xde, 0xe9, 0x86, 0xbe, + 0xea, 0x62, 0x1f, 0x0a, 0x5f, 0xb2, 0x15, 0x06, 0xd0, 0x38, 0x3c, 0xd6, 0x4f, 0xfd, 0x3b, 0xf7, + 0xd3, 0x8f, 0xf5, 0x06, 0xa3, 0x6d, 0x9e, 0x7a, 0x1b, 0xb6, 0x73, 0xd2, 0x55, 0xbb, 0xed, 0xaa, + 0x4b, 0xd0, 0x57, 0x75, 0xea, 0xd2, 0xd1, 0x05, 0xee, 0x07, 0x5c, 0xa7, 0xce, 0x8f, 0x2d, 0x7c, + 0x24, 0xa3, 0x2b, 0xbb, 0x1e, 0xd2, 0xf5, 0x85, 0x74, 0x86, 0xeb, 0x09, 0x3a, 0x81, 0x14, 0x74, + 0x8b, 0xb6, 0xe3, 0x89, 0x8e, 0x0b, 0xe8, 0x5a, 0xb6, 0xe3, 0x69, 0x3e, 0x92, 0x7c, 0x08, 0x60, + 0x69, 0x72, 0xd1, 0x77, 0xb6, 0x1f, 0x08, 0x7d, 0x01, 0x85, 0x97, 0xbd, 0x26, 0xa1, 0xc9, 0x12, + 0x0c, 0x2c, 0xb4, 0xa8, 0xc3, 0xb7, 0x42, 0xfc, 0x65, 0xc7, 0x07, 0x63, 0xa2, 0x15, 0xfd, 0x3e, + 0x2e, 0xfe, 0x0f, 0xc8, 0xf9, 0xfa, 0x62, 0xfb, 0x3f, 0xb5, 0x90, 0x11, 0x79, 0x1e, 0x0a, 0x25, + 0x6e, 0xe7, 0x0d, 0x22, 0xcb, 0x40, 0x64, 0xb8, 0x05, 0xe5, 0x28, 0xbe, 0x67, 0xd7, 0xf1, 0x6f, + 0x4d, 0x90, 0xab, 0x57, 0x60, 0x34, 0x5e, 0x0d, 0x19, 0x84, 0xbe, 0xc9, 0x85, 0xf9, 0xf9, 0xa9, + 0xc9, 0xa5, 0xd1, 0x1e, 0xd2, 0x0f, 0xf9, 0xea, 0xd4, 0x7c, 0x79, 0x34, 0xa3, 0xfe, 0xb2, 0x34, + 0x83, 0x30, 0xd5, 0x3a, 0xb9, 0x1a, 0x3e, 0xd0, 0x7d, 0xcb, 0x28, 0xde, 0x87, 0xe2, 0x89, 0x41, + 0xd3, 0xf4, 0x3c, 0x6a, 0x88, 0x55, 0x02, 0xef, 0x0b, 0xbd, 0x7b, 0x5a, 0x02, 0x4f, 0x9e, 0x84, + 0x61, 0x84, 0x89, 0x2b, 0x42, 0xbe, 0x3f, 0x16, 0x05, 0x9c, 0x7b, 0x5a, 0x14, 0xa9, 0x7e, 0x33, + 0xbc, 0x1d, 0x9e, 0xa5, 0xfa, 0x71, 0xbd, 0x51, 0x7c, 0x8f, 0xf4, 0x97, 0xfa, 0xb7, 0x79, 0xfe, + 0x04, 0x84, 0x3f, 0xdc, 0x3b, 0x0a, 0x51, 0x86, 0x47, 0xba, 0xb9, 0x3d, 0x1c, 0xe9, 0x3e, 0x09, + 0x85, 0x39, 0xea, 0xad, 0xd9, 0xbe, 0xe3, 0x17, 0x7a, 0xe8, 0x35, 0x11, 0x22, 0x7b, 0xe8, 0x71, + 0x1a, 0xb2, 0x0e, 0xc4, 0x7f, 0x95, 0x17, 0x38, 0x62, 0xfb, 0x47, 0xc8, 0xe7, 0x12, 0xfb, 0x94, + 0x2a, 0x3e, 0xc9, 0x45, 0x1f, 0xfb, 0x33, 0x81, 0xa3, 0xb7, 0xe4, 0x89, 0xf5, 0x37, 0x5b, 0xc5, + 0x02, 0xa7, 0xd1, 0x52, 0xd8, 0x92, 0xd7, 0x61, 0x60, 0x6e, 0xba, 0x24, 0x5e, 0xe8, 0x71, 0xaf, + 0x88, 0x07, 0x03, 0x29, 0xfa, 0x88, 0x40, 0x24, 0xf8, 0xde, 0xa6, 0xb9, 0xa2, 0x27, 0x1f, 0xe8, + 0x85, 0x5c, 0x98, 0xb6, 0xf0, 0x97, 0x3b, 0xe2, 0x74, 0x21, 0xd0, 0x96, 0xe8, 0x7b, 0x9e, 0xb8, + 0xac, 0x38, 0x36, 0xa6, 0x2d, 0xfd, 0x07, 0x18, 0xdd, 0x0b, 0x30, 0x56, 0x6a, 0xb5, 0x1a, 0x26, + 0x35, 0x50, 0x5f, 0xb4, 0x76, 0x83, 0xba, 0xc2, 0xe5, 0x07, 0x1f, 0x83, 0xe8, 0x1c, 0x59, 0xc3, + 0x77, 0xa1, 0x35, 0xa7, 0x1d, 0xf5, 0xcf, 0x4c, 0x96, 0x55, 0x7f, 0x34, 0x0b, 0x67, 0x27, 0x1d, + 0xaa, 0x7b, 0x74, 0x6e, 0xba, 0x54, 0x6a, 0xa3, 0x8f, 0x5c, 0xa3, 0x41, 0xad, 0xd5, 0xa3, 0x19, + 0xd6, 0x1f, 0x85, 0x91, 0xa0, 0x01, 0xd5, 0xba, 0xdd, 0xa2, 0xf2, 0xc3, 0xaa, 0xba, 0x8f, 0xa9, + 0xb9, 0x0c, 0xa5, 0xc5, 0x48, 0xc9, 0x4d, 0x38, 0x1d, 0x40, 0x4a, 0x8d, 0x86, 0xbd, 0xa1, 0xd1, + 0xb6, 0xcb, 0x1d, 0x63, 0xfb, 0xb9, 0x63, 0x6c, 0xc8, 0x41, 0x67, 0xf8, 0x9a, 0xc3, 0x08, 0xb4, + 0xb4, 0x52, 0xea, 0x57, 0x73, 0x70, 0xee, 0xb6, 0xde, 0x30, 0x8d, 0x50, 0x34, 0x1a, 0x75, 0x5b, + 0xb6, 0xe5, 0xd2, 0x63, 0x34, 0x4a, 0x23, 0x43, 0x21, 0x7f, 0x28, 0x43, 0x21, 0xd9, 0x45, 0xbd, + 0x07, 0xee, 0xa2, 0xc2, 0xbe, 0xba, 0xe8, 0x9f, 0x65, 0x60, 0xd4, 0x77, 0xfc, 0x97, 0x5f, 0x53, + 0x4b, 0x5e, 0xe9, 0x78, 0x84, 0x18, 0xf3, 0x83, 0x46, 0x3c, 0xa9, 0x42, 0xdf, 0xd4, 0xbd, 0x96, + 0xe9, 0x50, 0x77, 0x17, 0x4e, 0xdc, 0x0f, 0x8b, 0xe3, 0x92, 0x31, 0xca, 0x8b, 0x24, 0x4e, 0x4a, + 0x38, 0x18, 0x9f, 0xf3, 0xf1, 0xa7, 0x0f, 0x13, 0xfe, 0x13, 0x71, 0xfe, 0x9c, 0x4f, 0x3c, 0x91, + 0x88, 0xbc, 0xcf, 0x0c, 0x49, 0xc9, 0x63, 0x90, 0x5b, 0x5a, 0x9a, 0x15, 0x33, 0x29, 0x3e, 0xcd, + 0xf7, 0x3c, 0xf9, 0xbd, 0x22, 0xc3, 0xaa, 0x7f, 0x96, 0x05, 0x60, 0xaa, 0xc0, 0x87, 0xeb, 0x91, + 0x28, 0xe1, 0x04, 0xf4, 0xfb, 0x02, 0x17, 0x6a, 0x18, 0x78, 0xed, 0xc7, 0x3b, 0x22, 0x5e, 0x77, + 0xf0, 0x42, 0xa3, 0xe8, 0x3b, 0x92, 0xf3, 0x7b, 0x00, 0xdc, 0xd9, 0xa0, 0x23, 0xb9, 0xef, 0x3e, + 0xfe, 0x21, 0x18, 0x10, 0x33, 0x9e, 0x1d, 0x39, 0xff, 0xaf, 0xfb, 0x40, 0x2d, 0xc4, 0xc7, 0xa6, + 0xd6, 0xc2, 0x01, 0x16, 0x62, 0x5f, 0xbc, 0xbc, 0x57, 0x4e, 0xc4, 0x7b, 0xc8, 0xe2, 0xfd, 0x92, + 0x10, 0x2f, 0x7f, 0xc1, 0x73, 0x6c, 0xc5, 0x7b, 0x68, 0x67, 0xdf, 0xea, 0x1f, 0x67, 0x80, 0xb0, + 0x66, 0x2d, 0xea, 0xae, 0xbb, 0x61, 0x3b, 0x06, 0x77, 0x4e, 0x3f, 0x12, 0xc1, 0x1c, 0xde, 0x7d, + 0xe5, 0x37, 0xfa, 0xe1, 0x74, 0xc4, 0xf1, 0xf7, 0x98, 0x4f, 0x56, 0x57, 0xa2, 0xa3, 0xa9, 0xdb, + 0xab, 0x97, 0x0f, 0xc8, 0x17, 0xa2, 0xbd, 0x91, 0x07, 0x68, 0xd2, 0x4d, 0xe8, 0x53, 0x30, 0x24, + 0x7e, 0xb0, 0x15, 0xda, 0xbf, 0xe9, 0xc2, 0x51, 0xea, 0x32, 0x80, 0x16, 0x41, 0x93, 0x67, 0x61, + 0x80, 0x0d, 0x98, 0x55, 0x8c, 0xe2, 0xd1, 0x17, 0xbe, 0x28, 0x31, 0x7c, 0xa0, 0xbc, 0x9e, 0x04, + 0x94, 0xd2, 0x3b, 0xa2, 0xfe, 0x5d, 0xbc, 0x23, 0x7a, 0x13, 0x06, 0x4b, 0x96, 0x65, 0x7b, 0xb8, + 0x49, 0x77, 0xc5, 0xd5, 0x44, 0x47, 0xab, 0xfc, 0x31, 0x7c, 0x1c, 0x1f, 0xd2, 0xa7, 0x9a, 0xe5, + 0x32, 0x43, 0x72, 0xcd, 0x7f, 0x15, 0x43, 0x1d, 0xe1, 0x55, 0x8e, 0xd7, 0x33, 0x8e, 0x80, 0x25, + 0x1f, 0xc5, 0x60, 0xe7, 0x0d, 0x2f, 0x3a, 0x76, 0xcb, 0x76, 0xa9, 0xc1, 0x05, 0x35, 0x18, 0x86, + 0x1a, 0x68, 0x09, 0x04, 0xbe, 0x63, 0x8b, 0x44, 0xd4, 0x88, 0x14, 0x21, 0x2b, 0x70, 0xc6, 0xbf, + 0x28, 0x0e, 0x5e, 0x0c, 0x56, 0xca, 0xae, 0x32, 0x84, 0xaf, 0x92, 0x48, 0x5c, 0x19, 0x2a, 0xe5, + 0x89, 0x8b, 0xfe, 0xb5, 0x88, 0xff, 0xe4, 0xb0, 0x66, 0x1a, 0x72, 0x57, 0xa7, 0xf2, 0x23, 0xdf, + 0x05, 0x83, 0x73, 0xfa, 0xbd, 0x72, 0x5b, 0x9c, 0xbd, 0x0c, 0xef, 0xfe, 0xf6, 0xa5, 0xa9, 0xdf, + 0xab, 0x19, 0xa2, 0x5c, 0xcc, 0xa6, 0x90, 0x59, 0x92, 0x1a, 0x9c, 0x5d, 0x74, 0xec, 0xa6, 0xed, + 0x51, 0x23, 0xf6, 0xf8, 0xee, 0x54, 0xf8, 0x5a, 0xb7, 0x25, 0x28, 0x6a, 0x5d, 0x5e, 0xe1, 0x75, + 0x60, 0x43, 0x9a, 0x70, 0xaa, 0xe4, 0xba, 0xed, 0x26, 0x0d, 0x6f, 0xa8, 0x46, 0x77, 0xfc, 0x8c, + 0x0f, 0x0a, 0xaf, 0xe5, 0x87, 0x74, 0x2c, 0xca, 0x2f, 0xa8, 0x6a, 0x9e, 0x29, 0xd7, 0x88, 0xdf, + 0x12, 0xe7, 0xfd, 0x5a, 0xbe, 0x7f, 0x64, 0xf4, 0x94, 0x76, 0x2e, 0xd9, 0x98, 0x25, 0xd3, 0x6b, + 0x50, 0xf5, 0xeb, 0x19, 0x80, 0x50, 0xc0, 0xe4, 0xa9, 0x68, 0xa8, 0xa0, 0x4c, 0x78, 0xd1, 0x21, + 0xa2, 0x17, 0x44, 0x62, 0x03, 0x91, 0x0b, 0x90, 0xc7, 0x08, 0x17, 0xd9, 0xf0, 0x60, 0x75, 0xdd, + 0xb4, 0x0c, 0x0d, 0xa1, 0x0c, 0x2b, 0x3d, 0x45, 0x47, 0x2c, 0x5e, 0xea, 0x73, 0xab, 0xb0, 0x0c, + 0xa7, 0xaa, 0xed, 0x65, 0xbf, 0x6e, 0xe9, 0x5d, 0x1d, 0x06, 0xda, 0x70, 0xdb, 0xcb, 0xc1, 0x63, + 0xd4, 0x48, 0x18, 0x93, 0x68, 0x11, 0xf5, 0x57, 0x33, 0xb1, 0x59, 0xf0, 0x08, 0x17, 0xbd, 0x0f, + 0x24, 0xfd, 0x34, 0x92, 0xd3, 0x92, 0xfa, 0xdf, 0x66, 0x61, 0x70, 0xd1, 0x76, 0x3c, 0x11, 0x32, + 0xe4, 0x78, 0xaf, 0x42, 0xd2, 0x5e, 0x29, 0xbf, 0x87, 0xbd, 0xd2, 0x05, 0xc8, 0x4b, 0x2e, 0xca, + 0xfc, 0x5e, 0xc4, 0x30, 0x1c, 0x0d, 0xa1, 0xea, 0x77, 0x67, 0x01, 0x3e, 0xfe, 0xf4, 0xd3, 0xf7, + 0xb1, 0x80, 0xd4, 0x9f, 0xca, 0xc0, 0x29, 0x71, 0x51, 0x27, 0x05, 0xdd, 0xea, 0xf3, 0xaf, 0x58, + 0xe5, 0x71, 0xc9, 0x41, 0x9a, 0x8f, 0x63, 0x4b, 0xc0, 0xd4, 0x3d, 0xd3, 0xc3, 0xbb, 0x0a, 0x29, + 0xea, 0x16, 0x15, 0x30, 0x79, 0x09, 0xf0, 0xe9, 0xc8, 0x53, 0xfe, 0x15, 0x64, 0x2e, 0x5c, 0xf7, + 0x58, 0x81, 0xa9, 0xd4, 0x6b, 0x48, 0xf5, 0x37, 0xf2, 0x90, 0x9f, 0xba, 0x47, 0xeb, 0xc7, 0xbc, + 0x6b, 0xa4, 0x83, 0xcd, 0xfc, 0x01, 0x0f, 0x36, 0xf7, 0xe3, 0x53, 0xf1, 0x4a, 0xd8, 0x9f, 0x85, + 0x68, 0xf5, 0xb1, 0x9e, 0x8f, 0x57, 0xef, 0xf7, 0xf4, 0xf1, 0x73, 0xc9, 0xf9, 0x3f, 0x73, 0x90, + 0xab, 0x4e, 0x2e, 0x9e, 0xe8, 0xcd, 0x91, 0xea, 0x4d, 0xf7, 0x3b, 0x6b, 0x35, 0xb8, 0x86, 0xea, + 0x0f, 0xbd, 0x44, 0x63, 0x37, 0x4e, 0xdf, 0xc9, 0xc1, 0x48, 0x75, 0x7a, 0x69, 0x51, 0x3a, 0x09, + 0xbe, 0xc9, 0x3d, 0xf9, 0xd0, 0xa7, 0x8c, 0x77, 0xe9, 0x85, 0x84, 0x3d, 0x73, 0xab, 0x62, 0x79, + 0xcf, 0x5d, 0xbf, 0xad, 0x37, 0xda, 0x14, 0x8f, 0x5e, 0xb8, 0xdf, 0xaf, 0x6b, 0xbe, 0x4d, 0xbf, + 0x8a, 0x0f, 0xff, 0x7d, 0x06, 0xe4, 0xa3, 0x90, 0xbb, 0x25, 0x3c, 0x32, 0x3a, 0xf1, 0x79, 0xe6, + 0x1a, 0xe7, 0xc3, 0x26, 0xc1, 0x5c, 0xdb, 0x34, 0x90, 0x03, 0x2b, 0xc5, 0x0a, 0xdf, 0x10, 0x0b, + 0xf0, 0xae, 0x0a, 0xaf, 0xfa, 0x85, 0x6f, 0x54, 0xca, 0xa4, 0x0a, 0x83, 0x8b, 0xd4, 0x69, 0x9a, + 0xd8, 0x51, 0xfe, 0x9c, 0xdd, 0x9d, 0x09, 0xdb, 0xa9, 0x0c, 0xb6, 0xc2, 0x42, 0xc8, 0x4c, 0xe6, + 0x42, 0xde, 0x00, 0xe0, 0x36, 0xca, 0x2e, 0x03, 0x39, 0x3e, 0x8c, 0x76, 0x3f, 0x37, 0x2d, 0x53, + 0x6c, 0x3c, 0x89, 0x19, 0x59, 0x87, 0xd1, 0x39, 0xdb, 0x30, 0x57, 0x4c, 0xee, 0x7a, 0x89, 0x15, + 0x14, 0x76, 0x76, 0x78, 0x62, 0xa6, 0x64, 0x53, 0x2a, 0x97, 0x56, 0x4d, 0x82, 0xb1, 0xfa, 0xbf, + 0xf5, 0x42, 0x9e, 0x75, 0xfb, 0xc9, 0xf8, 0x3d, 0xc8, 0xf8, 0x2d, 0xc1, 0xe8, 0x1d, 0xdb, 0x59, + 0x37, 0xad, 0xd5, 0xc0, 0x2b, 0x5e, 0xec, 0x4d, 0xd1, 0x93, 0x67, 0x83, 0xe3, 0x6a, 0x81, 0x03, + 0xbd, 0x96, 0x20, 0xdf, 0x61, 0x04, 0xbf, 0x00, 0xc0, 0xdf, 0xba, 0x23, 0x4d, 0x7f, 0x18, 0xac, + 0x82, 0xbf, 0x84, 0x47, 0x47, 0x7b, 0x39, 0x58, 0x45, 0x48, 0xcc, 0x36, 0xe1, 0xdc, 0x17, 0x62, + 0x00, 0xfd, 0xee, 0x71, 0x13, 0x8e, 0xbe, 0x10, 0xb2, 0x11, 0xc0, 0xbd, 0x22, 0x16, 0x01, 0xa4, + 0xfb, 0x25, 0x88, 0x09, 0x22, 0x32, 0x39, 0x88, 0xf0, 0x70, 0x29, 0xd7, 0x4b, 0x9a, 0xc4, 0x83, + 0x3c, 0x17, 0xbb, 0x00, 0x27, 0x11, 0x6e, 0x1d, 0xef, 0xbf, 0x43, 0x07, 0xaa, 0xa1, 0x9d, 0x1c, + 0xa8, 0xd4, 0x2f, 0x64, 0x61, 0xa0, 0xda, 0x5e, 0x76, 0x37, 0x5d, 0x8f, 0x36, 0x8f, 0xb9, 0x1a, + 0xfb, 0xdb, 0xab, 0x7c, 0xea, 0xf6, 0xea, 0x31, 0x5f, 0x28, 0xd2, 0xb9, 0x63, 0x60, 0xd2, 0xf9, + 0xe2, 0xf8, 0x9f, 0xb2, 0x30, 0xca, 0x2f, 0xce, 0xca, 0xa6, 0x5b, 0x3f, 0x04, 0x67, 0xfe, 0xa3, + 0x97, 0xca, 0xc1, 0x2e, 0x9b, 0x77, 0xf1, 0x44, 0x42, 0xfd, 0x6c, 0x16, 0x06, 0x4b, 0x6d, 0x6f, + 0xad, 0xe4, 0xa1, 0x6e, 0xdd, 0x97, 0xfb, 0x93, 0xdf, 0xcf, 0xc0, 0x29, 0xd6, 0x90, 0x25, 0x7b, + 0x9d, 0x5a, 0x87, 0x70, 0xf0, 0x28, 0x1f, 0x20, 0x66, 0xf7, 0x79, 0x80, 0xe8, 0xcb, 0x32, 0xb7, + 0x37, 0x59, 0xe2, 0x71, 0xb9, 0x66, 0x37, 0xe8, 0xf1, 0xfe, 0x8c, 0x43, 0x3c, 0x2e, 0xf7, 0x05, + 0x72, 0x08, 0xd7, 0x33, 0xef, 0x2f, 0x81, 0x1c, 0xc2, 0xd9, 0xd2, 0xfb, 0x43, 0x20, 0xdf, 0xc8, + 0xc0, 0xc0, 0x84, 0xed, 0x1d, 0xf3, 0x81, 0x2f, 0xbe, 0xe2, 0x78, 0xab, 0xb9, 0xff, 0x15, 0xc7, + 0x5b, 0x37, 0xd5, 0x1f, 0xcf, 0xc2, 0x19, 0x11, 0xa4, 0x5b, 0x9c, 0x3f, 0x9c, 0x4c, 0xc7, 0x62, + 0xb0, 0x25, 0x45, 0x73, 0x32, 0x0f, 0x09, 0xd1, 0xfc, 0x42, 0x0e, 0xce, 0x60, 0x28, 0x53, 0xb6, + 0x2d, 0x7b, 0x1f, 0xd8, 0x22, 0xa4, 0x1e, 0xbd, 0x04, 0x9d, 0x4b, 0xb9, 0x04, 0xfd, 0x9b, 0xad, + 0xe2, 0x73, 0xab, 0xa6, 0xb7, 0xd6, 0x5e, 0x1e, 0xaf, 0xdb, 0xcd, 0xab, 0xab, 0x8e, 0x7e, 0xd7, + 0xe4, 0xd7, 0x7f, 0x7a, 0xe3, 0x6a, 0x90, 0xef, 0x42, 0x6f, 0x99, 0x22, 0x13, 0x46, 0x15, 0xf7, + 0x3a, 0x8c, 0xab, 0x7f, 0x7d, 0xea, 0x02, 0xbc, 0x66, 0x9b, 0x96, 0xf0, 0x29, 0xe4, 0x86, 0x6e, + 0x95, 0xed, 0x0f, 0xdf, 0xb2, 0x4d, 0xab, 0x16, 0x77, 0x2c, 0xdc, 0x6b, 0x7d, 0x21, 0x6b, 0x4d, + 0xaa, 0x46, 0xfd, 0xff, 0x32, 0xf0, 0x60, 0x54, 0x8b, 0xdf, 0x0f, 0xb6, 0xe3, 0x4f, 0x64, 0xe1, + 0x81, 0x1b, 0x28, 0x9c, 0xc0, 0x91, 0xe3, 0x64, 0xde, 0x12, 0x83, 0x33, 0x45, 0x36, 0x27, 0x16, + 0x65, 0x67, 0xd9, 0x9c, 0x4c, 0xea, 0x42, 0x36, 0x7f, 0x90, 0x81, 0xd3, 0x0b, 0x95, 0xf2, 0xe4, + 0xfb, 0x64, 0x44, 0x25, 0xbf, 0xe7, 0x98, 0x1b, 0x9c, 0x89, 0xef, 0x39, 0xe6, 0xa6, 0x27, 0xfb, + 0x9e, 0x6a, 0x69, 0x6e, 0xf6, 0xfd, 0xa4, 0x6f, 0x91, 0xef, 0x79, 0x1f, 0xe8, 0x5b, 0xe4, 0x7b, + 0x8e, 0xb9, 0xbe, 0xfd, 0x1f, 0x05, 0x18, 0xbc, 0xd9, 0x5e, 0xa6, 0xc2, 0x25, 0xe4, 0xbe, 0x3e, + 0x6f, 0xbd, 0x06, 0x83, 0x42, 0x0c, 0x78, 0x57, 0x21, 0x85, 0xac, 0x13, 0x21, 0x48, 0x78, 0x54, + 0x20, 0x99, 0x88, 0x5c, 0x80, 0xfc, 0x6d, 0xea, 0x2c, 0xcb, 0xaf, 0x39, 0xef, 0x52, 0x67, 0x59, + 0x43, 0x28, 0x99, 0x0d, 0x1d, 0xd5, 0x4b, 0x8b, 0x15, 0x4c, 0x5f, 0x22, 0xae, 0x49, 0x30, 0x1f, + 0x4b, 0xe0, 0x6d, 0xa6, 0xb7, 0x4c, 0x9e, 0xf8, 0x44, 0x7e, 0x49, 0x1e, 0x2f, 0x49, 0xe6, 0x61, + 0x4c, 0x76, 0x37, 0xe2, 0xb9, 0x3b, 0xfa, 0x53, 0xd8, 0xa5, 0x65, 0xed, 0x48, 0x16, 0x25, 0xaf, + 0xc0, 0x90, 0x0f, 0x44, 0xc7, 0xa9, 0x81, 0x30, 0x60, 0x7c, 0xc0, 0x2a, 0x96, 0x18, 0x28, 0x52, + 0x40, 0x66, 0x80, 0x87, 0xff, 0x90, 0xc2, 0x20, 0xe6, 0x88, 0x16, 0x29, 0x40, 0x9e, 0x45, 0x06, + 0xf8, 0xb8, 0x02, 0x5d, 0x44, 0x06, 0xf1, 0xa9, 0x23, 0x3a, 0xc2, 0x3b, 0x02, 0xce, 0x1f, 0xb4, + 0x46, 0xc8, 0xc8, 0x02, 0x40, 0x78, 0x95, 0x2f, 0xc2, 0x06, 0xec, 0xd9, 0xc9, 0x40, 0x62, 0x21, + 0x5f, 0xc2, 0x0d, 0xef, 0xe7, 0x12, 0x4e, 0xfd, 0xa3, 0x2c, 0x0c, 0x96, 0x5a, 0xad, 0x60, 0x28, + 0x3c, 0x05, 0x85, 0x52, 0xab, 0x75, 0x4b, 0xab, 0xc8, 0x01, 0xc4, 0xf5, 0x56, 0xab, 0xd6, 0x76, + 0x4c, 0xd9, 0x13, 0x93, 0x13, 0x91, 0x49, 0x18, 0x2e, 0xb5, 0x5a, 0x8b, 0xed, 0xe5, 0x86, 0x59, + 0x97, 0xf2, 0x11, 0xf1, 0xd4, 0x69, 0xad, 0x56, 0xad, 0x85, 0x98, 0x78, 0x52, 0xaa, 0x68, 0x19, + 0xf2, 0x26, 0x06, 0xdb, 0x11, 0xe9, 0x70, 0x78, 0xc2, 0x0d, 0x35, 0x08, 0x1d, 0x1e, 0xb6, 0x6d, + 0x3c, 0x20, 0xe2, 0x21, 0xd6, 0x2f, 0xf8, 0x81, 0xea, 0x59, 0x45, 0x89, 0xb4, 0x37, 0x21, 0x4b, + 0xf2, 0x61, 0xe8, 0x2b, 0xb5, 0x5a, 0xd2, 0x2d, 0x0f, 0xba, 0xf2, 0xb0, 0x52, 0xb1, 0x3e, 0xf6, + 0xc9, 0xce, 0xbf, 0x04, 0x23, 0xd1, 0xca, 0xf6, 0x14, 0xa2, 0xfd, 0xaf, 0x33, 0xf8, 0x41, 0xc7, + 0xdc, 0x93, 0xf8, 0x19, 0xc8, 0x95, 0x5a, 0x2d, 0x31, 0x1f, 0x9d, 0x4e, 0xe9, 0x8f, 0xf8, 0xc3, + 0xe3, 0x52, 0xab, 0xe5, 0x7f, 0xfa, 0x31, 0x7f, 0x92, 0xb0, 0xaf, 0x4f, 0xff, 0x06, 0xff, 0xf4, + 0xe3, 0xfd, 0x5c, 0x40, 0xfd, 0x8d, 0x1c, 0x9c, 0x2a, 0xb5, 0x5a, 0x27, 0xa1, 0xdd, 0x0f, 0xeb, + 0x79, 0xf3, 0xd3, 0x00, 0xd2, 0xf4, 0xd8, 0x17, 0x3c, 0x98, 0x1a, 0x94, 0xa6, 0x46, 0x25, 0xa3, + 0x49, 0x44, 0xbe, 0xfa, 0xf5, 0xef, 0x49, 0xfd, 0x3e, 0x9b, 0xc3, 0xa9, 0xf8, 0xb8, 0x87, 0x6a, + 0x7a, 0xaf, 0x74, 0x9b, 0xe8, 0x83, 0xc2, 0x9e, 0xfa, 0xe0, 0xf7, 0x22, 0x83, 0x07, 0x43, 0x85, + 0x9f, 0xf4, 0x42, 0xef, 0x81, 0xcc, 0xe2, 0x11, 0x59, 0x98, 0x22, 0x7e, 0x8c, 0x9f, 0xbe, 0x48, + 0x44, 0x33, 0xaa, 0x33, 0x54, 0xcd, 0x34, 0xb4, 0x18, 0xad, 0xdf, 0x87, 0x7d, 0x7b, 0xea, 0xc3, + 0xad, 0x2c, 0xbe, 0x58, 0x0e, 0xa2, 0x21, 0x1d, 0x7c, 0x77, 0x71, 0x15, 0x80, 0xdf, 0xf7, 0x07, + 0xce, 0xc4, 0xc3, 0x3c, 0xf0, 0x09, 0xcf, 0x6a, 0x24, 0x02, 0x9f, 0x84, 0x24, 0x81, 0x5f, 0x52, + 0x2e, 0xd5, 0x2f, 0xe9, 0x0a, 0xf4, 0x6b, 0xfa, 0xc6, 0xeb, 0x6d, 0xea, 0x6c, 0x0a, 0x73, 0x86, + 0x07, 0x1b, 0xd4, 0x37, 0x6a, 0x9f, 0x61, 0x40, 0x2d, 0x40, 0x13, 0x35, 0x78, 0xf2, 0x2e, 0xf9, + 0x61, 0xf0, 0x93, 0xe9, 0xe0, 0xa1, 0xfb, 0x7e, 0x14, 0x9d, 0xbc, 0x08, 0xb9, 0xd2, 0x9d, 0xaa, + 0x90, 0x6c, 0xd0, 0xb5, 0xa5, 0x3b, 0x55, 0x21, 0xaf, 0x8e, 0x65, 0xef, 0x54, 0xd5, 0xcf, 0x66, + 0x81, 0x24, 0x29, 0xc9, 0x73, 0x30, 0x80, 0xd0, 0x55, 0xa6, 0x33, 0x72, 0x3a, 0xcc, 0x0d, 0xb7, + 0xe6, 0x20, 0x34, 0x62, 0xdc, 0xf9, 0xa4, 0xe4, 0x05, 0xcc, 0xfc, 0x2b, 0x12, 0xb2, 0x45, 0xd2, + 0x61, 0x6e, 0xb8, 0x7e, 0xae, 0xdc, 0x58, 0xe2, 0x5f, 0x41, 0x8c, 0x76, 0xe1, 0x9d, 0xea, 0x8c, + 0xed, 0x7a, 0x42, 0xd4, 0xdc, 0x2e, 0xdc, 0x70, 0x31, 0x0f, 0x6b, 0xc4, 0x2e, 0xe4, 0x64, 0x98, + 0x4b, 0xea, 0x4e, 0x95, 0x3f, 0x0e, 0x31, 0x34, 0xbb, 0xe1, 0x1b, 0x94, 0x3c, 0x97, 0xd4, 0x86, + 0x5b, 0xe3, 0x0f, 0x4b, 0x0c, 0x4c, 0x39, 0x1c, 0xc9, 0x25, 0x15, 0x29, 0xa5, 0x7e, 0xb1, 0x1f, + 0x46, 0xcb, 0xba, 0xa7, 0x2f, 0xeb, 0x2e, 0x95, 0x76, 0xd3, 0xa7, 0x7c, 0x98, 0xff, 0x39, 0x92, + 0x1c, 0x8c, 0xe5, 0x94, 0xaf, 0x89, 0x17, 0x20, 0x1f, 0x0d, 0xf9, 0x06, 0x99, 0x3e, 0xe5, 0xd4, + 0x61, 0xcb, 0xb5, 0x96, 0x00, 0x6b, 0x09, 0x42, 0xf2, 0x24, 0x0c, 0xfa, 0x30, 0xb6, 0x01, 0xc8, + 0x85, 0x3a, 0x63, 0x2c, 0x33, 0xfb, 0x5f, 0x93, 0xd1, 0xe4, 0x05, 0x18, 0xf2, 0x7f, 0x4a, 0xa6, + 0x35, 0xcf, 0x83, 0xb6, 0x9c, 0xd8, 0x3d, 0xc9, 0xa4, 0x72, 0x51, 0x9c, 0xdf, 0x7a, 0x23, 0x45, + 0x63, 0xa9, 0xc6, 0x22, 0xa4, 0xe4, 0x33, 0x30, 0xe2, 0xff, 0x16, 0x1b, 0x06, 0x9e, 0x95, 0xed, + 0xc9, 0x20, 0xa3, 0x71, 0x4c, 0xac, 0xe3, 0x51, 0x72, 0xbe, 0x75, 0x78, 0xc8, 0xcf, 0x9e, 0x65, + 0x2c, 0x27, 0x77, 0x0e, 0xb1, 0x0a, 0x48, 0x05, 0xc6, 0x7c, 0x48, 0xa8, 0xa1, 0x7d, 0xe1, 0x8e, + 0xd1, 0x58, 0xae, 0xa5, 0x2a, 0x69, 0xb2, 0x14, 0x69, 0xc0, 0x85, 0x08, 0xd0, 0x70, 0xd7, 0xcc, + 0x15, 0x4f, 0x6c, 0xf7, 0x44, 0xe4, 0x5f, 0x91, 0x2e, 0x31, 0xe0, 0xca, 0x69, 0xfc, 0xbc, 0xa7, + 0xd1, 0x9c, 0x4c, 0x5d, 0xb9, 0x91, 0x2a, 0x9c, 0xf1, 0xf1, 0x37, 0x26, 0x17, 0x17, 0x1d, 0xfb, + 0x2d, 0x5a, 0xf7, 0x2a, 0x65, 0xb1, 0x5d, 0xc6, 0x88, 0x70, 0xc6, 0x72, 0x6d, 0xb5, 0xde, 0x62, + 0x4a, 0xc1, 0x70, 0x51, 0xe6, 0xa9, 0x85, 0xc9, 0x6d, 0x78, 0x40, 0x82, 0x57, 0x2c, 0xd7, 0xd3, + 0xad, 0x3a, 0xad, 0x94, 0xc5, 0x1e, 0x1a, 0xf7, 0xf3, 0x82, 0xab, 0x29, 0x90, 0x51, 0xb6, 0xe9, + 0xc5, 0xc9, 0x4b, 0x30, 0xec, 0x23, 0xf8, 0xdd, 0xdd, 0x20, 0xde, 0xdd, 0xe1, 0x90, 0x34, 0x96, + 0x6b, 0xf1, 0x37, 0x8c, 0x51, 0x62, 0x59, 0xa3, 0x30, 0xa1, 0xfc, 0x50, 0x44, 0xa3, 0xbc, 0xcd, + 0x56, 0xaa, 0x32, 0x62, 0x92, 0xf9, 0x57, 0x42, 0x8d, 0x5a, 0x70, 0xcc, 0x55, 0x93, 0xef, 0xa4, + 0xfd, 0x67, 0x8b, 0xcb, 0x35, 0x1b, 0x81, 0x69, 0xfa, 0xc1, 0xc9, 0xcf, 0x97, 0xe0, 0x74, 0x8a, + 0x8e, 0xed, 0x69, 0xc7, 0xf8, 0x85, 0x6c, 0xd8, 0x88, 0x63, 0xbe, 0x6d, 0x9c, 0x80, 0x7e, 0xff, + 0x4b, 0x84, 0xf1, 0xa0, 0x74, 0x1a, 0x9a, 0x71, 0x1e, 0x3e, 0x3e, 0x22, 0x8e, 0x63, 0xbe, 0x95, + 0x3c, 0x0c, 0x71, 0xbc, 0x93, 0x09, 0xc5, 0x71, 0xcc, 0xb7, 0x97, 0x7f, 0x90, 0x0b, 0xe7, 0xa4, + 0x93, 0x3d, 0xe6, 0x61, 0x99, 0xc9, 0xa1, 0xf7, 0x69, 0x61, 0x0f, 0xcf, 0x07, 0x65, 0xd5, 0xec, + 0xdb, 0xa7, 0x6a, 0xfe, 0x49, 0xb2, 0x3f, 0xb9, 0xe9, 0x79, 0x2c, 0xfb, 0xf3, 0x10, 0x06, 0x2b, + 0xb9, 0x16, 0xae, 0x63, 0xdc, 0x46, 0xef, 0x95, 0x02, 0xeb, 0x2d, 0x0b, 0x13, 0x3d, 0x4a, 0x42, + 0x3e, 0x09, 0xe7, 0x22, 0x80, 0x45, 0xdd, 0xd1, 0x9b, 0xd4, 0x0b, 0xf3, 0xfc, 0x61, 0xa8, 0x24, + 0xbf, 0x74, 0xad, 0x15, 0xa0, 0xe5, 0xdc, 0x81, 0x1d, 0x38, 0x48, 0xca, 0xd1, 0xb7, 0x07, 0xd7, + 0xe4, 0x3f, 0xcd, 0x83, 0x12, 0x18, 0x88, 0xc1, 0x23, 0x9c, 0x23, 0x9c, 0x8c, 0xdf, 0x13, 0x9d, + 0x6b, 0xc2, 0x58, 0x28, 0x8c, 0x6a, 0xbb, 0xd9, 0xd4, 0xb1, 0x83, 0x99, 0x01, 0x5a, 0x8c, 0x33, + 0x0b, 0x09, 0xb9, 0xcd, 0x79, 0x5e, 0xd8, 0x9c, 0x24, 0x7c, 0xe4, 0x54, 0x73, 0x39, 0x0b, 0x2d, + 0xc9, 0x95, 0x7c, 0x29, 0x03, 0x67, 0x4a, 0x2b, 0x2b, 0xb4, 0xee, 0x51, 0x63, 0x61, 0x99, 0x19, + 0x5f, 0x93, 0x76, 0xdb, 0xf2, 0x7c, 0x7b, 0xf7, 0xc5, 0xce, 0xd5, 0xf1, 0x4e, 0x1a, 0x4f, 0x2b, + 0xcc, 0x5b, 0x12, 0x04, 0x0d, 0xd0, 0x05, 0x49, 0xcd, 0x46, 0x9a, 0x5a, 0x1d, 0x89, 0xb4, 0xd4, + 0x7a, 0xcf, 0xdf, 0x80, 0x07, 0x3b, 0xb2, 0xdc, 0xc9, 0xd8, 0xe9, 0x95, 0x8d, 0x9d, 0xbf, 0x97, + 0x09, 0xd5, 0x3d, 0x26, 0x24, 0x32, 0x0e, 0x10, 0x82, 0xc4, 0xf6, 0x67, 0x64, 0x7b, 0xab, 0x08, + 0xa1, 0xd0, 0x34, 0x89, 0x82, 0x2c, 0x40, 0x41, 0x88, 0x85, 0x67, 0x6e, 0xfd, 0xd0, 0x0e, 0xbd, + 0x30, 0x2e, 0xcb, 0x01, 0xb7, 0x36, 0xe2, 0x9b, 0x05, 0x9b, 0xf3, 0x2f, 0xc0, 0xe0, 0x7e, 0xbf, + 0xeb, 0x4b, 0x39, 0x20, 0xf2, 0x5e, 0xe5, 0x08, 0x0d, 0xb9, 0xf7, 0xc4, 0x60, 0xd9, 0x5f, 0xe6, + 0x95, 0xcb, 0xd0, 0xcf, 0x3e, 0x01, 0x73, 0x19, 0x48, 0xb1, 0x4b, 0xdb, 0x02, 0xa6, 0x05, 0xd8, + 0x30, 0x70, 0x50, 0x5f, 0x7a, 0xe0, 0x20, 0xf5, 0x47, 0x72, 0x70, 0x56, 0xee, 0x90, 0x32, 0xc5, + 0x70, 0xe8, 0x27, 0x9d, 0xf2, 0x2e, 0x76, 0x8a, 0x0a, 0x05, 0x6e, 0xa2, 0x8a, 0xb8, 0xf4, 0xfc, + 0xf8, 0x00, 0x21, 0x9a, 0xc0, 0xa8, 0xff, 0x38, 0x0b, 0xc3, 0x8b, 0xb6, 0xeb, 0xad, 0x3a, 0xd4, + 0x5d, 0xd4, 0x1d, 0xf7, 0x3e, 0xee, 0x8e, 0x8f, 0xc0, 0x30, 0x86, 0x7e, 0x69, 0x52, 0x8b, 0x87, + 0x47, 0xe9, 0x95, 0x12, 0x49, 0xf8, 0x08, 0x91, 0x33, 0x28, 0x42, 0xc8, 0xb4, 0x9f, 0xdb, 0x17, + 0x52, 0x40, 0x1e, 0x6e, 0x5c, 0x70, 0xb8, 0xfa, 0xb3, 0x39, 0x18, 0xf2, 0xa5, 0x3c, 0x61, 0x1e, + 0xd7, 0xfb, 0x80, 0xa3, 0x15, 0xf2, 0x55, 0x80, 0x45, 0xdb, 0xf1, 0xf4, 0xc6, 0x7c, 0xa8, 0xf9, + 0x78, 0x90, 0xd6, 0x42, 0x28, 0x2f, 0x23, 0x91, 0xe0, 0xfa, 0x15, 0x1a, 0x6f, 0x7c, 0x62, 0xe2, + 0xeb, 0x57, 0x00, 0xd5, 0x24, 0x0a, 0xf5, 0x77, 0xb2, 0x70, 0xca, 0xef, 0xa4, 0xa9, 0x7b, 0xb4, + 0xde, 0xbe, 0x9f, 0xe7, 0xa6, 0xa8, 0xb4, 0x7b, 0x77, 0x94, 0xb6, 0xfa, 0xaf, 0xa4, 0x89, 0x64, + 0xb2, 0x61, 0x9f, 0x4c, 0x24, 0x7f, 0x17, 0x3a, 0xae, 0x7e, 0x6f, 0x0e, 0xce, 0xf8, 0x52, 0x9f, + 0x6e, 0x5b, 0xb8, 0x05, 0x9d, 0xd4, 0x1b, 0x8d, 0xfb, 0x79, 0xcf, 0x37, 0xe8, 0x0b, 0x62, 0x41, + 0xc4, 0x52, 0x13, 0xf9, 0xdb, 0x56, 0x04, 0xb8, 0x66, 0x9b, 0x86, 0x26, 0x13, 0x91, 0x57, 0x60, + 0xc8, 0xff, 0x59, 0x72, 0x56, 0xfd, 0x8d, 0x1e, 0x1e, 0x28, 0x07, 0x85, 0x74, 0x27, 0xf2, 0x64, + 0x3c, 0x52, 0x40, 0xfd, 0xa7, 0x05, 0x38, 0x7f, 0xc7, 0xb4, 0x0c, 0x7b, 0xc3, 0xf5, 0xd3, 0xff, + 0x1d, 0xfb, 0x03, 0x95, 0xa3, 0x4e, 0xfb, 0xf7, 0x3a, 0x3c, 0x10, 0x17, 0xa9, 0x13, 0x04, 0x65, + 0x16, 0xbd, 0xb3, 0xc1, 0x09, 0x6a, 0x7e, 0x22, 0x40, 0x71, 0x2b, 0xa3, 0xa5, 0x97, 0x8c, 0x67, + 0x12, 0xec, 0xdb, 0x4d, 0x26, 0xc1, 0x27, 0xa0, 0x50, 0xb6, 0x9b, 0xba, 0xe9, 0x07, 0x0f, 0xc1, + 0x51, 0x1c, 0xd4, 0x8b, 0x18, 0x4d, 0x50, 0x30, 0xfe, 0xa2, 0x62, 0xec, 0xb2, 0x81, 0x90, 0xbf, + 0x5f, 0x80, 0x59, 0x69, 0x9a, 0x4c, 0x44, 0x6c, 0x18, 0x16, 0xd5, 0x89, 0x3b, 0x14, 0xc0, 0xcd, + 0xd3, 0xb3, 0xbe, 0x8c, 0x3a, 0xab, 0xd5, 0x78, 0xa4, 0x1c, 0xdf, 0x46, 0xf1, 0x04, 0x87, 0xe2, + 0x63, 0xf8, 0x6d, 0x8a, 0x16, 0xe5, 0x2f, 0x09, 0x01, 0x27, 0x99, 0xc1, 0xa4, 0x10, 0x70, 0x96, + 0x91, 0x89, 0xc8, 0x14, 0x8c, 0x61, 0xe8, 0xdc, 0x60, 0x2b, 0xc5, 0x54, 0x62, 0x08, 0x8d, 0x4a, + 0x3c, 0x9a, 0xe7, 0xd1, 0x76, 0xd9, 0xc7, 0xd5, 0xea, 0x02, 0xad, 0x25, 0x4b, 0x9c, 0x7f, 0x15, + 0x48, 0xb2, 0xcd, 0x7b, 0x3a, 0x9c, 0xff, 0x62, 0x36, 0xdc, 0xd7, 0x1d, 0x77, 0xf7, 0x8a, 0xc3, + 0x38, 0x8e, 0xfe, 0x95, 0x0c, 0x8c, 0x25, 0x42, 0x31, 0x93, 0x67, 0x00, 0x38, 0x44, 0x0a, 0x79, + 0x87, 0x31, 0x24, 0xc2, 0xf0, 0xcc, 0x62, 0x29, 0x09, 0xc9, 0xc8, 0x55, 0xe8, 0xe7, 0xbf, 0x44, + 0x98, 0x9a, 0x64, 0x91, 0x76, 0xdb, 0x34, 0xb4, 0x80, 0x28, 0xac, 0x05, 0x6f, 0x79, 0x72, 0xa9, + 0x45, 0xbc, 0xcd, 0x56, 0x50, 0x0b, 0x23, 0x63, 0x1d, 0x38, 0x14, 0x34, 0xb8, 0x64, 0x1c, 0x55, + 0xd7, 0x15, 0x44, 0x54, 0xeb, 0xdc, 0x4e, 0x51, 0xad, 0x63, 0x73, 0x93, 0x08, 0x63, 0x7d, 0x78, + 0x4f, 0x43, 0xbe, 0x9c, 0x85, 0x53, 0x41, 0xad, 0x47, 0x78, 0xa1, 0xf0, 0x1e, 0x12, 0xc9, 0x97, + 0x32, 0xa0, 0x4c, 0x98, 0x8d, 0x86, 0x69, 0xad, 0x56, 0xac, 0x15, 0xdb, 0x69, 0xe2, 0xe4, 0x71, + 0x74, 0xc7, 0x9d, 0xea, 0x0f, 0x64, 0x60, 0x4c, 0x34, 0x68, 0x52, 0x77, 0x8c, 0xa3, 0x3b, 0x4b, + 0x8a, 0xb7, 0xe4, 0xe8, 0xf4, 0x45, 0xfd, 0x5a, 0x16, 0x60, 0xd6, 0xae, 0xaf, 0x1f, 0xf3, 0xb7, + 0x81, 0x1f, 0x85, 0x02, 0x8f, 0x15, 0x24, 0x34, 0x76, 0x6c, 0x9c, 0x3f, 0xf9, 0x64, 0x9f, 0xc6, + 0x11, 0x13, 0xa3, 0xe2, 0x84, 0xb6, 0xc0, 0x63, 0x0d, 0x29, 0x19, 0x4d, 0x14, 0x61, 0x95, 0x32, + 0x3a, 0x61, 0xd5, 0x04, 0x95, 0x32, 0x58, 0xb4, 0xd2, 0xed, 0xad, 0x62, 0xbe, 0x61, 0xd7, 0xd7, + 0x35, 0xa4, 0x57, 0xff, 0x36, 0xc3, 0x65, 0x77, 0xcc, 0xdf, 0xc7, 0xf9, 0x9f, 0x9f, 0xdf, 0xe3, + 0xe7, 0xff, 0x60, 0x06, 0xce, 0x68, 0xb4, 0x6e, 0xdf, 0xa5, 0xce, 0xe6, 0xa4, 0x6d, 0xd0, 0x1b, + 0xd4, 0xa2, 0xce, 0x51, 0x8d, 0xa8, 0xff, 0x15, 0xd3, 0x00, 0x84, 0x8d, 0xb9, 0xe5, 0x52, 0xe3, + 0xf8, 0xa4, 0x68, 0x50, 0xff, 0x97, 0x3e, 0x50, 0x52, 0x2d, 0xc4, 0x63, 0x6b, 0x15, 0x75, 0x34, + 0xfb, 0xf3, 0x87, 0x65, 0xf6, 0xf7, 0xee, 0xcd, 0xec, 0x2f, 0xec, 0xd5, 0xec, 0xef, 0xdb, 0x8d, + 0xd9, 0xdf, 0x8c, 0x9b, 0xfd, 0xfd, 0x68, 0xf6, 0x3f, 0xd3, 0xd5, 0xec, 0x9f, 0xb2, 0x8c, 0x7d, + 0x1a, 0xfd, 0xc7, 0x36, 0x7d, 0xe8, 0x7e, 0x76, 0x2b, 0x97, 0xd9, 0xa4, 0x58, 0xb7, 0x1d, 0x83, + 0x1a, 0x62, 0x93, 0x82, 0x27, 0xe4, 0x8e, 0x80, 0x69, 0x01, 0x36, 0x91, 0x8b, 0x75, 0x78, 0x37, + 0xb9, 0x58, 0x0f, 0x61, 0x1b, 0xf3, 0x85, 0x2c, 0x8c, 0x4d, 0x52, 0xc7, 0xe3, 0xc1, 0x08, 0x0f, + 0xc3, 0xcd, 0xa8, 0x04, 0xa7, 0x24, 0x86, 0x68, 0x91, 0x67, 0x43, 0xd7, 0xa9, 0x3a, 0x75, 0xbc, + 0xb8, 0xe7, 0x55, 0x9c, 0x9e, 0x55, 0xef, 0xe7, 0x43, 0x12, 0x63, 0x37, 0xa8, 0xde, 0x87, 0x73, + 0x41, 0x9a, 0xe2, 0x97, 0x16, 0xd0, 0x4b, 0x29, 0x8e, 0xf2, 0x7b, 0x4f, 0x71, 0xa4, 0xfe, 0x72, + 0x06, 0x2e, 0x69, 0xd4, 0xa2, 0x1b, 0xfa, 0x72, 0x83, 0x4a, 0xcd, 0x12, 0x2b, 0x03, 0x9b, 0x35, + 0x4c, 0xb7, 0xa9, 0x7b, 0xf5, 0xb5, 0x03, 0xc9, 0x68, 0x1a, 0x86, 0xe4, 0xf9, 0x6b, 0x0f, 0x73, + 0x5b, 0xa4, 0x9c, 0xfa, 0xdb, 0x39, 0xe8, 0x9b, 0xb0, 0xbd, 0xd7, 0xec, 0x03, 0xe6, 0xdc, 0x0a, + 0xa7, 0xfc, 0xec, 0x1e, 0xce, 0x45, 0x3e, 0x8c, 0x95, 0x4b, 0x61, 0xc8, 0xd1, 0x2d, 0x6f, 0xd9, + 0x4e, 0x84, 0x6b, 0xf7, 0xc9, 0xf6, 0x98, 0x6d, 0xeb, 0x39, 0x18, 0xc0, 0x38, 0x16, 0xd2, 0xc9, + 0x25, 0x3a, 0xbd, 0x7a, 0x0c, 0x18, 0xaf, 0x23, 0x24, 0x25, 0x9f, 0x8c, 0x44, 0x4f, 0x2c, 0x1c, + 0x3c, 0x3b, 0x97, 0x1c, 0x48, 0xf1, 0xd0, 0x92, 0x60, 0xa9, 0xdf, 0xc9, 0xc3, 0x90, 0xef, 0xea, + 0x78, 0x44, 0x3d, 0xf8, 0x14, 0x14, 0x66, 0x6c, 0x29, 0xa4, 0x3a, 0xba, 0x46, 0xae, 0xd9, 0x6e, + 0xcc, 0xe7, 0x53, 0x10, 0x91, 0x67, 0xa0, 0x7f, 0xde, 0x36, 0x64, 0xc7, 0x5e, 0x1c, 0xd3, 0x96, + 0x6d, 0x24, 0x1e, 0x46, 0x06, 0x84, 0xe4, 0x12, 0xe4, 0xd1, 0x27, 0x5a, 0x3a, 0x7a, 0x8e, 0xf9, + 0x41, 0x23, 0x5e, 0xd2, 0x8d, 0xc2, 0x5e, 0x75, 0xa3, 0x6f, 0xbf, 0xba, 0xd1, 0x7f, 0xb8, 0xba, + 0xf1, 0x06, 0x0c, 0x61, 0x4d, 0x7e, 0x46, 0xa6, 0x9d, 0x97, 0xb7, 0x07, 0xc5, 0x0a, 0x34, 0xcc, + 0xdb, 0x2d, 0xf2, 0x32, 0xe1, 0xc2, 0x13, 0x61, 0x15, 0x53, 0x3b, 0x38, 0x80, 0xda, 0xfd, 0x49, + 0x06, 0xfa, 0x6e, 0x59, 0xeb, 0x96, 0xbd, 0x71, 0x30, 0x8d, 0x7b, 0x06, 0x06, 0x05, 0x1b, 0x69, + 0x8e, 0xc7, 0xb7, 0xae, 0x6d, 0x0e, 0xae, 0x21, 0x27, 0x4d, 0xa6, 0x22, 0x2f, 0x05, 0x85, 0xf0, + 0xd9, 0x43, 0x2e, 0x4c, 0x4a, 0xe0, 0x17, 0xaa, 0x47, 0xe3, 0xa8, 0xcb, 0xe4, 0xe4, 0x02, 0xe4, + 0xcb, 0xac, 0xa9, 0x52, 0x54, 0x4e, 0xd6, 0x14, 0x0d, 0xa1, 0xea, 0xff, 0x93, 0x85, 0x91, 0xd8, + 0xf1, 0xd3, 0x13, 0x30, 0x20, 0x8e, 0x7f, 0x4c, 0x3f, 0xb0, 0x3b, 0x3e, 0x8b, 0x08, 0x80, 0x5a, + 0x3f, 0xff, 0xb3, 0x62, 0x90, 0x8f, 0x41, 0x9f, 0xed, 0xe2, 0xd2, 0x84, 0xdf, 0x32, 0x12, 0x0e, + 0xa1, 0x85, 0x2a, 0x6b, 0x3b, 0x1f, 0x1c, 0x82, 0x44, 0xd6, 0x48, 0xdb, 0xc5, 0x4f, 0xbb, 0x0e, + 0x03, 0xba, 0xeb, 0x52, 0xaf, 0xe6, 0xe9, 0xab, 0x72, 0xac, 0xf7, 0x00, 0x28, 0x8f, 0x0e, 0x04, + 0x2e, 0xe9, 0xab, 0xe4, 0x55, 0x18, 0xae, 0x3b, 0x14, 0x17, 0x2f, 0xbd, 0xc1, 0x5a, 0x29, 0x19, + 0x97, 0x11, 0x84, 0x7c, 0xe2, 0x1f, 0x22, 0x2a, 0x06, 0xb9, 0x0d, 0xc3, 0xe2, 0x73, 0xb8, 0x4f, + 0x32, 0x0e, 0xb4, 0x91, 0x70, 0x31, 0xe1, 0x22, 0xe1, 0x5e, 0xc9, 0xc2, 0x35, 0x5d, 0x26, 0x97, + 0xf9, 0x1a, 0x12, 0xa9, 0xfa, 0xcd, 0x0c, 0x33, 0x78, 0x18, 0x00, 0x73, 0xa4, 0x32, 0x5d, 0x69, + 0xee, 0x51, 0x57, 0x9a, 0x61, 0x36, 0xb3, 0x82, 0xdb, 0x65, 0x76, 0xd2, 0x04, 0x96, 0x8c, 0x43, + 0xc1, 0x90, 0xcf, 0x7e, 0xce, 0x46, 0x3f, 0xc2, 0xaf, 0x47, 0x13, 0x54, 0xe4, 0x32, 0xe4, 0x99, + 0x41, 0x1b, 0xdf, 0xf8, 0xc9, 0x6b, 0xa4, 0x86, 0x14, 0xea, 0x77, 0x67, 0x61, 0x48, 0xfa, 0x9a, + 0x6b, 0x07, 0xfa, 0x9c, 0x17, 0x77, 0xd7, 0x4c, 0xdf, 0xcd, 0x01, 0x77, 0x04, 0x7e, 0x93, 0xaf, + 0x07, 0xa2, 0xd8, 0xd5, 0x15, 0x84, 0x10, 0xcc, 0x73, 0xe2, 0x43, 0x0b, 0xbb, 0xdf, 0x04, 0x31, + 0xfa, 0xd7, 0xf2, 0xfd, 0xd9, 0xd1, 0xdc, 0x6b, 0xf9, 0xfe, 0xfc, 0x68, 0x2f, 0xc6, 0xc5, 0xc1, + 0x50, 0xb4, 0x7c, 0x87, 0x69, 0xad, 0x98, 0xab, 0xc7, 0xdc, 0xab, 0xfc, 0x70, 0x63, 0x06, 0xc5, + 0x64, 0x73, 0xcc, 0x5d, 0xcc, 0xdf, 0x55, 0xd9, 0x9c, 0x64, 0x3f, 0x13, 0xb2, 0xf9, 0xd3, 0x0c, + 0x28, 0xa9, 0xb2, 0x29, 0x1d, 0xd1, 0xcd, 0xf7, 0xe1, 0xe5, 0x40, 0xfb, 0x76, 0x16, 0xc6, 0x2a, + 0x96, 0x47, 0x57, 0xf9, 0xbe, 0xe7, 0x98, 0x4f, 0x15, 0x37, 0x61, 0x50, 0xfa, 0x18, 0xd1, 0xe7, + 0x0f, 0x05, 0xbb, 0xca, 0x10, 0xd5, 0x81, 0x93, 0x5c, 0xfa, 0x10, 0xd3, 0x26, 0xc7, 0x84, 0x7c, + 0xcc, 0xe7, 0x9c, 0xe3, 0x21, 0xe4, 0x63, 0x3e, 0x79, 0xbd, 0x47, 0x85, 0xfc, 0x2f, 0x32, 0x70, + 0x3a, 0xa5, 0x72, 0x72, 0x09, 0xfa, 0xaa, 0xed, 0x65, 0x0c, 0xc8, 0x93, 0x09, 0x7d, 0x44, 0xdd, + 0xf6, 0x32, 0xc6, 0xe2, 0xd1, 0x7c, 0x24, 0x59, 0xc2, 0x67, 0xb7, 0x0b, 0x95, 0xf2, 0xa4, 0x90, + 0xaa, 0x2a, 0x3d, 0x20, 0x66, 0xe0, 0xb4, 0x2f, 0x0b, 0x9e, 0xe6, 0xda, 0xa6, 0x51, 0x8f, 0x3d, + 0xcd, 0x65, 0x65, 0xc8, 0xa7, 0x60, 0xa0, 0xf4, 0x76, 0xdb, 0xa1, 0xc8, 0x97, 0x4b, 0xfc, 0x03, + 0x01, 0x5f, 0x1f, 0x91, 0xc6, 0x99, 0xbf, 0x32, 0x66, 0x14, 0x71, 0xde, 0x21, 0x43, 0xf5, 0x8b, + 0x19, 0x38, 0xdf, 0xb9, 0x75, 0xe4, 0xc3, 0xd0, 0xc7, 0x76, 0xb6, 0x25, 0x6d, 0x5e, 0x7c, 0x3a, + 0xcf, 0x17, 0x68, 0x37, 0x68, 0x4d, 0x77, 0x64, 0xc3, 0xdb, 0x27, 0x23, 0x2f, 0xc3, 0x60, 0xc5, + 0x75, 0xdb, 0xd4, 0xa9, 0x3e, 0x73, 0x4b, 0xab, 0x88, 0x3d, 0x15, 0xda, 0xec, 0x26, 0x82, 0x6b, + 0xee, 0x33, 0xb1, 0x90, 0x3b, 0x32, 0xbd, 0xfa, 0xb9, 0x0c, 0x5c, 0xe8, 0xf6, 0x55, 0x6c, 0x03, + 0xbf, 0x44, 0x2d, 0xdd, 0x62, 0x3b, 0xfe, 0x4c, 0xb8, 0x45, 0xf1, 0x10, 0x16, 0xdd, 0x64, 0x04, + 0x84, 0xac, 0x10, 0x3f, 0x1d, 0x0b, 0xae, 0xe3, 0xf9, 0x49, 0x1e, 0xc2, 0x62, 0x85, 0x7c, 0x42, + 0xf5, 0xd7, 0x96, 0xa1, 0x77, 0xc1, 0xa2, 0x0b, 0x2b, 0xe4, 0x69, 0x29, 0x31, 0xbc, 0x18, 0x68, + 0x63, 0xf2, 0x80, 0x41, 0xc4, 0x4c, 0x8f, 0x26, 0xa5, 0x8f, 0xbf, 0x2e, 0x67, 0x08, 0x16, 0xea, + 0x40, 0xe4, 0x32, 0x1c, 0x33, 0xd3, 0xa3, 0xc9, 0x99, 0x84, 0xaf, 0xcb, 0x99, 0x59, 0x45, 0x67, + 0x47, 0x4a, 0x71, 0x8c, 0x5f, 0x4a, 0x4c, 0x03, 0xb3, 0x69, 0xe9, 0x4b, 0xe3, 0x36, 0x41, 0x92, + 0x62, 0xa6, 0x47, 0x4b, 0x4f, 0x7b, 0x3a, 0x24, 0x3b, 0xc6, 0xc4, 0x2f, 0xe4, 0x64, 0xdc, 0x4c, + 0x8f, 0x16, 0xa1, 0x25, 0xcf, 0xc3, 0xa0, 0xf8, 0xfd, 0x9a, 0x6d, 0x5a, 0xf1, 0xb7, 0xf7, 0x12, + 0x6a, 0xa6, 0x47, 0x93, 0x29, 0xa5, 0x4a, 0x17, 0x1d, 0x33, 0xc8, 0xed, 0x1e, 0xaf, 0x14, 0x71, + 0x52, 0xa5, 0xf8, 0x9b, 0xbc, 0x0c, 0xc3, 0x41, 0x50, 0x83, 0xb7, 0x68, 0xdd, 0x13, 0x47, 0x22, + 0x0f, 0xc4, 0x0a, 0x73, 0xe4, 0x4c, 0x8f, 0x16, 0xa5, 0x26, 0x97, 0xa1, 0xa0, 0x51, 0xd7, 0x7c, + 0xdb, 0x3f, 0xca, 0x1f, 0x91, 0xa6, 0x33, 0xf3, 0x6d, 0x26, 0x25, 0x81, 0x67, 0xbd, 0x13, 0xde, + 0x1d, 0x88, 0x03, 0x0c, 0x12, 0xab, 0x65, 0xca, 0x32, 0x58, 0xef, 0x48, 0x17, 0x47, 0xaf, 0x86, + 0xa1, 0x1e, 0x44, 0x5a, 0xa6, 0xc1, 0xf8, 0x9b, 0x3a, 0x19, 0x3b, 0xd3, 0xa3, 0xc5, 0xe8, 0x25, + 0xa9, 0x96, 0x4d, 0x77, 0x5d, 0x44, 0xd7, 0x8a, 0x4b, 0x95, 0xa1, 0x24, 0xa9, 0xb2, 0x9f, 0x52, + 0xd5, 0xf3, 0xd4, 0xdb, 0xb0, 0x9d, 0x75, 0x11, 0x4b, 0x2b, 0x5e, 0xb5, 0xc0, 0x4a, 0x55, 0x0b, + 0x88, 0x5c, 0x35, 0x5b, 0x64, 0x46, 0xd2, 0xab, 0xd6, 0x3d, 0x5d, 0xae, 0x9a, 0xef, 0x2f, 0xfd, + 0x4e, 0x9a, 0xa5, 0xfa, 0x5d, 0x9e, 0x1d, 0x33, 0xd9, 0xa1, 0x88, 0x93, 0x3a, 0x14, 0x7f, 0xb3, + 0x4a, 0xa5, 0x0c, 0x88, 0x22, 0xfd, 0x65, 0x50, 0xa9, 0x84, 0x62, 0x95, 0xca, 0xb9, 0x12, 0xaf, + 0xcb, 0x89, 0x01, 0x95, 0xb1, 0x68, 0x07, 0x85, 0x18, 0xd6, 0x41, 0x52, 0x02, 0xc1, 0x22, 0x26, + 0x1d, 0x53, 0x08, 0x92, 0x0f, 0x06, 0x2d, 0x9c, 0x5c, 0x9c, 0xe9, 0xd1, 0x30, 0x1d, 0x99, 0xca, + 0xd3, 0xd9, 0x29, 0xa7, 0x91, 0x62, 0xc8, 0xa7, 0x60, 0xb0, 0x99, 0x1e, 0x8d, 0xa7, 0xba, 0x7b, + 0x5a, 0x4a, 0x1c, 0xa3, 0x9c, 0x89, 0x4e, 0x11, 0x01, 0x82, 0x4d, 0x11, 0x61, 0x7a, 0x99, 0xe9, + 0x64, 0x72, 0x15, 0xe5, 0x81, 0xe8, 0x8a, 0x1a, 0xc7, 0xcf, 0xf4, 0x68, 0xc9, 0x84, 0x2c, 0xcf, + 0x47, 0xf2, 0x8d, 0x28, 0x67, 0x63, 0x01, 0x2f, 0x42, 0x14, 0x13, 0x97, 0x9c, 0x99, 0x64, 0x21, + 0x35, 0x43, 0xb0, 0x72, 0x2e, 0xba, 0x1c, 0xa7, 0x90, 0xcc, 0xf4, 0x68, 0xa9, 0xb9, 0x85, 0x27, + 0x13, 0x59, 0x3f, 0x14, 0x25, 0x7a, 0x6f, 0x19, 0x43, 0xcf, 0xf4, 0x68, 0x89, 0x3c, 0x21, 0xd7, + 0xe5, 0x74, 0x1b, 0xca, 0x83, 0xd1, 0x4e, 0x0c, 0x31, 0xac, 0x13, 0xa5, 0xb4, 0x1c, 0xd7, 0xe5, + 0x14, 0x0c, 0xca, 0xf9, 0x64, 0xa9, 0x70, 0xe6, 0x94, 0x52, 0x35, 0x68, 0xe9, 0x51, 0xe5, 0x95, + 0x87, 0x44, 0x5e, 0x2f, 0x51, 0x3e, 0x8d, 0x66, 0xa6, 0x47, 0x4b, 0x8f, 0x48, 0xaf, 0xa5, 0x87, + 0x63, 0x57, 0x2e, 0x74, 0xe3, 0x19, 0xb4, 0x2e, 0x3d, 0x94, 0xbb, 0xde, 0x25, 0x38, 0xb6, 0xf2, + 0x70, 0x34, 0xda, 0x5e, 0x47, 0xc2, 0x99, 0x1e, 0xad, 0x4b, 0x88, 0xed, 0x5b, 0x1d, 0x22, 0x55, + 0x2b, 0x17, 0xa3, 0x69, 0xfd, 0x52, 0x89, 0x66, 0x7a, 0xb4, 0x0e, 0x71, 0xae, 0x6f, 0x75, 0x08, + 0x64, 0xac, 0x14, 0xbb, 0xb2, 0x0d, 0xe4, 0xd1, 0x21, 0x0c, 0xf2, 0x42, 0x6a, 0x0c, 0x60, 0xe5, + 0x91, 0xa8, 0xea, 0xa6, 0x90, 0x30, 0xd5, 0x4d, 0x8b, 0x1e, 0xbc, 0x90, 0x1a, 0xb4, 0x56, 0x79, + 0xb4, 0x0b, 0xc3, 0xa0, 0x8d, 0xa9, 0xe1, 0x6e, 0x17, 0x52, 0xa3, 0xc6, 0x2a, 0x6a, 0x94, 0x61, + 0x0a, 0x09, 0x63, 0x98, 0x16, 0x6f, 0x76, 0x21, 0x35, 0xcc, 0xa9, 0xf2, 0x58, 0x17, 0x86, 0x61, + 0x0b, 0xd3, 0x02, 0xa4, 0x3e, 0x1f, 0x89, 0x33, 0xaa, 0x7c, 0x20, 0x3a, 0x6f, 0x48, 0x28, 0x36, + 0x6f, 0xc8, 0x11, 0x49, 0x27, 0x13, 0x91, 0xd4, 0x94, 0xc7, 0xa3, 0xc3, 0x3c, 0x86, 0x66, 0xc3, + 0x3c, 0x1e, 0x7b, 0x6d, 0x32, 0x11, 0x51, 0x4a, 0xb9, 0xd4, 0x89, 0x09, 0xa2, 0xa3, 0x4c, 0x78, + 0x0c, 0xaa, 0x4a, 0x4a, 0x48, 0x23, 0xe5, 0x83, 0x51, 0x9f, 0xbb, 0x04, 0xc1, 0x4c, 0x8f, 0x96, + 0x12, 0x08, 0x49, 0x4b, 0x7f, 0xbf, 0xaf, 0x5c, 0x8e, 0x0e, 0xdb, 0x34, 0x1a, 0x36, 0x6c, 0x53, + 0xdf, 0xfe, 0xcf, 0xa6, 0xf9, 0xd7, 0x2a, 0x57, 0xa2, 0x86, 0x59, 0x92, 0x82, 0x19, 0x66, 0x29, + 0x7e, 0xb9, 0x5a, 0xfa, 0x8b, 0x74, 0xe5, 0x89, 0xae, 0x2d, 0x44, 0x9a, 0x94, 0x16, 0xf2, 0x07, + 0xda, 0xa1, 0xed, 0x74, 0xab, 0xd5, 0xb0, 0x75, 0x43, 0xf9, 0x50, 0xaa, 0xed, 0xc4, 0x91, 0x92, + 0xed, 0xc4, 0x01, 0x6c, 0x95, 0x97, 0xfd, 0x4f, 0x95, 0x27, 0xa3, 0xab, 0xbc, 0x8c, 0x63, 0xab, + 0x7c, 0xc4, 0x57, 0x75, 0x32, 0xe1, 0xab, 0xa9, 0x3c, 0x15, 0x55, 0x80, 0x18, 0x9a, 0x29, 0x40, + 0xdc, 0xbb, 0xf3, 0xcd, 0xce, 0xde, 0x8d, 0xca, 0x38, 0x72, 0x7b, 0xc4, 0xe7, 0xd6, 0x89, 0x6e, + 0xa6, 0x47, 0xeb, 0xec, 0x21, 0x59, 0x49, 0x71, 0x56, 0x54, 0xae, 0x46, 0x15, 0x2c, 0x41, 0xc0, + 0x14, 0x2c, 0xe9, 0xe2, 0x58, 0x49, 0xf1, 0x36, 0x54, 0x3e, 0xdc, 0x91, 0x55, 0xf0, 0xcd, 0x29, + 0x3e, 0x8a, 0xd7, 0x65, 0x77, 0x41, 0xe5, 0xe9, 0xe8, 0x62, 0x17, 0x62, 0xd8, 0x62, 0x27, 0xb9, + 0x15, 0x5e, 0x97, 0x1d, 0xe5, 0x94, 0x6b, 0xc9, 0x52, 0xe1, 0x12, 0x29, 0x39, 0xd4, 0x69, 0xe9, + 0xfe, 0x65, 0xca, 0x33, 0x51, 0xad, 0x4b, 0xa3, 0x61, 0x5a, 0x97, 0xea, 0x9b, 0x36, 0x9d, 0x74, + 0x13, 0x53, 0xae, 0xc7, 0xcf, 0x12, 0xa2, 0x78, 0x66, 0xf9, 0x24, 0x5c, 0xcb, 0x5e, 0x8d, 0x07, + 0x97, 0x51, 0x9e, 0x8d, 0x5d, 0x66, 0x44, 0xb0, 0xcc, 0xbe, 0x8d, 0x05, 0xa3, 0x79, 0x35, 0x1e, + 0x8f, 0x45, 0x79, 0x2e, 0x9d, 0x43, 0xa0, 0x2b, 0xf1, 0xf8, 0x2d, 0xaf, 0xc6, 0x43, 0x98, 0x28, + 0xcf, 0xa7, 0x73, 0x08, 0xa4, 0x1b, 0x0f, 0x79, 0xf2, 0xb4, 0x14, 0x54, 0x55, 0xf9, 0x48, 0xd4, + 0x74, 0x0c, 0x10, 0xcc, 0x74, 0x0c, 0x43, 0xaf, 0x3e, 0x2d, 0x05, 0x23, 0x55, 0x5e, 0x48, 0x14, + 0x09, 0x1a, 0x2b, 0x85, 0x2c, 0x7d, 0x5a, 0x0a, 0xe2, 0xa9, 0xbc, 0x98, 0x28, 0x12, 0xb4, 0x4e, + 0x0a, 0xf5, 0x69, 0x74, 0x7b, 0x87, 0xa3, 0x7c, 0x34, 0x7a, 0xc4, 0xd1, 0x99, 0x72, 0xa6, 0x47, + 0xeb, 0xf6, 0x9e, 0xe7, 0xcd, 0xce, 0x4e, 0x77, 0xca, 0x4b, 0xd1, 0x21, 0xdc, 0x89, 0x8e, 0x0d, + 0xe1, 0x8e, 0x8e, 0x7b, 0x2f, 0xc7, 0xde, 0xe4, 0x2a, 0x2f, 0x47, 0xa7, 0xb8, 0x08, 0x92, 0x4d, + 0x71, 0xf1, 0x17, 0xbc, 0x91, 0xc7, 0xa6, 0xca, 0xc7, 0xa2, 0x53, 0x9c, 0x8c, 0x63, 0x53, 0x5c, + 0xe4, 0x61, 0xea, 0x64, 0xe2, 0x0d, 0xa4, 0xf2, 0x4a, 0x74, 0x8a, 0x8b, 0xa1, 0xd9, 0x14, 0x17, + 0x7f, 0x35, 0xf9, 0x72, 0xec, 0x29, 0xa0, 0xf2, 0x6a, 0x7a, 0xfb, 0x11, 0x29, 0xb7, 0x9f, 0x3f, + 0x1c, 0xd4, 0xd2, 0xdf, 0xb4, 0x29, 0xa5, 0xe8, 0xf8, 0x4d, 0xa3, 0x61, 0xe3, 0x37, 0xf5, 0x3d, + 0xdc, 0x42, 0x6a, 0x52, 0x7d, 0x65, 0xa2, 0xcb, 0xc6, 0x21, 0x34, 0x45, 0xd2, 0xd2, 0xf1, 0xcb, + 0x7b, 0x64, 0xbe, 0x11, 0x9a, 0xec, 0xb0, 0x47, 0xf6, 0xb7, 0x41, 0x31, 0x7a, 0x36, 0xbb, 0x26, + 0x7c, 0xc0, 0x94, 0x72, 0x74, 0x76, 0x4d, 0x10, 0xb0, 0xd9, 0x35, 0xe9, 0x39, 0x36, 0x0d, 0xa3, + 0x42, 0x8b, 0xb8, 0x6b, 0x9b, 0x69, 0xad, 0x2a, 0x53, 0xb1, 0x27, 0x25, 0x31, 0x3c, 0x9b, 0x9d, + 0xe2, 0x30, 0x5c, 0xaf, 0x39, 0x6c, 0xb2, 0x61, 0xb6, 0x96, 0x6d, 0xdd, 0x31, 0xaa, 0xd4, 0x32, + 0x94, 0xe9, 0xd8, 0x7a, 0x9d, 0x42, 0x83, 0xeb, 0x75, 0x0a, 0x1c, 0x03, 0xaa, 0xc4, 0xe0, 0x1a, + 0xad, 0x53, 0xf3, 0x2e, 0x55, 0x6e, 0x20, 0xdb, 0x62, 0x27, 0xb6, 0x82, 0x6c, 0xa6, 0x47, 0xeb, + 0xc4, 0x81, 0xd9, 0xea, 0x73, 0x9b, 0xd5, 0xd7, 0x67, 0x83, 0x67, 0x94, 0x8b, 0x0e, 0x6d, 0xe9, + 0x0e, 0x55, 0x66, 0xa2, 0xb6, 0x7a, 0x2a, 0x11, 0xb3, 0xd5, 0x53, 0x11, 0x49, 0xb6, 0xfe, 0x58, + 0xa8, 0x74, 0x63, 0x1b, 0x8e, 0x88, 0xf4, 0xd2, 0x6c, 0x76, 0x8a, 0x22, 0x98, 0x80, 0x66, 0x6d, + 0x6b, 0x15, 0x4f, 0x2a, 0x5e, 0x8b, 0xce, 0x4e, 0x9d, 0x29, 0xd9, 0xec, 0xd4, 0x19, 0xcb, 0x54, + 0x3d, 0x8a, 0xe5, 0x63, 0xf0, 0x66, 0x54, 0xd5, 0x53, 0x48, 0x98, 0xaa, 0xa7, 0x80, 0x93, 0x0c, + 0x35, 0xea, 0x52, 0x4f, 0x99, 0xed, 0xc6, 0x10, 0x49, 0x92, 0x0c, 0x11, 0x9c, 0x64, 0x38, 0x4d, + 0xbd, 0xfa, 0x9a, 0x32, 0xd7, 0x8d, 0x21, 0x92, 0x24, 0x19, 0x22, 0x98, 0x6d, 0x36, 0xa3, 0xe0, + 0x89, 0x76, 0x63, 0xdd, 0xef, 0xb3, 0xf9, 0xe8, 0x66, 0xb3, 0x23, 0x21, 0xdb, 0x6c, 0x76, 0x44, + 0x92, 0xcf, 0xed, 0xda, 0x47, 0x51, 0x59, 0xc0, 0x0a, 0xc7, 0x43, 0xbb, 0x60, 0x37, 0xa5, 0x66, + 0x7a, 0xb4, 0xdd, 0xfa, 0x40, 0x7e, 0x28, 0x70, 0x25, 0x52, 0x16, 0xb1, 0xaa, 0x53, 0xc1, 0x59, + 0x05, 0x07, 0xcf, 0xf4, 0x68, 0x81, 0xb3, 0xd1, 0xf3, 0x30, 0x88, 0x1f, 0x55, 0xb1, 0x4c, 0xaf, + 0x3c, 0xa1, 0xbc, 0x1e, 0xdd, 0x32, 0x49, 0x28, 0xb6, 0x65, 0x92, 0x7e, 0xb2, 0x49, 0x1c, 0x7f, + 0xf2, 0x29, 0xa6, 0x3c, 0xa1, 0x68, 0xd1, 0x49, 0x3c, 0x82, 0x64, 0x93, 0x78, 0x04, 0x10, 0xd4, + 0x5b, 0x76, 0xec, 0x56, 0x79, 0x42, 0xa9, 0xa6, 0xd4, 0xcb, 0x51, 0x41, 0xbd, 0xfc, 0x67, 0x50, + 0x6f, 0x75, 0xad, 0xed, 0x95, 0xd9, 0x37, 0x2e, 0xa5, 0xd4, 0xeb, 0x23, 0x83, 0x7a, 0x7d, 0x00, + 0x9b, 0x0a, 0x11, 0xb0, 0xe8, 0xd8, 0x6c, 0xd2, 0xbe, 0x69, 0x36, 0x1a, 0xca, 0xad, 0xe8, 0x54, + 0x18, 0xc7, 0xb3, 0xa9, 0x30, 0x0e, 0x63, 0xa6, 0x27, 0x6f, 0x15, 0x5d, 0x6e, 0xaf, 0x2a, 0xb7, + 0xa3, 0xa6, 0x67, 0x88, 0x61, 0xa6, 0x67, 0xf8, 0x0b, 0x77, 0x17, 0xec, 0x97, 0x46, 0x57, 0x1c, + 0xea, 0xae, 0x29, 0x77, 0x62, 0xbb, 0x0b, 0x09, 0x87, 0xbb, 0x0b, 0xe9, 0x37, 0x59, 0x85, 0x87, + 0x22, 0x0b, 0x8d, 0x7f, 0xf7, 0x54, 0xa5, 0xba, 0x53, 0x5f, 0x53, 0x3e, 0x8e, 0xac, 0x1e, 0x4b, + 0x5d, 0xaa, 0xa2, 0xa4, 0x33, 0x3d, 0x5a, 0x37, 0x4e, 0xb8, 0x2d, 0x7f, 0x7d, 0x96, 0x47, 0x3e, + 0xd3, 0x16, 0x27, 0xfd, 0x4d, 0xe8, 0x1b, 0xb1, 0x6d, 0x79, 0x92, 0x04, 0xb7, 0xe5, 0x49, 0x30, + 0x69, 0xc1, 0xc5, 0xd8, 0x56, 0x6d, 0x4e, 0x6f, 0xb0, 0x7d, 0x09, 0x35, 0x16, 0xf5, 0xfa, 0x3a, + 0xf5, 0x94, 0x4f, 0x20, 0xef, 0x4b, 0x1d, 0x36, 0x7c, 0x31, 0xea, 0x99, 0x1e, 0x6d, 0x07, 0x7e, + 0x44, 0xe5, 0x69, 0xdb, 0x95, 0x4f, 0x46, 0xcf, 0x37, 0x19, 0x6c, 0xa6, 0x47, 0xe3, 0x29, 0xdd, + 0xdf, 0x04, 0xe5, 0x56, 0x6b, 0xd5, 0xd1, 0x0d, 0xca, 0x0d, 0x2d, 0xb4, 0xdd, 0x84, 0x01, 0xfa, + 0xa9, 0xa8, 0x95, 0xd6, 0x89, 0x8e, 0x59, 0x69, 0x9d, 0x70, 0x4c, 0x51, 0x23, 0x41, 0xbe, 0x95, + 0x4f, 0x47, 0x15, 0x35, 0x82, 0x64, 0x8a, 0x1a, 0x0d, 0x09, 0xfe, 0x71, 0x38, 0x1b, 0xec, 0xe7, + 0xc5, 0xfa, 0xcb, 0x3b, 0x4d, 0x79, 0x13, 0xf9, 0x5c, 0x4c, 0x5c, 0x06, 0x44, 0xa8, 0x66, 0x7a, + 0xb4, 0x0e, 0xe5, 0xd9, 0x8a, 0x9b, 0xc8, 0x5f, 0x21, 0xcc, 0x8b, 0xef, 0x8a, 0xae, 0xb8, 0x1d, + 0xc8, 0xd8, 0x8a, 0xdb, 0x01, 0x95, 0xca, 0x5c, 0x08, 0x55, 0xdf, 0x81, 0x79, 0x20, 0xd3, 0x4e, + 0x1c, 0x52, 0x99, 0x0b, 0x4b, 0x6d, 0x79, 0x07, 0xe6, 0x81, 0xb5, 0xd6, 0x89, 0x03, 0xb9, 0x0c, + 0x85, 0x6a, 0x75, 0x4e, 0x6b, 0x5b, 0x4a, 0x3d, 0xe6, 0x03, 0x86, 0xd0, 0x99, 0x1e, 0x4d, 0xe0, + 0x99, 0x19, 0x34, 0xd5, 0xd0, 0x5d, 0xcf, 0xac, 0xbb, 0x38, 0x62, 0xfc, 0x11, 0x62, 0x44, 0xcd, + 0xa0, 0x34, 0x1a, 0x66, 0x06, 0xa5, 0xc1, 0x99, 0xbd, 0x38, 0xa9, 0xbb, 0xae, 0x6e, 0x19, 0x8e, + 0x3e, 0x81, 0xcb, 0x04, 0x8d, 0x79, 0xca, 0x47, 0xb0, 0xcc, 0x5e, 0x8c, 0x42, 0xf0, 0xf0, 0xdd, + 0x87, 0xf8, 0x66, 0xce, 0x4a, 0xec, 0xf0, 0x3d, 0x86, 0xc7, 0xc3, 0xf7, 0x18, 0x0c, 0xed, 0x4e, + 0x1f, 0xa6, 0xd1, 0x55, 0x93, 0x89, 0x48, 0x59, 0x8d, 0xd9, 0x9d, 0x71, 0x02, 0xb4, 0x3b, 0xe3, + 0xc0, 0x48, 0x93, 0xfc, 0xe5, 0x76, 0xad, 0x43, 0x93, 0xc2, 0x55, 0x36, 0x51, 0x86, 0xad, 0xdf, + 0xe1, 0xe0, 0x28, 0x6f, 0x5a, 0x7a, 0xd3, 0x2e, 0x4f, 0xf8, 0x52, 0x37, 0xa3, 0xeb, 0x77, 0x47, + 0x42, 0xb6, 0x7e, 0x77, 0x44, 0xb2, 0xd9, 0xd5, 0xdf, 0x68, 0xad, 0xe9, 0x0e, 0x35, 0xca, 0xa6, + 0x83, 0x27, 0x8b, 0x9b, 0x7c, 0x6b, 0xf8, 0x56, 0x74, 0x76, 0xed, 0x42, 0xca, 0x66, 0xd7, 0x2e, + 0x68, 0x66, 0xe4, 0xa5, 0xa3, 0x35, 0xaa, 0x1b, 0xca, 0x7a, 0xd4, 0xc8, 0xeb, 0x4c, 0xc9, 0x8c, + 0xbc, 0xce, 0xd8, 0xce, 0x9f, 0x73, 0xc7, 0x31, 0x3d, 0xaa, 0x34, 0x76, 0xf3, 0x39, 0x48, 0xda, + 0xf9, 0x73, 0x10, 0xcd, 0x36, 0x84, 0xf1, 0x0e, 0x69, 0x46, 0x37, 0x84, 0xc9, 0x6e, 0x88, 0x97, + 0x60, 0x16, 0x8b, 0x78, 0x30, 0xa1, 0x58, 0x51, 0x8b, 0x45, 0x80, 0x99, 0xc5, 0x12, 0x3e, 0xa9, + 0x88, 0x38, 0xe8, 0x2b, 0x76, 0x74, 0x0d, 0x95, 0x71, 0x6c, 0x0d, 0x8d, 0x38, 0xf3, 0x3f, 0x1f, + 0xf1, 0x9e, 0x55, 0x5a, 0x51, 0xab, 0x43, 0x42, 0x31, 0xab, 0x43, 0xf6, 0xb3, 0x9d, 0x84, 0x53, + 0x78, 0x0b, 0xae, 0xb5, 0x83, 0x7b, 0x9c, 0xcf, 0x44, 0x3f, 0x33, 0x86, 0x66, 0x9f, 0x19, 0x03, + 0x45, 0x98, 0x88, 0x69, 0xcb, 0xe9, 0xc0, 0x24, 0x3c, 0x1f, 0x8c, 0x81, 0xc8, 0x2c, 0x90, 0x6a, + 0x69, 0x6e, 0xb6, 0x62, 0x2c, 0xca, 0x57, 0x64, 0x6e, 0xf4, 0x04, 0x36, 0x49, 0x31, 0xd3, 0xa3, + 0xa5, 0x94, 0x23, 0x6f, 0xc1, 0x05, 0x01, 0x15, 0xaf, 0xe1, 0x30, 0xb9, 0xac, 0x11, 0x2c, 0x08, + 0x5e, 0xd4, 0x3b, 0xa3, 0x1b, 0xed, 0x4c, 0x8f, 0xd6, 0x95, 0x57, 0xe7, 0xba, 0xc4, 0xfa, 0xd0, + 0xde, 0x4d, 0x5d, 0xc1, 0x22, 0xd1, 0x95, 0x57, 0xe7, 0xba, 0x84, 0xdc, 0xef, 0xee, 0xa6, 0xae, + 0xa0, 0x13, 0xba, 0xf2, 0x22, 0x2e, 0x14, 0xbb, 0xe1, 0x4b, 0x8d, 0x86, 0xb2, 0x81, 0xd5, 0x7d, + 0x70, 0x37, 0xd5, 0x95, 0xd0, 0xe0, 0xdc, 0x89, 0x23, 0x9b, 0xa5, 0x17, 0x5a, 0xd4, 0xaa, 0x46, + 0x16, 0xa0, 0x7b, 0xd1, 0x59, 0x3a, 0x41, 0xc0, 0x66, 0xe9, 0x04, 0x90, 0x0d, 0x28, 0xd9, 0x09, + 0x5b, 0xd9, 0x8c, 0x0e, 0x28, 0x19, 0xc7, 0x06, 0x54, 0xc4, 0x61, 0x7b, 0x01, 0x4e, 0x2f, 0xac, + 0x7b, 0xba, 0x6f, 0x41, 0xba, 0xa2, 0x2b, 0xdf, 0x8e, 0x5d, 0x32, 0x25, 0x49, 0xf0, 0x92, 0x29, + 0x09, 0x66, 0x63, 0x84, 0x81, 0xab, 0x9b, 0x56, 0x7d, 0x5a, 0x37, 0x1b, 0x6d, 0x87, 0x2a, 0xff, + 0x51, 0x74, 0x8c, 0xc4, 0xd0, 0x6c, 0x8c, 0xc4, 0x40, 0x6c, 0x81, 0x66, 0xa0, 0x92, 0xeb, 0x9a, + 0xab, 0x96, 0xd8, 0x57, 0xb6, 0x1b, 0x9e, 0xf2, 0x1f, 0x47, 0x17, 0xe8, 0x34, 0x1a, 0xb6, 0x40, + 0xa7, 0xc1, 0xf1, 0xd4, 0x29, 0x25, 0xf1, 0xb2, 0xf2, 0x9f, 0xc4, 0x4e, 0x9d, 0x52, 0x68, 0xf0, + 0xd4, 0x29, 0x2d, 0x69, 0xf3, 0x34, 0x8c, 0x72, 0x9b, 0x6c, 0xd6, 0x0c, 0xee, 0xaa, 0xff, 0xd3, + 0xe8, 0xfa, 0x18, 0xc7, 0xb3, 0xf5, 0x31, 0x0e, 0x8b, 0xf2, 0x11, 0x5d, 0xf0, 0x9f, 0x75, 0xe2, + 0x13, 0xc8, 0x3f, 0x51, 0x86, 0xdc, 0x90, 0xf9, 0x88, 0x91, 0xf2, 0xdd, 0x99, 0x4e, 0x8c, 0x82, + 0xe1, 0x91, 0x28, 0x14, 0x65, 0xa4, 0xd1, 0xbb, 0x26, 0xdd, 0x50, 0x3e, 0xdb, 0x91, 0x11, 0x27, + 0x88, 0x32, 0xe2, 0x30, 0xf2, 0x06, 0x9c, 0x0d, 0x61, 0x73, 0xb4, 0xb9, 0x1c, 0xcc, 0x4c, 0xdf, + 0x93, 0x89, 0x9a, 0xc1, 0xe9, 0x64, 0xcc, 0x0c, 0x4e, 0xc7, 0xa4, 0xb1, 0x16, 0xa2, 0xfb, 0xcf, + 0x77, 0x60, 0x1d, 0x48, 0xb0, 0x03, 0x83, 0x34, 0xd6, 0x42, 0x9a, 0xdf, 0xbb, 0x03, 0xeb, 0x40, + 0xa6, 0x1d, 0x18, 0x90, 0xcf, 0x67, 0xe0, 0x52, 0x3a, 0xaa, 0xd4, 0x68, 0x4c, 0xdb, 0x4e, 0x88, + 0x53, 0xbe, 0x2f, 0x13, 0x3d, 0x68, 0xd8, 0x5d, 0xb1, 0x99, 0x1e, 0x6d, 0x97, 0x15, 0x90, 0x8f, + 0xc1, 0x70, 0xa9, 0x6d, 0x98, 0x1e, 0x5e, 0xbc, 0x31, 0xc3, 0xf9, 0xfb, 0x33, 0xb1, 0x2d, 0x8e, + 0x8c, 0xc5, 0x2d, 0x8e, 0x0c, 0x20, 0xaf, 0xc1, 0x58, 0x95, 0xd6, 0xdb, 0x8e, 0xe9, 0x6d, 0x6a, + 0x98, 0x54, 0x9b, 0xf1, 0xf8, 0x81, 0x4c, 0x74, 0x12, 0x4b, 0x50, 0xb0, 0x49, 0x2c, 0x01, 0x24, + 0xb7, 0x3b, 0xa4, 0x5e, 0x56, 0x3e, 0x97, 0xe9, 0x7a, 0x2d, 0x1f, 0xf4, 0x65, 0x87, 0xcc, 0xcd, + 0x8b, 0xa9, 0xa9, 0x6c, 0x95, 0xcf, 0x67, 0xba, 0x5c, 0xa3, 0x4b, 0x33, 0x5c, 0x4a, 0x16, 0xdc, + 0xc5, 0xd4, 0x64, 0xa5, 0xca, 0x0f, 0x66, 0xba, 0x5c, 0x7b, 0x87, 0x1c, 0xd3, 0xf2, 0x9c, 0x3e, + 0xcb, 0x3d, 0x45, 0x04, 0xa3, 0xff, 0x22, 0x93, 0x74, 0x15, 0x09, 0xca, 0x4b, 0x84, 0xac, 0xd8, + 0x2d, 0x37, 0x50, 0xfa, 0x2f, 0x64, 0x92, 0xbe, 0x79, 0x61, 0xb1, 0xf0, 0x17, 0xa1, 0x70, 0x7e, + 0xea, 0x9e, 0x47, 0x1d, 0x4b, 0x6f, 0x60, 0x77, 0x56, 0x3d, 0xdb, 0xd1, 0x57, 0xe9, 0x94, 0xa5, + 0x2f, 0x37, 0xa8, 0xf2, 0xc5, 0x4c, 0xd4, 0x82, 0xed, 0x4c, 0xca, 0x2c, 0xd8, 0xce, 0x58, 0xb2, + 0x06, 0x0f, 0xa5, 0x61, 0xcb, 0xa6, 0x8b, 0xf5, 0x7c, 0x29, 0x13, 0x35, 0x61, 0xbb, 0xd0, 0x32, + 0x13, 0xb6, 0x0b, 0x9a, 0x5c, 0x83, 0x81, 0x09, 0xdb, 0x9f, 0x7e, 0x7f, 0x28, 0xe6, 0x0c, 0x19, + 0x60, 0x66, 0x7a, 0xb4, 0x90, 0x4c, 0x94, 0x11, 0x83, 0xfa, 0xcb, 0xc9, 0x32, 0xe1, 0xe5, 0x53, + 0xf0, 0x43, 0x94, 0x11, 0xe2, 0xfe, 0x2f, 0x93, 0x65, 0xc2, 0x3b, 0xae, 0xe0, 0x07, 0x9b, 0x49, + 0x78, 0x8d, 0x73, 0xd3, 0x25, 0x66, 0xb7, 0x4d, 0xae, 0xe9, 0x8d, 0x06, 0xb5, 0x56, 0xa9, 0xf2, + 0x95, 0xd8, 0x4c, 0x92, 0x4e, 0xc6, 0x66, 0x92, 0x74, 0x0c, 0xf9, 0x14, 0x9c, 0xbb, 0xad, 0x37, + 0x4c, 0x23, 0xc4, 0xf9, 0xf9, 0x2f, 0x95, 0x1f, 0xce, 0x44, 0x77, 0xd3, 0x1d, 0xe8, 0xd8, 0x6e, + 0xba, 0x03, 0x8a, 0xcc, 0x01, 0xc1, 0x65, 0x34, 0x98, 0x2d, 0xd8, 0xfa, 0xac, 0xfc, 0x57, 0x99, + 0xa8, 0x9d, 0x9a, 0x24, 0x61, 0x76, 0x6a, 0x12, 0x4a, 0x6a, 0x9d, 0x43, 0x9c, 0x2b, 0x3f, 0x92, + 0x89, 0x9e, 0xd6, 0x74, 0x22, 0x9c, 0xe9, 0xd1, 0x3a, 0xc7, 0x49, 0xbf, 0x01, 0xa3, 0xd5, 0xc5, + 0xca, 0xf4, 0xf4, 0x54, 0xf5, 0x76, 0xa5, 0x8c, 0xee, 0xbb, 0x86, 0xf2, 0xa3, 0xb1, 0x15, 0x2b, + 0x4e, 0xc0, 0x56, 0xac, 0x38, 0x8c, 0x54, 0xe1, 0x0c, 0x13, 0xc4, 0xa2, 0x43, 0x57, 0xa8, 0x43, + 0xad, 0xba, 0x3f, 0x2c, 0x7f, 0x3c, 0x13, 0x35, 0x14, 0xd2, 0x88, 0x98, 0xa1, 0x90, 0x06, 0x27, + 0xeb, 0x70, 0x21, 0x7e, 0x98, 0x23, 0xbf, 0x87, 0x52, 0x7e, 0x22, 0x13, 0xb3, 0x67, 0xbb, 0x10, + 0xa3, 0x3d, 0xdb, 0x05, 0x4f, 0x2c, 0x78, 0x58, 0x9c, 0x8c, 0x08, 0x9f, 0xc9, 0x78, 0x6d, 0x3f, + 0xc9, 0x6b, 0x7b, 0x3c, 0xf4, 0xe9, 0xeb, 0x42, 0x3d, 0xd3, 0xa3, 0x75, 0x67, 0xc7, 0x54, 0x25, + 0x19, 0x8b, 0x5b, 0xf9, 0xa9, 0x4c, 0xba, 0x53, 0x49, 0xc4, 0xd3, 0x38, 0x2d, 0x88, 0xf7, 0x1b, + 0x9d, 0x22, 0x49, 0x2b, 0x3f, 0x1d, 0x1b, 0x32, 0xe9, 0x64, 0x6c, 0xc8, 0x74, 0x08, 0x45, 0xfd, + 0x1a, 0x8c, 0x71, 0xbd, 0x5c, 0xd4, 0x71, 0x24, 0x59, 0xab, 0xd4, 0x50, 0xfe, 0xeb, 0xd8, 0x82, + 0x95, 0xa0, 0x40, 0xef, 0x9c, 0x38, 0x90, 0xcd, 0xbe, 0xd5, 0x96, 0x6e, 0x59, 0x78, 0x52, 0xaa, + 0xfc, 0x37, 0xb1, 0xd9, 0x37, 0x44, 0xa1, 0xef, 0x6d, 0xf0, 0x0b, 0x73, 0xfa, 0xa4, 0x3d, 0x17, + 0x54, 0xbe, 0x1a, 0x5b, 0xe7, 0x52, 0xa9, 0xd8, 0x3a, 0x97, 0xfe, 0xda, 0xf0, 0x76, 0x87, 0xa7, + 0x76, 0xca, 0xcf, 0x74, 0xe7, 0x1b, 0xae, 0x9f, 0xe9, 0x2f, 0xf5, 0x6e, 0x77, 0x78, 0xa6, 0xa6, + 0xfc, 0x6c, 0x77, 0xbe, 0xa1, 0xbb, 0x5c, 0xfa, 0x2b, 0xb7, 0x5a, 0xe7, 0x27, 0x5e, 0xca, 0xcf, + 0xc5, 0x27, 0x84, 0x0e, 0x84, 0x38, 0x21, 0x74, 0x7a, 0x27, 0xb6, 0x0c, 0x0f, 0xf2, 0x4e, 0xbb, + 0xe1, 0xe8, 0xad, 0xb5, 0x2a, 0xf5, 0x3c, 0xd3, 0x5a, 0xf5, 0xf7, 0x37, 0xff, 0x5d, 0x26, 0x76, + 0xe8, 0xd4, 0x89, 0x12, 0x0f, 0x9d, 0x3a, 0x21, 0x99, 0x3e, 0x25, 0x1e, 0x73, 0x29, 0x3f, 0x1f, + 0xd3, 0xa7, 0x04, 0x05, 0xd3, 0xa7, 0xe4, 0x1b, 0xb0, 0xd7, 0x52, 0xde, 0x2c, 0x29, 0xff, 0x7d, + 0x67, 0x5e, 0x41, 0xfb, 0x52, 0x9e, 0x3a, 0xbd, 0x96, 0xf2, 0x34, 0x47, 0xf9, 0x1f, 0x3a, 0xf3, + 0x0a, 0x3d, 0x7b, 0x92, 0x2f, 0x7a, 0xde, 0x80, 0xb3, 0x7c, 0x8e, 0x9c, 0xa6, 0x06, 0x8d, 0x7c, + 0xe8, 0x2f, 0xc4, 0x86, 0x63, 0x3a, 0x19, 0x1e, 0x64, 0xa7, 0x62, 0xd2, 0x58, 0x8b, 0xb6, 0xfe, + 0xe2, 0x0e, 0xac, 0x43, 0x33, 0x3b, 0x1d, 0x33, 0xd1, 0x07, 0xbd, 0xb8, 0xc3, 0x55, 0xbf, 0x9a, + 0x81, 0xa1, 0xaa, 0xe7, 0x50, 0xbd, 0x29, 0xa2, 0x33, 0x9c, 0x87, 0x7e, 0xee, 0x2a, 0xe6, 0xbf, + 0xd6, 0xd0, 0x82, 0xdf, 0xe4, 0x12, 0x8c, 0xcc, 0xea, 0xae, 0x87, 0x25, 0x2b, 0x96, 0x41, 0xef, + 0xe1, 0x33, 0x89, 0x9c, 0x16, 0x83, 0x92, 0x59, 0x4e, 0xc7, 0xcb, 0x61, 0x58, 0x9c, 0xdc, 0x8e, + 0x41, 0x09, 0xfa, 0xdf, 0xd9, 0x2a, 0xf6, 0x60, 0x0c, 0x82, 0x58, 0x59, 0xf5, 0x9b, 0x19, 0x48, + 0x38, 0xb1, 0xed, 0xff, 0x15, 0xd5, 0x02, 0x9c, 0x8a, 0x85, 0x62, 0x12, 0x6f, 0x3d, 0x76, 0x19, + 0xa9, 0x29, 0x5e, 0x9a, 0x7c, 0x30, 0x78, 0x63, 0x70, 0x4b, 0x9b, 0x15, 0x01, 0x27, 0xfa, 0xb6, + 0xb7, 0x8a, 0xb9, 0xb6, 0xd3, 0xd0, 0x24, 0x94, 0x78, 0x10, 0xfd, 0x3f, 0x8f, 0x86, 0x71, 0x66, + 0xc8, 0x25, 0xf1, 0xa4, 0x2b, 0x13, 0x86, 0xa9, 0x88, 0xa5, 0x9c, 0xe3, 0x4f, 0xb8, 0x3e, 0x06, + 0x43, 0x95, 0x66, 0x8b, 0x3a, 0xae, 0x6d, 0xe9, 0x9e, 0xed, 0xa7, 0xb6, 0xc6, 0x10, 0x06, 0xa6, + 0x04, 0x97, 0x9f, 0xd5, 0xcb, 0xf4, 0xe4, 0x8a, 0x9f, 0x9f, 0x20, 0x87, 0x11, 0x7e, 0x30, 0x4c, + 0x65, 0x3c, 0x8d, 0x19, 0xa7, 0x60, 0xa4, 0xb7, 0x5c, 0x1d, 0x5f, 0xa3, 0x04, 0xa4, 0x6d, 0x06, + 0x90, 0x49, 0x91, 0x82, 0x3c, 0x09, 0x05, 0x3c, 0xbd, 0x73, 0x31, 0xef, 0x88, 0x08, 0x9e, 0xd1, + 0x40, 0x88, 0x1c, 0xaa, 0x80, 0xd3, 0x90, 0x9b, 0x30, 0x1a, 0x5e, 0x4d, 0x60, 0x32, 0x76, 0x3f, + 0xd2, 0x30, 0xa6, 0x7f, 0x5b, 0x0f, 0x70, 0x3c, 0x8b, 0xbb, 0xcc, 0x22, 0x51, 0x90, 0xcc, 0xc0, + 0xa9, 0x10, 0xc6, 0x44, 0xe4, 0x47, 0x38, 0xc7, 0xf4, 0x87, 0x12, 0x2f, 0x26, 0x4e, 0x99, 0x55, + 0xbc, 0x18, 0xa9, 0x40, 0x9f, 0x1f, 0x39, 0xa3, 0x7f, 0x47, 0x25, 0x3d, 0x2d, 0x22, 0x67, 0xf4, + 0xc9, 0x31, 0x33, 0xfc, 0xf2, 0x64, 0x1a, 0x46, 0x34, 0xbb, 0xed, 0xd1, 0x25, 0x5b, 0x18, 0x04, + 0x22, 0x04, 0x2e, 0xb6, 0xc9, 0x61, 0x98, 0x9a, 0x67, 0xfb, 0xd9, 0xf3, 0xe4, 0x2c, 0x6e, 0xd1, + 0x52, 0x64, 0x1e, 0xc6, 0x12, 0x97, 0x38, 0x72, 0x4e, 0x3b, 0xe9, 0xf3, 0x92, 0xcc, 0x92, 0x45, + 0xc9, 0xf7, 0x67, 0xa0, 0xb0, 0xe4, 0xe8, 0xa6, 0xe7, 0x8a, 0x87, 0x2c, 0x0f, 0x8c, 0x6f, 0x38, + 0x7a, 0x8b, 0xe9, 0xc7, 0x38, 0x86, 0x70, 0xba, 0xad, 0x37, 0xda, 0xd4, 0x9d, 0xb8, 0xc3, 0xbe, + 0xee, 0xef, 0x6f, 0x15, 0x3f, 0xba, 0x8a, 0x5b, 0xc5, 0xf1, 0xba, 0xdd, 0xbc, 0xba, 0xea, 0xe8, + 0x77, 0x4d, 0x0f, 0xa7, 0x0e, 0xbd, 0x71, 0xd5, 0xa3, 0x0d, 0xdc, 0x91, 0x5e, 0xd5, 0x5b, 0xe6, + 0x55, 0x0c, 0x15, 0x78, 0x35, 0xe0, 0xc4, 0x6b, 0x60, 0x2a, 0xe0, 0xe1, 0x5f, 0xb2, 0x0a, 0x70, + 0x1c, 0x99, 0x67, 0x1b, 0x39, 0xfc, 0xd4, 0x52, 0xab, 0x25, 0x5e, 0xc5, 0x48, 0xfb, 0x38, 0x1f, + 0xc3, 0x15, 0x3b, 0x10, 0x98, 0xde, 0x92, 0x53, 0xfa, 0x4b, 0x1c, 0x98, 0x16, 0x2c, 0x89, 0x16, + 0xf9, 0x62, 0x1a, 0x0e, 0x25, 0xee, 0x37, 0x36, 0x45, 0x48, 0xf1, 0x62, 0x64, 0x19, 0x4e, 0x09, + 0xbe, 0x41, 0x4c, 0xda, 0x91, 0xe8, 0xac, 0x10, 0x43, 0x73, 0xa5, 0x0d, 0xda, 0x68, 0x08, 0xb0, + 0x5c, 0x47, 0xac, 0x04, 0x99, 0x08, 0xd3, 0x31, 0xcd, 0xeb, 0x4d, 0xea, 0x2a, 0xa7, 0x50, 0x63, + 0x2f, 0x6c, 0x6f, 0x15, 0x15, 0xbf, 0x3c, 0x06, 0x91, 0x49, 0x4d, 0x2e, 0x88, 0x45, 0x64, 0x1e, + 0x5c, 0xeb, 0x47, 0x53, 0x78, 0xc4, 0x75, 0x3e, 0x5a, 0x84, 0x4c, 0xc2, 0x70, 0xe0, 0x94, 0x7b, + 0xeb, 0x56, 0xa5, 0x8c, 0xcf, 0x6e, 0x44, 0xa2, 0xfc, 0x58, 0xb8, 0x5b, 0x99, 0x49, 0xa4, 0x8c, + 0xf4, 0x3e, 0x8f, 0xbf, 0xc3, 0x89, 0xbd, 0xcf, 0x6b, 0xa5, 0xbc, 0xcf, 0x5b, 0x24, 0x2f, 0xc3, + 0x60, 0xe9, 0x4e, 0x55, 0xbc, 0x3b, 0x74, 0x95, 0xd3, 0x61, 0x9c, 0x71, 0xcc, 0x2f, 0x29, 0xde, + 0x28, 0xca, 0x4d, 0x97, 0xe9, 0xc9, 0x14, 0x8c, 0x44, 0xee, 0xf5, 0x5d, 0xe5, 0x0c, 0x72, 0xe0, + 0x29, 0xfe, 0x11, 0x53, 0x73, 0x04, 0x2a, 0x92, 0xf1, 0x34, 0x52, 0x88, 0x69, 0x0d, 0xdb, 0x1a, + 0x37, 0x1a, 0xf6, 0x86, 0x46, 0xf1, 0x89, 0x23, 0x3e, 0xe2, 0xe9, 0xe7, 0x5a, 0x63, 0x08, 0x54, + 0xcd, 0xe1, 0xb8, 0x48, 0x8a, 0xd3, 0x68, 0x31, 0xf2, 0x16, 0x10, 0x8c, 0xf2, 0x4c, 0x0d, 0xff, + 0x98, 0xb7, 0x52, 0x76, 0x95, 0xb3, 0x18, 0xca, 0x8e, 0xc4, 0xdf, 0xd8, 0x56, 0xca, 0x13, 0x97, 0xc4, 0xf4, 0x71, 0x51, 0xe7, 0xa5, 0x6a, 0x8e, 0xc0, 0xd5, 0x4c, 0x43, 0x6e, 0x71, 0x0a, 0x57, 0xb2, 0x01, 0xe7, 0x16, 0x1d, 0x7a, 0xd7, 0xb4, 0xdb, 0xae, 0xbf, 0x7c, 0xf8, 0xf3, 0xd6, 0xb9, - 0x1d, 0xe7, 0xad, 0x47, 0x45, 0xc5, 0x0f, 0xb4, 0x1c, 0x7a, 0xb7, 0xe6, 0x07, 0x17, 0x8b, 0x44, - 0xe5, 0xe9, 0xc4, 0x9d, 0x89, 0x0b, 0x9f, 0x5e, 0x0a, 0xb8, 0x49, 0x5d, 0x45, 0x09, 0xa7, 0x5a, - 0xfe, 0x92, 0xd4, 0x0c, 0x70, 0xb2, 0xb8, 0x62, 0xc5, 0x88, 0x06, 0xe4, 0xc6, 0xa4, 0x7f, 0x1c, - 0x5f, 0xaa, 0xf3, 0x54, 0x44, 0xca, 0x83, 0xc8, 0x4c, 0x65, 0x62, 0x59, 0xad, 0x07, 0x81, 0x06, - 0x6b, 0xba, 0xc0, 0xcb, 0x62, 0x49, 0x96, 0x26, 0xb3, 0x30, 0xba, 0xe8, 0xe0, 0xce, 0xe2, 0x26, - 0xdd, 0x5c, 0xb4, 0x1b, 0x66, 0x7d, 0x13, 0xdf, 0xf9, 0x88, 0xa9, 0xb2, 0xc5, 0x71, 0xb5, 0x75, - 0xba, 0x59, 0x6b, 0x21, 0x56, 0x5e, 0x56, 0xe2, 0x25, 0xe5, 0xc0, 0x5f, 0x0f, 0xed, 0x2e, 0xf0, - 0x17, 0x85, 0x51, 0x71, 0x98, 0x7f, 0xcf, 0xa3, 0x16, 0x5b, 0xea, 0x5d, 0xf1, 0xa6, 0x47, 0x89, - 0x1d, 0xfe, 0x07, 0x78, 0x91, 0x8a, 0x94, 0x8f, 0x32, 0x1a, 0x80, 0xe5, 0x86, 0xc5, 0x8b, 0xa8, - 0x5f, 0xca, 0xc9, 0x53, 0x27, 0xb9, 0x00, 0x79, 0x29, 0xee, 0x34, 0xc6, 0x0b, 0xc2, 0x18, 0x7d, - 0x79, 0x11, 0x8c, 0x6c, 0x40, 0x98, 0x1d, 0xc1, 0xc3, 0x56, 0x4c, 0xca, 0xe1, 0x07, 0x03, 0x34, - 0x0d, 0x2d, 0x24, 0xc0, 0x84, 0x08, 0x61, 0xc6, 0xf6, 0x9c, 0x94, 0x10, 0x21, 0xcc, 0xd8, 0x1e, - 0xc9, 0xd7, 0x7e, 0x0d, 0x06, 0xfd, 0xcd, 0x68, 0x18, 0x2f, 0x0b, 0x03, 0xfa, 0xf9, 0x49, 0x5b, - 0x79, 0xbc, 0x40, 0x89, 0x88, 0xbc, 0x88, 0x69, 0x8b, 0xfd, 0x47, 0xc3, 0xbd, 0xa1, 0xf9, 0x22, - 0x0f, 0xfc, 0x58, 0xde, 0x62, 0xff, 0xed, 0xf0, 0x04, 0x0c, 0xcb, 0x9a, 0xe4, 0xa7, 0x80, 0xc1, - 0x39, 0x2f, 0xa2, 0x7e, 0x72, 0xdf, 0x46, 0x8b, 0x90, 0x05, 0x18, 0x4b, 0x28, 0x8f, 0x88, 0xae, - 0x85, 0xc9, 0xe6, 0x52, 0x34, 0x4f, 0x5e, 0x53, 0x13, 0x65, 0xd5, 0xef, 0xc9, 0x26, 0x56, 0x0c, + 0x1d, 0xe7, 0xad, 0x47, 0x45, 0xc5, 0x0f, 0xb4, 0x1c, 0x7a, 0xb7, 0xe6, 0x07, 0x30, 0x8b, 0x44, + 0xfe, 0xe9, 0xc4, 0x9d, 0x89, 0x0b, 0x9f, 0x77, 0x0a, 0xb8, 0x49, 0x5d, 0x45, 0x09, 0xa7, 0x5a, + 0xfe, 0x5a, 0xd5, 0x0c, 0x70, 0xb2, 0xb8, 0x62, 0xc5, 0x88, 0x06, 0xe4, 0xc6, 0xa4, 0x7f, 0xe4, + 0x5f, 0xaa, 0xf3, 0x74, 0x47, 0xca, 0x83, 0xc8, 0x4c, 0x65, 0x62, 0x59, 0xad, 0x07, 0xc1, 0x0c, + 0x6b, 0xba, 0xc0, 0xcb, 0x62, 0x49, 0x96, 0x26, 0xb3, 0x30, 0xba, 0xe8, 0xe0, 0xee, 0xe5, 0x26, + 0xdd, 0x5c, 0xb4, 0x1b, 0x66, 0x7d, 0x13, 0xdf, 0x12, 0x89, 0xa9, 0xb2, 0xc5, 0x71, 0xb5, 0x75, + 0xba, 0x59, 0x6b, 0x21, 0x56, 0x5e, 0x56, 0xe2, 0x25, 0xe5, 0xe0, 0x62, 0x0f, 0xed, 0x2e, 0xb8, + 0x18, 0x85, 0x51, 0x71, 0x61, 0x70, 0xcf, 0xa3, 0x16, 0x5b, 0xea, 0x5d, 0xf1, 0x6e, 0x48, 0x89, + 0x5d, 0x30, 0x04, 0x78, 0x91, 0xee, 0x94, 0x8f, 0x32, 0x1a, 0x80, 0xe5, 0x86, 0xc5, 0x8b, 0xa8, + 0x5f, 0xca, 0xc9, 0x53, 0x27, 0xb9, 0x00, 0x79, 0x29, 0xb6, 0x35, 0xc6, 0x24, 0xc2, 0x38, 0x80, + 0x79, 0x11, 0xf0, 0x6c, 0x40, 0x98, 0x1d, 0xc1, 0xe3, 0x59, 0x4c, 0xfc, 0xe1, 0x07, 0x1c, 0x34, + 0x0d, 0x2d, 0x24, 0xc0, 0xa4, 0x0b, 0x61, 0x56, 0xf8, 0x9c, 0x94, 0x74, 0x21, 0xcc, 0x0a, 0x1f, + 0xc9, 0x09, 0x7f, 0x0d, 0x06, 0xfd, 0x0d, 0x6f, 0x18, 0x93, 0x0b, 0x83, 0x06, 0xfa, 0x89, 0x61, + 0x79, 0x4c, 0x42, 0x89, 0x88, 0xbc, 0x88, 0xa9, 0x91, 0xfd, 0x87, 0xc9, 0xbd, 0xa1, 0xf9, 0x22, + 0x0f, 0xfc, 0x58, 0x6e, 0x64, 0xff, 0x7d, 0xf2, 0x04, 0x0c, 0xcb, 0x9a, 0xe4, 0xa7, 0x99, 0xc1, + 0x39, 0x2f, 0xa2, 0x7e, 0x72, 0xdf, 0x46, 0x8b, 0x90, 0x05, 0x18, 0x4b, 0x28, 0x8f, 0x88, 0xe0, + 0x85, 0x09, 0xed, 0x52, 0x34, 0x4f, 0x5e, 0x53, 0x13, 0x65, 0xd5, 0xef, 0xc9, 0x26, 0x56, 0x0c, 0x26, 0x18, 0x41, 0x25, 0x75, 0x0e, 0x0a, 0xc6, 0x67, 0xcd, 0x05, 0x23, 0x11, 0x91, 0xcb, 0xd0, - 0x1f, 0xcb, 0x5c, 0x8c, 0xcf, 0xc8, 0x83, 0xb4, 0xc5, 0x01, 0x96, 0x5c, 0x93, 0x92, 0x12, 0x49, - 0x51, 0xe9, 0xfc, 0xa4, 0x44, 0xf2, 0x84, 0x1b, 0xa4, 0x27, 0xba, 0x16, 0x8b, 0x7f, 0xee, 0x27, - 0x98, 0x4d, 0xae, 0x56, 0x61, 0x76, 0x87, 0xc0, 0x56, 0xec, 0xdd, 0xc9, 0x56, 0x54, 0x7f, 0x3b, - 0x93, 0xd4, 0x7e, 0x72, 0x3d, 0x19, 0x9a, 0x8a, 0xe7, 0x96, 0xf5, 0x81, 0x72, 0xad, 0x41, 0x90, - 0xaa, 0x48, 0x90, 0xa9, 0xec, 0xbe, 0x83, 0x4c, 0xe5, 0xf6, 0x18, 0x64, 0x4a, 0xfd, 0xf7, 0xf9, - 0xae, 0x2e, 0x61, 0x47, 0x12, 0x4c, 0xe1, 0x05, 0xb6, 0xdf, 0x61, 0xb5, 0x97, 0xdc, 0x84, 0xd5, - 0xce, 0x3d, 0x5e, 0x6a, 0x3a, 0x1f, 0x35, 0xae, 0x16, 0xa5, 0x24, 0xaf, 0xc0, 0x90, 0xff, 0x01, - 0x18, 0xbc, 0x4c, 0x0a, 0xba, 0x15, 0xac, 0x35, 0xf1, 0xf4, 0xc0, 0x72, 0x01, 0xf2, 0x2c, 0x0c, - 0xa0, 0xa5, 0xd1, 0xd2, 0xeb, 0x7e, 0x64, 0x3b, 0x1e, 0x0a, 0xcf, 0x07, 0xca, 0x01, 0x03, 0x02, - 0x4a, 0xf2, 0x69, 0x28, 0x44, 0xf2, 0x53, 0x5f, 0xdd, 0x85, 0x0f, 0xdd, 0xb8, 0x1c, 0x60, 0x95, - 0xef, 0x1d, 0xe2, 0xb9, 0xa9, 0x05, 0x53, 0xb2, 0x04, 0xa7, 0x17, 0x1d, 0x6a, 0xa0, 0xb7, 0xe6, - 0xd4, 0xbd, 0x96, 0x23, 0xc2, 0xdf, 0xf2, 0x01, 0x8c, 0x4b, 0x47, 0xcb, 0x47, 0xb3, 0x45, 0x4d, + 0x1f, 0xcb, 0x8e, 0x8c, 0x4f, 0xd5, 0x83, 0xd4, 0xc8, 0x01, 0x96, 0x5c, 0x93, 0x12, 0x1f, 0x49, + 0x91, 0xef, 0xfc, 0xc4, 0x47, 0xf2, 0x84, 0x1b, 0xa4, 0x40, 0xba, 0x16, 0x8b, 0xb1, 0xee, 0x27, + 0xb1, 0x4d, 0xae, 0x56, 0x61, 0x06, 0x89, 0xc0, 0x56, 0xec, 0xdd, 0xc9, 0x56, 0x54, 0x7f, 0x37, + 0x93, 0xd4, 0x7e, 0x72, 0x3d, 0x19, 0xfe, 0x8a, 0xe7, 0xaf, 0xf5, 0x81, 0x72, 0xad, 0x41, 0x20, + 0xac, 0x48, 0x20, 0xab, 0xec, 0xbe, 0x03, 0x59, 0xe5, 0xf6, 0x18, 0xc8, 0x4a, 0xfd, 0xb7, 0xf9, + 0xae, 0x6e, 0x67, 0x47, 0x12, 0xb0, 0xe1, 0x05, 0xb6, 0xdf, 0x61, 0xb5, 0x97, 0xdc, 0x84, 0xd5, + 0xce, 0xbd, 0x6a, 0x6a, 0x3a, 0x1f, 0x35, 0xae, 0x16, 0xa5, 0x24, 0xaf, 0xc0, 0x90, 0xff, 0x01, + 0x18, 0x20, 0x4d, 0x0a, 0xec, 0x15, 0xac, 0x35, 0xf1, 0x14, 0xc4, 0x72, 0x01, 0xf2, 0x2c, 0x0c, + 0xa0, 0xa5, 0xd1, 0xd2, 0xeb, 0x7e, 0xf4, 0x3c, 0x1e, 0x6e, 0xcf, 0x07, 0xca, 0x41, 0x09, 0x02, + 0x4a, 0xf2, 0x69, 0x28, 0x44, 0x72, 0x60, 0x5f, 0xdd, 0x85, 0x9f, 0xde, 0xb8, 0x1c, 0xc4, 0x95, + 0xef, 0x1d, 0xe2, 0xf9, 0xaf, 0x05, 0x53, 0xb2, 0x04, 0xa7, 0x17, 0x1d, 0x6a, 0xa0, 0x47, 0xe8, + 0xd4, 0xbd, 0x96, 0x23, 0x42, 0xec, 0xf2, 0x01, 0x8c, 0x4b, 0x47, 0xcb, 0x47, 0xb3, 0x45, 0x4d, 0xe0, 0x25, 0x46, 0x69, 0xc5, 0x99, 0x3d, 0xc1, 0x5b, 0x72, 0x93, 0x6e, 0x6e, 0xd8, 0x8e, 0xc1, - 0x23, 0xc4, 0x0a, 0x7b, 0x42, 0x08, 0x7a, 0x5d, 0xa0, 0x64, 0x7b, 0x22, 0x5a, 0xe8, 0xfc, 0x0b, - 0x30, 0xb8, 0xdf, 0x20, 0xa5, 0xbf, 0x9a, 0xed, 0xe0, 0x5c, 0x7d, 0xff, 0x26, 0x97, 0x09, 0x12, - 0x7d, 0xf5, 0x76, 0x48, 0xf4, 0xf5, 0x9d, 0x6c, 0x07, 0xcf, 0xf1, 0xfb, 0x3a, 0x21, 0x4f, 0x20, - 0x8c, 0x68, 0x42, 0x9e, 0x30, 0x17, 0x92, 0x69, 0x68, 0x32, 0x51, 0x2c, 0x75, 0x57, 0x61, 0xc7, - 0xd4, 0x5d, 0x3f, 0x9f, 0xeb, 0xe6, 0x59, 0x7f, 0x22, 0xfb, 0xbd, 0xc8, 0xfe, 0x1a, 0x0c, 0x06, - 0x92, 0xad, 0x94, 0xd1, 0x9e, 0x19, 0x0e, 0x42, 0x22, 0x73, 0x30, 0x96, 0x91, 0x88, 0xc8, 0x15, - 0xde, 0xd6, 0xaa, 0xf9, 0x36, 0x0f, 0x0b, 0x3a, 0x2c, 0x02, 0x3e, 0xea, 0x9e, 0x5e, 0x73, 0xcd, - 0xb7, 0xa9, 0x16, 0xa0, 0xd5, 0xff, 0x27, 0x9b, 0xfa, 0x3c, 0xe1, 0xa4, 0x8f, 0xf6, 0xd0, 0x47, - 0x29, 0x42, 0xe4, 0x0f, 0x2b, 0x4e, 0x84, 0xb8, 0x07, 0x21, 0xfe, 0x45, 0x36, 0xf5, 0x19, 0xca, - 0x89, 0x10, 0xf7, 0x32, 0x5b, 0x3c, 0x09, 0x03, 0x9a, 0xbd, 0xe1, 0x62, 0x9e, 0x5e, 0x31, 0x57, - 0xe0, 0x44, 0xed, 0xd8, 0x1b, 0x2e, 0xcf, 0x61, 0xac, 0x85, 0x04, 0xea, 0x5f, 0x65, 0xbb, 0x3c, - 0xd4, 0x39, 0x11, 0xfc, 0xbb, 0xb9, 0x44, 0xfe, 0x7a, 0x36, 0xf2, 0x10, 0xe8, 0xbe, 0xce, 0x6c, - 0x59, 0xad, 0xaf, 0xd1, 0xa6, 0x1e, 0xcf, 0x6c, 0xe9, 0x22, 0x54, 0x24, 0xc6, 0x0a, 0x49, 0xd4, - 0xaf, 0x65, 0x63, 0x2f, 0xa1, 0x4e, 0x64, 0xb7, 0x6b, 0xd9, 0x05, 0x5a, 0x27, 0x1e, 0x77, 0x9d, - 0x48, 0x6e, 0xb7, 0x92, 0xfb, 0x5c, 0x36, 0xf6, 0x0e, 0xee, 0xfe, 0x4d, 0x72, 0xf7, 0xb5, 0x6c, - 0xf2, 0x4d, 0xdf, 0xfd, 0xab, 0x49, 0x4f, 0xc2, 0x80, 0x90, 0x43, 0xb0, 0x54, 0xf0, 0x79, 0x9f, - 0x03, 0xf1, 0x00, 0x35, 0x20, 0x50, 0xbf, 0x2f, 0x0b, 0xd1, 0xf7, 0x89, 0xf7, 0xa9, 0x0e, 0xfd, - 0x7a, 0x36, 0xfa, 0x32, 0xf3, 0xfe, 0xd5, 0x9f, 0x71, 0x80, 0x6a, 0x7b, 0xb9, 0x2e, 0x02, 0xfb, - 0xf5, 0x4a, 0x27, 0xf0, 0x01, 0x54, 0x93, 0x28, 0xd4, 0xff, 0x90, 0x4d, 0x7d, 0x2e, 0x7a, 0xff, - 0x0a, 0xf0, 0x19, 0x3c, 0x15, 0xaf, 0x5b, 0xe1, 0x44, 0x8e, 0x87, 0x90, 0x6c, 0xfc, 0x25, 0xf2, - 0x71, 0xf8, 0x84, 0xe4, 0x23, 0x29, 0xe6, 0x1a, 0x46, 0x3b, 0x0d, 0xcd, 0x35, 0xf9, 0x86, 0x41, - 0x32, 0xdc, 0xfe, 0x4e, 0x76, 0xa7, 0xd7, 0xb5, 0xf7, 0xf3, 0xaa, 0xda, 0xb7, 0xa8, 0x6f, 0x62, - 0x14, 0x28, 0xd6, 0x13, 0x43, 0x3c, 0x5b, 0x44, 0x8b, 0x83, 0xe4, 0x1b, 0x31, 0x41, 0xa5, 0xfe, - 0x79, 0x6f, 0xfa, 0xd3, 0xce, 0xfb, 0x57, 0x84, 0x17, 0x20, 0xbf, 0xa8, 0x7b, 0x6b, 0x42, 0x93, - 0xf1, 0xb6, 0xae, 0xa5, 0x7b, 0x6b, 0x1a, 0x42, 0xc9, 0x15, 0xe8, 0xd7, 0xf4, 0x0d, 0x7e, 0xe6, - 0x59, 0x08, 0x33, 0x79, 0x38, 0xfa, 0x46, 0x8d, 0x9f, 0x7b, 0x06, 0x68, 0xa2, 0x06, 0x99, 0x64, - 0xf8, 0xc9, 0x37, 0xa6, 0x61, 0xe0, 0x99, 0x64, 0x82, 0xfc, 0x31, 0x17, 0x20, 0x3f, 0x61, 0x1b, - 0x9b, 0xe8, 0xcc, 0x32, 0xc4, 0x2b, 0x5b, 0xb6, 0x8d, 0x4d, 0x0d, 0xa1, 0xe4, 0xf3, 0x19, 0xe8, - 0x9b, 0xa1, 0xba, 0xc1, 0x46, 0xc8, 0x40, 0x37, 0x5f, 0x90, 0x8f, 0x1f, 0x8e, 0x2f, 0xc8, 0xd8, - 0x1a, 0xaf, 0x4c, 0x56, 0x14, 0x51, 0x3f, 0xb9, 0x01, 0xfd, 0x93, 0xba, 0x47, 0x57, 0x6d, 0x67, - 0x13, 0xbd, 0x5b, 0x46, 0x42, 0x47, 0xc6, 0x88, 0xfe, 0xf8, 0x44, 0xfc, 0x66, 0xac, 0x2e, 0x7e, - 0x69, 0x41, 0x61, 0x26, 0x16, 0x91, 0x61, 0x72, 0x30, 0x14, 0x0b, 0x4f, 0x25, 0x19, 0x24, 0x92, - 0x0c, 0x8e, 0x95, 0x87, 0xd2, 0x8f, 0x95, 0xd1, 0x7a, 0x44, 0x0f, 0x38, 0xcc, 0xdf, 0x32, 0x8c, - 0x8b, 0x3e, 0xb7, 0x1e, 0x11, 0x8a, 0xe9, 0x5b, 0x34, 0x89, 0x44, 0xfd, 0x56, 0x2f, 0xa4, 0x3e, - 0x04, 0x3b, 0x51, 0xf2, 0x13, 0x25, 0x0f, 0x95, 0xbc, 0x9c, 0x50, 0xf2, 0xf3, 0xc9, 0xa7, 0x85, - 0xef, 0x51, 0x0d, 0xff, 0xd1, 0x7c, 0xe2, 0x61, 0xf2, 0xfd, 0xbd, 0xbb, 0x0c, 0xa5, 0xd7, 0xbb, - 0xa3, 0xf4, 0x82, 0x01, 0x51, 0xd8, 0x71, 0x40, 0xf4, 0xed, 0x76, 0x40, 0xf4, 0x77, 0x1c, 0x10, - 0xa1, 0x82, 0x0c, 0x74, 0x54, 0x90, 0x8a, 0x18, 0x34, 0xd0, 0x3d, 0x37, 0xd8, 0x85, 0xed, 0xad, - 0xe2, 0x08, 0x1b, 0x4d, 0xa9, 0x59, 0xc1, 0x90, 0x85, 0xfa, 0xcd, 0x7c, 0x97, 0x68, 0x02, 0x47, - 0xa2, 0x23, 0xcf, 0x40, 0xae, 0xd4, 0x6a, 0x09, 0xfd, 0x38, 0x2d, 0x05, 0x32, 0xe8, 0x50, 0x8a, - 0x51, 0x93, 0x17, 0x21, 0x57, 0xba, 0x53, 0x8d, 0xc7, 0x44, 0x2f, 0xdd, 0xa9, 0x8a, 0x2f, 0xe9, - 0x58, 0xf6, 0x4e, 0x95, 0xbc, 0x14, 0x06, 0x27, 0x5b, 0x6b, 0x5b, 0xeb, 0x62, 0xa3, 0x28, 0x9c, - 0x60, 0x7d, 0x4f, 0x9b, 0x3a, 0x43, 0xb1, 0xed, 0x62, 0x8c, 0x36, 0xa6, 0x4d, 0x85, 0xdd, 0x6b, - 0x53, 0xdf, 0x8e, 0xda, 0xd4, 0xbf, 0x5b, 0x6d, 0x1a, 0xd8, 0x85, 0x36, 0xc1, 0x8e, 0xda, 0x34, - 0x78, 0x70, 0x6d, 0x6a, 0xc1, 0xf9, 0x64, 0x04, 0x98, 0x40, 0x23, 0x34, 0x20, 0x49, 0xac, 0x70, - 0x2c, 0xc1, 0xab, 0xff, 0x36, 0xc7, 0xd6, 0x78, 0x26, 0xd8, 0x78, 0x1e, 0x55, 0x2d, 0xa5, 0xb4, - 0xfa, 0xab, 0xd9, 0xce, 0x81, 0x6b, 0x8e, 0xe7, 0x14, 0xf7, 0x5d, 0xa9, 0x52, 0xca, 0x47, 0x1f, - 0x12, 0x76, 0x96, 0x72, 0x8c, 0x6d, 0x9a, 0xcc, 0xbe, 0x91, 0xe9, 0x14, 0x4d, 0xe7, 0x40, 0x12, - 0x7b, 0x3c, 0xe9, 0xac, 0x86, 0xde, 0xf3, 0x6e, 0xd4, 0x4b, 0x2d, 0x9e, 0x58, 0x34, 0xb7, 0xcf, - 0xc4, 0xa2, 0xbf, 0x9d, 0x81, 0xd3, 0x37, 0xdb, 0xcb, 0x54, 0x38, 0xa7, 0x05, 0xcd, 0x78, 0x0b, - 0x80, 0x81, 0x85, 0x13, 0x4b, 0x06, 0x9d, 0x58, 0x3e, 0x24, 0x47, 0xc2, 0x89, 0x15, 0x18, 0x0f, - 0xa9, 0xb9, 0x03, 0xcb, 0xc3, 0xbe, 0x8b, 0xe5, 0x7a, 0x7b, 0x99, 0xd6, 0x12, 0x9e, 0x2c, 0x12, - 0xf7, 0xf3, 0x2f, 0x73, 0xe7, 0xf5, 0xfd, 0x3a, 0x8d, 0xfc, 0x72, 0xb6, 0x63, 0xf0, 0xa1, 0x63, - 0x9b, 0xfb, 0xe5, 0x93, 0xa9, 0xbd, 0x12, 0xcf, 0x01, 0x93, 0x42, 0x12, 0xe3, 0x98, 0xc6, 0x25, - 0x5d, 0x60, 0xc7, 0x3c, 0x23, 0xd1, 0xbb, 0x2a, 0xb0, 0x3f, 0xcc, 0x74, 0x0c, 0x12, 0x75, 0x5c, - 0x05, 0xa6, 0xfe, 0xb3, 0x9c, 0x1f, 0x9b, 0xea, 0x40, 0x9f, 0xf0, 0x24, 0x0c, 0x88, 0x04, 0x1c, - 0x51, 0xdf, 0x5a, 0x71, 0x94, 0x87, 0x47, 0xc3, 0x01, 0x01, 0x5b, 0xe6, 0xfd, 0xd8, 0x39, 0x41, - 0x2a, 0x5a, 0x5c, 0xe6, 0x4d, 0x01, 0x65, 0xf4, 0x12, 0x09, 0x5b, 0xc8, 0xa7, 0xee, 0x99, 0x1e, - 0x5a, 0x05, 0xac, 0x2f, 0x73, 0x7c, 0x21, 0xa7, 0xf7, 0x4c, 0x8f, 0xdb, 0x04, 0x01, 0x9a, 0x2d, - 0xd2, 0xd5, 0x30, 0xdf, 0xa2, 0x58, 0xa4, 0x5d, 0x91, 0x76, 0x52, 0x3c, 0xe6, 0x7a, 0x12, 0x06, - 0x84, 0xc3, 0xaa, 0x70, 0x33, 0x11, 0xad, 0x15, 0x2e, 0xae, 0xd8, 0xda, 0x80, 0x80, 0x71, 0xd4, - 0xe8, 0x6a, 0xe8, 0x58, 0x87, 0x1c, 0x1d, 0x84, 0x68, 0x02, 0x43, 0xae, 0xc1, 0x48, 0xd5, 0xd3, - 0x2d, 0x43, 0x77, 0x8c, 0x85, 0xb6, 0xd7, 0x6a, 0x7b, 0xb2, 0x51, 0xea, 0x7a, 0x86, 0xdd, 0xf6, - 0xb4, 0x18, 0x05, 0xf9, 0x30, 0x0c, 0xfb, 0x90, 0x29, 0xc7, 0xb1, 0x1d, 0xd9, 0xf2, 0x70, 0x3d, - 0x83, 0x3a, 0x8e, 0x16, 0x25, 0x20, 0x1f, 0x81, 0xe1, 0x8a, 0x75, 0xd7, 0xae, 0xf3, 0x47, 0x7b, - 0xda, 0xac, 0xb0, 0x43, 0xf0, 0x81, 0x94, 0x19, 0x20, 0x6a, 0x6d, 0xa7, 0xa1, 0x45, 0x09, 0xd5, - 0xed, 0x6c, 0x32, 0x84, 0xd7, 0xfd, 0xbb, 0x69, 0xb9, 0x12, 0x75, 0xa6, 0x43, 0x0f, 0x52, 0x34, - 0x08, 0x65, 0x5f, 0x5e, 0x6e, 0x17, 0x5e, 0x83, 0xfe, 0x9b, 0x74, 0x93, 0xfb, 0x7d, 0x16, 0x42, - 0x57, 0xe1, 0x75, 0x01, 0x93, 0x4f, 0x5c, 0x7d, 0x3a, 0xf5, 0xeb, 0xd9, 0x64, 0x70, 0xb2, 0xfb, - 0x57, 0xd8, 0x1f, 0x86, 0x3e, 0x14, 0x65, 0xc5, 0x3f, 0xf2, 0x47, 0x01, 0xa2, 0xb8, 0xa3, 0x1e, - 0xc8, 0x3e, 0x99, 0xfa, 0xd3, 0x85, 0x78, 0xc4, 0xba, 0xfb, 0x57, 0x7a, 0x1f, 0x85, 0xc1, 0x49, - 0xdb, 0x72, 0x4d, 0xd7, 0xa3, 0x56, 0xdd, 0x57, 0xd8, 0x07, 0x99, 0x41, 0x55, 0x0f, 0xc1, 0xf2, - 0xcb, 0x20, 0x89, 0x7a, 0x3f, 0xca, 0x4b, 0x9e, 0x83, 0x01, 0x14, 0x39, 0xfa, 0x49, 0x4b, 0x89, - 0xb6, 0x97, 0x19, 0x30, 0xee, 0x24, 0x1d, 0x92, 0x92, 0x5b, 0xd0, 0x3f, 0xb9, 0x66, 0x36, 0x0c, - 0x87, 0x5a, 0xe8, 0x2f, 0x2c, 0xc5, 0xcd, 0x8b, 0xf6, 0xe5, 0x38, 0xfe, 0x8b, 0xb4, 0xbc, 0x39, - 0x75, 0x51, 0x2c, 0xf2, 0x36, 0x4a, 0xc0, 0xce, 0xff, 0x70, 0x16, 0x20, 0x2c, 0x40, 0x1e, 0x81, - 0x6c, 0x90, 0xca, 0x0c, 0xdd, 0x54, 0x22, 0x1a, 0x94, 0xc5, 0xa5, 0x42, 0x8c, 0xed, 0xec, 0x8e, - 0x63, 0xfb, 0x16, 0x14, 0xf8, 0x89, 0x17, 0x7a, 0x92, 0x4b, 0x41, 0xb4, 0x3a, 0x36, 0x78, 0x1c, - 0xe9, 0xf9, 0x66, 0x16, 0x2d, 0xcf, 0x88, 0x57, 0x36, 0x67, 0x76, 0xbe, 0x0e, 0xbd, 0xf8, 0x17, - 0xb9, 0x04, 0x79, 0x94, 0x62, 0x06, 0xf7, 0xb1, 0x38, 0x4b, 0xc7, 0xe4, 0x87, 0x78, 0xd6, 0x4d, - 0x93, 0xb6, 0xe5, 0xb1, 0xaa, 0xb1, 0xd5, 0x43, 0x42, 0x2e, 0x02, 0x16, 0x91, 0x8b, 0x80, 0xa9, - 0xff, 0x7f, 0x36, 0x25, 0x96, 0xe2, 0xfd, 0x3b, 0x4c, 0x5e, 0x00, 0xc0, 0x87, 0xd6, 0x4c, 0x9e, - 0xfe, 0x13, 0x0d, 0x1c, 0x25, 0xc8, 0x08, 0xd5, 0x36, 0xb2, 0xed, 0x08, 0x89, 0xd5, 0xdf, 0xcd, - 0x24, 0x02, 0xf0, 0x1d, 0x48, 0x8e, 0xb2, 0x55, 0x96, 0xdd, 0xa7, 0x19, 0xeb, 0xf7, 0x45, 0x6e, - 0x6f, 0x7d, 0x11, 0xfd, 0x96, 0x43, 0xb0, 0x4c, 0x8f, 0xf2, 0x5b, 0xbe, 0x95, 0x4d, 0x0b, 0x47, - 0x78, 0x3c, 0x55, 0xfc, 0x7a, 0x60, 0x94, 0xe6, 0x77, 0x93, 0x04, 0x5c, 0x98, 0xa9, 0x6f, 0xc2, - 0xa9, 0x58, 0x90, 0x3e, 0x91, 0x5f, 0xf0, 0x52, 0xf7, 0x68, 0x7f, 0x9d, 0x9f, 0xe8, 0x47, 0xc8, - 0xd4, 0xff, 0x98, 0xe9, 0x1e, 0xa2, 0xf1, 0xc8, 0x55, 0x27, 0x45, 0x00, 0xb9, 0xbf, 0x1d, 0x01, - 0x1c, 0xc2, 0x36, 0xf8, 0x78, 0x0b, 0xe0, 0x3d, 0x32, 0x79, 0xbc, 0xdb, 0x02, 0xf8, 0xe9, 0xcc, - 0x8e, 0x11, 0x36, 0x8f, 0x5a, 0x06, 0xea, 0x3f, 0xce, 0xa4, 0x46, 0xc2, 0x3c, 0x50, 0xbb, 0x5e, - 0x82, 0x02, 0x77, 0xab, 0x11, 0xad, 0x92, 0x72, 0x87, 0x30, 0x68, 0x87, 0xf2, 0xa2, 0x0c, 0x99, - 0x85, 0x3e, 0xde, 0x06, 0x23, 0x9e, 0x63, 0x37, 0xa5, 0x9d, 0x46, 0xa7, 0xc9, 0x51, 0xa0, 0xd5, - 0xdf, 0xc9, 0x24, 0x02, 0x73, 0x1e, 0xe1, 0xb7, 0x85, 0x53, 0x75, 0x6e, 0xf7, 0x53, 0xb5, 0xfa, - 0x67, 0xd9, 0xf4, 0xb8, 0xa0, 0x47, 0xf8, 0x21, 0x87, 0x71, 0x9c, 0xb6, 0xbf, 0x75, 0x6b, 0x09, - 0x46, 0xa2, 0xb2, 0x10, 0xcb, 0xd6, 0xc5, 0xf4, 0xe8, 0xa8, 0x1d, 0x5a, 0x11, 0xe3, 0xa1, 0xbe, - 0x93, 0x49, 0x86, 0x34, 0x3d, 0xf2, 0xf9, 0x69, 0x7f, 0xda, 0x12, 0xfd, 0x94, 0xf7, 0xc8, 0x5a, - 0x73, 0x18, 0x9f, 0xf2, 0x1e, 0x59, 0x35, 0xf6, 0xf7, 0x29, 0xbf, 0x98, 0xed, 0x14, 0x11, 0xf6, - 0xc8, 0x3f, 0xe8, 0x13, 0xb2, 0x90, 0x79, 0xcb, 0xc4, 0xa7, 0x3d, 0xd2, 0x29, 0x04, 0x6b, 0x07, - 0x9e, 0x09, 0x3e, 0xfb, 0x1b, 0xe3, 0xa9, 0xc2, 0x7a, 0x8f, 0x28, 0xf2, 0xf1, 0x10, 0xd6, 0x7b, - 0x64, 0xa8, 0xbc, 0xf7, 0x84, 0xf5, 0x9b, 0xd9, 0xdd, 0x86, 0x21, 0x3e, 0x11, 0x5e, 0x42, 0x78, - 0x5f, 0xce, 0x26, 0xc3, 0x63, 0x1f, 0xb9, 0x98, 0xa6, 0xa1, 0x20, 0x02, 0x75, 0x77, 0x14, 0x0e, - 0xc7, 0x77, 0xb2, 0x68, 0xc4, 0x77, 0x5c, 0x07, 0x71, 0x91, 0xb3, 0x3b, 0x91, 0x70, 0x5a, 0xf5, - 0xaf, 0x32, 0xb1, 0x58, 0xd2, 0x47, 0x72, 0x84, 0xb0, 0xaf, 0x25, 0x89, 0xbc, 0xec, 0x1f, 0x66, - 0xe6, 0x63, 0x81, 0x40, 0x83, 0xef, 0x29, 0x53, 0x4f, 0x37, 0x1b, 0xf1, 0xf2, 0x22, 0x26, 0xc0, - 0xd7, 0xb3, 0x30, 0x96, 0x20, 0x25, 0x97, 0x22, 0x51, 0x72, 0xf0, 0x58, 0x32, 0xe6, 0x3c, 0xce, - 0xe3, 0xe5, 0xec, 0xe1, 0x24, 0xf5, 0x12, 0xe4, 0xcb, 0xfa, 0x26, 0xff, 0xb6, 0x5e, 0xce, 0xd2, - 0xd0, 0x37, 0xe5, 0x13, 0x37, 0xc4, 0x93, 0x65, 0x78, 0x80, 0xdf, 0x87, 0x98, 0xb6, 0xb5, 0x64, - 0x36, 0x69, 0xc5, 0x9a, 0x33, 0x1b, 0x0d, 0xd3, 0x15, 0x97, 0x7a, 0x4f, 0x6e, 0x6f, 0x15, 0x2f, - 0x7b, 0xb6, 0xa7, 0x37, 0x6a, 0xd4, 0x27, 0xab, 0x79, 0x66, 0x93, 0xd6, 0x4c, 0xab, 0xd6, 0x44, - 0x4a, 0x89, 0x65, 0x3a, 0x2b, 0x52, 0xe1, 0x31, 0x5f, 0xab, 0x75, 0xdd, 0xb2, 0xa8, 0x51, 0xb1, - 0x26, 0x36, 0x3d, 0xca, 0x2f, 0x03, 0x73, 0xfc, 0x48, 0x90, 0xbf, 0x0d, 0xe7, 0x68, 0xc6, 0x78, - 0x99, 0x11, 0x68, 0x29, 0x85, 0xd4, 0xdf, 0xca, 0xa7, 0x84, 0x11, 0x3f, 0x46, 0xea, 0xe3, 0xf7, - 0x74, 0x7e, 0x87, 0x9e, 0xbe, 0x0a, 0x7d, 0xb7, 0xa9, 0x83, 0xe7, 0x5b, 0xfc, 0x82, 0x01, 0x9d, - 0xd9, 0xef, 0x72, 0x90, 0x7c, 0x43, 0x23, 0xa8, 0x48, 0x03, 0xce, 0x2f, 0xb1, 0x6e, 0x4a, 0xef, - 0xcc, 0xc2, 0x3e, 0x3a, 0xb3, 0x0b, 0x3f, 0xf2, 0x06, 0x9c, 0x43, 0x6c, 0x4a, 0xb7, 0xf6, 0x61, - 0x55, 0x18, 0x39, 0x8a, 0x57, 0x95, 0xde, 0xb9, 0x9d, 0xca, 0x93, 0x4f, 0xc0, 0x50, 0x30, 0x40, - 0x4c, 0xea, 0x8a, 0x9b, 0x8b, 0x2e, 0xe3, 0x8c, 0x87, 0x65, 0x63, 0x60, 0x74, 0x21, 0x8b, 0x86, - 0xf6, 0x8a, 0xf0, 0x52, 0xff, 0x51, 0xa6, 0x5b, 0x38, 0xf3, 0x23, 0x9f, 0x95, 0x5f, 0x86, 0x3e, - 0x83, 0x7f, 0x94, 0xd0, 0xa9, 0xee, 0x01, 0xcf, 0x39, 0xa9, 0xe6, 0x97, 0x51, 0xff, 0x34, 0xd3, - 0x35, 0x8a, 0xfa, 0x71, 0xff, 0xbc, 0x2f, 0xe7, 0x3a, 0x7c, 0x9e, 0x98, 0x44, 0xaf, 0xc0, 0xa8, - 0x19, 0x06, 0xbd, 0xad, 0x85, 0xe1, 0xa7, 0xb4, 0x53, 0x12, 0x1c, 0x47, 0xd7, 0x75, 0x38, 0xeb, - 0x3b, 0x3e, 0x3a, 0xbe, 0x87, 0x98, 0x5b, 0x6b, 0x3b, 0x26, 0x1f, 0x97, 0xda, 0x19, 0x37, 0xe6, - 0x3e, 0xe6, 0xde, 0x72, 0x4c, 0x56, 0x81, 0xee, 0xad, 0x51, 0x4b, 0xaf, 0x6d, 0xd8, 0xce, 0x3a, - 0xc6, 0xfe, 0xe4, 0x83, 0x53, 0x3b, 0xc5, 0xe1, 0x77, 0x7c, 0x30, 0x79, 0x0c, 0x86, 0x57, 0x1b, - 0x6d, 0x1a, 0x44, 0x5b, 0xe4, 0x77, 0x7d, 0xda, 0x10, 0x03, 0x06, 0x37, 0x24, 0x0f, 0x03, 0x20, - 0x91, 0x87, 0x31, 0xee, 0xf1, 0x62, 0x4f, 0x1b, 0x60, 0x90, 0x25, 0xd1, 0x5d, 0xe7, 0xb9, 0x56, - 0x73, 0x21, 0xd5, 0x1a, 0xb6, 0xb5, 0x5a, 0xf3, 0xa8, 0xd3, 0xc4, 0x86, 0xa2, 0x33, 0x83, 0x76, - 0x16, 0x29, 0xf0, 0xea, 0xc4, 0x9d, 0xb5, 0xad, 0xd5, 0x25, 0xea, 0x34, 0x59, 0x53, 0x9f, 0x04, - 0x22, 0x9a, 0xea, 0xe0, 0xa1, 0x07, 0xff, 0x38, 0xf4, 0x66, 0xd0, 0xc4, 0x47, 0xf0, 0xd3, 0x10, - 0xfc, 0xb0, 0x22, 0x0c, 0xf2, 0x90, 0x73, 0x5c, 0x68, 0xe8, 0xc2, 0xa0, 0x01, 0x07, 0xa1, 0xbc, - 0xce, 0x82, 0xf0, 0xae, 0xe0, 0x5e, 0xdd, 0x9a, 0xf8, 0xa5, 0x7e, 0x21, 0x97, 0x16, 0xf8, 0xfd, - 0x40, 0x8a, 0x16, 0x4e, 0xab, 0xd9, 0x3d, 0x4d, 0xab, 0xa7, 0xac, 0x76, 0xb3, 0xa6, 0xb7, 0x5a, - 0xb5, 0x15, 0xb3, 0x81, 0xcf, 0xaa, 0x70, 0xe1, 0xd3, 0x86, 0xad, 0x76, 0xb3, 0xd4, 0x6a, 0x4d, - 0x73, 0x20, 0x79, 0x02, 0xc6, 0x18, 0x1d, 0x76, 0x52, 0x40, 0x99, 0x47, 0x4a, 0xc6, 0x00, 0x63, - 0xb6, 0xfa, 0xb4, 0x0f, 0x42, 0xbf, 0xe0, 0xc9, 0xd7, 0xaa, 0x5e, 0xad, 0x8f, 0x33, 0x73, 0x59, - 0xcf, 0x05, 0x6c, 0xf8, 0xe4, 0xda, 0xab, 0x0d, 0xf8, 0xe5, 0x31, 0x32, 0xb1, 0xd5, 0x6e, 0xf2, - 0x88, 0x58, 0x7d, 0x88, 0x0c, 0x7e, 0x93, 0x4b, 0x30, 0xc2, 0xb8, 0x04, 0x02, 0xe3, 0xc1, 0x5c, - 0x7b, 0xb5, 0x18, 0x94, 0x5c, 0x83, 0x33, 0x11, 0x08, 0xb7, 0x41, 0xf9, 0x33, 0x81, 0x5e, 0x2d, - 0x15, 0xa7, 0xbe, 0x93, 0x4b, 0xc6, 0xb5, 0x3f, 0x92, 0xb5, 0x71, 0x06, 0x40, 0xa4, 0xad, 0x08, - 0x2f, 0x68, 0x02, 0xaf, 0xe5, 0x10, 0xd3, 0x81, 0x87, 0x54, 0x96, 0x5c, 0x81, 0x7e, 0xfe, 0x45, - 0x95, 0xb2, 0x58, 0x33, 0xd1, 0xcd, 0xc8, 0x6d, 0x99, 0x2b, 0x2b, 0xe8, 0x93, 0x14, 0xa0, 0xc9, - 0x25, 0xe8, 0x2b, 0xcf, 0x57, 0xab, 0xa5, 0x79, 0xff, 0xb6, 0x11, 0xdf, 0x28, 0x18, 0x96, 0x5b, - 0x73, 0x75, 0xcb, 0xd5, 0x7c, 0x24, 0x79, 0x0c, 0x0a, 0x95, 0x45, 0x24, 0xe3, 0x2f, 0xef, 0x06, - 0xb7, 0xb7, 0x8a, 0x7d, 0x66, 0x8b, 0x53, 0x09, 0x14, 0xd6, 0x7b, 0xbb, 0x52, 0x96, 0xae, 0xdc, - 0x79, 0xbd, 0x77, 0x4d, 0x03, 0xaf, 0x2e, 0xb5, 0x00, 0x4d, 0x9e, 0x85, 0xa1, 0x2a, 0x75, 0x4c, - 0xbd, 0x31, 0xdf, 0xc6, 0xed, 0x06, 0x77, 0x33, 0x1a, 0xdb, 0xde, 0x2a, 0x0e, 0xbb, 0x08, 0xaf, - 0x59, 0x88, 0xd0, 0x22, 0x64, 0xe4, 0x02, 0xe4, 0x67, 0x4c, 0xcb, 0x77, 0x83, 0x47, 0x3f, 0xe9, - 0x35, 0xd3, 0xf2, 0x34, 0x84, 0xaa, 0xff, 0x3a, 0x9b, 0x9e, 0x59, 0xe0, 0x08, 0xc6, 0xd6, 0x3e, - 0x6f, 0x0b, 0x63, 0x4a, 0x90, 0x3f, 0x80, 0x12, 0xac, 0xc0, 0xa9, 0x92, 0xd1, 0x34, 0xad, 0x12, - 0xfe, 0x74, 0xe7, 0xa6, 0x4b, 0x38, 0x20, 0xa5, 0x67, 0x58, 0x31, 0xb4, 0xf8, 0x1e, 0x1e, 0x6e, - 0x95, 0xa1, 0x6a, 0x3a, 0xc7, 0xd5, 0x9a, 0x2b, 0x7a, 0xad, 0xce, 0x83, 0xf2, 0x6b, 0x71, 0xa6, - 0xea, 0x0f, 0x65, 0x77, 0x48, 0x86, 0x70, 0x3f, 0x4a, 0x5f, 0xfd, 0x4a, 0xb6, 0x7b, 0x3e, 0x8a, - 0xfb, 0x52, 0x28, 0x7f, 0x91, 0x4d, 0xc9, 0x0e, 0x71, 0x20, 0x49, 0x5c, 0x81, 0x7e, 0xce, 0x26, - 0x70, 0xd7, 0xc4, 0x19, 0x87, 0x2b, 0x2b, 0xce, 0x74, 0x3e, 0x9a, 0xcc, 0xc3, 0x99, 0xd2, 0xca, - 0x0a, 0xad, 0x7b, 0x61, 0xe0, 0xdd, 0xf9, 0x30, 0xd8, 0x26, 0x8f, 0x56, 0x2a, 0xf0, 0x61, 0xe0, - 0x5e, 0x0c, 0x2a, 0x91, 0x5a, 0x8e, 0x2c, 0xc1, 0xd9, 0x38, 0xbc, 0xca, 0x4d, 0xbd, 0xbc, 0x14, - 0xc0, 0x34, 0xc1, 0x91, 0xff, 0xa7, 0x75, 0x28, 0x9b, 0xd6, 0x4a, 0x9c, 0x4e, 0x7b, 0xbb, 0xb5, - 0x12, 0xe7, 0xd6, 0xd4, 0x72, 0xea, 0xd7, 0x73, 0x72, 0x12, 0x8d, 0xfb, 0xd7, 0xb1, 0xe6, 0x7a, - 0xc4, 0x9d, 0x76, 0xb7, 0x43, 0xe6, 0x59, 0x11, 0x29, 0xc2, 0x68, 0x3b, 0xbe, 0xe7, 0x59, 0xf0, - 0x52, 0x1d, 0x81, 0xb2, 0x0f, 0x59, 0x40, 0x49, 0x2a, 0x90, 0x2f, 0x39, 0xab, 0xdc, 0x8c, 0xd9, - 0xe9, 0xf1, 0x8c, 0xee, 0xac, 0xba, 0xe9, 0x8f, 0x67, 0x18, 0x0b, 0xf5, 0x27, 0xb2, 0x9d, 0x12, - 0x50, 0x1c, 0x57, 0x87, 0x98, 0x43, 0x9c, 0x4f, 0xd2, 0x84, 0x73, 0xbc, 0xbd, 0x85, 0x0e, 0x4f, - 0x38, 0x4f, 0xcc, 0xf1, 0x80, 0xc2, 0x37, 0x4d, 0xcb, 0x20, 0x0f, 0xc2, 0x03, 0xb7, 0xaa, 0x53, - 0x5a, 0xed, 0x66, 0x65, 0xbe, 0x5c, 0xbb, 0x35, 0x5f, 0x5d, 0x9c, 0x9a, 0xac, 0x4c, 0x57, 0xa6, - 0xca, 0xa3, 0x3d, 0xe4, 0x34, 0x9c, 0x0a, 0x51, 0x33, 0xb7, 0xe6, 0x4a, 0xf3, 0xa3, 0x19, 0x32, - 0x06, 0xc3, 0x21, 0x70, 0x62, 0x61, 0x69, 0x34, 0xfb, 0xc4, 0x07, 0x61, 0x10, 0x77, 0x4c, 0x7c, - 0xe5, 0x27, 0x43, 0xd0, 0xbf, 0x30, 0x51, 0x9d, 0xd2, 0x6e, 0x23, 0x13, 0x80, 0x42, 0x79, 0x6a, - 0x9e, 0x31, 0xcc, 0x3c, 0xf1, 0xef, 0x32, 0x00, 0xd5, 0xe9, 0xa5, 0x45, 0x41, 0x38, 0x08, 0x7d, - 0x95, 0xf9, 0xdb, 0xa5, 0xd9, 0x0a, 0xa3, 0xeb, 0x87, 0xfc, 0xc2, 0xe2, 0x14, 0xab, 0x61, 0x00, - 0x7a, 0x27, 0x67, 0x17, 0xaa, 0x53, 0xa3, 0x59, 0x06, 0xd4, 0xa6, 0x4a, 0xe5, 0xd1, 0x1c, 0x03, - 0xde, 0xd1, 0x2a, 0x4b, 0x53, 0xa3, 0x79, 0xf6, 0xe7, 0x6c, 0x75, 0xa9, 0xb4, 0x34, 0xda, 0xcb, - 0xfe, 0x9c, 0xc6, 0x3f, 0x0b, 0x8c, 0x59, 0x75, 0x6a, 0x09, 0x7f, 0xf4, 0xb1, 0x26, 0x4c, 0xfb, - 0xbf, 0xfa, 0x19, 0x8a, 0xb1, 0x2e, 0x57, 0xb4, 0xd1, 0x01, 0xf6, 0x83, 0xb1, 0x64, 0x3f, 0x80, - 0x35, 0x4e, 0x9b, 0x9a, 0x5b, 0xb8, 0x3d, 0x35, 0x3a, 0xc8, 0x78, 0xcd, 0xdd, 0x64, 0xe0, 0x21, - 0xf6, 0xa7, 0x36, 0xc7, 0xfe, 0x1c, 0x66, 0x9c, 0xb4, 0xa9, 0xd2, 0xec, 0x62, 0x69, 0x69, 0x66, - 0x74, 0x84, 0xb5, 0x07, 0x79, 0x9e, 0xe2, 0x25, 0xe7, 0x4b, 0x73, 0x53, 0xa3, 0xa3, 0x82, 0xa6, - 0x3c, 0x5b, 0x99, 0xbf, 0x39, 0x3a, 0x86, 0x0d, 0x79, 0x63, 0x0e, 0x7f, 0x10, 0x56, 0x00, 0xff, - 0x3a, 0xfd, 0xc4, 0xa7, 0xa0, 0xb0, 0x50, 0x45, 0xfb, 0xf6, 0x1c, 0x9c, 0x5e, 0xa8, 0xd6, 0x96, - 0xde, 0x58, 0x9c, 0x8a, 0xc9, 0x7b, 0x0c, 0x86, 0x7d, 0xc4, 0x6c, 0x65, 0xfe, 0xd6, 0xc7, 0xb9, - 0xb4, 0x7d, 0xd0, 0x5c, 0x69, 0x72, 0xa1, 0x3a, 0x9a, 0x65, 0xbd, 0xe2, 0x83, 0xee, 0x54, 0xe6, - 0xcb, 0x0b, 0x77, 0xaa, 0xa3, 0xb9, 0x27, 0xee, 0xfa, 0x59, 0x48, 0x17, 0x1c, 0x73, 0xd5, 0xb4, - 0xc8, 0xc3, 0xf0, 0x60, 0x79, 0xea, 0x76, 0x65, 0x72, 0xaa, 0xb6, 0xa0, 0x55, 0x6e, 0x54, 0xe6, - 0x63, 0x35, 0x3d, 0x00, 0x63, 0x51, 0x74, 0x69, 0xb1, 0x32, 0x9a, 0x21, 0x67, 0x81, 0x44, 0xc1, - 0xaf, 0x95, 0xe6, 0xa6, 0x47, 0xb3, 0x44, 0x81, 0x33, 0x51, 0x78, 0x65, 0x7e, 0xe9, 0xd6, 0xfc, - 0xd4, 0x68, 0xee, 0x89, 0x9f, 0xcd, 0xc0, 0x03, 0xa9, 0x4f, 0xf6, 0x89, 0x0a, 0x17, 0xa7, 0x66, - 0x4b, 0xd5, 0xa5, 0xca, 0x64, 0x75, 0xaa, 0xa4, 0x4d, 0xce, 0xd4, 0x26, 0x4b, 0x4b, 0x53, 0x37, - 0x16, 0xb4, 0x37, 0x6a, 0x37, 0xa6, 0xe6, 0xa7, 0xb4, 0xd2, 0xec, 0x68, 0x0f, 0x79, 0x0c, 0x8a, - 0x1d, 0x68, 0xaa, 0x53, 0x93, 0xb7, 0xb4, 0xca, 0xd2, 0x1b, 0xa3, 0x19, 0xf2, 0x28, 0x3c, 0xdc, - 0x91, 0x88, 0xfd, 0x1e, 0xcd, 0x92, 0x8b, 0x70, 0xbe, 0x13, 0xc9, 0xeb, 0xb3, 0xa3, 0xb9, 0x27, - 0x7e, 0x2c, 0x03, 0x24, 0xf9, 0xe6, 0x9a, 0x3c, 0x02, 0x17, 0x98, 0x5e, 0xd4, 0x3a, 0x37, 0xf0, - 0x51, 0x78, 0x38, 0x95, 0x42, 0x6a, 0x5e, 0x11, 0x1e, 0xea, 0x40, 0x22, 0x1a, 0x77, 0x01, 0x94, - 0x74, 0x02, 0x6c, 0xda, 0xaf, 0x65, 0xe0, 0x81, 0x54, 0x63, 0x9b, 0x5c, 0x86, 0x0f, 0x94, 0xca, - 0x73, 0xac, 0x6f, 0x26, 0x97, 0x2a, 0x0b, 0xf3, 0xd5, 0xda, 0xdc, 0x74, 0xa9, 0xc6, 0xb4, 0xef, - 0x56, 0x35, 0xd6, 0x9b, 0x97, 0x40, 0xed, 0x42, 0x39, 0x39, 0x53, 0x9a, 0xbf, 0xc1, 0x86, 0x1f, - 0xf9, 0x00, 0x3c, 0xd2, 0x91, 0x6e, 0x6a, 0xbe, 0x34, 0x31, 0x3b, 0x55, 0x1e, 0xcd, 0x92, 0xc7, - 0xe1, 0xd1, 0x8e, 0x54, 0xe5, 0x4a, 0x95, 0x93, 0xe5, 0x26, 0xca, 0xef, 0xfc, 0x93, 0x8b, 0x3d, - 0xef, 0x7c, 0xfb, 0x62, 0xe6, 0x0f, 0xbe, 0x7d, 0x31, 0xf3, 0x67, 0xdf, 0xbe, 0x98, 0xf9, 0xc4, - 0xb5, 0xbd, 0xbc, 0xa5, 0xe7, 0xd3, 0xd6, 0x72, 0x01, 0x17, 0xbe, 0x67, 0xfe, 0x53, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x86, 0x00, 0xc7, 0x54, 0x45, 0x52, 0x01, 0x00, + 0xa3, 0xd0, 0x0a, 0x7b, 0x42, 0x08, 0x7a, 0x5d, 0xa0, 0x64, 0x7b, 0x22, 0x5a, 0xe8, 0xfc, 0x0b, + 0x30, 0xb8, 0xdf, 0x40, 0xa8, 0xbf, 0x9e, 0xed, 0xe0, 0xc0, 0x7d, 0xff, 0x26, 0xb0, 0x09, 0x92, + 0x89, 0xf5, 0x76, 0x48, 0x26, 0xf6, 0x9d, 0x6c, 0x07, 0xef, 0xf4, 0xfb, 0x3a, 0xe9, 0x4f, 0x20, + 0x8c, 0x68, 0xd2, 0x9f, 0x30, 0xdf, 0x92, 0x69, 0x68, 0x32, 0x51, 0x2c, 0x3d, 0x58, 0x61, 0xc7, + 0xf4, 0x60, 0xbf, 0x90, 0xeb, 0xe6, 0xbd, 0x7f, 0x22, 0xfb, 0xbd, 0xc8, 0xfe, 0x1a, 0x0c, 0x06, + 0x92, 0xad, 0x94, 0xd1, 0x9e, 0x19, 0x0e, 0xc2, 0x2e, 0x73, 0x30, 0x96, 0x91, 0x88, 0xc8, 0x15, + 0xde, 0xd6, 0xaa, 0xf9, 0x36, 0x0f, 0x3d, 0x3a, 0x2c, 0x82, 0x4a, 0xea, 0x9e, 0x5e, 0x73, 0xcd, + 0xb7, 0xa9, 0x16, 0xa0, 0xd5, 0xff, 0x3d, 0x9b, 0xfa, 0x04, 0xe2, 0xa4, 0x8f, 0xf6, 0xd0, 0x47, + 0x29, 0x42, 0xe4, 0x8f, 0x37, 0x4e, 0x84, 0xb8, 0x07, 0x21, 0xfe, 0x65, 0x36, 0xf5, 0xa9, 0xcb, + 0x89, 0x10, 0xf7, 0x32, 0x5b, 0x3c, 0x09, 0x03, 0x9a, 0xbd, 0xe1, 0x62, 0x2e, 0x60, 0x31, 0x57, + 0xe0, 0x44, 0xed, 0xd8, 0x1b, 0x2e, 0xcf, 0x93, 0xac, 0x85, 0x04, 0xea, 0x5f, 0x67, 0xbb, 0x3c, + 0x06, 0x3a, 0x11, 0xfc, 0xbb, 0xb9, 0x44, 0xfe, 0x66, 0x36, 0xf2, 0xd8, 0xe8, 0xbe, 0xce, 0x9e, + 0x59, 0xad, 0xaf, 0xd1, 0xa6, 0x1e, 0xcf, 0x9e, 0xe9, 0x22, 0x54, 0x24, 0xdf, 0x0a, 0x49, 0xd4, + 0xaf, 0x65, 0x63, 0xaf, 0xad, 0x4e, 0x64, 0xb7, 0x6b, 0xd9, 0x05, 0x5a, 0x27, 0x1e, 0x90, 0x9d, + 0x48, 0x6e, 0xb7, 0x92, 0xfb, 0x5c, 0x36, 0xf6, 0xd6, 0xee, 0xfe, 0x4d, 0xa4, 0xf7, 0xb5, 0x6c, + 0xf2, 0xdd, 0xe0, 0xfd, 0xab, 0x49, 0x4f, 0xc2, 0x80, 0x90, 0x43, 0xb0, 0x54, 0xf0, 0x79, 0x9f, + 0x03, 0xf1, 0x00, 0x35, 0x20, 0x50, 0xbf, 0x2f, 0x0b, 0xd1, 0x37, 0x90, 0xf7, 0xa9, 0x0e, 0xfd, + 0x66, 0x36, 0xfa, 0xfa, 0xf3, 0xfe, 0xd5, 0x9f, 0x71, 0x80, 0x6a, 0x7b, 0xb9, 0x2e, 0x82, 0x07, + 0xf6, 0x4a, 0x27, 0xf0, 0x01, 0x54, 0x93, 0x28, 0xd4, 0x7f, 0x97, 0x4d, 0x7d, 0x92, 0x7a, 0xff, + 0x0a, 0xf0, 0x19, 0x3c, 0x15, 0xaf, 0x5b, 0xe1, 0x44, 0x8e, 0x87, 0x90, 0x6c, 0xfc, 0x25, 0x72, + 0x7e, 0xf8, 0x84, 0xe4, 0x23, 0x29, 0xe6, 0x1a, 0x46, 0x54, 0x0d, 0xcd, 0x35, 0xf9, 0x86, 0x41, + 0x32, 0xdc, 0xfe, 0xef, 0xec, 0x4e, 0x2f, 0x78, 0xef, 0xe7, 0x55, 0xb5, 0x6f, 0x51, 0xdf, 0xc4, + 0x48, 0x53, 0xac, 0x27, 0x86, 0x78, 0x46, 0x8a, 0x16, 0x07, 0xc9, 0x37, 0x62, 0x82, 0x4a, 0xfd, + 0x8b, 0xde, 0xf4, 0xe7, 0xa3, 0xf7, 0xaf, 0x08, 0x2f, 0x40, 0x7e, 0x51, 0xf7, 0xd6, 0x84, 0x26, + 0xe3, 0x6d, 0x5d, 0x4b, 0xf7, 0xd6, 0x34, 0x84, 0x92, 0x2b, 0xd0, 0xaf, 0xe9, 0x1b, 0xfc, 0xcc, + 0xb3, 0x10, 0x66, 0x0b, 0x71, 0xf4, 0x8d, 0x1a, 0x3f, 0xf7, 0x0c, 0xd0, 0x44, 0x0d, 0xb2, 0xd5, + 0xf0, 0x93, 0x6f, 0x4c, 0xf5, 0xc0, 0xb3, 0xd5, 0x04, 0x39, 0x6a, 0x2e, 0x40, 0x7e, 0xc2, 0x36, + 0x36, 0xd1, 0x99, 0x65, 0x88, 0x57, 0xb6, 0x6c, 0x1b, 0x9b, 0x1a, 0x42, 0xc9, 0xe7, 0x33, 0xd0, + 0x37, 0x43, 0x75, 0x83, 0x8d, 0x90, 0x81, 0x6e, 0xbe, 0x20, 0x1f, 0x3f, 0x1c, 0x5f, 0x90, 0xb1, + 0x35, 0x5e, 0x99, 0xac, 0x28, 0xa2, 0x7e, 0x72, 0x03, 0xfa, 0x27, 0x75, 0x8f, 0xae, 0xda, 0xce, + 0x26, 0x7a, 0xb7, 0x8c, 0x84, 0xce, 0x92, 0x11, 0xfd, 0xf1, 0x89, 0xf8, 0xcd, 0x58, 0x5d, 0xfc, + 0xd2, 0x82, 0xc2, 0x4c, 0x2c, 0x22, 0x8b, 0xe5, 0x60, 0x28, 0x16, 0x9e, 0xae, 0x32, 0x48, 0x56, + 0x19, 0x1c, 0x2b, 0x0f, 0xa5, 0x1f, 0x2b, 0xa3, 0xf5, 0x88, 0x1e, 0x70, 0x98, 0x23, 0x66, 0x18, + 0x17, 0x7d, 0x6e, 0x3d, 0x22, 0x14, 0x53, 0xc4, 0x68, 0x12, 0x89, 0xfa, 0xad, 0x5e, 0x48, 0x7d, + 0x6c, 0x76, 0xa2, 0xe4, 0x27, 0x4a, 0x1e, 0x2a, 0x79, 0x39, 0xa1, 0xe4, 0xe7, 0x93, 0xcf, 0x17, + 0xdf, 0xa3, 0x1a, 0xfe, 0x63, 0xf9, 0xc4, 0xe3, 0xe7, 0xfb, 0x7b, 0x77, 0x19, 0x4a, 0xaf, 0x77, + 0x47, 0xe9, 0x05, 0x03, 0xa2, 0xb0, 0xe3, 0x80, 0xe8, 0xdb, 0xed, 0x80, 0xe8, 0xef, 0x38, 0x20, + 0x42, 0x05, 0x19, 0xe8, 0xa8, 0x20, 0x15, 0x31, 0x68, 0xa0, 0x7b, 0xfe, 0xb1, 0x0b, 0xdb, 0x5b, + 0xc5, 0x11, 0x36, 0x9a, 0x52, 0x33, 0x8f, 0x21, 0x0b, 0xf5, 0x9b, 0xf9, 0x2e, 0x11, 0x0b, 0x8e, + 0x44, 0x47, 0x9e, 0x81, 0x5c, 0xa9, 0xd5, 0x12, 0xfa, 0x71, 0x5a, 0x0a, 0x96, 0xd0, 0xa1, 0x14, + 0xa3, 0x26, 0x2f, 0x42, 0xae, 0x74, 0xa7, 0x1a, 0x8f, 0xbb, 0x5e, 0xba, 0x53, 0x15, 0x5f, 0xd2, + 0xb1, 0xec, 0x9d, 0x2a, 0x79, 0x29, 0x0c, 0x80, 0xb6, 0xd6, 0xb6, 0xd6, 0xc5, 0x46, 0x51, 0x38, + 0xc1, 0xfa, 0x9e, 0x36, 0x75, 0x86, 0x62, 0xdb, 0xc5, 0x18, 0x6d, 0x4c, 0x9b, 0x0a, 0xbb, 0xd7, + 0xa6, 0xbe, 0x1d, 0xb5, 0xa9, 0x7f, 0xb7, 0xda, 0x34, 0xb0, 0x0b, 0x6d, 0x82, 0x1d, 0xb5, 0x69, + 0xf0, 0xe0, 0xda, 0xd4, 0x82, 0xf3, 0xc9, 0x28, 0x33, 0x81, 0x46, 0x68, 0x40, 0x92, 0x58, 0xe1, + 0x58, 0x82, 0x57, 0xff, 0x6d, 0x8e, 0xad, 0xf1, 0x6c, 0xb3, 0xf1, 0x5c, 0xad, 0x5a, 0x4a, 0x69, + 0xf5, 0xd7, 0xb3, 0x9d, 0x83, 0xe3, 0x1c, 0xcf, 0x29, 0xee, 0xbb, 0x52, 0xa5, 0x94, 0x8f, 0x3e, + 0x56, 0xec, 0x2c, 0xe5, 0x18, 0xdb, 0x34, 0x99, 0x7d, 0x23, 0xd3, 0x29, 0x62, 0xcf, 0x81, 0x24, + 0xf6, 0x78, 0xd2, 0x59, 0x0d, 0xbd, 0xe7, 0xdd, 0xa8, 0x97, 0x5a, 0x3c, 0x79, 0x69, 0x6e, 0x9f, + 0xc9, 0x4b, 0x7f, 0x37, 0x03, 0xa7, 0x6f, 0xb6, 0x97, 0xa9, 0x70, 0x4e, 0x0b, 0x9a, 0xf1, 0x16, + 0x00, 0x03, 0x0b, 0x27, 0x96, 0x0c, 0x3a, 0xb1, 0x7c, 0x48, 0x8e, 0xb6, 0x13, 0x2b, 0x30, 0x1e, + 0x52, 0x73, 0x07, 0x96, 0x87, 0x7d, 0x17, 0xcb, 0xf5, 0xf6, 0x32, 0xad, 0x25, 0x3c, 0x59, 0x24, + 0xee, 0xe7, 0x5f, 0xe6, 0xce, 0xeb, 0xfb, 0x75, 0x1a, 0xf9, 0x95, 0x6c, 0xc7, 0x00, 0x47, 0xc7, + 0x36, 0xbf, 0xcc, 0x27, 0x53, 0x7b, 0x25, 0x9e, 0x67, 0x26, 0x85, 0x24, 0xc6, 0x31, 0x8d, 0x4b, + 0xba, 0xc0, 0x8e, 0x79, 0xd6, 0xa3, 0x77, 0x55, 0x60, 0x7f, 0x94, 0xe9, 0x18, 0x88, 0xea, 0xb8, + 0x0a, 0x4c, 0xfd, 0x27, 0x39, 0x3f, 0xfe, 0xd5, 0x81, 0x3e, 0xe1, 0x49, 0x18, 0x10, 0x49, 0x3e, + 0xa2, 0xbe, 0xb5, 0xe2, 0x28, 0x0f, 0x8f, 0x86, 0x03, 0x02, 0xb6, 0xcc, 0xfb, 0xf1, 0x79, 0x82, + 0x74, 0xb7, 0xb8, 0xcc, 0x9b, 0x02, 0xca, 0xe8, 0x25, 0x12, 0xb6, 0x90, 0x4f, 0xdd, 0x33, 0x3d, + 0xb4, 0x0a, 0x58, 0x5f, 0xe6, 0xf8, 0x42, 0x4e, 0xef, 0x99, 0x1e, 0xb7, 0x09, 0x02, 0x34, 0x5b, + 0xa4, 0xab, 0x61, 0x4e, 0x47, 0xb1, 0x48, 0xbb, 0x22, 0xb5, 0xa5, 0x78, 0xcc, 0xf5, 0x24, 0x0c, + 0x08, 0x87, 0x55, 0xe1, 0x66, 0x22, 0x5a, 0x2b, 0x5c, 0x5c, 0xb1, 0xb5, 0x01, 0x01, 0xe3, 0xa8, + 0xd1, 0xd5, 0xd0, 0xb1, 0x0e, 0x39, 0x3a, 0x08, 0xd1, 0x04, 0x86, 0x5c, 0x83, 0x91, 0xaa, 0xa7, + 0x5b, 0x86, 0xee, 0x18, 0x0b, 0x6d, 0xaf, 0xd5, 0xf6, 0x64, 0xa3, 0xd4, 0xf5, 0x0c, 0xbb, 0xed, + 0x69, 0x31, 0x0a, 0xf2, 0x61, 0x18, 0xf6, 0x21, 0x53, 0x8e, 0x63, 0x3b, 0xb2, 0xe5, 0xe1, 0x7a, + 0x06, 0x75, 0x1c, 0x2d, 0x4a, 0x40, 0x3e, 0x02, 0xc3, 0x15, 0xeb, 0xae, 0x5d, 0xe7, 0x8f, 0xf6, + 0xb4, 0x59, 0x61, 0x87, 0xe0, 0x03, 0x29, 0x33, 0x40, 0xd4, 0xda, 0x4e, 0x43, 0x8b, 0x12, 0xaa, + 0xdb, 0xd9, 0x64, 0x98, 0xb0, 0xfb, 0x77, 0xd3, 0x72, 0x25, 0xea, 0x4c, 0x87, 0x1e, 0xa4, 0x68, + 0x10, 0xca, 0xbe, 0xbc, 0xdc, 0x2e, 0xbc, 0x06, 0xfd, 0x37, 0xe9, 0x26, 0xf7, 0xfb, 0x2c, 0x84, + 0xae, 0xc2, 0xeb, 0x02, 0x26, 0x9f, 0xb8, 0xfa, 0x74, 0xea, 0xd7, 0xb3, 0xc9, 0x00, 0x68, 0xf7, + 0xaf, 0xb0, 0x3f, 0x0c, 0x7d, 0x28, 0xca, 0x8a, 0x7f, 0xe4, 0x8f, 0x02, 0x44, 0x71, 0x47, 0x3d, + 0x90, 0x7d, 0x32, 0xf5, 0x67, 0x0a, 0xf1, 0xa8, 0x78, 0xf7, 0xaf, 0xf4, 0x3e, 0x0a, 0x83, 0x93, + 0xb6, 0xe5, 0x9a, 0xae, 0x47, 0xad, 0xba, 0xaf, 0xb0, 0x0f, 0x32, 0x83, 0xaa, 0x1e, 0x82, 0xe5, + 0x97, 0x41, 0x12, 0xf5, 0x7e, 0x94, 0x97, 0x3c, 0x07, 0x03, 0x28, 0x72, 0xf4, 0x93, 0x96, 0x92, + 0x79, 0x2f, 0x33, 0x60, 0xdc, 0x49, 0x3a, 0x24, 0x25, 0xb7, 0xa0, 0x7f, 0x72, 0xcd, 0x6c, 0x18, + 0x0e, 0xb5, 0xd0, 0x5f, 0x58, 0x7a, 0x26, 0x1d, 0xed, 0xcb, 0x71, 0xfc, 0x17, 0x69, 0x79, 0x73, + 0xea, 0xa2, 0x58, 0xe4, 0x6d, 0x94, 0x80, 0x9d, 0xff, 0x91, 0x2c, 0x40, 0x58, 0x80, 0x3c, 0x02, + 0xd9, 0x20, 0x5d, 0x1a, 0xba, 0xa9, 0x44, 0x34, 0x28, 0x8b, 0x4b, 0x85, 0x18, 0xdb, 0xd9, 0x1d, + 0xc7, 0xf6, 0x2d, 0x28, 0xf0, 0x13, 0x2f, 0xf4, 0x24, 0x97, 0x02, 0x75, 0x75, 0x6c, 0xf0, 0x38, + 0xd2, 0xf3, 0xcd, 0x2c, 0x5a, 0x9e, 0x11, 0xaf, 0x6c, 0xce, 0xec, 0x7c, 0x1d, 0x7a, 0xf1, 0x2f, + 0x72, 0x09, 0xf2, 0x28, 0xc5, 0x0c, 0xee, 0x63, 0x71, 0x96, 0x8e, 0xc9, 0x0f, 0xf1, 0xac, 0x9b, + 0x26, 0x6d, 0xcb, 0x63, 0x55, 0x63, 0xab, 0x87, 0x84, 0x5c, 0x04, 0x2c, 0x22, 0x17, 0x01, 0x53, + 0xff, 0xaf, 0x6c, 0x4a, 0xbc, 0xc6, 0xfb, 0x77, 0x98, 0xbc, 0x00, 0x80, 0x0f, 0xad, 0x99, 0x3c, + 0xfd, 0x27, 0x1a, 0x38, 0x4a, 0x90, 0x11, 0xaa, 0x6d, 0x64, 0xdb, 0x11, 0x12, 0xab, 0xbf, 0x9f, + 0x49, 0x04, 0xf9, 0x3b, 0x90, 0x1c, 0x65, 0xab, 0x2c, 0xbb, 0x4f, 0x33, 0xd6, 0xef, 0x8b, 0xdc, + 0xde, 0xfa, 0x22, 0xfa, 0x2d, 0x87, 0x60, 0x99, 0x1e, 0xe5, 0xb7, 0x7c, 0x2b, 0x9b, 0x16, 0xf2, + 0xf0, 0x78, 0xaa, 0xf8, 0xf5, 0xc0, 0x28, 0xcd, 0xef, 0x26, 0xd1, 0xb8, 0x30, 0x53, 0xdf, 0x84, + 0x53, 0xb1, 0x40, 0x80, 0x22, 0x87, 0xe1, 0xa5, 0xee, 0x11, 0x05, 0x3b, 0x3f, 0xd1, 0x8f, 0x90, + 0xa9, 0xff, 0x3e, 0xd3, 0x3d, 0x0c, 0xe4, 0x91, 0xab, 0x4e, 0x8a, 0x00, 0x72, 0x7f, 0x37, 0x02, + 0x38, 0x84, 0x6d, 0xf0, 0xf1, 0x16, 0xc0, 0x7b, 0x64, 0xf2, 0x78, 0xb7, 0x05, 0xf0, 0x33, 0x99, + 0x1d, 0xa3, 0x78, 0x1e, 0xb5, 0x0c, 0xd4, 0x7f, 0x98, 0x49, 0x8d, 0xb6, 0x79, 0xa0, 0x76, 0xbd, + 0x04, 0x05, 0xee, 0x56, 0x23, 0x5a, 0x25, 0xe5, 0x27, 0x61, 0xd0, 0x0e, 0xe5, 0x45, 0x19, 0x32, + 0x0b, 0x7d, 0xbc, 0x0d, 0x46, 0x3c, 0x8f, 0x6f, 0x4a, 0x3b, 0x8d, 0x4e, 0x93, 0xa3, 0x40, 0xab, + 0xbf, 0x97, 0x49, 0x04, 0xff, 0x3c, 0xc2, 0x6f, 0x0b, 0xa7, 0xea, 0xdc, 0xee, 0xa7, 0x6a, 0xf5, + 0xcf, 0xb3, 0xe9, 0xb1, 0x47, 0x8f, 0xf0, 0x43, 0x0e, 0xe3, 0x38, 0x6d, 0x7f, 0xeb, 0xd6, 0x12, + 0x8c, 0x44, 0x65, 0x21, 0x96, 0xad, 0x8b, 0xe9, 0x11, 0x58, 0x3b, 0xb4, 0x22, 0xc6, 0x43, 0x7d, + 0x27, 0x93, 0x0c, 0x9b, 0x7a, 0xe4, 0xf3, 0xd3, 0xfe, 0xb4, 0x25, 0xfa, 0x29, 0xef, 0x91, 0xb5, + 0xe6, 0x30, 0x3e, 0xe5, 0x3d, 0xb2, 0x6a, 0xec, 0xef, 0x53, 0x7e, 0x29, 0xdb, 0x29, 0xea, 0xec, + 0x91, 0x7f, 0xd0, 0x27, 0x64, 0x21, 0xf3, 0x96, 0x89, 0x4f, 0x7b, 0xa4, 0x53, 0x98, 0xd7, 0x0e, + 0x3c, 0x13, 0x7c, 0xf6, 0x37, 0xc6, 0x53, 0x85, 0xf5, 0x1e, 0x51, 0xe4, 0xe3, 0x21, 0xac, 0xf7, + 0xc8, 0x50, 0x79, 0xef, 0x09, 0xeb, 0xb7, 0xb3, 0xbb, 0x0d, 0x75, 0x7c, 0x22, 0xbc, 0x84, 0xf0, + 0xbe, 0x9c, 0x4d, 0x86, 0xe0, 0x3e, 0x72, 0x31, 0x4d, 0x43, 0x41, 0x04, 0x03, 0xef, 0x28, 0x1c, + 0x8e, 0xef, 0x64, 0xd1, 0x88, 0xef, 0xb8, 0x0e, 0xe2, 0x22, 0x67, 0x77, 0x22, 0xe1, 0xb4, 0xea, + 0x5f, 0x67, 0x62, 0xf1, 0xaa, 0x8f, 0xe4, 0x08, 0x61, 0x5f, 0x4b, 0x12, 0x79, 0xd9, 0x3f, 0xcc, + 0xcc, 0xc7, 0x82, 0x8d, 0x06, 0xdf, 0x53, 0xa6, 0x9e, 0x6e, 0x36, 0xe2, 0xe5, 0x45, 0x4c, 0x80, + 0xaf, 0x67, 0x61, 0x2c, 0x41, 0x4a, 0x2e, 0x45, 0xa2, 0xe4, 0xe0, 0xb1, 0x64, 0xcc, 0x79, 0x9c, + 0xc7, 0xcb, 0xd9, 0xc3, 0x49, 0xea, 0x25, 0xc8, 0x97, 0xf5, 0x4d, 0xfe, 0x6d, 0xbd, 0x9c, 0xa5, + 0xa1, 0x6f, 0xca, 0x27, 0x6e, 0x88, 0x27, 0xcb, 0xf0, 0x00, 0xbf, 0x0f, 0x31, 0x6d, 0x6b, 0xc9, + 0x6c, 0xd2, 0x8a, 0x35, 0x67, 0x36, 0x1a, 0xa6, 0x2b, 0x2e, 0xf5, 0x9e, 0xdc, 0xde, 0x2a, 0x5e, + 0xf6, 0x6c, 0x4f, 0x6f, 0xd4, 0xa8, 0x4f, 0x56, 0xf3, 0xcc, 0x26, 0xad, 0x99, 0x56, 0xad, 0x89, + 0x94, 0x12, 0xcb, 0x74, 0x56, 0xa4, 0xc2, 0xe3, 0xca, 0x56, 0xeb, 0xba, 0x65, 0x51, 0xa3, 0x62, + 0x4d, 0x6c, 0x7a, 0x94, 0x5f, 0x06, 0xe6, 0xf8, 0x91, 0x20, 0x7f, 0x1b, 0xce, 0xd1, 0x8c, 0xf1, + 0x32, 0x23, 0xd0, 0x52, 0x0a, 0xa9, 0xbf, 0x93, 0x4f, 0x09, 0x55, 0x7e, 0x8c, 0xd4, 0xc7, 0xef, + 0xe9, 0xfc, 0x0e, 0x3d, 0x7d, 0x15, 0xfa, 0x6e, 0x53, 0x07, 0xcf, 0xb7, 0xf8, 0x05, 0x03, 0x3a, + 0xb3, 0xdf, 0xe5, 0x20, 0xf9, 0x86, 0x46, 0x50, 0x91, 0x06, 0x9c, 0x5f, 0x62, 0xdd, 0x94, 0xde, + 0x99, 0x85, 0x7d, 0x74, 0x66, 0x17, 0x7e, 0xe4, 0x0d, 0x38, 0x87, 0xd8, 0x94, 0x6e, 0xed, 0xc3, + 0xaa, 0x30, 0x72, 0x14, 0xaf, 0x2a, 0xbd, 0x73, 0x3b, 0x95, 0x27, 0x9f, 0x80, 0xa1, 0x60, 0x80, + 0x98, 0xd4, 0x15, 0x37, 0x17, 0x5d, 0xc6, 0x19, 0x0f, 0xcb, 0xc6, 0xc0, 0xe8, 0x42, 0x16, 0x0d, + 0xed, 0x15, 0xe1, 0xa5, 0xfe, 0x83, 0x4c, 0xb7, 0x90, 0xe9, 0x47, 0x3e, 0x2b, 0xbf, 0x0c, 0x7d, + 0x06, 0xff, 0x28, 0xa1, 0x53, 0xdd, 0x83, 0xaa, 0x73, 0x52, 0xcd, 0x2f, 0xa3, 0xfe, 0x59, 0xa6, + 0x6b, 0xa4, 0xf6, 0xe3, 0xfe, 0x79, 0x5f, 0xce, 0x75, 0xf8, 0x3c, 0x31, 0x89, 0x5e, 0x81, 0x51, + 0x33, 0x0c, 0x7a, 0x5b, 0x0b, 0xc3, 0x4f, 0x69, 0xa7, 0x24, 0x38, 0x8e, 0xae, 0xeb, 0x70, 0xd6, + 0x77, 0x7c, 0x74, 0x7c, 0x0f, 0x31, 0xb7, 0xd6, 0x76, 0x4c, 0x3e, 0x2e, 0xb5, 0x33, 0x6e, 0xcc, + 0x7d, 0xcc, 0xbd, 0xe5, 0x98, 0xac, 0x02, 0xdd, 0x5b, 0xa3, 0x96, 0x5e, 0xdb, 0xb0, 0x9d, 0x75, + 0x8c, 0xfd, 0xc9, 0x07, 0xa7, 0x76, 0x8a, 0xc3, 0xef, 0xf8, 0x60, 0xf2, 0x18, 0x0c, 0xaf, 0x36, + 0xda, 0x34, 0x88, 0xb6, 0xc8, 0xef, 0xfa, 0xb4, 0x21, 0x06, 0x0c, 0x6e, 0x48, 0x1e, 0x06, 0x40, + 0x22, 0x0f, 0xe3, 0xe8, 0xe3, 0xc5, 0x9e, 0x36, 0xc0, 0x20, 0x4b, 0xa2, 0xbb, 0xce, 0x73, 0xad, + 0xe6, 0x42, 0xaa, 0x35, 0x6c, 0x6b, 0xb5, 0xe6, 0x51, 0xa7, 0x89, 0x0d, 0x45, 0x67, 0x06, 0xed, + 0x2c, 0x52, 0xe0, 0xd5, 0x89, 0x3b, 0x6b, 0x5b, 0xab, 0x4b, 0xd4, 0x69, 0xb2, 0xa6, 0x3e, 0x09, + 0x44, 0x34, 0xd5, 0xc1, 0x43, 0x0f, 0xfe, 0x71, 0xe8, 0xcd, 0xa0, 0x89, 0x8f, 0xe0, 0xa7, 0x21, + 0xf8, 0x61, 0x45, 0x18, 0xe4, 0x21, 0xe7, 0xb8, 0xd0, 0xd0, 0x85, 0x41, 0x03, 0x0e, 0x42, 0x79, + 0x9d, 0x05, 0xe1, 0x5d, 0xc1, 0xbd, 0xba, 0x35, 0xf1, 0x4b, 0xfd, 0x42, 0x2e, 0x2d, 0xb8, 0xfc, + 0x81, 0x14, 0x2d, 0x9c, 0x56, 0xb3, 0x7b, 0x9a, 0x56, 0x4f, 0x59, 0xed, 0x66, 0x4d, 0x6f, 0xb5, + 0x6a, 0x2b, 0x66, 0x03, 0x9f, 0x55, 0xe1, 0xc2, 0xa7, 0x0d, 0x5b, 0xed, 0x66, 0xa9, 0xd5, 0x9a, + 0xe6, 0x40, 0xf2, 0x04, 0x8c, 0x31, 0x3a, 0xec, 0xa4, 0x80, 0x32, 0x8f, 0x94, 0x8c, 0x01, 0xc6, + 0x6c, 0xf5, 0x69, 0x1f, 0x84, 0x7e, 0xc1, 0x93, 0xaf, 0x55, 0xbd, 0x5a, 0x1f, 0x67, 0xe6, 0xb2, + 0x9e, 0x0b, 0xd8, 0xf0, 0xc9, 0xb5, 0x57, 0x1b, 0xf0, 0xcb, 0x63, 0x64, 0x62, 0xab, 0xdd, 0xe4, + 0x11, 0xb1, 0xfa, 0x10, 0x19, 0xfc, 0x26, 0x97, 0x60, 0x84, 0x71, 0x09, 0x04, 0xc6, 0x83, 0xb9, + 0xf6, 0x6a, 0x31, 0x28, 0xb9, 0x06, 0x67, 0x22, 0x10, 0x6e, 0x83, 0xf2, 0x67, 0x02, 0xbd, 0x5a, + 0x2a, 0x4e, 0x7d, 0x27, 0x97, 0x8c, 0x9d, 0x7f, 0x24, 0x6b, 0xe3, 0x0c, 0x80, 0x48, 0x8d, 0x11, + 0x5e, 0xd0, 0x04, 0x5e, 0xcb, 0x21, 0xa6, 0x03, 0x0f, 0xa9, 0x2c, 0xb9, 0x02, 0xfd, 0xfc, 0x8b, + 0x2a, 0x65, 0xb1, 0x66, 0xa2, 0x9b, 0x91, 0xdb, 0x32, 0x57, 0x56, 0xd0, 0x27, 0x29, 0x40, 0x93, + 0x4b, 0xd0, 0x57, 0x9e, 0xaf, 0x56, 0x4b, 0xf3, 0xfe, 0x6d, 0x23, 0xbe, 0x51, 0x30, 0x2c, 0xb7, + 0xe6, 0xea, 0x96, 0xab, 0xf9, 0x48, 0xf2, 0x18, 0x14, 0x2a, 0x8b, 0x48, 0xc6, 0x5f, 0xde, 0x0d, + 0x6e, 0x6f, 0x15, 0xfb, 0xcc, 0x16, 0xa7, 0x12, 0x28, 0xac, 0xf7, 0x76, 0xa5, 0x2c, 0x5d, 0xb9, + 0xf3, 0x7a, 0xef, 0x9a, 0x06, 0x5e, 0x5d, 0x6a, 0x01, 0x9a, 0x3c, 0x0b, 0x43, 0x55, 0xea, 0x98, + 0x7a, 0x63, 0xbe, 0x8d, 0xdb, 0x0d, 0xee, 0x66, 0x34, 0xb6, 0xbd, 0x55, 0x1c, 0x76, 0x11, 0x5e, + 0xb3, 0x10, 0xa1, 0x45, 0xc8, 0xc8, 0x05, 0xc8, 0xcf, 0x98, 0x96, 0xef, 0x06, 0x8f, 0x7e, 0xd2, + 0x6b, 0xa6, 0xe5, 0x69, 0x08, 0x55, 0xff, 0x65, 0x36, 0x3d, 0x7b, 0xc1, 0x11, 0x8c, 0xad, 0x7d, + 0xde, 0x16, 0xc6, 0x94, 0x20, 0x7f, 0x00, 0x25, 0x58, 0x81, 0x53, 0x25, 0xa3, 0x69, 0x5a, 0x25, + 0xfc, 0xe9, 0xce, 0x4d, 0x97, 0x70, 0x40, 0x4a, 0xcf, 0xb0, 0x62, 0x68, 0xf1, 0x3d, 0x3c, 0xdc, + 0x2a, 0x43, 0xd5, 0x74, 0x8e, 0xab, 0x35, 0x57, 0xf4, 0x5a, 0x9d, 0x07, 0xfe, 0xd7, 0xe2, 0x4c, + 0xd5, 0x1f, 0xce, 0xee, 0x90, 0x70, 0xe1, 0x7e, 0x94, 0xbe, 0xfa, 0x95, 0x6c, 0xf7, 0x9c, 0x17, + 0xf7, 0xa5, 0x50, 0xfe, 0x32, 0x9b, 0x92, 0x81, 0xe2, 0x40, 0x92, 0xb8, 0x02, 0xfd, 0x9c, 0x4d, + 0xe0, 0xae, 0x89, 0x33, 0x0e, 0x57, 0x56, 0x9c, 0xe9, 0x7c, 0x34, 0x99, 0x87, 0x33, 0xa5, 0x95, + 0x15, 0x5a, 0xf7, 0xc2, 0xc0, 0xbb, 0xf3, 0x61, 0xb0, 0x4d, 0x1e, 0xad, 0x54, 0xe0, 0xc3, 0xc0, + 0xbd, 0x18, 0x54, 0x22, 0xb5, 0x1c, 0x59, 0x82, 0xb3, 0x71, 0x78, 0x95, 0x9b, 0x7a, 0x79, 0x29, + 0x80, 0x69, 0x82, 0x23, 0xff, 0x4f, 0xeb, 0x50, 0x36, 0xad, 0x95, 0x38, 0x9d, 0xf6, 0x76, 0x6b, + 0x25, 0xce, 0xad, 0xa9, 0xe5, 0xd4, 0xaf, 0xe7, 0xe4, 0x44, 0x1d, 0xf7, 0xaf, 0x63, 0xcd, 0xf5, + 0x88, 0x3b, 0xed, 0x6e, 0x87, 0xcc, 0xb3, 0x22, 0x52, 0x84, 0xd1, 0x76, 0x7c, 0xcf, 0xb3, 0xe0, + 0xa5, 0x3a, 0x02, 0x65, 0x1f, 0xb2, 0x80, 0x92, 0x54, 0x20, 0x5f, 0x72, 0x56, 0xb9, 0x19, 0xb3, + 0xd3, 0xe3, 0x19, 0xdd, 0x59, 0x75, 0xd3, 0x1f, 0xcf, 0x30, 0x16, 0xea, 0x0f, 0x65, 0xbb, 0x24, + 0xf2, 0xb8, 0x2f, 0x27, 0x91, 0x9f, 0xcc, 0x76, 0x4a, 0xc9, 0x71, 0x5c, 0x5d, 0x84, 0xde, 0x65, + 0xe1, 0x1c, 0x6f, 0xff, 0xa9, 0xc3, 0x13, 0xce, 0x13, 0x73, 0x3c, 0xc4, 0xf2, 0x4d, 0xd3, 0x32, + 0xc8, 0x83, 0xf0, 0xc0, 0xad, 0xea, 0x94, 0x56, 0xbb, 0x59, 0x99, 0x2f, 0xd7, 0x6e, 0xcd, 0x57, + 0x17, 0xa7, 0x26, 0x2b, 0xd3, 0x95, 0xa9, 0xf2, 0x68, 0x0f, 0x39, 0x0d, 0xa7, 0x42, 0xd4, 0xcc, + 0xad, 0xb9, 0xd2, 0xfc, 0x68, 0x86, 0x8c, 0xc1, 0x70, 0x08, 0x9c, 0x58, 0x58, 0x1a, 0xcd, 0x3e, + 0xf1, 0x41, 0x18, 0xc4, 0x3d, 0x24, 0xb7, 0x85, 0xc8, 0x10, 0xf4, 0x2f, 0x4c, 0x54, 0xa7, 0xb4, + 0xdb, 0xc8, 0x04, 0xa0, 0x50, 0x9e, 0x9a, 0x67, 0x0c, 0x33, 0x4f, 0xfc, 0x9b, 0x0c, 0x40, 0x75, + 0x7a, 0x69, 0x51, 0x10, 0x0e, 0x42, 0x5f, 0x65, 0xfe, 0x76, 0x69, 0xb6, 0xc2, 0xe8, 0xfa, 0x21, + 0xbf, 0xb0, 0x38, 0xc5, 0x6a, 0x18, 0x80, 0xde, 0xc9, 0xd9, 0x85, 0xea, 0xd4, 0x68, 0x96, 0x01, + 0xb5, 0xa9, 0x52, 0x79, 0x34, 0xc7, 0x80, 0x77, 0xb4, 0xca, 0xd2, 0xd4, 0x68, 0x9e, 0xfd, 0x39, + 0x5b, 0x5d, 0x2a, 0x2d, 0x8d, 0xf6, 0xb2, 0x3f, 0xa7, 0xf1, 0xcf, 0x02, 0x63, 0x56, 0x9d, 0x5a, + 0xc2, 0x1f, 0x7d, 0xac, 0x09, 0xd3, 0xfe, 0xaf, 0x7e, 0x86, 0x62, 0xac, 0xcb, 0x15, 0x6d, 0x74, + 0x80, 0xfd, 0x60, 0x2c, 0xd9, 0x0f, 0x60, 0x8d, 0xd3, 0xa6, 0xe6, 0x16, 0x6e, 0x4f, 0x8d, 0x0e, + 0x32, 0x5e, 0x73, 0x37, 0x19, 0x78, 0x88, 0xfd, 0xa9, 0xcd, 0xb1, 0x3f, 0x87, 0x19, 0x27, 0x6d, + 0xaa, 0x34, 0xbb, 0x58, 0x5a, 0x9a, 0x19, 0x1d, 0x61, 0xed, 0x41, 0x9e, 0xa7, 0x78, 0xc9, 0xf9, + 0xd2, 0xdc, 0xd4, 0xe8, 0xa8, 0xa0, 0x29, 0xcf, 0x56, 0xe6, 0x6f, 0x8e, 0x8e, 0x61, 0x43, 0xde, + 0x98, 0xc3, 0x1f, 0x84, 0x15, 0xc0, 0xbf, 0x4e, 0x3f, 0xf1, 0x29, 0x28, 0x2c, 0x54, 0xd1, 0xe2, + 0x3f, 0x07, 0xa7, 0x17, 0xaa, 0xb5, 0xa5, 0x37, 0x16, 0xa7, 0x62, 0xf2, 0x1e, 0x83, 0x61, 0x1f, + 0x31, 0x5b, 0x99, 0xbf, 0xf5, 0x71, 0x2e, 0x6d, 0x1f, 0x34, 0x57, 0x9a, 0x5c, 0xa8, 0x8e, 0x66, + 0x59, 0xaf, 0xf8, 0xa0, 0x3b, 0x95, 0xf9, 0xf2, 0xc2, 0x9d, 0xea, 0x68, 0xee, 0x89, 0xbb, 0x7e, + 0xee, 0xd7, 0x05, 0xc7, 0x5c, 0x35, 0x2d, 0xf2, 0x30, 0x3c, 0x58, 0x9e, 0xba, 0x5d, 0x99, 0x9c, + 0xaa, 0x2d, 0x68, 0x95, 0x1b, 0x95, 0xf9, 0x58, 0x4d, 0x0f, 0xc0, 0x58, 0x14, 0x5d, 0x5a, 0xac, + 0x8c, 0x66, 0xc8, 0x59, 0x20, 0x51, 0xf0, 0x6b, 0xa5, 0xb9, 0xe9, 0xd1, 0x2c, 0x51, 0xe0, 0x4c, + 0x14, 0x5e, 0x99, 0x5f, 0xba, 0x35, 0x3f, 0x35, 0x9a, 0x7b, 0xe2, 0xe7, 0x32, 0xf0, 0x40, 0x6a, + 0x10, 0x03, 0xa2, 0xc2, 0xc5, 0xa9, 0xd9, 0x52, 0x75, 0xa9, 0x32, 0x59, 0x9d, 0x2a, 0x69, 0x93, + 0x33, 0xb5, 0xc9, 0xd2, 0xd2, 0xd4, 0x8d, 0x05, 0xed, 0x8d, 0xda, 0x8d, 0xa9, 0xf9, 0x29, 0xad, + 0x34, 0x3b, 0xda, 0x43, 0x1e, 0x83, 0x62, 0x07, 0x9a, 0xea, 0xd4, 0xe4, 0x2d, 0xad, 0xb2, 0xf4, + 0xc6, 0x68, 0x86, 0x3c, 0x0a, 0x0f, 0x77, 0x24, 0x62, 0xbf, 0x47, 0xb3, 0xe4, 0x22, 0x9c, 0xef, + 0x44, 0xf2, 0xfa, 0xec, 0x68, 0xee, 0x89, 0x1f, 0xcf, 0x00, 0x49, 0xbe, 0x42, 0x27, 0x8f, 0xc0, + 0x05, 0xa6, 0x17, 0xb5, 0xce, 0x0d, 0x7c, 0x14, 0x1e, 0x4e, 0xa5, 0x90, 0x9a, 0x57, 0x84, 0x87, + 0x3a, 0x90, 0x88, 0xc6, 0x5d, 0x00, 0x25, 0x9d, 0x00, 0x9b, 0xf6, 0x1b, 0x19, 0x78, 0x20, 0x75, + 0xfb, 0x41, 0x2e, 0xc3, 0x07, 0x4a, 0xe5, 0x39, 0xd6, 0x37, 0x93, 0x4b, 0x95, 0x85, 0xf9, 0x6a, + 0x6d, 0x6e, 0xba, 0x54, 0x63, 0xda, 0x77, 0xab, 0x1a, 0xeb, 0xcd, 0x4b, 0xa0, 0x76, 0xa1, 0x9c, + 0x9c, 0x29, 0xcd, 0xdf, 0x60, 0xc3, 0x8f, 0x7c, 0x00, 0x1e, 0xe9, 0x48, 0x37, 0x35, 0x5f, 0x9a, + 0x98, 0x9d, 0x2a, 0x8f, 0x66, 0xc9, 0xe3, 0xf0, 0x68, 0x47, 0xaa, 0x72, 0xa5, 0xca, 0xc9, 0x72, + 0x13, 0xe5, 0x77, 0xfe, 0xd1, 0xc5, 0x9e, 0x77, 0xbe, 0x7d, 0x31, 0xf3, 0x87, 0xdf, 0xbe, 0x98, + 0xf9, 0xf3, 0x6f, 0x5f, 0xcc, 0x7c, 0xe2, 0xda, 0x5e, 0xa2, 0x0b, 0xf0, 0x69, 0x6b, 0xb9, 0x80, + 0xa6, 0xc0, 0x33, 0xff, 0x21, 0x00, 0x00, 0xff, 0xff, 0x35, 0x75, 0x3c, 0xb8, 0xbb, 0x53, 0x01, + 0x00, } func (m *Metadata) Marshal() (dAtA []byte, err error) { @@ -28184,6 +28249,29 @@ func (m *OneOf_DiscoveryConfigDeleteAll) MarshalToSizedBuffer(dAtA []byte) (int, } return len(dAtA) - i, nil } +func (m *OneOf_AccessGraphSettingsUpdate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *OneOf_AccessGraphSettingsUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + if m.AccessGraphSettingsUpdate != nil { + { + size, err := m.AccessGraphSettingsUpdate.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + i-- + dAtA[i] = 0xa2 + } + return len(dAtA) - i, nil +} func (m *OneOf_IntegrationCreate) MarshalTo(dAtA []byte) (int, error) { size := m.Size() return m.MarshalToSizedBuffer(dAtA[:size]) @@ -28323,12 +28411,12 @@ func (m *StreamStatus) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - n602, err602 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastUploadTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastUploadTime):]) - if err602 != nil { - return 0, err602 + n603, err603 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.LastUploadTime, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.LastUploadTime):]) + if err603 != nil { + return 0, err603 } - i -= n602 - i = encodeVarintEvents(dAtA, i, uint64(n602)) + i -= n603 + i = encodeVarintEvents(dAtA, i, uint64(n603)) i-- dAtA[i] = 0x1a if m.LastEventIndex != 0 { @@ -28478,12 +28566,12 @@ func (m *Identity) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0xc2 } } - n606, err606 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.PreviousIdentityExpires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.PreviousIdentityExpires):]) - if err606 != nil { - return 0, err606 + n607, err607 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.PreviousIdentityExpires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.PreviousIdentityExpires):]) + if err607 != nil { + return 0, err607 } - i -= n606 - i = encodeVarintEvents(dAtA, i, uint64(n606)) + i -= n607 + i = encodeVarintEvents(dAtA, i, uint64(n607)) i-- dAtA[i] = 0x1 i-- @@ -28631,12 +28719,12 @@ func (m *Identity) MarshalToSizedBuffer(dAtA []byte) (int, error) { i-- dAtA[i] = 0x4a } - n610, err610 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) - if err610 != nil { - return 0, err610 + n611, err611 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Expires, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Expires):]) + if err611 != nil { + return 0, err611 } - i -= n610 - i = encodeVarintEvents(dAtA, i, uint64(n610)) + i -= n611 + i = encodeVarintEvents(dAtA, i, uint64(n611)) i-- dAtA[i] = 0x42 if len(m.KubernetesUsers) > 0 { @@ -33682,6 +33770,73 @@ func (m *SpannerRPC) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *AccessGraphSettingsUpdate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *AccessGraphSettingsUpdate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *AccessGraphSettingsUpdate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + { + size, err := m.ConnectionMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size, err := m.UserMetadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Status.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + { + size, err := m.Metadata.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintEvents(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + func (m *SPIFFEFederationCreate) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -39410,6 +39565,18 @@ func (m *OneOf_DiscoveryConfigDeleteAll) Size() (n int) { } return n } +func (m *OneOf_AccessGraphSettingsUpdate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.AccessGraphSettingsUpdate != nil { + l = m.AccessGraphSettingsUpdate.Size() + n += 2 + l + sovEvents(uint64(l)) + } + return n +} func (m *OneOf_IntegrationCreate) Size() (n int) { if m == nil { return 0 @@ -41453,6 +41620,26 @@ func (m *SpannerRPC) Size() (n int) { return n } +func (m *AccessGraphSettingsUpdate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Metadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.Status.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.UserMetadata.Size() + n += 1 + l + sovEvents(uint64(l)) + l = m.ConnectionMetadata.Size() + n += 1 + l + sovEvents(uint64(l)) + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *SPIFFEFederationCreate) Size() (n int) { if m == nil { return 0 @@ -77305,6 +77492,41 @@ func (m *OneOf) Unmarshal(dAtA []byte) error { } m.Event = &OneOf_DiscoveryConfigDeleteAll{v} iNdEx = postIndex + case 164: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AccessGraphSettingsUpdate", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + v := &AccessGraphSettingsUpdate{} + if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Event = &OneOf_AccessGraphSettingsUpdate{v} + iNdEx = postIndex case 165: if wireType != 2 { return fmt.Errorf("proto: wrong wireType = %d for field IntegrationCreate", wireType) @@ -93492,6 +93714,189 @@ func (m *SpannerRPC) Unmarshal(dAtA []byte) error { } return nil } +func (m *AccessGraphSettingsUpdate) 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 ErrIntOverflowEvents + } + 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: AccessGraphSettingsUpdate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: AccessGraphSettingsUpdate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Metadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UserMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UserMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ConnectionMetadata", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ConnectionMetadata.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *SPIFFEFederationCreate) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/api/types/events/oneof.go b/api/types/events/oneof.go index dd1ef0e55c0e4..c805f62fe10b5 100644 --- a/api/types/events/oneof.go +++ b/api/types/events/oneof.go @@ -647,6 +647,10 @@ func ToOneOf(in AuditEvent) (*OneOf, error) { out.Event = &OneOf_SessionRecordingConfigUpdate{ SessionRecordingConfigUpdate: e, } + case *AccessGraphSettingsUpdate: + out.Event = &OneOf_AccessGraphSettingsUpdate{ + AccessGraphSettingsUpdate: e, + } case *DatabaseUserCreate: out.Event = &OneOf_DatabaseUserCreate{ DatabaseUserCreate: e, diff --git a/api/types/header/convert/legacy/header.go b/api/types/header/convert/legacy/header.go index c9e82a5dd7ade..3f989c4a9cc33 100644 --- a/api/types/header/convert/legacy/header.go +++ b/api/types/header/convert/legacy/header.go @@ -17,6 +17,8 @@ limitations under the License. package legacy import ( + "time" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/header" ) @@ -33,3 +35,19 @@ func FromHeaderMetadata(metadata header.Metadata) types.Metadata { Revision: metadata.Revision, } } + +// ToHeaderMetadata will convert a types.Metadata object to this metadata object. +// TODO: Remove this once we get rid of the old Metadata object. +func ToHeaderMetadata(metadata types.Metadata) header.Metadata { + var expires time.Time + if metadata.Expires != nil { + expires = *metadata.Expires + } + return header.Metadata{ + Name: metadata.Name, + Expires: expires, + Description: metadata.Description, + Labels: metadata.Labels, + Revision: metadata.Revision, + } +} diff --git a/buf.yaml b/buf.yaml index a60eb8d931282..0b2f078c9bd53 100644 --- a/buf.yaml +++ b/buf.yaml @@ -69,6 +69,7 @@ lint: - api/proto/teleport/devicetrust/v1/devicetrust_service.proto - api/proto/teleport/legacy/client/proto/joinservice.proto - api/proto/teleport/transport/v1/transport_service.proto + - api/proto/teleport/access_graph/v1/secrets_service.proto - proto/accessgraph/v1alpha/access_graph_service.proto - proto/teleport/lib/teleterm/v1/service.proto disallow_comment_ignores: true diff --git a/gen/proto/go/accessgraph/v1alpha/resources.pb.go b/gen/proto/go/accessgraph/v1alpha/resources.pb.go index 7167142666dad..d901be034b673 100644 --- a/gen/proto/go/accessgraph/v1alpha/resources.pb.go +++ b/gen/proto/go/accessgraph/v1alpha/resources.pb.go @@ -24,8 +24,10 @@ package accessgraphv1alpha import ( + v13 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1" v11 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" + v12 "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" types "github.com/gravitational/teleport/api/types" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -307,6 +309,9 @@ type ResourceEntry struct { // *ResourceEntry_WindowsDesktop // *ResourceEntry_AccessList // *ResourceEntry_CrownJewel + // *ResourceEntry_Device + // *ResourceEntry_PrivateKey + // *ResourceEntry_AuthorizedKey Resource isResourceEntry_Resource `protobuf_oneof:"resource"` } @@ -419,6 +424,27 @@ func (x *ResourceEntry) GetCrownJewel() *v11.CrownJewel { return nil } +func (x *ResourceEntry) GetDevice() *v12.Device { + if x, ok := x.GetResource().(*ResourceEntry_Device); ok { + return x.Device + } + return nil +} + +func (x *ResourceEntry) GetPrivateKey() *v13.PrivateKey { + if x, ok := x.GetResource().(*ResourceEntry_PrivateKey); ok { + return x.PrivateKey + } + return nil +} + +func (x *ResourceEntry) GetAuthorizedKey() *v13.AuthorizedKey { + if x, ok := x.GetResource().(*ResourceEntry_AuthorizedKey); ok { + return x.AuthorizedKey + } + return nil +} + type isResourceEntry_Resource interface { isResourceEntry_Resource() } @@ -473,6 +499,21 @@ type ResourceEntry_CrownJewel struct { CrownJewel *v11.CrownJewel `protobuf:"bytes,10,opt,name=crown_jewel,json=crownJewel,proto3,oneof"` } +type ResourceEntry_Device struct { + // device is a device trust resource. + Device *v12.Device `protobuf:"bytes,12,opt,name=device,proto3,oneof"` +} + +type ResourceEntry_PrivateKey struct { + // private_key represents a private key resource found in user's laptops. + PrivateKey *v13.PrivateKey `protobuf:"bytes,13,opt,name=private_key,json=privateKey,proto3,oneof"` +} + +type ResourceEntry_AuthorizedKey struct { + // authorized_key represents a authorized key for a server. + AuthorizedKey *v13.AuthorizedKey `protobuf:"bytes,14,opt,name=authorized_key,json=authorizedKey,proto3,oneof"` +} + func (*ResourceEntry_User) isResourceEntry_Resource() {} func (*ResourceEntry_Role) isResourceEntry_Resource() {} @@ -493,92 +534,119 @@ func (*ResourceEntry_AccessList) isResourceEntry_Resource() {} func (*ResourceEntry_CrownJewel) isResourceEntry_Resource() {} +func (*ResourceEntry_Device) isResourceEntry_Resource() {} + +func (*ResourceEntry_PrivateKey) isResourceEntry_Resource() {} + +func (*ResourceEntry_AuthorizedKey) isResourceEntry_Resource() {} + var File_accessgraph_v1alpha_resources_proto protoreflect.FileDescriptor var file_accessgraph_v1alpha_resources_proto_rawDesc = []byte{ 0x0a, 0x23, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, - 0x70, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2f, - 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x72, - 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x6f, 0x77, - 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x50, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x40, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x22, 0x49, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4e, 0x0a, 0x12, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x12, 0x38, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x63, 0x0a, 0x19, - 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x73, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x73, 0x22, 0x56, 0x0a, 0x17, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xe6, 0x04, 0x0a, 0x0d, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x12, 0x23, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, 0x52, - 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x33, - 0x48, 0x00, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x48, 0x0a, 0x11, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x10, 0x6b, 0x75, 0x62, 0x65, 0x72, - 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, 0x61, - 0x70, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x09, 0x61, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x12, 0x42, 0x0a, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x5f, - 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, - 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, - 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, - 0x45, 0x0a, 0x0b, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x5f, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x72, 0x6f, 0x77, - 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, - 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, - 0x72, 0x61, 0x70, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x70, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x1a, 0x2d, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, + 0x6b, 0x65, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, + 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, + 0x77, 0x65, 0x6c, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, + 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x24, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, + 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x50, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x40, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x22, 0x49, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x4e, 0x0a, + 0x12, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x22, 0x63, 0x0a, + 0x19, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x73, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x22, 0x56, 0x0a, 0x17, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1f, 0x0a, + 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xbc, 0x06, 0x0a, 0x0d, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x12, 0x23, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, + 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, + 0x33, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x48, 0x0a, 0x11, 0x6b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x10, 0x6b, 0x75, 0x62, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x0a, + 0x61, 0x70, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x09, 0x61, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, + 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, + 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x77, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x45, 0x0a, 0x0b, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x45, 0x0a, 0x0b, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x5f, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x72, 0x6f, + 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x12, 0x39, 0x0a, 0x06, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x48, 0x00, 0x52, 0x06, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0b, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, + 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x50, 0x0a, 0x0e, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x0d, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x57, 0x5a, 0x55, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, + 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x67, 0x72, 0x61, 0x70, 0x68, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -613,6 +681,9 @@ var file_accessgraph_v1alpha_resources_proto_goTypes = []interface{}{ (*types.WindowsDesktopV3)(nil), // 15: types.WindowsDesktopV3 (*v1.AccessList)(nil), // 16: teleport.accesslist.v1.AccessList (*v11.CrownJewel)(nil), // 17: teleport.crownjewel.v1.CrownJewel + (*v12.Device)(nil), // 18: teleport.devicetrust.v1.Device + (*v13.PrivateKey)(nil), // 19: teleport.access_graph.v1.PrivateKey + (*v13.AuthorizedKey)(nil), // 20: teleport.access_graph.v1.AuthorizedKey } var file_accessgraph_v1alpha_resources_proto_depIdxs = []int32{ 5, // 0: accessgraph.v1alpha.ResourceList.resources:type_name -> accessgraph.v1alpha.ResourceEntry @@ -629,11 +700,14 @@ var file_accessgraph_v1alpha_resources_proto_depIdxs = []int32{ 15, // 11: accessgraph.v1alpha.ResourceEntry.windows_desktop:type_name -> types.WindowsDesktopV3 16, // 12: accessgraph.v1alpha.ResourceEntry.access_list:type_name -> teleport.accesslist.v1.AccessList 17, // 13: accessgraph.v1alpha.ResourceEntry.crown_jewel:type_name -> teleport.crownjewel.v1.CrownJewel - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 18, // 14: accessgraph.v1alpha.ResourceEntry.device:type_name -> teleport.devicetrust.v1.Device + 19, // 15: accessgraph.v1alpha.ResourceEntry.private_key:type_name -> teleport.access_graph.v1.PrivateKey + 20, // 16: accessgraph.v1alpha.ResourceEntry.authorized_key:type_name -> teleport.access_graph.v1.AuthorizedKey + 17, // [17:17] is the sub-list for method output_type + 17, // [17:17] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_accessgraph_v1alpha_resources_proto_init() } @@ -726,6 +800,9 @@ func file_accessgraph_v1alpha_resources_proto_init() { (*ResourceEntry_WindowsDesktop)(nil), (*ResourceEntry_AccessList)(nil), (*ResourceEntry_CrownJewel)(nil), + (*ResourceEntry_Device)(nil), + (*ResourceEntry_PrivateKey)(nil), + (*ResourceEntry_AuthorizedKey)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/go.mod b/go.mod index 382797d99eea4..fde2cb0875ad0 100644 --- a/go.mod +++ b/go.mod @@ -234,6 +234,8 @@ require ( // Updating causes breaking changes. require github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect +require github.com/fsnotify/fsnotify v1.7.0 + require ( cloud.google.com/go v0.112.2 // indirect cloud.google.com/go/auth v0.3.0 // indirect @@ -318,7 +320,6 @@ require ( github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 4d19e289b4ff9..1fdb585b23933 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -88,6 +88,7 @@ import ( "github.com/gravitational/teleport/lib/circleci" "github.com/gravitational/teleport/lib/cloud" "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/devicetrust/assertserver" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/gcp" "github.com/gravitational/teleport/lib/githubactions" @@ -618,6 +619,8 @@ type Services struct { services.KubeWaitingContainer services.AccessMonitoringRules services.CrownJewels + services.AccessGraphSecretsGetter + services.DevicesGetter } // GetWebSession returns existing web session described by req. @@ -772,6 +775,10 @@ var ( // successfully authenticated. An example would be creating objects based on the user. type LoginHook func(context.Context, types.User) error +// CreateDeviceAssertionFunc creates a new device assertion ceremony to authenticate +// a trusted device. +type CreateDeviceAssertionFunc func() (assertserver.Ceremony, error) + // ReadOnlyCache is a type alias used to assist with embedding [readonly.Cache] in places // where it would have a naming conflict with other types named Cache. type ReadOnlyCache = readonly.Cache @@ -950,6 +957,15 @@ type Server struct { // ulsGenerator is the user login state generator. ulsGenerator *userloginstate.Generator + // deviceAssertionServer holds the server-side implementation of device assertions. + // + // It is used to authenticate devices previously enrolled in the cluster. The goal + // is to provide an API for devices to authenticate with the cluster without the need + // for valid user credentials, e.g. when running `tsh scan keys`. + // + // The value is nil on OSS clusters. + deviceAssertionServer CreateDeviceAssertionFunc + // bcryptCostOverride overrides the bcrypt cost for operations executed // directly by [Server]. // Used for testing. @@ -1098,6 +1114,26 @@ func (a *Server) SetHeadlessAuthenticationWatcher(headlessAuthenticationWatcher a.headlessAuthenticationWatcher = headlessAuthenticationWatcher } +// SetDeviceAssertionServer sets the device assertion implementation. +func (a *Server) SetDeviceAssertionServer(f CreateDeviceAssertionFunc) { + a.lock.Lock() + a.deviceAssertionServer = f + a.lock.Unlock() +} + +// GetDeviceAssertionServer returns the device assertion implementation. +// On OSS clusters, this will return a non nil function that returns an error. +func (a *Server) GetDeviceAssertionServer() CreateDeviceAssertionFunc { + a.lock.RLock() + defer a.lock.RUnlock() + if a.deviceAssertionServer == nil { + return func() (assertserver.Ceremony, error) { + return nil, trace.NotImplemented("device assertions are not supported on OSS clusters") + } + } + return a.deviceAssertionServer +} + func (a *Server) bcryptCost() int { if cost := a.bcryptCostOverride; cost != nil { return *cost @@ -1698,6 +1734,16 @@ func (a *Server) SetSCIMService(scim services.SCIM) { a.Services.SCIM = scim } +// SetAccessGraphSecretService sets the server's access graph secret service +func (a *Server) SetAccessGraphSecretService(s services.AccessGraphSecretsGetter) { + a.Services.AccessGraphSecretsGetter = s +} + +// SetDevicesGetter sets the server's device service +func (a *Server) SetDevicesGetter(s services.DevicesGetter) { + a.Services.DevicesGetter = s +} + // SetAuditLog sets the server's audit log func (a *Server) SetAuditLog(auditLog events.AuditLogSessionStreamer) { a.Services.AuditLogSessionStreamer = auditLog diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index d3d9a0aad6200..37b7d5af11b7f 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -28,6 +28,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" accessmonitoringrules "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" @@ -1169,6 +1170,9 @@ type Cache interface { GetAccessMonitoringRule(ctx context.Context, name string) (*accessmonitoringrules.AccessMonitoringRule, error) // ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules. ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrules.AccessMonitoringRule, string, error) + + // GetAccessGraphSettings returns the access graph settings. + GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) } type NodeWrapper struct { diff --git a/lib/auth/authclient/clt.go b/lib/auth/authclient/clt.go index fd0d6ba856139..19aa718b187fc 100644 --- a/lib/auth/authclient/clt.go +++ b/lib/auth/authclient/clt.go @@ -41,6 +41,7 @@ import ( "github.com/gravitational/teleport/api/client/secreport" apidefaults "github.com/gravitational/teleport/api/defaults" assistpb "github.com/gravitational/teleport/api/gen/proto/go/assist/v1" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1" @@ -545,6 +546,10 @@ func (c *Client) AccessGraphClient() accessgraphv1.AccessGraphServiceClient { return accessgraphv1.NewAccessGraphServiceClient(c.APIClient.GetConnection()) } +func (c *Client) AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient { + return accessgraphsecretsv1pb.NewSecretsScannerServiceClient(c.APIClient.GetConnection()) +} + func (c *Client) IntegrationAWSOIDCClient() integrationv1.AWSOIDCServiceClient { return integrationv1.NewAWSOIDCServiceClient(c.APIClient.GetConnection()) } @@ -698,6 +703,31 @@ func (r *CreateUserTokenRequest) CheckAndSetDefaults() error { return nil } +// GetAccessGraphSettings gets the access graph settings from the backend. +func (c *Client) GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + +// CreateAccessGraphSettings creates the access graph settings in the backend. +func (c *Client) CreateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + +// UpdateAccessGraphSettings updates the access graph settings in the backend. +func (c *Client) UpdateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + +// UpsertAccessGraphSettings creates or updates the access graph settings in the backend. +func (c *Client) UpsertAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + return nil, trace.NotImplemented(notImplementedMessage) +} + +// DeleteAccessGraphSettings deletes the access graph settings from the backend. +func (c *Client) DeleteAccessGraphSettings(context.Context) error { + return trace.NotImplemented(notImplementedMessage) +} + type WebSessionReq struct { // User is the user name associated with the session id. User string `json:"user"` @@ -1390,6 +1420,8 @@ type ClientI interface { // AccessGraphClient returns a client to the Access Graph gRPC service. AccessGraphClient() accessgraphv1.AccessGraphServiceClient + AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient + // IntegrationAWSOIDCClient returns a client to the Integration AWS OIDC gRPC service. IntegrationAWSOIDCClient() integrationv1.AWSOIDCServiceClient diff --git a/lib/auth/clusterconfig/clusterconfigv1/service.go b/lib/auth/clusterconfig/clusterconfigv1/service.go index d990155b4eb83..8edecb8757bea 100644 --- a/lib/auth/clusterconfig/clusterconfigv1/service.go +++ b/lib/auth/clusterconfig/clusterconfigv1/service.go @@ -25,6 +25,7 @@ import ( "github.com/gravitational/teleport/api/constants" clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/clusterconfig" apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/lib/authz" dtconfig "github.com/gravitational/teleport/lib/devicetrust/config" @@ -38,6 +39,7 @@ type Cache interface { GetAuthPreference(context.Context) (types.AuthPreference, error) GetClusterNetworkingConfig(ctx context.Context) (types.ClusterNetworkingConfig, error) GetSessionRecordingConfig(ctx context.Context) (types.SessionRecordingConfig, error) + GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) } // ReadOnlyCache abstracts over the required methods of [readonly.Cache]. @@ -45,6 +47,7 @@ type ReadOnlyCache interface { GetReadOnlyAuthPreference(context.Context) (readonly.AuthPreference, error) GetReadOnlyClusterNetworkingConfig(ctx context.Context) (readonly.ClusterNetworkingConfig, error) GetReadOnlySessionRecordingConfig(ctx context.Context) (readonly.SessionRecordingConfig, error) + GetReadOnlyAccessGraphSettings(context.Context) (readonly.AccessGraphSettings, error) } // Backend is used by the [Service] to mutate cluster config resources. @@ -60,6 +63,10 @@ type Backend interface { CreateSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error) UpdateSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error) UpsertSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error) + + CreateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) + UpdateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) + UpsertAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) } // ServiceConfig contain dependencies required to create a [Service]. @@ -930,12 +937,214 @@ func (s *Service) GetClusterAccessGraphConfig(ctx context.Context, _ *clustercon }, nil } + var sshScanEnabled bool + switch obj, err := s.readOnlyCache.GetReadOnlyAccessGraphSettings(ctx); { + case err != nil && !trace.IsNotFound(err): + return nil, trace.Wrap(err) + case err == nil: + sshScanEnabled = obj.SecretsScanConfig() == clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED + } + return &clusterconfigpb.GetClusterAccessGraphConfigResponse{ AccessGraph: &clusterconfigpb.AccessGraphConfig{ Enabled: s.accessGraph.Enabled, Address: s.accessGraph.Address, Ca: s.accessGraph.CA, Insecure: s.accessGraph.Insecure, + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{ + SshScanEnabled: sshScanEnabled, + }, }, }, nil } + +func (s *Service) GetAccessGraphSettings(ctx context.Context, _ *clusterconfigpb.GetAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) { + authzCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbRead); err != nil { + return nil, trace.Wrap(err) + } + + cfg, err := s.readOnlyCache.GetReadOnlyAccessGraphSettings(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + return cfg.Clone(), nil +} + +func (s *Service) CreateAccessGraphSettings(ctx context.Context, req *clusterconfigpb.CreateAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) { + authzCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbCreate); err != nil { + return nil, trace.Wrap(err) + } + + if !authz.HasBuiltinRole(*authzCtx, string(types.RoleAuth)) { + return nil, trace.AccessDenied("this request can be only executed by an auth server") + } + + cfg := req.GetAccessGraphSettings() + if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil { + return nil, trace.Wrap(err) + } + + created, err := s.backend.CreateAccessGraphSettings(ctx, cfg) + if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{ + Metadata: apievents.Metadata{ + Type: events.AccessGraphSettingsUpdateEvent, + Code: events.AccessGraphSettingsUpdateCode, + }, + UserMetadata: authzCtx.GetUserMetadata(), + ConnectionMetadata: authz.ConnectionMetadata(ctx), + Status: eventStatus(err), + }); auditErr != nil { + slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr) + } + + // don't handle the update error until after we emit an audit event + if err != nil { + return nil, trace.Wrap(err) + } + + return created, nil +} + +func (s *Service) UpdateAccessGraphSettings(ctx context.Context, req *clusterconfigpb.UpdateAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) { + authzCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if !modules.GetModules().Features().Policy.Enabled && !modules.GetModules().Features().AccessGraph { + return nil, trace.AccessDenied("access graph is feature isn't enabled") + } + + cfg := req.GetAccessGraphSettings() + if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.backend.UpdateAccessGraphSettings(ctx, cfg) + + if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{ + Metadata: apievents.Metadata{ + Type: events.AccessGraphSettingsUpdateEvent, + Code: events.AccessGraphSettingsUpdateCode, + }, + UserMetadata: authzCtx.GetUserMetadata(), + ConnectionMetadata: authz.ConnectionMetadata(ctx), + Status: eventStatus(err), + }); auditErr != nil { + slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr) + } + + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil +} + +func (s *Service) UpsertAccessGraphSettings(ctx context.Context, req *clusterconfigpb.UpsertAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) { + authzCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbCreate, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if !modules.GetModules().Features().Policy.Enabled && !modules.GetModules().Features().AccessGraph { + return nil, trace.AccessDenied("access graph is feature isn't enabled") + } + + cfg := req.GetAccessGraphSettings() + if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.backend.UpsertAccessGraphSettings(ctx, cfg) + + if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{ + Metadata: apievents.Metadata{ + Type: events.AccessGraphSettingsUpdateEvent, + Code: events.AccessGraphSettingsUpdateCode, + }, + UserMetadata: authzCtx.GetUserMetadata(), + ConnectionMetadata: authz.ConnectionMetadata(ctx), + Status: eventStatus(err), + }); auditErr != nil { + slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr) + } + + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil +} + +func (s *Service) ResetAccessGraphSettings(ctx context.Context, _ *clusterconfigpb.ResetAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) { + authzCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + + if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if !modules.GetModules().Features().Policy.Enabled && !modules.GetModules().Features().AccessGraph { + return nil, trace.AccessDenied("access graph is feature isn't enabled") + } + + obj, err := clusterconfig.NewAccessGraphSettings(&clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }) + if err != nil { + return nil, trace.Wrap(err) + } + rsp, err := s.backend.UpsertAccessGraphSettings(ctx, obj) + + if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{ + Metadata: apievents.Metadata{ + Type: events.AccessGraphSettingsUpdateEvent, + Code: events.AccessGraphSettingsUpdateCode, + }, + UserMetadata: authzCtx.GetUserMetadata(), + ConnectionMetadata: authz.ConnectionMetadata(ctx), + Status: eventStatus(err), + }); auditErr != nil { + slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr) + } + + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil +} diff --git a/lib/auth/clusterconfig/clusterconfigv1/service_test.go b/lib/auth/clusterconfig/clusterconfigv1/service_test.go index 7bda35fabc733..b3ac67e1cc342 100644 --- a/lib/auth/clusterconfig/clusterconfigv1/service_test.go +++ b/lib/auth/clusterconfig/clusterconfigv1/service_test.go @@ -32,6 +32,7 @@ import ( "github.com/gravitational/teleport/api/constants" clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/clusterconfig" apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/lib/auth/clusterconfig/clusterconfigv1" "github.com/gravitational/teleport/lib/authz" @@ -77,7 +78,7 @@ func TestCreateAuthPreference(t *testing.T) { return authRoleContext, nil }), assertion: func(t *testing.T, created types.AuthPreference, err error) { - require.NoError(t, err, "got (%v), expected auth role to create auth preference", err) + require.NoError(t, err, "got (%v), expected auth role to create auth mutator", err) require.NotNil(t, created) }, }, @@ -106,7 +107,7 @@ func TestCreateAuthPreference(t *testing.T) { pp.Spec.RequireMFAType = types.RequireMFAType_HARDWARE_KEY_PIN }, assertion: func(t *testing.T, created types.AuthPreference, err error) { - require.NoError(t, err, "got (%v), expected auth role to create auth preference", err) + require.NoError(t, err, "got (%v), expected auth role to create auth mutator", err) require.NotNil(t, created) }, }, @@ -1673,13 +1674,14 @@ func (f fakeChecker) CheckAccessToRule(context services.RuleContext, namespace s } type envConfig struct { - authorizer authz.Authorizer - emitter apievents.Emitter - defaultAuthPreference types.AuthPreference - defaultNetworkingConfig types.ClusterNetworkingConfig - defaultRecordingConfig types.SessionRecordingConfig - service services.ClusterConfiguration - accessGraphConfig clusterconfigv1.AccessGraphConfig + authorizer authz.Authorizer + emitter apievents.Emitter + defaultAuthPreference types.AuthPreference + defaultNetworkingConfig types.ClusterNetworkingConfig + defaultRecordingConfig types.SessionRecordingConfig + service services.ClusterConfiguration + accessGraphConfig clusterconfigv1.AccessGraphConfig + defaultAccessGraphSettings *clusterconfigpb.AccessGraphSettings } type serviceOpt = func(config *envConfig) @@ -1719,12 +1721,19 @@ func withAccessGraphConfig(cfg clusterconfigv1.AccessGraphConfig) serviceOpt { } } +func withAccessGraphSettings(cfg *clusterconfigpb.AccessGraphSettings) serviceOpt { + return func(config *envConfig) { + config.defaultAccessGraphSettings = cfg + } +} + type env struct { *clusterconfigv1.Service - emitter *eventstest.ChannelEmitter - defaultPreference types.AuthPreference - defaultNetworkingConfig types.ClusterNetworkingConfig - defaultRecordingConfig types.SessionRecordingConfig + emitter *eventstest.ChannelEmitter + defaultPreference types.AuthPreference + defaultNetworkingConfig types.ClusterNetworkingConfig + defaultRecordingConfig types.SessionRecordingConfig + defaultAccessGraphSettings *clusterconfigpb.AccessGraphSettings } func newTestEnv(opts ...serviceOpt) (*env, error) { @@ -1763,7 +1772,7 @@ func newTestEnv(opts ...serviceOpt) (*env, error) { if cfg.defaultAuthPreference != nil { defaultPreference, err = cfg.service.CreateAuthPreference(ctx, cfg.defaultAuthPreference) if err != nil { - return nil, trace.Wrap(err, "creating default auth preference") + return nil, trace.Wrap(err, "creating default auth mutator") } } @@ -1783,16 +1792,33 @@ func newTestEnv(opts ...serviceOpt) (*env, error) { } } + var defaultAccessGraphSettings *clusterconfigpb.AccessGraphSettings + if cfg.defaultAccessGraphSettings != nil { + defaultAccessGraphSettings, err = cfg.service.CreateAccessGraphSettings(ctx, cfg.defaultAccessGraphSettings) + if err != nil { + return nil, trace.Wrap(err, "creating access graph settings") + } + } + return &env{ - Service: svc, - defaultPreference: defaultPreference, - defaultNetworkingConfig: defaultNetworkingConfig, - defaultRecordingConfig: defaultSessionRecordingConfig, - emitter: emitter, + Service: svc, + defaultPreference: defaultPreference, + defaultNetworkingConfig: defaultNetworkingConfig, + defaultRecordingConfig: defaultSessionRecordingConfig, + defaultAccessGraphSettings: defaultAccessGraphSettings, + emitter: emitter, }, nil } func TestGetAccessGraphConfig(t *testing.T) { + + settings, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + ) + require.NoError(t, err) + cfgEnabled := clusterconfigv1.AccessGraphConfig{ Enabled: true, Address: "address", @@ -1800,12 +1826,13 @@ func TestGetAccessGraphConfig(t *testing.T) { Insecure: true, } cases := []struct { - name string - accessGraphConfig clusterconfigv1.AccessGraphConfig - role types.SystemRole - testSetup func(*testing.T) - errorAssertion require.ErrorAssertionFunc - responseAssertion *clusterconfigpb.GetClusterAccessGraphConfigResponse + name string + accessGraphConfig clusterconfigv1.AccessGraphConfig + role types.SystemRole + testSetup func(*testing.T) + errorAssertion require.ErrorAssertionFunc + responseAssertion *clusterconfigpb.GetClusterAccessGraphConfigResponse + accessGraphSettings *clusterconfigpb.AccessGraphSettings }{ { name: "authorized proxy with non empty access graph config; Policy module is disabled", @@ -1836,10 +1863,11 @@ func TestGetAccessGraphConfig(t *testing.T) { errorAssertion: require.NoError, responseAssertion: &clusterconfigpb.GetClusterAccessGraphConfigResponse{ AccessGraph: &clusterconfigpb.AccessGraphConfig{ - Enabled: true, - Insecure: true, - Address: "address", - Ca: []byte("ca"), + Enabled: true, + Insecure: true, + Address: "address", + Ca: []byte("ca"), + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{}, }, }, }, @@ -1858,12 +1886,41 @@ func TestGetAccessGraphConfig(t *testing.T) { }, accessGraphConfig: cfgEnabled, errorAssertion: require.NoError, + responseAssertion: &clusterconfigpb.GetClusterAccessGraphConfigResponse{ + AccessGraph: &clusterconfigpb.AccessGraphConfig{ + Enabled: true, + Insecure: true, + Address: "address", + Ca: []byte("ca"), + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{}, + }, + }, + }, + { + name: "Policy module is enabled with secrets scan option", + role: types.RoleDiscovery, + testSetup: func(t *testing.T) { + m := modules.TestModules{ + TestFeatures: modules.Features{ + Policy: modules.PolicyFeature{ + Enabled: true, + }, + }, + } + modules.SetTestModules(t, &m) + }, + accessGraphConfig: cfgEnabled, + accessGraphSettings: settings, + errorAssertion: require.NoError, responseAssertion: &clusterconfigpb.GetClusterAccessGraphConfigResponse{ AccessGraph: &clusterconfigpb.AccessGraphConfig{ Enabled: true, Insecure: true, Address: "address", Ca: []byte("ca"), + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{ + SshScanEnabled: true, + }, }, }, }, @@ -1881,7 +1938,8 @@ func TestGetAccessGraphConfig(t *testing.T) { authorizer := authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { return authRoleContext, nil }) - env, err := newTestEnv(withAuthorizer(authorizer), withAccessGraphConfig(test.accessGraphConfig)) + + env, err := newTestEnv(withAuthorizer(authorizer), withAccessGraphConfig(test.accessGraphConfig), withAccessGraphSettings(test.accessGraphSettings)) require.NoError(t, err, "creating test service") got, err := env.GetClusterAccessGraphConfig(context.Background(), &clusterconfigpb.GetClusterAccessGraphConfigRequest{}) @@ -1891,3 +1949,379 @@ func TestGetAccessGraphConfig(t *testing.T) { }) } } + +func TestGetAccessGraphSettings(t *testing.T) { + cases := []struct { + name string + authorizer authz.Authorizer + assertion func(t *testing.T, err error) + }{ + { + name: "unauthorized", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{}, + }, nil + }), + assertion: func(t *testing.T, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected unauthorized user to be prevented from getting access graph settings", err) + }, + }, { + name: "authorized", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbRead}}, + }, + }, nil + }), + assertion: func(t *testing.T, err error) { + require.NoError(t, err) + }, + }, + } + + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + settings, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + ) + require.NoError(t, err) + env, err := newTestEnv(withAuthorizer(test.authorizer), withAccessGraphSettings(settings)) + require.NoError(t, err, "creating test service") + + got, err := env.GetAccessGraphSettings(context.Background(), &clusterconfigpb.GetAccessGraphSettingsRequest{}) + test.assertion(t, err) + if err == nil { + require.Empty(t, cmp.Diff(settings, got, cmpopts.IgnoreFields(types.Metadata{}, "Revision"), protocmp.Transform())) + } + }) + } +} + +func TestUpdateAccessGraphSettings(t *testing.T) { + cases := []struct { + name string + mutator func(p *clusterconfigpb.AccessGraphSettings) + authorizer authz.Authorizer + testSetup func(*testing.T) + assertion func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) + }{ + { + name: "unauthorized", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{}, + }, nil + }), + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected unauthorized user to prevent updating access graph settings", err) + }, + }, + { + name: "no admin action", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate}}, + }, + }, nil + }), + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected lack of admin action to prevent updating access graph settings", err) + }, + }, + { + name: "update without access graph being enabled", + + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate}}, + }, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, + Identity: authz.LocalUser{ + Username: "llama", + Identity: tlsca.Identity{Username: "llama"}, + }, + }, nil + }), + mutator: func(p *clusterconfigpb.AccessGraphSettings) { + p.Spec.SecretsScanConfig = clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED + }, + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.Error(t, err) + }, + }, + { + name: "updated", + testSetup: func(t *testing.T) { + m := modules.TestModules{ + TestFeatures: modules.Features{ + Policy: modules.PolicyFeature{ + Enabled: true, + }, + }, + } + modules.SetTestModules(t, &m) + }, + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate}}, + }, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, + Identity: authz.LocalUser{ + Username: "llama", + Identity: tlsca.Identity{Username: "llama"}, + }, + }, nil + }), + mutator: func(p *clusterconfigpb.AccessGraphSettings) { + p.Spec.SecretsScanConfig = clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED + }, + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.NoError(t, err) + require.Equal(t, clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, updated.GetSpec().GetSecretsScanConfig()) + }, + }, + } + + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + if test.testSetup != nil { + test.testSetup(t) + } + settings, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + ) + require.NoError(t, err) + env, err := newTestEnv(withAuthorizer(test.authorizer), withAccessGraphSettings(settings)) + require.NoError(t, err, "creating test service") + + // Set revisions to allow the update to succeed. + pref := env.defaultAccessGraphSettings + if test.mutator != nil { + test.mutator(pref) + } + + updated, err := env.UpdateAccessGraphSettings(context.Background(), &clusterconfigpb.UpdateAccessGraphSettingsRequest{AccessGraphSettings: pref}) + test.assertion(t, updated, err) + }) + } +} + +func TestUpsertAccessGraphSettings(t *testing.T) { + cases := []struct { + name string + testSetup func(*testing.T) + mutator func(p *clusterconfigpb.AccessGraphSettings) + authorizer authz.Authorizer + assertion func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) + }{ + { + name: "unauthorized", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{}, + }, nil + }), + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected unauthorized user to prevent upserting access graph settings", err) + }, + }, + { + name: "access prevented", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate}}, + }, + AdminActionAuthState: authz.AdminActionAuthUnauthorized, + }, nil + }), + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected lack of admin action to prevent upserting access graph settings", err) + }, + }, + { + name: "no admin action", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbCreate, types.VerbUpdate}}, + }, + AdminActionAuthState: authz.AdminActionAuthUnauthorized, + }, nil + }), + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), expected lack of admin action to prevent upserting access graph settings", err) + }, + }, + { + name: "policy not enabled", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbCreate, types.VerbUpdate}}, + }, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, + }, nil + }), + mutator: func(p *clusterconfigpb.AccessGraphSettings) { + + }, + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.True(t, trace.IsAccessDenied(err), "got (%v), upserting access graph settings must fail when policy isn't enabled", err) + }, + }, + + { + name: "upserted", + testSetup: func(t *testing.T) { + m := modules.TestModules{ + TestFeatures: modules.Features{ + Policy: modules.PolicyFeature{ + Enabled: true, + }, + }, + } + modules.SetTestModules(t, &m) + }, + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate, types.VerbCreate}}, + }, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, + Identity: authz.LocalUser{ + Username: "llama", + Identity: tlsca.Identity{Username: "llama"}, + }, + }, nil + }), + mutator: func(p *clusterconfigpb.AccessGraphSettings) { + p.Spec.SecretsScanConfig = clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED + }, + assertion: func(t *testing.T, updated *clusterconfigpb.AccessGraphSettings, err error) { + require.NoError(t, err) + require.Equal(t, clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, updated.Spec.SecretsScanConfig) + }, + }, + } + + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + if test.testSetup != nil { + test.testSetup(t) + } + settings, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }) + + require.NoError(t, err) + + env, err := newTestEnv(withAuthorizer(test.authorizer), withAccessGraphSettings(settings)) + require.NoError(t, err, "creating test service") + + // Discard revisions to allow the update to succeed. + pref := settings + if test.mutator != nil { + test.mutator(pref) + } + + updated, err := env.UpsertAccessGraphSettings(context.Background(), &clusterconfigpb.UpsertAccessGraphSettingsRequest{AccessGraphSettings: pref}) + test.assertion(t, updated, err) + }) + } +} + +func TestResetAccessGraphSettings(t *testing.T) { + cases := []struct { + name string + authorizer authz.Authorizer + testSetup func(*testing.T) + assertion func(t *testing.T, reset *clusterconfigpb.AccessGraphSettings, err error) + }{ + { + name: "unauthorized", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{}, + }, nil + }), + assertion: func(t *testing.T, reset *clusterconfigpb.AccessGraphSettings, err error) { + assert.Nil(t, reset) + require.True(t, trace.IsAccessDenied(err), "got (%v), expected unauthorized user to prevent resetting access graph settings", err) + }, + }, + { + name: "no admin action", + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate}}, + }, + }, nil + }), + assertion: func(t *testing.T, reset *clusterconfigpb.AccessGraphSettings, err error) { + assert.Nil(t, reset) + require.True(t, trace.IsAccessDenied(err), "got (%v), expected lack of admin action to prevent resetting access graph settings", err) + }, + }, + { + name: "reset", + testSetup: func(t *testing.T) { + m := modules.TestModules{ + TestFeatures: modules.Features{ + Policy: modules.PolicyFeature{ + Enabled: true, + }, + }, + } + modules.SetTestModules(t, &m) + }, + authorizer: authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { + return &authz.Context{ + Checker: fakeChecker{ + rules: map[string][]string{types.KindAccessGraphSettings: {types.VerbUpdate, types.VerbCreate}}, + }, + AdminActionAuthState: authz.AdminActionAuthMFAVerified, + Identity: authz.LocalUser{ + Username: "llama", + Identity: tlsca.Identity{Username: "llama"}, + }, + }, nil + }), + assertion: func(t *testing.T, reset *clusterconfigpb.AccessGraphSettings, err error) { + require.NoError(t, err) + require.Equal(t, clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, reset.GetSpec().GetSecretsScanConfig()) + }, + }, + } + + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + if test.testSetup != nil { + test.testSetup(t) + } + settings, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }) + + require.NoError(t, err) + + env, err := newTestEnv(withAuthorizer(test.authorizer), withAccessGraphSettings(settings)) + require.NoError(t, err, "creating test service") + + reset, err := env.ResetAccessGraphSettings(context.Background(), &clusterconfigpb.ResetAccessGraphSettingsRequest{}) + test.assertion(t, reset, err) + }) + } +} diff --git a/lib/auth/grpcserver_test.go b/lib/auth/grpcserver_test.go index c579095093670..6e60ebfe5496d 100644 --- a/lib/auth/grpcserver_test.go +++ b/lib/auth/grpcserver_test.go @@ -4666,9 +4666,10 @@ func TestGetAccessGraphConfig(t *testing.T) { user, _, err := CreateUserAndRole(server.Auth(), "test", []string{"role"}, nil) require.NoError(t, err) positiveResponse := &clusterconfigpb.AccessGraphConfig{ - Enabled: true, - Ca: []byte("ca"), - Address: "addr", + Enabled: true, + Ca: []byte("ca"), + Address: "addr", + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{}, } tests := []struct { diff --git a/lib/auth/init.go b/lib/auth/init.go index 1577fce2f4cde..58db50da3b94e 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -41,9 +41,11 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/client/proto" apidefaults "github.com/gravitational/teleport/api/defaults" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" dbobjectimportrulev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1" machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/clusterconfig" apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/lib" "github.com/gravitational/teleport/lib/ai" @@ -445,6 +447,12 @@ func initCluster(ctx context.Context, cfg InitConfig, asrv *Server) error { return trace.Wrap(initializeSessionRecordingConfig(ctx, asrv, cfg.SessionRecordingConfig)) }) + g.Go(func() error { + ctx, span := cfg.Tracer.Start(gctx, "auth/InitializeAccessGraphSettings") + defer span.End() + return trace.Wrap(initializeAccessGraphSettings(ctx, asrv)) + }) + g.Go(func() error { ctx, span := cfg.Tracer.Start(gctx, "auth/initializeAuthPreference") defer span.End() @@ -848,6 +856,31 @@ func initializeSessionRecordingConfig(ctx context.Context, asrv *Server, newRecC return trace.LimitExceeded("failed to initialize session recording config in %v iterations", iterationLimit) } +func initializeAccessGraphSettings(ctx context.Context, asrv *Server) error { + stored, err := asrv.Services.GetAccessGraphSettings(ctx) + if err != nil && !trace.IsNotFound(err) { + return trace.Wrap(err) + } + if stored != nil { + return nil + } + + stored, err = clusterconfig.NewAccessGraphSettings(&clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }) + if err != nil { + return trace.Wrap(err) + } + + log.Infof("Creating access graph settings: %v.", stored) + _, err = asrv.CreateAccessGraphSettings(ctx, stored) + if trace.IsAlreadyExists(err) { + return nil + } + + return trace.Wrap(err) +} + // shouldInitReplaceResourceWithOrigin determines whether the candidate // resource should be used to replace the stored resource during auth server // initialization. Dynamically configured resources must not be overwritten diff --git a/lib/auth/join/join.go b/lib/auth/join/join.go index 367b091612ac5..d5d6b8f3b96c9 100644 --- a/lib/auth/join/join.go +++ b/lib/auth/join/join.go @@ -18,28 +18,20 @@ package join import ( "context" - "crypto/tls" "crypto/x509" "log/slog" "os" - "slices" "time" "github.com/gravitational/trace" "github.com/jonboulle/clockwork" log "github.com/sirupsen/logrus" "go.opentelemetry.io/otel" - "golang.org/x/net/http2" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/breaker" "github.com/gravitational/teleport/api/client" "github.com/gravitational/teleport/api/client/proto" - "github.com/gravitational/teleport/api/constants" - apidefaults "github.com/gravitational/teleport/api/defaults" - "github.com/gravitational/teleport/api/metadata" "github.com/gravitational/teleport/api/observability/tracing" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/aws" @@ -47,6 +39,7 @@ import ( "github.com/gravitational/teleport/lib/auth/join/iam" "github.com/gravitational/teleport/lib/auth/state" "github.com/gravitational/teleport/lib/circleci" + proxyinsecureclient "github.com/gravitational/teleport/lib/client/proxy/insecure" "github.com/gravitational/teleport/lib/cloud/imds/azure" "github.com/gravitational/teleport/lib/cloud/imds/gcp" "github.com/gravitational/teleport/lib/defaults" @@ -54,7 +47,6 @@ import ( "github.com/gravitational/teleport/lib/gitlab" "github.com/gravitational/teleport/lib/kubernetestoken" "github.com/gravitational/teleport/lib/spacelift" - "github.com/gravitational/teleport/lib/srv/alpnproxy/common" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/tpm" "github.com/gravitational/teleport/lib/utils" @@ -292,7 +284,16 @@ func registerThroughProxy( switch params.JoinMethod { case types.JoinMethodIAM, types.JoinMethodAzure, types.JoinMethodTPM: // IAM and Azure join methods require gRPC client - conn, err := proxyJoinServiceConn(ctx, params, params.Insecure) + conn, err := proxyinsecureclient.NewConnection( + ctx, + proxyinsecureclient.ConnectionConfig{ + ProxyServer: getHostAddresses(params)[0], + CipherSuites: params.CipherSuites, + Clock: params.Clock, + Insecure: params.Insecure, + Log: slog.Default(), + }, + ) if err != nil { return nil, trace.Wrap(err) } @@ -401,56 +402,6 @@ func registerThroughAuth( return certs, trace.Wrap(err) } -// proxyJoinServiceConn attempts to connect to the join service running on the -// proxy. The Proxy's TLS cert will be verified using the host's root CA pool -// (PKI) unless the --insecure flag was passed. -func proxyJoinServiceConn( - ctx context.Context, params RegisterParams, insecure bool, -) (*grpc.ClientConn, error) { - tlsConfig := utils.TLSConfig(params.CipherSuites) - tlsConfig.Time = params.Clock.Now - // set NextProtos for TLS routing, the actual protocol will be h2 - tlsConfig.NextProtos = []string{string(common.ProtocolProxyGRPCInsecure), http2.NextProtoTLS} - - if insecure { - tlsConfig.InsecureSkipVerify = true - log.Warnf("Joining cluster without validating the identity of the Proxy Server.") - } - - // Check if proxy is behind a load balancer. If so, the connection upgrade - // will verify the load balancer's cert using system cert pool. This - // provides the same level of security as the client only verifies Proxy's - // web cert against system cert pool when connection upgrade is not - // required. - // - // With the ALPN connection upgrade, the tunneled TLS Routing request will - // skip verify as the Proxy server will present its host cert which is not - // fully verifiable at this point since the client does not have the host - // CAs yet before completing registration. - alpnConnUpgrade := client.IsALPNConnUpgradeRequired(ctx, getHostAddresses(params)[0], insecure) - if alpnConnUpgrade && !insecure { - tlsConfig.InsecureSkipVerify = true - tlsConfig.VerifyConnection = verifyALPNUpgradedConn(params.Clock) - } - - dialer := client.NewDialer( - ctx, - apidefaults.DefaultIdleTimeout, - apidefaults.DefaultIOTimeout, - client.WithInsecureSkipVerify(insecure), - client.WithALPNConnUpgrade(alpnConnUpgrade), - ) - - conn, err := grpc.Dial( - getHostAddresses(params)[0], - grpc.WithContextDialer(client.GRPCContextDialer(dialer)), - grpc.WithUnaryInterceptor(metadata.UnaryClientInterceptor), - grpc.WithStreamInterceptor(metadata.StreamClientInterceptor), - grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), - ) - return conn, trace.Wrap(err) -} - func getHostAddresses(params RegisterParams) []string { if !params.ProxyServer.IsEmpty() { return []string{params.ProxyServer.String()} @@ -459,25 +410,6 @@ func getHostAddresses(params RegisterParams) []string { return utils.NetAddrsToStrings(params.AuthServers) } -// verifyALPNUpgradedConn is a tls.Config.VerifyConnection callback function -// used by the tunneled TLS Routing request to verify the host cert of a Proxy -// behind a L7 load balancer. -// -// Since the client has not obtained the cluster CAs at this point, the -// presented cert cannot be fully verified yet. For now, this function only -// checks if "teleport.cluster.local" is present as one of the DNS names and -// verifies the cert is not expired. -func verifyALPNUpgradedConn(clock clockwork.Clock) func(tls.ConnectionState) error { - return func(server tls.ConnectionState) error { - for _, cert := range server.PeerCertificates { - if slices.Contains(cert.DNSNames, constants.APIDomain) && clock.Now().Before(cert.NotAfter) { - return nil - } - } - return trace.AccessDenied("server is not a Teleport proxy or server certificate is expired") - } -} - // insecureRegisterClient attempts to connects to the Auth Server using the // CA on disk. If no CA is found on disk, Teleport will not verify the Auth // Server it is connecting to. diff --git a/lib/auth/join/join_test.go b/lib/auth/join/join_test.go index c0f29758de2ea..ed37766abbc15 100644 --- a/lib/auth/join/join_test.go +++ b/lib/auth/join/join_test.go @@ -18,7 +18,6 @@ package join import ( "context" - "crypto/tls" "errors" "net" "testing" @@ -39,7 +38,6 @@ import ( "github.com/gravitational/teleport/lib/auth/testauthority" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/events" - "github.com/gravitational/teleport/lib/fixtures" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" ) @@ -274,48 +272,3 @@ func newBotToken(t *testing.T, tokenName, botName string, role types.SystemRole, require.NoError(t, err, "could not create bot token") return token } - -func TestVerifyALPNUpgradedConn(t *testing.T) { - t.Parallel() - - srv := newTestTLSServer(t) - proxy, err := auth.NewServerIdentity(srv.Auth(), "test-proxy", types.RoleProxy) - require.NoError(t, err) - - tests := []struct { - name string - serverCert []byte - clock clockwork.Clock - checkError require.ErrorAssertionFunc - }{ - { - name: "proxy verified", - serverCert: proxy.TLSCertBytes, - clock: srv.Clock(), - checkError: require.NoError, - }, - { - name: "proxy expired", - serverCert: proxy.TLSCertBytes, - clock: clockwork.NewFakeClockAt(srv.Clock().Now().Add(defaults.CATTL + time.Hour)), - checkError: require.Error, - }, - { - name: "not proxy", - serverCert: []byte(fixtures.TLSCACertPEM), - clock: srv.Clock(), - checkError: require.Error, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - serverCert, err := utils.ReadCertificates(test.serverCert) - require.NoError(t, err) - - test.checkError(t, verifyALPNUpgradedConn(test.clock)(tls.ConnectionState{ - PeerCertificates: serverCert, - })) - }) - } -} diff --git a/lib/authz/permissions.go b/lib/authz/permissions.go index d3d73a15a48d9..d930710f28824 100644 --- a/lib/authz/permissions.go +++ b/lib/authz/permissions.go @@ -36,6 +36,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/defaults" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/mfa" "github.com/gravitational/teleport/api/types" @@ -113,7 +114,7 @@ func NewAuthorizer(opts AuthorizerOpts) (Authorizer, error) { // cannot handle caching, and will fail if caching is enabled. var err error opts.ReadOnlyAccessPoint, err = readonly.NewCache(readonly.CacheConfig{ - Upstream: opts.AccessPoint, + Upstream: accessPointWrapper{opts.AccessPoint}, Disabled: !opts.PermitCaching, }) if err != nil { @@ -133,6 +134,15 @@ func NewAuthorizer(opts AuthorizerOpts) (Authorizer, error) { }, nil } +type accessPointWrapper struct { + AuthorizerAccessPoint +} + +// GetAccessGraphSettings returns the access graph settings. +func (accessPointWrapper) GetAccessGraphSettings(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + return nil, trace.NotImplemented("GetAccessGraphSettings is not implemented") +} + // Authorizer authorizes identity and returns auth context type Authorizer interface { // Authorize authorizes user based on identity supplied via context diff --git a/lib/cache/cache.go b/lib/cache/cache.go index 415b26585a49c..1b4e3807d25a9 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -32,11 +32,13 @@ import ( "go.opentelemetry.io/otel/attribute" oteltrace "go.opentelemetry.io/otel/trace" "golang.org/x/sync/errgroup" + protobuf "google.golang.org/protobuf/proto" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/client/proto" apidefaults "github.com/gravitational/teleport/api/defaults" accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" @@ -173,6 +175,7 @@ func ForAuth(cfg Config) Config { {Kind: types.KindAccessListReview}, {Kind: types.KindKubeWaitingContainer}, {Kind: types.KindAccessMonitoringRule}, + {Kind: types.KindAccessGraphSettings}, } cfg.QueueSize = defaults.AuthQueueSize // We don't want to enable partial health for auth cache because auth uses an event stream @@ -3229,3 +3232,28 @@ func (c *Cache) ListResources(ctx context.Context, req proto.ListResourcesReques return rg.reader.ListResources(ctx, req) } + +// GetAccessGraphSettings gets AccessGraphSettings from the backend. +func (c *Cache) GetAccessGraphSettings(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + ctx, span := c.Tracer.Start(ctx, "cache/GetAccessGraphSettings") + defer span.End() + + rg, err := readCollectionCache(c, c.collections.accessGraphSettings) + if err != nil { + return nil, trace.Wrap(err) + } + defer rg.Release() + if !rg.IsCacheRead() { + cachedCfg, err := utils.FnCacheGet(ctx, c.fnCache, clusterConfigCacheKey{"access_graph_settings"}, func(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + cfg, err := rg.reader.GetAccessGraphSettings(ctx) + return cfg, err + }) + if err != nil { + return nil, trace.Wrap(err) + } + + clone := protobuf.Clone(cachedCfg).(*clusterconfigpb.AccessGraphSettings) + return clone, nil + } + return rg.reader.GetAccessGraphSettings(ctx) +} diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go index 745002e85db85..bf7fe8a2f80fc 100644 --- a/lib/cache/cache_test.go +++ b/lib/cache/cache_test.go @@ -43,11 +43,13 @@ import ( "github.com/gravitational/teleport/api/client/proto" apidefaults "github.com/gravitational/teleport/api/defaults" accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" + "github.com/gravitational/teleport/api/types/clusterconfig" "github.com/gravitational/teleport/api/types/discoveryconfig" "github.com/gravitational/teleport/api/types/header" "github.com/gravitational/teleport/api/types/kubewaitingcontainer" @@ -3079,6 +3081,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) { types.KindKubeWaitingContainer: newKubeWaitingContainer(t), types.KindAccessMonitoringRule: types.Resource153ToLegacy(newAccessMonitoringRule(t)), types.KindCrownJewel: types.Resource153ToLegacy(newCrownJewel(t, "test")), + types.KindAccessGraphSettings: types.Resource153ToLegacy(newAccessGraphSettings(t)), } for name, cfg := range cases { @@ -3542,6 +3545,16 @@ func newCrownJewel(t *testing.T, name string) *crownjewelv1.CrownJewel { return crownJewel } +func newAccessGraphSettings(t *testing.T) *clusterconfigpb.AccessGraphSettings { + t.Helper() + + r, err := clusterconfig.NewAccessGraphSettings(&clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }) + require.NoError(t, err) + return r +} + func newAccessMonitoringRule(t *testing.T) *accessmonitoringrulesv1.AccessMonitoringRule { t.Helper() notification := &accessmonitoringrulesv1.AccessMonitoringRule{ diff --git a/lib/cache/collections.go b/lib/cache/collections.go index 22354c5eebf03..ac02a82894c08 100644 --- a/lib/cache/collections.go +++ b/lib/cache/collections.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport/api/client/proto" apidefaults "github.com/gravitational/teleport/api/defaults" accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" @@ -242,6 +243,7 @@ type cacheCollections struct { webTokens collectionReader[webTokenGetter] windowsDesktops collectionReader[windowsDesktopsGetter] windowsDesktopServices collectionReader[windowsDesktopServiceGetter] + accessGraphSettings collectionReader[accessGraphSettingsGetter] accessMonitoringRules collectionReader[accessMonitoringRuleGetter] } @@ -699,6 +701,15 @@ func setupCollections(c *Cache, watches []types.WatchKind) (*cacheCollections, e } collections.accessMonitoringRules = &genericCollection[*accessmonitoringrulesv1.AccessMonitoringRule, accessMonitoringRuleGetter, accessMonitoringRulesExecutor]{cache: c, watch: watch} collections.byKind[resourceKind] = collections.accessMonitoringRules + case types.KindAccessGraphSettings: + if c.ClusterConfig == nil { + return nil, trace.BadParameter("missing parameter ClusterConfig") + } + collections.accessGraphSettings = &genericCollection[*clusterconfigpb.AccessGraphSettings, accessGraphSettingsGetter, accessGraphSettingsExecutor]{ + cache: c, + watch: watch, + } + collections.byKind[resourceKind] = collections.accessGraphSettings default: return nil, trace.BadParameter("resource %q is not supported", watch.Kind) } @@ -3018,3 +3029,42 @@ type accessMonitoringRuleGetter interface { ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) } + +type accessGraphSettingsExecutor struct{} + +func (accessGraphSettingsExecutor) getAll(ctx context.Context, cache *Cache, _ bool) ([]*clusterconfigpb.AccessGraphSettings, error) { + set, err := cache.ClusterConfig.GetAccessGraphSettings(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + return []*clusterconfigpb.AccessGraphSettings{set}, nil +} + +func (accessGraphSettingsExecutor) upsert(ctx context.Context, cache *Cache, resource *clusterconfigpb.AccessGraphSettings) error { + _, err := cache.clusterConfigCache.UpsertAccessGraphSettings(ctx, resource) + return trace.Wrap(err) +} + +func (accessGraphSettingsExecutor) deleteAll(ctx context.Context, cache *Cache) error { + return trace.Wrap(cache.clusterConfigCache.DeleteAccessGraphSettings(ctx)) +} + +func (accessGraphSettingsExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { + return trace.Wrap(cache.clusterConfigCache.DeleteAccessGraphSettings(ctx)) +} + +func (accessGraphSettingsExecutor) isSingleton() bool { return false } + +func (accessGraphSettingsExecutor) getReader(cache *Cache, cacheOK bool) accessGraphSettingsGetter { + if cacheOK { + return cache.clusterConfigCache + } + return cache.Config.ClusterConfig +} + +type accessGraphSettingsGetter interface { + GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) +} + +var _ executor[*clusterconfigpb.AccessGraphSettings, accessGraphSettingsGetter] = accessGraphSettingsExecutor{} diff --git a/lib/client/proxy/insecure/insecure.go b/lib/client/proxy/insecure/insecure.go new file mode 100644 index 0000000000000..97f7414be6101 --- /dev/null +++ b/lib/client/proxy/insecure/insecure.go @@ -0,0 +1,136 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package insecure creates a client that access the proxy unauthenticated gRPC service. +package insecure + +import ( + "context" + "crypto/tls" + "log/slog" + "slices" + + "github.com/gravitational/trace" + "github.com/jonboulle/clockwork" + "golang.org/x/net/http2" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + "github.com/gravitational/teleport/api/client" + "github.com/gravitational/teleport/api/constants" + apidefaults "github.com/gravitational/teleport/api/defaults" + "github.com/gravitational/teleport/api/metadata" + "github.com/gravitational/teleport/lib/srv/alpnproxy/common" + "github.com/gravitational/teleport/lib/utils" +) + +// ConnectionConfig specifies parameters for the client to dial credentialless via the proxy. +type ConnectionConfig struct { + // ProxyServer is the address of the proxy server + ProxyServer string + // CipherSuites is a list of cipher suites to use for TLS client connection + CipherSuites []uint16 + // Clock specifies the time provider. Will be used to override the time anchor + // for TLS certificate verification. + // Defaults to real clock if unspecified + Clock clockwork.Clock + // Insecure trusts the certificates from the Auth Server or Proxy during registration without verification. + Insecure bool + // Log is the logger. + Log *slog.Logger +} + +// NewConnection attempts to connect to the proxy insecure grpc server. +// The Proxy's TLS cert will be verified using the host's root CA pool +// (PKI) unless the insecure flag was passed. +func NewConnection( + ctx context.Context, params ConnectionConfig, +) (*grpc.ClientConn, error) { + if params.ProxyServer == "" { + return nil, trace.BadParameter("missing ProxyServer") + } + if params.Clock == nil { + params.Clock = clockwork.NewRealClock() + } + if params.Log == nil { + params.Log = slog.Default() + } + + tlsConfig, alpnConnUpgrade := buildTLSConfig(ctx, params) + + dialer := client.NewDialer( + ctx, + apidefaults.DefaultIdleTimeout, + apidefaults.DefaultIOTimeout, + client.WithInsecureSkipVerify(params.Insecure), + client.WithALPNConnUpgrade(alpnConnUpgrade), + ) + + conn, err := grpc.NewClient( + params.ProxyServer, + grpc.WithContextDialer(client.GRPCContextDialer(dialer)), + grpc.WithUnaryInterceptor(metadata.UnaryClientInterceptor), + grpc.WithStreamInterceptor(metadata.StreamClientInterceptor), + grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), + ) + return conn, trace.Wrap(err) +} + +// verifyALPNUpgradedConn is a tls.Config.VerifyConnection callback function +// used by the tunneled TLS Routing request to verify the host cert of a Proxy +// behind a L7 load balancer. +// +// Since the client has not obtained the cluster CAs at this point, the +// presented cert cannot be fully verified yet. For now, this function only +// checks if "teleport.cluster.local" is present as one of the DNS names and +// verifies the cert is not expired. +func verifyALPNUpgradedConn(clock clockwork.Clock) func(tls.ConnectionState) error { + return func(server tls.ConnectionState) error { + for _, cert := range server.PeerCertificates { + if slices.Contains(cert.DNSNames, constants.APIDomain) && clock.Now().Before(cert.NotAfter) { + return nil + } + } + return trace.AccessDenied("server is not a Teleport proxy or server certificate is expired") + } +} + +func buildTLSConfig(ctx context.Context, params ConnectionConfig) (*tls.Config, bool) { + tlsConfig := utils.TLSConfig(params.CipherSuites) + tlsConfig.Time = params.Clock.Now + // set NextProtos for TLS routing, the actual protocol will be h2 + tlsConfig.NextProtos = []string{string(common.ProtocolProxyGRPCInsecure), http2.NextProtoTLS} + + if params.Insecure { + tlsConfig.InsecureSkipVerify = true + params.Log.WarnContext(ctx, "Connecting to the cluster without validating the identity of the Proxy Server.") + } + + // Check if proxy is behind a load balancer. If so, the connection upgrade + // will verify the load balancer's cert using system cert pool. This + // provides the same level of security as the client only verifies Proxy's + // web cert against system cert pool when connection upgrade is not + // required. + // + // With the ALPN connection upgrade, the tunneled TLS Routing request will + // skip verify as the Proxy server will present its host cert which is not + // fully verifiable at this point since the client does not have the host + // CAs yet before completing registration. + alpnConnUpgrade := client.IsALPNConnUpgradeRequired(ctx, params.ProxyServer, params.Insecure) + if alpnConnUpgrade && !params.Insecure { + tlsConfig.InsecureSkipVerify = true + tlsConfig.VerifyConnection = verifyALPNUpgradedConn(params.Clock) + } + return tlsConfig, alpnConnUpgrade +} diff --git a/lib/client/proxy/insecure/insecure_test.go b/lib/client/proxy/insecure/insecure_test.go new file mode 100644 index 0000000000000..c4e68d285308d --- /dev/null +++ b/lib/client/proxy/insecure/insecure_test.go @@ -0,0 +1,155 @@ +// Copyright 2024 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package insecure + +import ( + "context" + "crypto/tls" + "errors" + "log/slog" + "net" + "os" + "strconv" + "testing" + "time" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/require" + + apidefaults "github.com/gravitational/teleport/api/defaults" + "github.com/gravitational/teleport/api/fixtures" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/auth" + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/srv/alpnproxy/common" + "github.com/gravitational/teleport/lib/utils" +) + +func TestMain(m *testing.M) { + os.Exit(m.Run()) +} + +func TestVerifyALPNUpgradedConn(t *testing.T) { + t.Parallel() + + srv := newTestTLSServer(t) + proxy, err := auth.NewServerIdentity(srv.Auth(), "test-proxy", types.RoleProxy) + require.NoError(t, err) + + tests := []struct { + name string + serverCert []byte + clock clockwork.Clock + checkError require.ErrorAssertionFunc + }{ + { + name: "proxy verified", + serverCert: proxy.TLSCertBytes, + clock: srv.Clock(), + checkError: require.NoError, + }, + { + name: "proxy expired", + serverCert: proxy.TLSCertBytes, + clock: clockwork.NewFakeClockAt(srv.Clock().Now().Add(defaults.CATTL + time.Hour)), + checkError: require.Error, + }, + { + name: "not proxy", + serverCert: []byte(fixtures.TLSCACertPEM), + clock: srv.Clock(), + checkError: require.Error, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + serverCert, err := utils.ReadCertificates(test.serverCert) + require.NoError(t, err) + + test.checkError(t, verifyALPNUpgradedConn(test.clock)(tls.ConnectionState{ + PeerCertificates: serverCert, + })) + }) + } +} + +func newTestTLSServer(t testing.TB) *auth.TestTLSServer { + as, err := auth.NewTestAuthServer(auth.TestAuthServerConfig{ + Dir: t.TempDir(), + Clock: clockwork.NewFakeClockAt(time.Now().Round(time.Second).UTC()), + }) + require.NoError(t, err) + + srv, err := as.NewTestTLSServer() + require.NoError(t, err) + + t.Cleanup(func() { + err := srv.Close() + if errors.Is(err, net.ErrClosed) { + return + } + require.NoError(t, err) + }) + + return srv +} + +func TestBuildTLSConfig(t *testing.T) { + tests := []struct { + name string + proxyAddr string + alpnEnvValue bool + insecure bool + expectInsecure bool + }{ + { + name: "insecure", + proxyAddr: "localhost:1234", + alpnEnvValue: false, + insecure: true, + expectInsecure: true, + }, + { + name: "secure", + proxyAddr: "localhost:1234", + alpnEnvValue: false, + insecure: false, + expectInsecure: false, + }, + { + name: "alpn upgrade required", + proxyAddr: "localhost:1234", + alpnEnvValue: true, + insecure: false, + expectInsecure: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Setenv(apidefaults.TLSRoutingConnUpgradeEnvVar, strconv.FormatBool(tt.alpnEnvValue)) + tlsConfig, alpnUpgrade := buildTLSConfig(context.Background(), ConnectionConfig{ + ProxyServer: tt.proxyAddr, + Insecure: tt.insecure, + Log: slog.Default(), + Clock: clockwork.NewRealClock(), + }) + require.Equal(t, alpnUpgrade, tt.alpnEnvValue) + require.Equal(t, tlsConfig.InsecureSkipVerify, tt.expectInsecure) + require.Contains(t, tlsConfig.NextProtos, string(common.ProtocolProxyGRPCInsecure)) + }) + } +} diff --git a/lib/devicetrust/assert/assert.go b/lib/devicetrust/assert/assert.go new file mode 100644 index 0000000000000..f69fb67f671ef --- /dev/null +++ b/lib/devicetrust/assert/assert.go @@ -0,0 +1,183 @@ +// Teleport +// Copyright (C) 2024 Gravitational, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package assert + +import ( + "context" + + "github.com/gravitational/trace" + "google.golang.org/grpc" + + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + "github.com/gravitational/teleport/lib/devicetrust/authn" +) + +// AssertDeviceClientStream is the client-side device assertion stream. +type AssertDeviceClientStream interface { + Send(*devicepb.AssertDeviceRequest) error + Recv() (*devicepb.AssertDeviceResponse, error) +} + +// Ceremony implements the client-side assertion ceremony. +// +// See [devicepb.AssertDeviceRequest] for details. +type Ceremony struct { + // newAuthnCeremony defaults to authn.NewCeremony. + newAuthnCeremony func() *authn.Ceremony +} + +// CeremonyOpt is a creation option for [Ceremony]. +type CeremonyOpt func(*Ceremony) + +// WithNewAuthnCeremonyFunc overrides the default authn.Ceremony constructor, +// allowing callers to change the underlying assert implementation. +// +// Useful for testing. Avoid for production code. +func WithNewAuthnCeremonyFunc(f func() *authn.Ceremony) CeremonyOpt { + return func(c *Ceremony) { + c.newAuthnCeremony = f + } +} + +// NewCeremony creates a new [Ceremony], binding all native device trust +// methods. +func NewCeremony(opts ...CeremonyOpt) (*Ceremony, error) { + c := &Ceremony{ + newAuthnCeremony: authn.NewCeremony, + } + for _, opt := range opts { + opt(c) + } + return c, nil +} + +// Run runs the client-side device assertion ceremony. +// Requests and responses are consumed from the stream until the device is +// asserted or authentication fails. +func (c *Ceremony) Run(ctx context.Context, stream AssertDeviceClientStream) error { + newAuthn := c.newAuthnCeremony + if newAuthn == nil { + newAuthn = authn.NewCeremony + } + + devices := &devicesClientAdapter{ + stream: stream, + } + certs := &devicepb.UserCertificates{} // required but unused + + // Implement Assertion in terms of Authentication, so we borrow both the + // Secure Enclave and TPM branches from it. + // TODO(codingllama): Refactor so we don't need so many adapters? + _, err := newAuthn().Run(ctx, devices, certs) + return trace.Wrap(err) +} + +type devicesClientAdapter struct { + devicepb.DeviceTrustServiceClient + + stream AssertDeviceClientStream +} + +func (d *devicesClientAdapter) AuthenticateDevice(ctx context.Context, opts ...grpc.CallOption) (devicepb.DeviceTrustService_AuthenticateDeviceClient, error) { + return &authnStreamAdapter{ + ctx: ctx, + stream: d.stream, + }, nil +} + +// authnStreamAdapter adapts an [AssertDeviceClientStream] to a +// [devicepb.DeviceTrustService_AuthenticateDeviceClient] stream. This allows +// the assertion ceremony to borrow the [authn.Ceremony] logic for itself. +type authnStreamAdapter struct { + devicepb.DeviceTrustService_AuthenticateDeviceClient + + ctx context.Context + stream AssertDeviceClientStream +} + +func (s *authnStreamAdapter) CloseSend() error { + return nil +} + +func (s *authnStreamAdapter) Context() context.Context { + return s.ctx +} + +func (s *authnStreamAdapter) Recv() (*devicepb.AuthenticateDeviceResponse, error) { + resp, err := s.stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + + if resp == nil || resp.Payload == nil { + return nil, trace.BadParameter("assertion response payload required") + } + + switch resp.Payload.(type) { + case *devicepb.AssertDeviceResponse_Challenge: + return &devicepb.AuthenticateDeviceResponse{ + Payload: &devicepb.AuthenticateDeviceResponse_Challenge{ + Challenge: resp.GetChallenge(), + }, + }, nil + case *devicepb.AssertDeviceResponse_TpmChallenge: + return &devicepb.AuthenticateDeviceResponse{ + Payload: &devicepb.AuthenticateDeviceResponse_TpmChallenge{ + TpmChallenge: resp.GetTpmChallenge(), + }, + }, nil + case *devicepb.AssertDeviceResponse_DeviceAsserted: + // Pass an empty UserCertificates to signify success. + return &devicepb.AuthenticateDeviceResponse{ + Payload: &devicepb.AuthenticateDeviceResponse_UserCertificates{ + UserCertificates: &devicepb.UserCertificates{}, + }, + }, nil + default: + return nil, trace.BadParameter("unexpected assertion response payload: %T", resp.Payload) + } +} + +func (s *authnStreamAdapter) Send(authnReq *devicepb.AuthenticateDeviceRequest) error { + if authnReq == nil || authnReq.Payload == nil { + return trace.BadParameter("authenticate request payload required") + } + + req := &devicepb.AssertDeviceRequest{} + switch authnReq.Payload.(type) { + case *devicepb.AuthenticateDeviceRequest_Init: + init := authnReq.GetInit() + req.Payload = &devicepb.AssertDeviceRequest_Init{ + Init: &devicepb.AssertDeviceInit{ + CredentialId: init.GetCredentialId(), + DeviceData: init.GetDeviceData(), + }, + } + case *devicepb.AuthenticateDeviceRequest_ChallengeResponse: + req.Payload = &devicepb.AssertDeviceRequest_ChallengeResponse{ + ChallengeResponse: authnReq.GetChallengeResponse(), + } + case *devicepb.AuthenticateDeviceRequest_TpmChallengeResponse: + req.Payload = &devicepb.AssertDeviceRequest_TpmChallengeResponse{ + TpmChallengeResponse: authnReq.GetTpmChallengeResponse(), + } + default: + return trace.BadParameter("unexpected authenticate request payload: %T", authnReq.Payload) + } + + return trace.Wrap(s.stream.Send(req)) +} diff --git a/lib/devicetrust/assert/assert_test.go b/lib/devicetrust/assert/assert_test.go new file mode 100644 index 0000000000000..b9068b222df2e --- /dev/null +++ b/lib/devicetrust/assert/assert_test.go @@ -0,0 +1,167 @@ +// Teleport +// Copyright (C) 2024 Gravitational, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package assert_test + +import ( + "context" + "testing" + + "github.com/google/uuid" + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" + + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + "github.com/gravitational/teleport/lib/devicetrust/assert" + "github.com/gravitational/teleport/lib/devicetrust/authn" + "github.com/gravitational/teleport/lib/devicetrust/testenv" +) + +func TestCeremony(t *testing.T) { + t.Parallel() + + deviceID := uuid.NewString() + + ctx := context.Background() + + macDev, err := testenv.NewFakeMacOSDevice() + require.NoError(t, err, "NewFakeMacOSDevice errored") + + linuxDev := testenv.NewFakeLinuxDevice() + + tests := []struct { + name string + dev testenv.FakeDevice + }{ + { + name: "ok (macOs)", + dev: macDev, + }, + { + name: "ok (TPM)", + dev: linuxDev, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + dev := test.dev + + // Create an enrolled device. + devpb, pubKey, err := testenv.CreateEnrolledDevice(deviceID, dev) + require.NoError(t, err, "CreateEnrolledDevice errored") + + env := testenv.MustNew( + testenv.WithAutoCreateDevice(true), + // Register the enrolled device with the service. + testenv.WithPreEnrolledDevice(devpb, pubKey), + ) + + assertC, err := assert.NewCeremony(assert.WithNewAuthnCeremonyFunc(func() *authn.Ceremony { + return &authn.Ceremony{ + GetDeviceCredential: func() (*devicepb.DeviceCredential, error) { + return dev.GetDeviceCredential(), nil + }, + CollectDeviceData: dev.CollectDeviceData, + SignChallenge: dev.SignChallenge, + SolveTPMAuthnDeviceChallenge: dev.SolveTPMAuthnDeviceChallenge, + GetDeviceOSType: dev.GetDeviceOSType, + } + })) + require.NoError(t, err, "NewCeremony errored") + + clientToServer := make(chan *devicepb.AssertDeviceRequest) + serverToClient := make(chan *devicepb.AssertDeviceResponse) + + group, ctx := errgroup.WithContext(ctx) + + // Run the client side of the ceremony. + group.Go(func() error { + err := assertC.Run(ctx, &assertStreamClientAdapter{ + ctx: ctx, + clientToServer: clientToServer, + serverToClient: serverToClient, + }) + return trace.Wrap(err, "server AssertDevice errored") + }) + + serverAssertC, err := env.Service.CreateAssertCeremony() + require.NoError(t, err, "CreateAssertCeremony errored") + // Run the server side of the ceremony. + group.Go(func() error { + _, err := serverAssertC.AssertDevice(ctx, &assertStreamServerAdapter{ + ctx: ctx, + clientToServer: clientToServer, + serverToClient: serverToClient, + }) + return trace.Wrap(err, "server AssertDevice errored") + }) + + err = group.Wait() + require.NoError(t, err, "group.Wait errored") + }) + } +} + +type assertStreamClientAdapter struct { + ctx context.Context + clientToServer chan *devicepb.AssertDeviceRequest + serverToClient chan *devicepb.AssertDeviceResponse +} + +func (s *assertStreamClientAdapter) Recv() (*devicepb.AssertDeviceResponse, error) { + select { + case resp := <-s.serverToClient: + return resp, nil + case <-s.ctx.Done(): + return nil, trace.Wrap(s.ctx.Err()) + } +} + +func (s *assertStreamClientAdapter) Send(req *devicepb.AssertDeviceRequest) error { + select { + case s.clientToServer <- req: + return nil + case <-s.ctx.Done(): + return trace.Wrap(s.ctx.Err()) + } +} + +type assertStreamServerAdapter struct { + ctx context.Context + clientToServer chan *devicepb.AssertDeviceRequest + serverToClient chan *devicepb.AssertDeviceResponse +} + +func (s *assertStreamServerAdapter) Recv() (*devicepb.AssertDeviceRequest, error) { + select { + case req := <-s.clientToServer: + return req, nil + case <-s.ctx.Done(): + return nil, trace.Wrap(s.ctx.Err()) + } +} + +func (s *assertStreamServerAdapter) Send(resp *devicepb.AssertDeviceResponse) error { + select { + case s.serverToClient <- resp: + return nil + case <-s.ctx.Done(): + return trace.Wrap(s.ctx.Err()) + } +} diff --git a/lib/devicetrust/assertserver/assert.go b/lib/devicetrust/assertserver/assert.go new file mode 100644 index 0000000000000..46047e465f3b3 --- /dev/null +++ b/lib/devicetrust/assertserver/assert.go @@ -0,0 +1,50 @@ +// Teleport +// Copyright (C) 2024 Gravitational, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package assertserver + +import ( + "context" + + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" +) + +// AssertDeviceServerStream represents a server-side device assertion stream. +type AssertDeviceServerStream interface { + Send(*devicepb.AssertDeviceResponse) error + Recv() (*devicepb.AssertDeviceRequest, error) +} + +// Ceremony is the server-side device assertion ceremony. +// +// Device assertion is a light form of device authentication where the user +// isn't considered and no side-effects (like certificate issuance) happen. +// +// Assertion is meant to be embedded in RPCs or streams external to the +// DeviceTrustService itself. +// +// Implementations are provided by e/. +// See e/lib/devicetrustv1.Service.CreateAssertCeremony. +type Ceremony interface { + // AssertDevice runs the device assertion ceremonies. + // + // Requests and responses are consumed from the stream until the device is + // asserted or authentication fails. + // + // As long as any device information is acquired from the stream, a non-nil + // device is returned, even if the ceremony itself failed. + AssertDevice(ctx context.Context, stream AssertDeviceServerStream) (*devicepb.Device, error) +} diff --git a/lib/devicetrust/assertserver/doc.go b/lib/devicetrust/assertserver/doc.go new file mode 100644 index 0000000000000..eebdb97e81933 --- /dev/null +++ b/lib/devicetrust/assertserver/doc.go @@ -0,0 +1,21 @@ +// Teleport +// Copyright (C) 2024 Gravitational, Inc. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Package assertserver provides server-side assert interfaces for device trust. +// +// It explicitly does not depend on devicetrust/native or other client-side +// packages. All implementations are provided by e/. +package assertserver diff --git a/lib/devicetrust/keys_prefix.go b/lib/devicetrust/keys_prefix.go new file mode 100644 index 0000000000000..ed0817c5b06a1 --- /dev/null +++ b/lib/devicetrust/keys_prefix.go @@ -0,0 +1,24 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package devicetrust + +var ( + // DevicesIDPrefix is the backend prefix used to store device resources. + DevicesIDPrefix = []string{"devices", "id"} +) diff --git a/lib/devicetrust/testenv/fake_device_service.go b/lib/devicetrust/testenv/fake_device_service.go index e6ccc9ee01acf..8cdf278c5ccb4 100644 --- a/lib/devicetrust/testenv/fake_device_service.go +++ b/lib/devicetrust/testenv/fake_device_service.go @@ -34,6 +34,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + "github.com/gravitational/teleport/lib/devicetrust/assertserver" ) // FakeEnrollmentToken is a "free", never spent enrollment token. @@ -414,6 +415,58 @@ func enrollMacOS(stream devicepb.DeviceTrustService_EnrollDeviceServer, initReq }, ecPubKey, nil } +// CreateAssertCeremony creates a fake, server-side device assertion ceremony. +func (s *FakeDeviceService) CreateAssertCeremony() (assertserver.Ceremony, error) { + return s, nil +} + +// AssertDevice implements a fake, server-side device assertion ceremony. +// +// AssertDevice requires an enrolled device, so the challenge signature +// can be verified. +func (s *FakeDeviceService) AssertDevice(ctx context.Context, stream assertserver.AssertDeviceServerStream) (*devicepb.Device, error) { + // 1. Init. + req, err := stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + initReq := req.GetInit() + switch { + case initReq == nil: + return nil, trace.BadParameter("init required") + case initReq.CredentialId == "": + return nil, trace.BadParameter("credential ID required") + } + if err := validateCollectedData(initReq.DeviceData); err != nil { + return nil, trace.Wrap(err) + } + + s.mu.Lock() + defer s.mu.Unlock() + + dev, err := s.findDeviceByCredential(initReq.DeviceData, initReq.CredentialId) + if err != nil { + return nil, trace.Wrap(err) + } + + switch dev.pb.OsType { + case devicepb.OSType_OS_TYPE_MACOS: + err = authenticateDeviceMacOS(dev, assertStreamAdapter{stream: stream}) + case devicepb.OSType_OS_TYPE_LINUX, devicepb.OSType_OS_TYPE_WINDOWS: + err = authenticateDeviceTPM(assertStreamAdapter{stream: stream}) + default: + err = fmt.Errorf("unrecognized os type %q", dev.pb.OsType) + } + if err != nil { + return nil, trace.Wrap(err) + } + + // Success. + return dev.pb, trace.Wrap(stream.Send(&devicepb.AssertDeviceResponse{ + Payload: &devicepb.AssertDeviceResponse_DeviceAsserted{}, + })) +} + // AuthenticateDevice implements a fake, server-side device authentication // ceremony. // @@ -469,7 +522,7 @@ func (s *FakeDeviceService) AuthenticateDevice(stream devicepb.DeviceTrustServic return trace.Wrap(err) } -func authenticateDeviceMacOS(dev *storedDevice, stream devicepb.DeviceTrustService_AuthenticateDeviceServer) error { +func authenticateDeviceMacOS(dev *storedDevice, stream authenticateDeviceStream) error { // 2. Challenge. chal, err := newChallenge() if err != nil { @@ -500,7 +553,7 @@ func authenticateDeviceMacOS(dev *storedDevice, stream devicepb.DeviceTrustServi return trace.Wrap(verifyChallenge(chal, chalResp.Signature, dev.pub)) } -func authenticateDeviceTPM(stream devicepb.DeviceTrustService_AuthenticateDeviceServer) error { +func authenticateDeviceTPM(stream authenticateDeviceStream) error { // Produce a nonce we can send in the challenge that we expect to see in // the EventLog field of the challenge response. nonce, err := randomBytes() @@ -595,3 +648,64 @@ func verifyChallenge(chal, sig []byte, pub *ecdsa.PublicKey) error { } return nil } + +type authenticateDeviceStream interface { + Recv() (*devicepb.AuthenticateDeviceRequest, error) + Send(*devicepb.AuthenticateDeviceResponse) error +} + +// assertStreamAdapter adapts an [assertserver.AssertDeviceServerStream] to an +// [authenticateDeviceStream]. +type assertStreamAdapter struct { + stream assertserver.AssertDeviceServerStream +} + +func (s assertStreamAdapter) Recv() (*devicepb.AuthenticateDeviceRequest, error) { + req, err := s.stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + + // Convert AssertDeviceRequest to AuthenticateDeviceRequest. + if req == nil || req.Payload == nil { + return nil, trace.BadParameter("assert request payload required") + } + authnReq := &devicepb.AuthenticateDeviceRequest{} + switch req.Payload.(type) { + case *devicepb.AssertDeviceRequest_ChallengeResponse: + authnReq.Payload = &devicepb.AuthenticateDeviceRequest_ChallengeResponse{ + ChallengeResponse: req.GetChallengeResponse(), + } + case *devicepb.AssertDeviceRequest_TpmChallengeResponse: + authnReq.Payload = &devicepb.AuthenticateDeviceRequest_TpmChallengeResponse{ + TpmChallengeResponse: req.GetTpmChallengeResponse(), + } + default: + return nil, trace.BadParameter("unexpected assert request payload: %T", req.Payload) + } + + return authnReq, nil +} + +func (s assertStreamAdapter) Send(authnResp *devicepb.AuthenticateDeviceResponse) error { + if authnResp == nil || authnResp.Payload == nil { + return trace.BadParameter("authenticate response payload required") + } + + // Convert AuthenticateDeviceResponse to AssertDeviceResponse. + resp := &devicepb.AssertDeviceResponse{} + switch authnResp.Payload.(type) { + case *devicepb.AuthenticateDeviceResponse_Challenge: + resp.Payload = &devicepb.AssertDeviceResponse_Challenge{ + Challenge: authnResp.GetChallenge(), + } + case *devicepb.AuthenticateDeviceResponse_TpmChallenge: + resp.Payload = &devicepb.AssertDeviceResponse_TpmChallenge{ + TpmChallenge: authnResp.GetTpmChallenge(), + } + default: + return trace.BadParameter("unexpected authentication response payload: %T", authnResp.Payload) + } + + return trace.Wrap(s.stream.Send(resp)) +} diff --git a/lib/devicetrust/testenv/testenv.go b/lib/devicetrust/testenv/testenv.go index 7dae3c97a07cb..a0226ee030b0e 100644 --- a/lib/devicetrust/testenv/testenv.go +++ b/lib/devicetrust/testenv/testenv.go @@ -20,6 +20,8 @@ package testenv import ( "context" + "crypto/ecdsa" + "crypto/x509" "net" "time" @@ -27,6 +29,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/test/bufconn" + "google.golang.org/protobuf/types/known/timestamppb" devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" "github.com/gravitational/teleport/api/utils/grpc/interceptors" @@ -45,6 +48,24 @@ func WithAutoCreateDevice(b bool) Opt { } } +// WithPreEnrolledDevice registers a device with the service without having to enroll it. +// This is useful for testing device authentication flows. +// [pub] is the public key of the macOS device and is used to verify the device. TPM devices +// do not require a public key and should pass nil. +func WithPreEnrolledDevice(dev *devicepb.Device, pub *ecdsa.PublicKey) Opt { + return func(e *E) { + e.Service.mu.Lock() + defer e.Service.mu.Unlock() + e.Service.devices = append(e.Service.devices, + storedDevice{ + pb: dev, + enrollToken: FakeEnrollmentToken, + pub: pub, + }, + ) + } +} + // E is an integrated test environment for device trust. type E struct { DevicesClient devicepb.DeviceTrustServiceClient @@ -150,3 +171,39 @@ type FakeDevice interface { SolveTPMAuthnDeviceChallenge(challenge *devicepb.TPMAuthenticateDeviceChallenge) (*devicepb.TPMAuthenticateDeviceChallengeResponse, error) GetDeviceCredential() *devicepb.DeviceCredential } + +// CreateEnrolledDevice converts a FakeDevice into a [*devicepb.Device] whose EnrollStatus is +// DEVICE_ENROLL_STATUS_ENROLLED and Id set to deviceID. It also returns the public key of the +// device if the device is a macOS device, otherwise it returns nil. +func CreateEnrolledDevice(deviceID string, d FakeDevice) (*devicepb.Device, *ecdsa.PublicKey, error) { + now := timestamppb.Now() + initReq, err := d.EnrollDeviceInit() + if err != nil { + return nil, nil, trace.Wrap(err) + } + + var pub *ecdsa.PublicKey + if d.GetDeviceOSType() == devicepb.OSType_OS_TYPE_MACOS { + pubKey, err := x509.ParsePKIXPublicKey(initReq.Macos.PublicKeyDer) + if err != nil { + return nil, nil, trace.Wrap(err) + } + var ok bool + pub, ok = pubKey.(*ecdsa.PublicKey) + if !ok { + return nil, nil, trace.BadParameter("expected ECDSA public key, got %T", pubKey) + } + } + + dev := &devicepb.Device{ + ApiVersion: "v1", + Id: deviceID, + OsType: d.GetDeviceOSType(), + AssetTag: initReq.DeviceData.SerialNumber, + CreateTime: now, + UpdateTime: now, + Credential: d.GetDeviceCredential(), + EnrollStatus: devicepb.DeviceEnrollStatus_DEVICE_ENROLL_STATUS_ENROLLED, + } + return dev, pub, nil +} diff --git a/lib/events/api.go b/lib/events/api.go index 064c104bf3f72..a007fe25ff106 100644 --- a/lib/events/api.go +++ b/lib/events/api.go @@ -751,6 +751,8 @@ const ( ClusterNetworkingConfigUpdateEvent = "cluster_networking_config.update" // SessionRecordingConfigUpdateEvent is emitted when a user updates the cluster session recording configuration. SessionRecordingConfigUpdateEvent = "session_recording_config.update" + // AccessGraphSettingsUpdateEvent is emitted when a user updates the access graph settings configuration. + AccessGraphSettingsUpdateEvent = "access_graph_settings.update" // AccessGraphAccessPathChangedEvent is emitted when an access path is changed in the access graph // and an identity/resource is affected. diff --git a/lib/events/codes.go b/lib/events/codes.go index e7407cb8e3e11..701826ada6400 100644 --- a/lib/events/codes.go +++ b/lib/events/codes.go @@ -609,6 +609,8 @@ const ( ClusterNetworkingConfigUpdateCode = "TCNET002I" // SessionRecordingConfigUpdateCode is the session recording config updated event code. SessionRecordingConfigUpdateCode = "TCREC003I" + // AccessGraphSettingsUpdateCode is the access graph settings updated event code. + AccessGraphSettingsUpdateCode = "TCAGC003I" // AccessGraphAccessPathChangedCode is the access graph access path changed event code. AccessGraphAccessPathChangedCode = "TAG001I" diff --git a/lib/events/dynamic.go b/lib/events/dynamic.go index a0dcea1922ac1..ec5037aff957f 100644 --- a/lib/events/dynamic.go +++ b/lib/events/dynamic.go @@ -371,6 +371,8 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) { e = &events.ClusterNetworkingConfigUpdate{} case SessionRecordingConfigUpdateEvent: e = &events.SessionRecordingConfigUpdate{} + case AccessGraphSettingsUpdateEvent: + e = &events.AccessGraphSettingsUpdate{} case DatabaseSessionSpannerRPCEvent: e = &events.SpannerRPC{} case UnknownEvent: diff --git a/lib/secretsscanner/authorizedkeys/authorized_keys.go b/lib/secretsscanner/authorizedkeys/authorized_keys.go new file mode 100644 index 0000000000000..ae6e2adb1b8c8 --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/authorized_keys.go @@ -0,0 +1,348 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +import ( + "bufio" + "context" + "errors" + "log/slog" + "os" + "os/user" + "path/filepath" + "runtime" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/gravitational/trace" + "github.com/jonboulle/clockwork" + "golang.org/x/crypto/ssh" + + "github.com/gravitational/teleport/api/constants" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + "github.com/gravitational/teleport/api/types/accessgraph" + "github.com/gravitational/teleport/api/utils/retryutils" +) + +var ( + // ErrUnsupportedPlatform is returned when the operating system is not supported. + ErrUnsupportedPlatform = errors.New("unsupported platform") +) + +// Watcher watches for changes to authorized_keys files +// and reports them to the cluster. If the cluster does not have +// scanning enabled, the watcher will hold until the feature is enabled. +type Watcher struct { + // client is the client to use to communicate with the cluster. + client ClusterClient + logger *slog.Logger + clock clockwork.Clock + hostID string + getHostUsers func() ([]user.User, error) +} + +// ClusterClient is the client to use to communicate with the cluster. +type ClusterClient interface { + GetClusterAccessGraphConfig(context.Context) (*clusterconfigpb.AccessGraphConfig, error) + AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient +} + +// WatcherConfig is the configuration for the Watcher. +type WatcherConfig struct { + // Client is the client to use to communicate with the cluster. + Client ClusterClient + // Logger is the logger to use. + Logger *slog.Logger + // Clock is the clock to use. + Clock clockwork.Clock + // HostID is the ID of the host. + HostID string + // getRuntimeOS returns the runtime operating system. + // used for testing purposes. + getRuntimeOS func() string + // getHostUsers is a function that returns the list of users on the system. + // used for testing purposes. When nil, it uses the default implementation + // that leverages getpwent. + getHostUsers func() ([]user.User, error) +} + +// NewWatcher creates a new Watcher instance. +// Returns [ErrUnsupportedPlatform] if the operating system is not supported. +func NewWatcher(ctx context.Context, config WatcherConfig) (*Watcher, error) { + + switch platform := getOS(config); platform { + case constants.LinuxOS, constants.DarwinOS: + default: + return nil, trace.Wrap(ErrUnsupportedPlatform) + } + + if config.HostID == "" { + return nil, trace.BadParameter("missing host ID") + } + if config.Client == nil { + return nil, trace.BadParameter("missing client") + } + if config.Logger == nil { + config.Logger = slog.Default() + } + if config.Clock == nil { + config.Clock = clockwork.NewRealClock() + } + if config.getHostUsers == nil { + config.getHostUsers = getHostUsers + } + + w := &Watcher{ + client: config.Client, + logger: config.Logger, + clock: config.Clock, + hostID: config.HostID, + getHostUsers: config.getHostUsers, + } + + return w, nil +} + +func (w *Watcher) Run(ctx context.Context) error { + return trace.Wrap(w.monitorClusterConfigAndStart(ctx)) +} + +func (w *Watcher) monitorClusterConfigAndStart(ctx context.Context) error { + const tickerInterval = 30 * time.Minute + return trace.Wrap(supervisorRunner(ctx, supervisorRunnerConfig{ + clock: w.clock, + tickerInterval: tickerInterval, + runner: w.start, + checkIfMonitorEnabled: w.isAuthorizedKeysReportEnabled, + logger: w.logger, + })) +} + +// start starts the watcher. +func (w *Watcher) start(ctx context.Context) error { + wg := sync.WaitGroup{} + defer wg.Wait() + + fileWatcher, err := fsnotify.NewWatcher() + if err != nil { + return trace.Wrap(err) + } + defer func() { + if err := fileWatcher.Close(); err != nil { + w.logger.WarnContext(ctx, "Failed to close watcher", "error", err) + } + }() + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + reload := make(chan struct{}) + wg.Add(1) + go func() { + defer wg.Done() + for { + select { + case <-ctx.Done(): + return + case <-fileWatcher.Events: + innerLoop: + for { + select { + case <-ctx.Done(): + return + case <-fileWatcher.Events: + case reload <- struct{}{}: + break innerLoop + } + } + case err := <-fileWatcher.Errors: + w.logger.WarnContext(ctx, "Error watching authorized_keys file", "error", err) + } + } + }() + + const etcPasswd = "/etc/passwd" + if err := fileWatcher.Add(etcPasswd); err != nil { + w.logger.WarnContext(ctx, "Failed to add watcher for file", "error", err) + } + + stream, err := w.client.AccessGraphSecretsScannerClient().ReportAuthorizedKeys(ctx) + if err != nil { + return trace.Wrap(err) + } + + // Wait for the initial delay before sending the first report to spread the load. + // The initial delay is a random value between 0 and maxInitialDelay. + const maxInitialDelay = 5 * time.Minute + select { + case <-ctx.Done(): + return nil + case <-w.clock.After(retryutils.NewFullJitter()(maxInitialDelay)): + } + + jitterFunc := retryutils.NewHalfJitter() + // maxReSendInterval is the maximum interval to re-send the authorized keys report + // to the cluster in case of no changes. + const maxReSendInterval = accessgraph.AuthorizedKeyDefaultKeyTTL - 20*time.Minute + timer := w.clock.NewTimer(jitterFunc(maxReSendInterval)) + defer timer.Stop() + for { + + if err := w.fetchAndReportAuthorizedKeys(ctx, stream, fileWatcher); err != nil { + w.logger.WarnContext(ctx, "Failed to report authorized keys", "error", err) + } + + if !timer.Stop() { + <-timer.Chan() + } + timer.Reset(jitterFunc(maxReSendInterval)) + + select { + case <-ctx.Done(): + return nil + case <-reload: + case <-timer.Chan(): + } + } +} + +// isAuthorizedKeysReportEnabled checks if the cluster has authorized keys report enabled. +func (w *Watcher) isAuthorizedKeysReportEnabled(ctx context.Context) (bool, error) { + accessGraphConfig, err := w.client.GetClusterAccessGraphConfig(ctx) + if err != nil { + return false, trace.Wrap(err) + } + return accessGraphConfig.GetEnabled() && accessGraphConfig.GetSecretsScanConfig().GetSshScanEnabled(), nil +} + +// fetchAndReportAuthorizedKeys fetches the authorized keys from the system and reports them to the cluster. +func (w *Watcher) fetchAndReportAuthorizedKeys( + ctx context.Context, + stream accessgraphsecretsv1pb.SecretsScannerService_ReportAuthorizedKeysClient, + fileWatcher *fsnotify.Watcher, +) error { + users, err := w.getHostUsers() + if err != nil { + return trace.Wrap(err) + } + var keys []*accessgraphsecretsv1pb.AuthorizedKey + for _, u := range users { + if u.HomeDir == "" { + w.logger.DebugContext(ctx, "Skipping user with empty home directory", "user", u.Name) + continue + } + + for _, file := range []string{"authorized_keys", "authorized_keys2"} { + authorizedKeysPath := filepath.Join(u.HomeDir, ".ssh", file) + if fs, err := os.Stat(authorizedKeysPath); err != nil || fs.IsDir() { + continue + } + + hostKeys, err := w.parseAuthorizedKeysFile(ctx, u, authorizedKeysPath) + if errors.Is(err, os.ErrNotExist) { + continue + } else if err != nil { + w.logger.WarnContext(ctx, "Failed to parse authorized_keys file", "error", err) + continue + } + + // Add the file to the watcher. If file was already added, this is a no-op. + if err := fileWatcher.Add(authorizedKeysPath); err != nil { + w.logger.WarnContext(ctx, "Failed to add watcher for file", "error", err) + } + keys = append(keys, hostKeys...) + } + } + + const maxKeysPerReport = 500 + for i := 0; i < len(keys); i += maxKeysPerReport { + start := i + end := min(i+maxKeysPerReport, len(keys)) + if err := stream.Send( + &accessgraphsecretsv1pb.ReportAuthorizedKeysRequest{ + Keys: keys[start:end], + Operation: accessgraphsecretsv1pb.OperationType_OPERATION_TYPE_ADD, + }, + ); err != nil { + return trace.Wrap(err) + } + } + + if err := stream.Send( + &accessgraphsecretsv1pb.ReportAuthorizedKeysRequest{Operation: accessgraphsecretsv1pb.OperationType_OPERATION_TYPE_SYNC}, + ); err != nil { + return trace.Wrap(err) + } + return nil +} + +func (w *Watcher) parseAuthorizedKeysFile(ctx context.Context, u user.User, authorizedKeysPath string) ([]*accessgraphsecretsv1pb.AuthorizedKey, error) { + file, err := os.Open(authorizedKeysPath) + if err != nil { + return nil, trace.Wrap(err) + } + defer func() { + if err := file.Close(); err != nil { + w.logger.WarnContext(ctx, "Failed to close file", "error", err, "path", authorizedKeysPath) + } + }() + + var keys []*accessgraphsecretsv1pb.AuthorizedKey + scanner := bufio.NewScanner(file) + scanner.Split(bufio.ScanLines) + for scanner.Scan() { + payload := scanner.Bytes() + if len(payload) == 0 || payload[0] == '#' { + continue + } + parsedKey, comment, _, _, err := ssh.ParseAuthorizedKey(payload) + if err != nil { + w.logger.WarnContext(ctx, "Failed to parse authorized key", "error", err) + continue + } else if parsedKey == nil { + continue + } + + authorizedKey, err := accessgraph.NewAuthorizedKey( + &accessgraphsecretsv1pb.AuthorizedKeySpec{ + HostId: w.hostID, + HostUser: u.Username, + KeyFingerprint: ssh.FingerprintSHA256(parsedKey), + KeyComment: comment, + KeyType: parsedKey.Type(), + }, + ) + if err != nil { + w.logger.WarnContext(ctx, "Failed to create authorized key", "error", err) + continue + } + keys = append(keys, authorizedKey) + } + + return keys, nil +} + +func getOS(config WatcherConfig) string { + goos := runtime.GOOS + if config.getRuntimeOS != nil { + goos = config.getRuntimeOS() + } + return goos +} diff --git a/lib/secretsscanner/authorizedkeys/authorized_keys_test.go b/lib/secretsscanner/authorizedkeys/authorized_keys_test.go new file mode 100644 index 0000000000000..1a512221041c8 --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/authorized_keys_test.go @@ -0,0 +1,246 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +import ( + "context" + "fmt" + "log/slog" + "os" + "os/user" + "path/filepath" + "slices" + "sync" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/gravitational/trace" + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" + "google.golang.org/protobuf/testing/protocmp" + + "github.com/gravitational/teleport/api/constants" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types/accessgraph" +) + +func TestAuthorizedKeys(t *testing.T) { + hostID := "hostID" + + dir := createFSData(t) + clock := clockwork.NewFakeClockAt(time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)) + client := &fakeClient{} + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + watcher, err := NewWatcher(ctx, WatcherConfig{ + Client: client, + getHostUsers: func() ([]user.User, error) { + return exampleUsers(dir) + }, + HostID: hostID, + Clock: clock, + Logger: slog.Default(), + getRuntimeOS: func() string { + return constants.LinuxOS + }, + }) + require.NoError(t, err) + + // Start the watcher + group, ctx := errgroup.WithContext(ctx) + group.Go(func() error { + return trace.Wrap(watcher.Run(ctx)) + }) + + // Wait for the watcher to start and to block on the initial spread. + clock.BlockUntil(2) // wait for clock to blocked at supervisor and initial delay routine + // Advance the clock to trigger the first scan + clock.Advance(5 * time.Minute) + + // Wait for the watcher to start + require.Eventually(t, func() bool { + return len(client.getReqReceived()) == 2 + }, 1*time.Second, 10*time.Millisecond, "expected watcher to start, but it did not") + + // Check the requests + got := client.getReqReceived() + require.Len(t, got, 2) + expected := []*accessgraphsecretsv1pb.ReportAuthorizedKeysRequest{ + { + Keys: createKeysForUsers(t, hostID), + Operation: accessgraphsecretsv1pb.OperationType_OPERATION_TYPE_ADD, + }, + { + Operation: accessgraphsecretsv1pb.OperationType_OPERATION_TYPE_SYNC, + }, + } + require.Empty(t, cmp.Diff(got, expected, + protocmp.Transform(), + protocmp.SortRepeated( + func(a, b *accessgraphsecretsv1pb.AuthorizedKey) bool { + return a.Metadata.Name < b.Metadata.Name + }, + ), + protocmp.IgnoreFields(&headerv1.Metadata{}, "expires"), + ), + ) + + // Clear the requests + client.clear() + + cancel() + err = group.Wait() + require.NoError(t, err) + +} + +func createFSData(t *testing.T) string { + dir := t.TempDir() + + createUsersAndAuthorizedKeys(t, dir) + return dir +} + +func createFile(t *testing.T, dir, name, content string) { + err := os.MkdirAll(dir, 0755) + require.NoError(t, err) + path := fmt.Sprintf("%s/%s", dir, name) + err = os.WriteFile(path, []byte(content), 0644) + require.NoError(t, err) +} + +func exampleUsers(dir string) ([]user.User, error) { + return []user.User{ + { + Name: "root", + Username: "root", + Uid: "0", + Gid: "0", + HomeDir: fmt.Sprintf("%s/root", dir), + }, + { + Name: "bin", + Username: "bin", + Uid: "1", + Gid: "1", + HomeDir: "/", + }, + { + Name: "user", + Username: "user", + Uid: "1000", + Gid: "1000", + HomeDir: fmt.Sprintf("%s/user", dir), + }, + }, nil + +} + +const authorizedFileExample = ` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQClwXUKOp/S4XEtFjgr8mfaCy4OyI7N9ZMibdCGxvk2VHP9+Vn8Al1lUSVwuBxHI7EHiq42RCTBetIpTjzn6yiPNAeGNL5cfl9i6r+P5k7og1hz+2oheWveGodx6Dp+Z4o2dw65NGf5EPaotXF8AcHJc3+OiMS5yp/x2A3tu2I1SPQ6dtPa067p8q1L49BKbFwrFRBCVwkr6kpEQAIjnMESMPGD5Buu/AtyAdEZQSLTt8RZajJZDfXFKMEtQm2UF248NFl3hSMAcbbTxITBbZxX7THbwQz22Yuw7422G5CYBPf6WRXBY84Rs6jCS4I4GMxj+3rF4mGtjvuz0wOE32s3w4eMh9h3bPuEynufjE8henmPCIW49+kuZO4LZut7Zg5BfVDQnZYclwokEIMz+gR02YpyflxQOa98t/0mENu+t4f0LNAdkQEBpYtGKKDth5kLphi2Sdi9JpGO2sTivlxMsGyBqdd0wT9VwQpWf4wro6t09HdZJX1SAuEi/0tNI10= friel@test +# comment +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGtqQKEkGIY5+Bc4EmEv7NeSn6aA7KMl5eiNEAOqwTBl friel@test +invalidLine +# comment +` + +func createUsersAndAuthorizedKeys(t *testing.T, dir string) { + for _, user := range []string{"root", "user"} { + dir := filepath.Join(dir, user, ".ssh") + createFile(t, dir, "authorized_keys", authorizedFileExample) + } +} + +type fakeClient struct { + accessgraphsecretsv1pb.SecretsScannerServiceClient + accessgraphsecretsv1pb.SecretsScannerService_ReportAuthorizedKeysClient + mu sync.Mutex + reqReceived []*accessgraphsecretsv1pb.ReportAuthorizedKeysRequest +} + +func (f *fakeClient) GetClusterAccessGraphConfig(_ context.Context) (*clusterconfigpb.AccessGraphConfig, error) { + return &clusterconfigpb.AccessGraphConfig{ + Enabled: true, + SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{ + SshScanEnabled: true, + }, + }, nil +} +func (f *fakeClient) AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient { + return f +} + +func (f *fakeClient) ReportAuthorizedKeys(_ context.Context, _ ...grpc.CallOption) (accessgraphsecretsv1pb.SecretsScannerService_ReportAuthorizedKeysClient, error) { + return f, nil +} + +func (f *fakeClient) Send(req *accessgraphsecretsv1pb.ReportAuthorizedKeysRequest) error { + f.mu.Lock() + defer f.mu.Unlock() + f.reqReceived = append(f.reqReceived, req) + return nil +} + +func (f *fakeClient) clear() { + f.mu.Lock() + defer f.mu.Unlock() + f.reqReceived = nil +} + +func (f *fakeClient) getReqReceived() []*accessgraphsecretsv1pb.ReportAuthorizedKeysRequest { + f.mu.Lock() + defer f.mu.Unlock() + return slices.Clone(f.reqReceived) +} + +func createKeysForUsers(t *testing.T, hostID string) []*accessgraphsecretsv1pb.AuthorizedKey { + var keys []*accessgraphsecretsv1pb.AuthorizedKey + for _, k := range []struct { + fingerprint string + keyType string + }{ + { + fingerprint: "SHA256:GbJlTLeQgZhvGoklWGXHo0AinGgGEcldllgYExoSy+s", + keyType: "ssh-ed25519", + }, + { + fingerprint: "SHA256:ewwMB/nCAYurNrYFXYZuxLZv7T7vgpPd7QuIo0d5n+U", + keyType: "ssh-rsa", + }, + } { + for _, user := range []string{"root", "user"} { + at, err := accessgraph.NewAuthorizedKey(&accessgraphsecretsv1pb.AuthorizedKeySpec{ + HostId: hostID, + HostUser: user, + KeyFingerprint: k.fingerprint, + KeyComment: "friel@test", + KeyType: k.keyType, + }) + require.NoError(t, err) + keys = append(keys, at) + } + } + return keys +} diff --git a/lib/secretsscanner/authorizedkeys/supervisor.go b/lib/secretsscanner/authorizedkeys/supervisor.go new file mode 100644 index 0000000000000..c0048abb07877 --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/supervisor.go @@ -0,0 +1,112 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +import ( + "context" + "errors" + "log/slog" + "sync" + "time" + + "github.com/jonboulle/clockwork" + + "github.com/gravitational/teleport/api/utils/retryutils" +) + +var errShutdown = errors.New("watcher is shutting down") + +type supervisorRunnerConfig struct { + clock clockwork.Clock + tickerInterval time.Duration + runner func(context.Context) error + checkIfMonitorEnabled func(context.Context) (bool, error) + logger *slog.Logger +} + +// supervisorRunner runs the runner based on the checkIfMonitorEnabled result. +// If the monitor is enabled, the runner is started. If the monitor is disabled, +// the runner is stopped if it is running. +// The checkIfMonitorEnabled is evaluated every tickerInterval duration to determine +// if the monitor should be started or stopped. +// tickerInterval is jittered to prevent all watchers from running at the same time. +// If the watcher is stopped, it will be restarted after the next checkIfMonitorEnabled evaluation. +func supervisorRunner(parentCtx context.Context, cfg supervisorRunnerConfig) error { + var ( + isRunning = false + runCtx context.Context + runCtxCancel context.CancelCauseFunc + wg sync.WaitGroup + mu sync.Mutex + ) + + getIsRunning := func() bool { + mu.Lock() + defer mu.Unlock() + return isRunning + } + + setIsRunning := func(s bool) { + mu.Lock() + defer mu.Unlock() + isRunning = s + } + + runRoutine := func(ctx context.Context, cancel context.CancelCauseFunc) { + defer func() { + wg.Done() + cancel(errShutdown) + setIsRunning(false) + }() + if err := cfg.runner(ctx); err != nil && !errors.Is(err, errShutdown) { + cfg.logger.WarnContext(ctx, "Runner failed", "error", err) + } + } + + jitterFunc := retryutils.NewHalfJitter() + t := cfg.clock.NewTimer(jitterFunc(cfg.tickerInterval)) + for { + switch enabled, err := cfg.checkIfMonitorEnabled(parentCtx); { + case err != nil: + cfg.logger.WarnContext(parentCtx, "Failed to check if authorized keys report is enabled", "error", err) + case enabled && !getIsRunning(): + runCtx, runCtxCancel = context.WithCancelCause(parentCtx) + setIsRunning(true) + wg.Add(1) + go runRoutine(runCtx, runCtxCancel) + case !enabled && getIsRunning(): + runCtxCancel(errShutdown) + // Wait for the runner to stop before checking if the monitor is enabled again. + wg.Wait() + } + + select { + case <-t.Chan(): + if !t.Stop() { + select { + case <-t.Chan(): + default: + } + } + t.Reset(jitterFunc(cfg.tickerInterval)) + case <-parentCtx.Done(): + return nil + } + } +} diff --git a/lib/secretsscanner/authorizedkeys/supervisor_test.go b/lib/secretsscanner/authorizedkeys/supervisor_test.go new file mode 100644 index 0000000000000..93399ec1fdc5b --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/supervisor_test.go @@ -0,0 +1,135 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +import ( + "context" + "log/slog" + "sync" + "testing" + "time" + + "github.com/jonboulle/clockwork" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" +) + +func TestSupervisorRunner(t *testing.T) { + // Create a mock clock + clock := clockwork.NewFakeClock() + + t.Run("runner starts and stops based on monitor state", func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var mu sync.Mutex + var running bool + + runner := func(ctx context.Context) error { + mu.Lock() + running = true + mu.Unlock() + <-ctx.Done() + mu.Lock() + running = false + mu.Unlock() + return nil + } + + checker, enable, disable := checkIfMonitorEnabled() + enable() + + cfg := supervisorRunnerConfig{ + clock: clock, + tickerInterval: 1 * time.Second, + runner: runner, + checkIfMonitorEnabled: checker, + logger: slog.Default(), + } + + g, ctx := errgroup.WithContext(ctx) + g.Go(func() error { + return supervisorRunner(ctx, cfg) + }) + + require.Eventually(t, func() bool { + mu.Lock() + defer mu.Unlock() + return running + }, 100*time.Millisecond, 10*time.Millisecond, "expected runner to start, but it did not") + + disable() + + clock.BlockUntil(1) + clock.Advance(2 * time.Second) + + require.Eventually(t, func() bool { + mu.Lock() + defer mu.Unlock() + return !running + }, 100*time.Millisecond, 10*time.Millisecond, "expected runner to stop, but it did not") + + enable() + clock.BlockUntil(1) + clock.Advance(2 * time.Second) + + require.Eventually(t, func() bool { + mu.Lock() + defer mu.Unlock() + return running + }, 100*time.Millisecond, 10*time.Millisecond, "expected runner to re-start, but it did not") + + disable() + clock.BlockUntil(1) + clock.Advance(2 * time.Second) + + require.Eventually(t, func() bool { + mu.Lock() + defer mu.Unlock() + return !running + }, 100*time.Millisecond, 10*time.Millisecond, "expected runner to re-stop, but it did not") + + // Cancel the context to stop the supervisor + cancel() + if err := g.Wait(); err != nil { + t.Fatal(err) + } + }) + +} + +func checkIfMonitorEnabled() (checker func(context.Context) (bool, error), enable func(), disable func()) { + var ( + enabled bool + mu sync.Mutex + ) + return func(ctx context.Context) (bool, error) { + mu.Lock() + defer mu.Unlock() + return enabled, nil + }, func() { + mu.Lock() + defer mu.Unlock() + enabled = true + }, func() { + mu.Lock() + defer mu.Unlock() + enabled = false + } +} diff --git a/lib/secretsscanner/authorizedkeys/users_list.go b/lib/secretsscanner/authorizedkeys/users_list.go new file mode 100644 index 0000000000000..70f3bc2bbdff1 --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/users_list.go @@ -0,0 +1,43 @@ +//go:build !windows + +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +/* +#cgo CFLAGS: -D_POSIX_PTHREAD_SEMANTICS +#include +*/ +import "C" + +import ( + "os/user" + "strconv" +) + +// passwdC2Go converts `passwd` struct from C to golang native struct +func passwdC2Go(passwdC *C.struct_passwd) user.User { + return user.User{ + Name: C.GoString(passwdC.pw_name), + Username: C.GoString(passwdC.pw_name), + Uid: strconv.FormatUint(uint64(passwdC.pw_uid), 10), + Gid: strconv.FormatUint(uint64(passwdC.pw_gid), 10), + HomeDir: C.GoString(passwdC.pw_dir), + } +} diff --git a/lib/secretsscanner/authorizedkeys/users_list_darwin.go b/lib/secretsscanner/authorizedkeys/users_list_darwin.go new file mode 100644 index 0000000000000..9155cf4392e68 --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/users_list_darwin.go @@ -0,0 +1,47 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +/* +#cgo CFLAGS: -D_POSIX_PTHREAD_SEMANTICS +#include +*/ +import "C" + +import ( + "os/user" +) + +// getHostUsers returns a list of all users on the host +// from local /etc/passwd file, LDAP, or other user databases. +func getHostUsers() (results []user.User, _ error) { + C.setpwent() + var result *C.struct_passwd + for { + result = C.getpwent() /* on darwin, getpwent() is reentrant */ + if result == nil { + break + } + results = append(results, passwdC2Go(result)) + } + + C.endpwent() + + return results, nil +} diff --git a/lib/secretsscanner/authorizedkeys/users_list_unix.go b/lib/secretsscanner/authorizedkeys/users_list_unix.go new file mode 100644 index 0000000000000..b8c2dc45ffa9c --- /dev/null +++ b/lib/secretsscanner/authorizedkeys/users_list_unix.go @@ -0,0 +1,67 @@ +//go:build !darwin + +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package authorizedkeys + +/* +#cgo CFLAGS: -D_POSIX_PTHREAD_SEMANTICS -D__USE_MISC +#include +#include +#include +#include +*/ +import "C" + +import ( + "os/user" + + "github.com/gravitational/trace" +) + +// getHostUsers returns a list of all users on the host +// from local /etc/passwd file, LDAP, or other user databases. +func getHostUsers() (results []user.User, _ error) { + + bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX) + if bufSize == -1 { + bufSize = 16384 + } + if bufSize <= 0 || bufSize > 1<<20 { + return nil, trace.BadParameter("unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize) + } + buf := C.malloc(C.size_t(bufSize)) + defer C.free(buf) + + C.setpwent() + + var pwdBuf C.struct_passwd + for { + var result *C.struct_passwd + rv := C.getpwent_r(&pwdBuf, (*C.char)(buf), C.size_t(bufSize), &result) + if rv != 0 || result == nil { + break + } + results = append(results, passwdC2Go(&pwdBuf)) + } + + C.endpwent() + + return results, nil +} diff --git a/lib/secretsscanner/client/client.go b/lib/secretsscanner/client/client.go new file mode 100644 index 0000000000000..1ea24ec1ff97f --- /dev/null +++ b/lib/secretsscanner/client/client.go @@ -0,0 +1,109 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package client + +import ( + "context" + "log/slog" + + "github.com/gravitational/trace" + "github.com/jonboulle/clockwork" + "google.golang.org/grpc" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + proxyinsecureclient "github.com/gravitational/teleport/lib/client/proxy/insecure" +) + +// Client is a client for the SecretsScannerService. +type Client interface { + // ReportSecrets is used by trusted devices to report secrets found on the host that could be used to bypass Teleport. + // The client (device) should first authenticate using the [ReportSecretsRequest.device_assertion] flow. Please refer to + // the [teleport.devicetrust.v1.AssertDeviceRequest] and [teleport.devicetrust.v1.AssertDeviceResponse] messages for more details. + // + // Once the device is asserted, the client can send the secrets using the [ReportSecretsRequest.private_keys] field + // and then close the client side of the stream. + // + // -> ReportSecrets (client) [1 or more] + // -> CloseStream (client) + // <- TerminateStream (server) + // + // Any failure in the assertion ceremony will result in the stream being terminated by the server. All secrets + // reported by the client before the assertion terminates will be ignored and result in the stream being terminated. + ReportSecrets(ctx context.Context, opts ...grpc.CallOption) (accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient, error) + // Close closes the client connection. + Close() error +} + +// ClientConfig specifies parameters for the client to dial credentialless via the proxy. +type ClientConfig struct { + // ProxyServer is the address of the proxy server + ProxyServer string + // CipherSuites is a list of cipher suites to use for TLS client connection + CipherSuites []uint16 + // Clock specifies the time provider. Will be used to override the time anchor + // for TLS certificate verification. + // Defaults to real clock if unspecified + Clock clockwork.Clock + // Insecure trusts the certificates from the Auth Server or Proxy during registration without verification. + Insecure bool + // Log is the logger. + Log *slog.Logger +} + +// NewSecretsScannerServiceClient creates a new SecretsScannerServiceClient that connects to the proxy +// gRPC server that does not require authentication (credentialless) to report secrets found during scanning. +func NewSecretsScannerServiceClient(ctx context.Context, cfg ClientConfig) (Client, error) { + if cfg.ProxyServer == "" { + return nil, trace.BadParameter("missing ProxyServer") + } + if cfg.Clock == nil { + cfg.Clock = clockwork.NewRealClock() + } + if cfg.Log == nil { + cfg.Log = slog.Default() + } + + grpcConn, err := proxyinsecureclient.NewConnection( + ctx, + proxyinsecureclient.ConnectionConfig{ + ProxyServer: cfg.ProxyServer, + CipherSuites: cfg.CipherSuites, + Clock: cfg.Clock, + Insecure: cfg.Insecure, + Log: cfg.Log, + }, + ) + if err != nil { + return nil, trace.Wrap(err, "failed to connect to the proxy") + } + + return &secretsSvcClient{ + SecretsScannerServiceClient: accessgraphsecretsv1pb.NewSecretsScannerServiceClient(grpcConn), + conn: grpcConn, + }, nil +} + +type secretsSvcClient struct { + accessgraphsecretsv1pb.SecretsScannerServiceClient + conn *grpc.ClientConn +} + +func (c *secretsSvcClient) Close() error { + return c.conn.Close() +} diff --git a/lib/secretsscanner/proxy/proxy.go b/lib/secretsscanner/proxy/proxy.go new file mode 100644 index 0000000000000..c9888f9b5910c --- /dev/null +++ b/lib/secretsscanner/proxy/proxy.go @@ -0,0 +1,134 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +// Package proxy implements a proxy service that proxies requests from the proxy unauthenticated +// gRPC service to the Auth's secret service. +package proxy + +import ( + "context" + "errors" + "io" + "log/slog" + + "github.com/gravitational/trace" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" +) + +// AuthClient is a subset of the full Auth API that must be connected +type AuthClient interface { + AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient +} + +// ServiceConfig is the configuration for the Service. +type ServiceConfig struct { + // AuthClient is the client to the Auth service. + AuthClient AuthClient + // Log is the logger. + Log *slog.Logger +} + +// New creates a new Service. +func New(cfg ServiceConfig) (*Service, error) { + if cfg.AuthClient == nil { + return nil, trace.BadParameter("missing AuthClient") + } + if cfg.Log == nil { + cfg.Log = slog.Default() + } + return &Service{ + authClient: cfg.AuthClient, + log: cfg.Log, + }, nil +} + +// Service is a service that proxies requests from the proxy to the Auth's secret service. +// It only implements the ReportSecrets method of the SecretsScannerService because it is the only method that needs to be proxied +// from the proxy to the Auth's secret service. +type Service struct { + accessgraphsecretsv1pb.UnimplementedSecretsScannerServiceServer + // authClient is the client to the Auth service. + authClient AuthClient + + log *slog.Logger +} + +// ReportSecrets proxies the ReportSecrets method from the proxy to the Auth's secret service. +func (s *Service) ReportSecrets(client accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer) error { + ctx, cancel := context.WithCancel(client.Context()) + defer cancel() + upstream, err := s.authClient.AccessGraphSecretsScannerClient().ReportSecrets(ctx) + if err != nil { + return trace.Wrap(err) + } + + errCh := make(chan error, 1) + go func() { + err := trace.Wrap(s.forwardClientToServer(ctx, client, upstream)) + if err != nil { + cancel() + } + errCh <- err + }() + + err = s.forwardServerToClient(ctx, client, upstream) + return trace.NewAggregate(err, <-errCh) +} + +func (s *Service) forwardClientToServer(ctx context.Context, + client accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer, + server accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient) (err error) { + for { + req, err := client.Recv() + if errors.Is(err, io.EOF) { + if err := server.CloseSend(); err != nil { + s.log.WarnContext(ctx, "Failed to close upstream stream", "error", err) + } + break + } + if err != nil { + s.log.WarnContext(ctx, "Failed to receive from client stream", "error", err) + return trace.Wrap(err) + } + if err := server.Send(req); err != nil { + s.log.WarnContext(ctx, "Failed to send to upstream stream", "error", err) + return trace.Wrap(err) + } + } + return nil +} + +func (s *Service) forwardServerToClient(ctx context.Context, + client accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer, + server accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient) (err error) { + for { + out, err := server.Recv() + if errors.Is(err, io.EOF) { + return nil + } + if err != nil { + s.log.WarnContext(ctx, "Failed to receive from upstream stream", "error", err) + return trace.Wrap(err) + } + if err := client.Send(out); err != nil { + s.log.WarnContext(ctx, "Failed to send to client stream", "error", err) + return trace.Wrap(err) + } + } +} diff --git a/lib/secretsscanner/proxy/proxy_test.go b/lib/secretsscanner/proxy/proxy_test.go new file mode 100644 index 0000000000000..91be3288fef85 --- /dev/null +++ b/lib/secretsscanner/proxy/proxy_test.go @@ -0,0 +1,221 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package proxy + +import ( + "context" + "crypto/tls" + "errors" + "io" + "net" + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" + + "github.com/gravitational/teleport/api/defaults" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + "github.com/gravitational/teleport/lib/fixtures" + secretscannerclient "github.com/gravitational/teleport/lib/secretsscanner/client" +) + +func TestProxy(t *testing.T) { + // Disable the TLS routing connection upgrade + t.Setenv(defaults.TLSRoutingConnUpgradeEnvVar, "false") + + authClient := newFakefakeSecretsScannerSvc(t) + + lis, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + + newProxyService(t, lis, authClient) + ctx := context.Background() + + client, err := secretscannerclient.NewSecretsScannerServiceClient(ctx, secretscannerclient.ClientConfig{ + ProxyServer: lis.Addr().String(), + Insecure: true, + }) + require.NoError(t, err) + + stream, err := client.ReportSecrets(ctx) + require.NoError(t, err) + + // Send the device assertion init message + err = stream.Send(&accessgraphsecretsv1pb.ReportSecretsRequest{ + Payload: &accessgraphsecretsv1pb.ReportSecretsRequest_DeviceAssertion{ + DeviceAssertion: &devicepb.AssertDeviceRequest{ + Payload: &devicepb.AssertDeviceRequest_Init{ + Init: &devicepb.AssertDeviceInit{}, + }, + }, + }, + }) + require.NoError(t, err) + + // Receive the device assertion challenge message + msg, err := stream.Recv() + require.NoError(t, err) + assert.NotNil(t, msg.GetDeviceAssertion().GetChallenge()) + + // Send the device assertion challenge response message + err = stream.Send(&accessgraphsecretsv1pb.ReportSecretsRequest{ + Payload: &accessgraphsecretsv1pb.ReportSecretsRequest_DeviceAssertion{ + DeviceAssertion: &devicepb.AssertDeviceRequest{ + Payload: &devicepb.AssertDeviceRequest_ChallengeResponse{ + ChallengeResponse: &devicepb.AuthenticateDeviceChallengeResponse{Signature: []byte("response")}, + }, + }, + }, + }) + require.NoError(t, err) + + // Receive the device assertion response message + msg, err = stream.Recv() + require.NoError(t, err) + assert.NotNil(t, msg.GetDeviceAssertion().GetDeviceAsserted()) + + // Send close message + err = stream.CloseSend() + require.NoError(t, err) + + // Receive the termination message + _, err = stream.Recv() + require.ErrorIs(t, err, io.EOF) + +} + +func newFakefakeSecretsScannerSvc(t *testing.T) *fakeSecretsClient { + lis, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + + server := grpc.NewServer() + accessgraphsecretsv1pb.RegisterSecretsScannerServiceServer(server, &fakeSecretsScannerSvc{}) + go func() { + err := server.Serve(lis) + assert.NoError(t, err) + }() + t.Cleanup(server.GracefulStop) + + client, err := grpc.NewClient(lis.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials())) + require.NoError(t, err) + + return &fakeSecretsClient{ + SecretsScannerServiceClient: accessgraphsecretsv1pb.NewSecretsScannerServiceClient(client), + } + +} + +type fakeSecretsClient struct { + accessgraphsecretsv1pb.SecretsScannerServiceClient +} + +func (s *fakeSecretsClient) AccessGraphSecretsScannerClient() accessgraphsecretsv1pb.SecretsScannerServiceClient { + return s +} + +type fakeSecretsScannerSvc struct { + accessgraphsecretsv1pb.UnimplementedSecretsScannerServiceServer +} + +func (f *fakeSecretsScannerSvc) ReportSecrets(in accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer) error { + msg, err := in.Recv() + if err != nil { + return trace.Wrap(err) + } + + if msg.GetDeviceAssertion().GetInit() == nil { + return trace.BadParameter("missing device init") + } + + err = in.Send(&accessgraphsecretsv1pb.ReportSecretsResponse{ + Payload: &accessgraphsecretsv1pb.ReportSecretsResponse_DeviceAssertion{ + DeviceAssertion: &devicepb.AssertDeviceResponse{ + Payload: &devicepb.AssertDeviceResponse_Challenge{ + Challenge: &devicepb.AuthenticateDeviceChallenge{Challenge: []byte("challenge")}, + }, + }, + }, + }) + if err != nil { + return trace.Wrap(err) + } + msg, err = in.Recv() + if err != nil { + return trace.Wrap(err) + } + + if msg.GetDeviceAssertion().GetChallengeResponse() == nil { + return trace.BadParameter("missing device challenge") + } + + err = in.Send(&accessgraphsecretsv1pb.ReportSecretsResponse{ + Payload: &accessgraphsecretsv1pb.ReportSecretsResponse_DeviceAssertion{ + DeviceAssertion: &devicepb.AssertDeviceResponse{ + Payload: &devicepb.AssertDeviceResponse_DeviceAsserted{ + DeviceAsserted: &devicepb.DeviceAsserted{}, + }, + }, + }, + }) + if err != nil { + return trace.Wrap(err) + } + + _, err = in.Recv() + if errors.Is(err, io.EOF) { + return nil + } + return trace.BadParameter("unexpected message") +} + +func newProxyService(t *testing.T, lis net.Listener, authClient AuthClient) { + localTLSConfig, err := fixtures.LocalTLSConfig() + require.NoError(t, err) + + tlsConfig := localTLSConfig.TLS.Clone() + tlsConfig.InsecureSkipVerify = true + tlsConfig.ClientAuth = tls.RequestClientCert + tlsConfig.RootCAs = nil + + s := grpc.NewServer( + grpc.Creds( + credentials.NewTLS(tlsConfig), + ), + ) + t.Cleanup(s.GracefulStop) + + proxy, err := New(ServiceConfig{ + AuthClient: authClient, + }, + ) + require.NoError(t, err) + + accessgraphsecretsv1pb.RegisterSecretsScannerServiceServer(s, proxy) + + go func() { + err := s.Serve(lis) + assert.NoError(t, err) + }() + +} diff --git a/lib/secretsscanner/reporter/env_test.go b/lib/secretsscanner/reporter/env_test.go new file mode 100644 index 0000000000000..04ffebb5c6711 --- /dev/null +++ b/lib/secretsscanner/reporter/env_test.go @@ -0,0 +1,199 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package reporter_test + +import ( + "errors" + "io" + "net" + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + dttestenv "github.com/gravitational/teleport/lib/devicetrust/testenv" + "github.com/gravitational/teleport/lib/fixtures" +) + +type env struct { + secretsScannerAddr string + service *serviceFake +} + +type opts struct { + device *device + preReconcileError error +} + +type device struct { + device dttestenv.FakeDevice + id string +} + +type option func(*opts) + +func withDevice(deviceID string, dev dttestenv.FakeDevice) option { + return func(o *opts) { + o.device = &device{ + device: dev, + id: deviceID, + } + } +} + +func withPreReconcileError(err error) option { + return func(o *opts) { + o.preReconcileError = err + } +} + +func setup(t *testing.T, ops ...option) env { + t.Helper() + + o := opts{} + for _, op := range ops { + op(&o) + } + + var opts []dttestenv.Opt + if o.device != nil { + dev, pubKey, err := dttestenv.CreateEnrolledDevice(o.device.id, o.device.device) + require.NoError(t, err) + opts = append(opts, dttestenv.WithPreEnrolledDevice(dev, pubKey)) + } + dtFakeSvc, err := dttestenv.New(opts...) + require.NoError(t, err) + t.Cleanup(func() { + err := dtFakeSvc.Close() + assert.NoError(t, err) + }) + + svc := newServiceFake(dtFakeSvc.Service) + svc.preReconcileError = o.preReconcileError + + tlsConfig, err := fixtures.LocalTLSConfig() + require.NoError(t, err) + + grpcServer := grpc.NewServer( + grpc.Creds( + credentials.NewTLS(tlsConfig.TLS), + ), + ) + accessgraphsecretsv1pb.RegisterSecretsScannerServiceServer(grpcServer, svc) + + lis, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + go func() { + err := grpcServer.Serve(lis) + assert.NoError(t, err) + }() + t.Cleanup(func() { + grpcServer.Stop() + _ = lis.Close() + }) + + return env{ + service: svc, + secretsScannerAddr: lis.Addr().String(), + } +} + +func newServiceFake(deviceTrustSvc *dttestenv.FakeDeviceService) *serviceFake { + return &serviceFake{ + deviceTrustSvc: deviceTrustSvc, + } +} + +type serviceFake struct { + accessgraphsecretsv1pb.UnimplementedSecretsScannerServiceServer + privateKeysReported []*accessgraphsecretsv1pb.PrivateKey + deviceTrustSvc *dttestenv.FakeDeviceService + preReconcileError error +} + +func (s *serviceFake) ReportSecrets(in accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer) error { + // Step 1. Assert the device. + if _, err := s.deviceTrustSvc.AssertDevice(in.Context(), streamAdapter{stream: in}); err != nil { + return trace.Wrap(err) + } + // Step 2. Collect the private keys into a temporary slice. + var collectedKeys []*accessgraphsecretsv1pb.PrivateKey + for { + msg, err := in.Recv() + // Step 4. When the client closes his side of the stream, we break the loop + // and collect the private keys. + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return trace.Wrap(err) + } + + if msg.GetPrivateKeys() == nil { + return trace.BadParameter("unexpected assert request payload: %T", msg.GetPayload()) + } + // Step 3. Collect the private keys into a temporary slice. + collectedKeys = append(collectedKeys, msg.GetPrivateKeys().GetKeys()...) + + } + + if s.preReconcileError != nil { + return s.preReconcileError + } + + // Step 5. Store the collected private keys. + // This only happens when the client closes his side of the stream. + s.privateKeysReported = collectedKeys + return nil +} + +// streamAdapter is a helper struct that adapts the [accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer] +// stream to the device trust assertion stream [assertserver.AssertDeviceServerStream]. +// This is needed because we need to extract the [*devicepb.AssertDeviceRequest] from the stream +// and return the [*devicepb.AssertDeviceResponse] to the stream. +type streamAdapter struct { + stream accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsServer +} + +func (s streamAdapter) Send(rsp *devicepb.AssertDeviceResponse) error { + msg := &accessgraphsecretsv1pb.ReportSecretsResponse{ + Payload: &accessgraphsecretsv1pb.ReportSecretsResponse_DeviceAssertion{ + DeviceAssertion: rsp, + }, + } + err := s.stream.Send(msg) + return trace.Wrap(err) +} + +func (s streamAdapter) Recv() (*devicepb.AssertDeviceRequest, error) { + msg, err := s.stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + + if msg.GetDeviceAssertion() == nil { + return nil, trace.BadParameter("unexpected assert request payload: %T", msg.GetPayload()) + } + + return msg.GetDeviceAssertion(), nil +} diff --git a/lib/secretsscanner/reporter/report.go b/lib/secretsscanner/reporter/report.go new file mode 100644 index 0000000000000..22dd8c22b9d3b --- /dev/null +++ b/lib/secretsscanner/reporter/report.go @@ -0,0 +1,195 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package reporter + +import ( + "context" + "errors" + "io" + "log/slog" + + "github.com/gravitational/trace" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + dtassert "github.com/gravitational/teleport/lib/devicetrust/assert" + secretsscannerclient "github.com/gravitational/teleport/lib/secretsscanner/client" +) + +// AssertCeremonyBuilderFunc is a function that builds the device authentication ceremony. +type AssertCeremonyBuilderFunc func() (*dtassert.Ceremony, error) + +// Config specifies the configuration for the reporter. +type Config struct { + // Client is a client for the SecretsScannerService. + Client secretsscannerclient.Client + // Log is the logger. + Log *slog.Logger + // BatchSize is the number of secrets to send in a single batch. Defaults to [defaultBatchSize] if not set. + BatchSize int + // AssertCeremonyBuilder is the device authentication ceremony builder. + // If not set, the default device authentication ceremony will be used. + // Used for testing, avoid in production code. + AssertCeremonyBuilder AssertCeremonyBuilderFunc +} + +// Reporter reports secrets to the Teleport Proxy. +type Reporter struct { + client secretsscannerclient.Client + log *slog.Logger + batchSize int + assertCeremonyBuilder AssertCeremonyBuilderFunc +} + +// New creates a new reporter instance. +func New(cfg Config) (*Reporter, error) { + if cfg.Client == nil { + return nil, trace.BadParameter("missing client") + } + if cfg.Log == nil { + cfg.Log = slog.Default() + } + if cfg.BatchSize == 0 { + const defaultBatchSize = 100 + cfg.BatchSize = defaultBatchSize + } + if cfg.AssertCeremonyBuilder == nil { + cfg.AssertCeremonyBuilder = func() (*dtassert.Ceremony, error) { + return dtassert.NewCeremony() + } + } + return &Reporter{ + client: cfg.Client, + log: cfg.Log, + batchSize: cfg.BatchSize, + assertCeremonyBuilder: cfg.AssertCeremonyBuilder, + }, nil +} + +// ReportPrivateKeys reports the private keys to the Teleport server. +// This function performs the following steps: +// 1. Create a new gRPC client to the Teleport Proxy. +// 2. Run the device assertion ceremony. +// 3. Report the private keys to the Teleport cluster. +// 4. Wait for the server to acknowledge the report. +func (r *Reporter) ReportPrivateKeys(ctx context.Context, pks []*accessgraphsecretsv1pb.PrivateKey) error { + + stream, err := r.client.ReportSecrets(ctx) + if err != nil { + return trace.Wrap(err, "failed to create client") + } + + if err := r.runAssertionCeremony(ctx, stream); err != nil { + return trace.Wrap(err, "failed to run assertion ceremony") + } + + if err := r.reportPrivateKeys(stream, pks); err != nil { + return trace.Wrap(err, "failed to report private keys") + } + + return trace.Wrap(r.terminateAndWaitAcknowledge(stream), "server failed to acknowledge the report") +} + +// runAssertionCeremony runs the device assertion ceremony. +func (r *Reporter) runAssertionCeremony(ctx context.Context, stream accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient) error { + // Create a new device authentication ceremony. + assertCeremony, err := r.assertCeremonyBuilder() + if err != nil { + return trace.Wrap(err, "failed to create assertCeremony") + } + + // Run the device authentication ceremony. + // If successful, the device will be authenticated and the device can report its secrets. + err = assertCeremony.Run( + ctx, + reportToAssertStreamAdapter{stream}, + ) + return trace.Wrap(err, "failed to run device authentication ceremony") +} + +// reportPrivateKeys reports the private keys to the Teleport server in batches of size [r.batchSize] using the given stream. +func (r *Reporter) reportPrivateKeys(stream accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient, privateKeys []*accessgraphsecretsv1pb.PrivateKey) error { + batchSize := r.batchSize + for i := 0; len(privateKeys) > i; i += batchSize { + start := i + end := i + batchSize + if end > len(privateKeys) { + end = len(privateKeys) + } + if err := stream.Send(&accessgraphsecretsv1pb.ReportSecretsRequest{ + Payload: &accessgraphsecretsv1pb.ReportSecretsRequest_PrivateKeys{ + PrivateKeys: &accessgraphsecretsv1pb.ReportPrivateKeys{ + Keys: privateKeys[start:end], + }, + }, + }); err != nil { + return trace.Wrap(err, "failed to send private keys") + } + } + return nil +} + +// terminateAndWaitAcknowledge terminates the client side of the stream and waits for the server to acknowledge the report. +func (r *Reporter) terminateAndWaitAcknowledge(stream accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient) error { + // Inform the server that there are no more private keys to report. + if err := stream.CloseSend(); err != nil { + return trace.Wrap(err, "failed to close send") + } + + // Wait for the server to acknowledge the report. + if _, err := stream.Recv(); err != nil && !errors.Is(err, io.EOF) { + return trace.Wrap(err, "error closing the stream") + } + return nil +} + +// reportToAssertStreamAdapter is a wrapper for the [accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient] that implements the +// [assert.AssertDeviceClientStream] interface. +// +// This adapter allows the [accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient] to be used with the [assert.AssertDeviceClientStream] +// interface, which is essential for the [assert.Ceremony] in executing the device authentication process. It handles the extraction and insertion +// of device assertion messages from and into the [accessgraphsecretsv1pb.ReportSecretsRequest] and [accessgraphsecretsv1pb.ReportSecretsResponse] messages. +type reportToAssertStreamAdapter struct { + stream accessgraphsecretsv1pb.SecretsScannerService_ReportSecretsClient +} + +func (s reportToAssertStreamAdapter) Send(request *devicepb.AssertDeviceRequest) error { + return trace.Wrap( + s.stream.Send( + &accessgraphsecretsv1pb.ReportSecretsRequest{ + Payload: &accessgraphsecretsv1pb.ReportSecretsRequest_DeviceAssertion{ + DeviceAssertion: request, + }, + }, + ), + ) +} + +func (s reportToAssertStreamAdapter) Recv() (*devicepb.AssertDeviceResponse, error) { + in, err := s.stream.Recv() + if err != nil { + return nil, trace.Wrap(err) + } + + if in.GetDeviceAssertion() == nil { + return nil, trace.BadParameter("unsupported response type: expected DeviceAssertion, got %T", in.Payload) + } + + return in.GetDeviceAssertion(), nil +} diff --git a/lib/secretsscanner/reporter/report_test.go b/lib/secretsscanner/reporter/report_test.go new file mode 100644 index 0000000000000..76c2d661cd116 --- /dev/null +++ b/lib/secretsscanner/reporter/report_test.go @@ -0,0 +1,157 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package reporter_test + +import ( + "context" + "errors" + "log/slog" + "sort" + "strconv" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + "github.com/gravitational/teleport/api/defaults" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" + "github.com/gravitational/teleport/api/types/accessgraph" + dtassert "github.com/gravitational/teleport/lib/devicetrust/assert" + dtauthn "github.com/gravitational/teleport/lib/devicetrust/authn" + dttestenv "github.com/gravitational/teleport/lib/devicetrust/testenv" + secretsscannerclient "github.com/gravitational/teleport/lib/secretsscanner/client" + "github.com/gravitational/teleport/lib/secretsscanner/reporter" +) + +func TestReporter(t *testing.T) { + // disable TLS routing check for tests + t.Setenv(defaults.TLSRoutingConnUpgradeEnvVar, "false") + deviceID := uuid.NewString() + device, err := dttestenv.NewFakeMacOSDevice() + require.NoError(t, err) + + tests := []struct { + name string + preReconcileError error + assertErr require.ErrorAssertionFunc + report []*accessgraphsecretsv1pb.PrivateKey + want []*accessgraphsecretsv1pb.PrivateKey + }{ + { + name: "success", + report: newPrivateKeys(t, deviceID), + want: newPrivateKeys(t, deviceID), + assertErr: require.NoError, + }, + { + name: "pre-reconcile error", + preReconcileError: errors.New("pre-reconcile error"), + report: newPrivateKeys(t, deviceID), + assertErr: func(t require.TestingT, err error, _ ...any) { + require.ErrorContains(t, err, "pre-reconcile error") + }, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + e := setup( + t, + withDevice(deviceID, device), + withPreReconcileError(tt.preReconcileError), + ) + + ctx := context.Background() + + client, err := secretsscannerclient.NewSecretsScannerServiceClient(ctx, + secretsscannerclient.ClientConfig{ + ProxyServer: e.secretsScannerAddr, + Insecure: true, + }, + ) + require.NoError(t, err) + + r, err := reporter.New( + reporter.Config{ + Log: slog.Default(), + Client: client, + BatchSize: 1, /* batch size for tests */ + AssertCeremonyBuilder: func() (*dtassert.Ceremony, error) { + return dtassert.NewCeremony( + dtassert.WithNewAuthnCeremonyFunc( + func() *dtauthn.Ceremony { + return &dtauthn.Ceremony{ + GetDeviceCredential: func() (*devicepb.DeviceCredential, error) { + return device.GetDeviceCredential(), nil + }, + CollectDeviceData: device.CollectDeviceData, + SignChallenge: device.SignChallenge, + SolveTPMAuthnDeviceChallenge: device.SolveTPMAuthnDeviceChallenge, + GetDeviceOSType: device.GetDeviceOSType, + } + }, + ), + ) + }, + }, + ) + require.NoError(t, err) + + err = r.ReportPrivateKeys(ctx, tt.report) + tt.assertErr(t, err) + + got := e.service.privateKeysReported + sortPrivateKeys(got) + sortPrivateKeys(tt.want) + + diff := cmp.Diff(tt.want, got, protocmp.Transform()) + require.Empty(t, diff, "ReportPrivateKeys keys mismatch (-got +want)") + + }) + } +} + +func sortPrivateKeys(keys []*accessgraphsecretsv1pb.PrivateKey) { + sort.Slice(keys, func(i, j int) bool { + return keys[i].Metadata.Name < keys[j].Metadata.Name + }) +} + +func newPrivateKeys(t *testing.T, deviceID string) []*accessgraphsecretsv1pb.PrivateKey { + t.Helper() + var pks []*accessgraphsecretsv1pb.PrivateKey + for i := 0; i < 10; i++ { + pk, err := accessgraph.NewPrivateKey( + &accessgraphsecretsv1pb.PrivateKeySpec{ + PublicKeyFingerprint: "key" + strconv.Itoa(i), + DeviceId: deviceID, + PublicKeyMode: accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + }, + ) + require.NoError(t, err) + pks = append(pks, pk) + } + + return pks +} diff --git a/lib/secretsscanner/scaner/scan.go b/lib/secretsscanner/scaner/scan.go new file mode 100644 index 0000000000000..664b6fcef8e67 --- /dev/null +++ b/lib/secretsscanner/scaner/scan.go @@ -0,0 +1,298 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package scanner + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "errors" + "io" + "io/fs" + "log/slog" + "os" + "path/filepath" + + "github.com/gravitational/trace" + "golang.org/x/crypto/ssh" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + "github.com/gravitational/teleport/api/types/accessgraph" +) + +// Config specifies parameters for the scanner. +type Config struct { + // Dirs is a list of directories to scan. + Dirs []string + // SkipPaths is a list of paths to skip. + // It supports glob patterns (e.g. "/etc/*/"). + // Please refer to the [filepath.Match] documentation for more information. + SkipPaths []string + // Log is the logger. + Log *slog.Logger +} + +// New creates a new scanner. +func New(cfg Config) (*Scanner, error) { + if len(cfg.Dirs) == 0 { + return nil, trace.BadParameter("missing dirs") + } + if cfg.Log == nil { + cfg.Log = slog.Default() + } + + // expand the glob patterns in the skipPaths list. + // we expand the glob patterns here to avoid expanding them for each file during the scan. + // only the directories matched by the glob patterns will be skipped. + skippedPaths, err := expandSkipPaths(cfg.SkipPaths) + if err != nil { + return nil, trace.Wrap(err) + } + + return &Scanner{ + dirs: cfg.Dirs, + log: cfg.Log, + skippedPaths: skippedPaths, + }, nil +} + +// Scanner is a scanner that scans directories for secrets. +type Scanner struct { + dirs []string + log *slog.Logger + skippedPaths map[string]struct{} +} + +// ScanPrivateKeys scans directories for SSH private keys. +func (s *Scanner) ScanPrivateKeys(ctx context.Context, deviceID string) []SSHPrivateKey { + // privateKeys is a map of private keys found during the scan. + // The key is the path to the private key file and the value is the private key representation. + privateKeysMap := make(map[string]*accessgraphsecretsv1pb.PrivateKey) + for _, dir := range s.dirs { + s.findPrivateKeys(ctx, dir, deviceID, privateKeysMap) + } + + keys := make([]SSHPrivateKey, 0, len(privateKeysMap)) + for path, key := range privateKeysMap { + keys = append(keys, SSHPrivateKey{ + Path: path, + Key: key, + }) + } + return keys +} + +// SSHPrivateKey represents an SSH private key found during the scan. +type SSHPrivateKey struct { + // Path is the absolute path to the private key file. + Path string + // Key is the private key representation. + Key *accessgraphsecretsv1pb.PrivateKey +} + +// findPrivateKeys walks through all files in a directory and its subdirectories +// and checks if they are SSH private keys. +func (s *Scanner) findPrivateKeys(ctx context.Context, root, deviceID string, privateKeysMap map[string]*accessgraphsecretsv1pb.PrivateKey) { + logger := s.log.With("root", root) + + err := filepath.WalkDir(root, func(path string, info fs.DirEntry, err error) error { + if err != nil { + logger.DebugContext(ctx, "error walking directory", "path", path, "error", err) + return fs.SkipDir + } + if info.IsDir() { + if _, ok := s.skippedPaths[path]; ok { + logger.DebugContext(ctx, "skipping directory", "path", path) + return fs.SkipDir + } + return nil + } + + if _, ok := s.skippedPaths[path]; ok { + logger.DebugContext(ctx, "skipping file", "path", path) + return nil + } + + switch fileData, isKey, err := s.readFileIfSSHPrivateKey(ctx, path); { + case err != nil: + logger.DebugContext(ctx, "error reading file", "path", path, "error", err) + case isKey: + key, err := extractSSHKey(ctx, path, deviceID, fileData) + if err != nil { + logger.DebugContext(ctx, "error extracting private key", "path", path, "error", err) + } else { + privateKeysMap[path] = key + } + } + return nil + }) + + if err != nil { + logger.WarnContext(ctx, "error walking directory", "root", root, "error", err) + } +} + +var ( + supportedPrivateKeyHeaders = [][]byte{ + []byte("RSA PRIVATE KEY"), + []byte("PRIVATE KEY"), + []byte("EC PRIVATE KEY"), + []byte("DSA PRIVATE KEY"), + []byte("OPENSSH PRIVATE KEY"), + } +) + +// readFileIfSSHPrivateKey checks if a file is an OpenSSH private key +func (s *Scanner) readFileIfSSHPrivateKey(ctx context.Context, filePath string) ([]byte, bool, error) { + file, err := os.Open(filePath) + if err != nil { + return nil, false, err + } + defer func() { + if err = file.Close(); err != nil { + s.log.DebugContext(ctx, "failed to close file", "path", filePath, "error", err) + } + }() + + // read the first bytes of the file to check if it's an OpenSSH private key. + // 40 bytes is the maximum length of the header of an OpenSSH private key. + var buf [40]byte + n, err := file.Read(buf[:]) + if errors.Is(err, io.EOF) || n < len(buf) { + return nil, false, nil + } else if err != nil { + return nil, false, trace.Wrap(err, "failed to read file") + } + + isPrivateKey := false + for _, header := range supportedPrivateKeyHeaders { + if bytes.Contains(buf[:], header) { + isPrivateKey = true + break + } + } + if !isPrivateKey { + return nil, false, nil + } + + // read the entire file + data, err := io.ReadAll(file) + if err != nil { + return nil, false, trace.Wrap(err, "failed to read file") + } + return append(buf[:], data...), true, nil +} + +func extractSSHKey(ctx context.Context, path, deviceID string, fileData []byte) (*accessgraphsecretsv1pb.PrivateKey, error) { + logger := slog.Default().With("private_key_file", path, "device_id", deviceID) + + var publicKey ssh.PublicKey + var mode accessgraphsecretsv1pb.PublicKeyMode + var pme *ssh.PassphraseMissingError + switch pk, err := ssh.ParsePrivateKey(fileData); { + case errors.As(err, &pme): + if pme.PublicKey != nil { + // If the key is a OpenSSH private key whose public key is embedded in the header, it will return the public key. This is + // a special case for OpenSSH private keys that have the public key embedded in the header, for more information see + // OpenSSH's ssh key format: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key + publicKey = pme.PublicKey + mode = accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED + break + } + const pubKeyFileSuffix = ".pub" + publicKey, mode = tryParsingPublicKeyFromPublicFilePath(ctx, logger, path+pubKeyFileSuffix) + case err != nil: + return nil, trace.Wrap(err) + default: + publicKey = pk.PublicKey() + mode = accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED + } + var fingerprint string + if publicKey != nil { + fingerprint = ssh.FingerprintSHA256(publicKey) + } + + key, err := accessgraph.NewPrivateKeyWithName( + privateKeyNameGen(path, deviceID, fingerprint), + &accessgraphsecretsv1pb.PrivateKeySpec{ + PublicKeyFingerprint: fingerprint, + DeviceId: deviceID, + PublicKeyMode: mode, + }, + ) + return key, trace.Wrap(err) +} + +// tryParsingPublicKeyFromPublicFilePath tries to read the public key from the public key file if the private key is password protected. +// If the public key file doesn't exist, it will return mode accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED +// identifying that the private key is password protected and the public key could not be extracted. +func tryParsingPublicKeyFromPublicFilePath(ctx context.Context, logger *slog.Logger, pubPath string) (ssh.PublicKey, accessgraphsecretsv1pb.PublicKeyMode) { + logger = logger.With("public_key_file", pubPath) + logger.DebugContext(ctx, "PrivateKey is password protected. Fallback to public key file.") + + pubData, err := os.ReadFile(pubPath) + if err != nil { + logger.DebugContext(ctx, "Unable to read public key file.", "err", err) + return nil, accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED + } + + logger.DebugContext(ctx, "Trying to parse public key as authorized key data.") + pub, _, _, _, err := ssh.ParseAuthorizedKey(pubData) + if err == nil { + return pub, accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE + } + logger.DebugContext(ctx, "Unable to parse ssh public key file.", "err", err) + + logger.DebugContext(ctx, "Trying to parse public key directly.") + + pub, err = ssh.ParsePublicKey(pubData) + if err == nil { + return pub, accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE + } + + logger.DebugContext(ctx, "Unable to parse ssh public key file.", "err", err) + + return nil, accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED + +} + +func privateKeyNameGen(path, deviceID, fingerprint string) string { + sha := sha256.New() + sha.Write([]byte(path)) + sha.Write([]byte(deviceID)) + sha.Write([]byte(fingerprint)) + return hex.EncodeToString(sha.Sum(nil)) +} + +// expandSkipPaths expands the glob patterns in the skipPaths list and returns a set of the +// paths matched by the glob patterns to be skipped. +func expandSkipPaths(skipPaths []string) (map[string]struct{}, error) { + set := make(map[string]struct{}) + for _, glob := range skipPaths { + matches, err := filepath.Glob(glob) + if err != nil { + return nil, trace.Wrap(err, "glob pattern %q is invalid", glob) + } + for _, match := range matches { + set[match] = struct{}{} + } + } + return set, nil +} diff --git a/lib/secretsscanner/scaner/scan_test.go b/lib/secretsscanner/scaner/scan_test.go new file mode 100644 index 0000000000000..df82e08eb0ea7 --- /dev/null +++ b/lib/secretsscanner/scaner/scan_test.go @@ -0,0 +1,237 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package scanner + +import ( + "context" + "os" + "path/filepath" + "sort" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "golang.org/x/crypto/ssh" + "google.golang.org/protobuf/testing/protocmp" + + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + "github.com/gravitational/teleport/api/types/accessgraph" + scantestdata "github.com/gravitational/teleport/lib/secretsscanner/scaner/testdata" +) + +var ( + deviceID = uuid.NewString() +) + +func TestNewScanner(t *testing.T) { + tests := []struct { + name string + keysGen func(t *testing.T, path string) []*accessgraphsecretsv1pb.PrivateKey + skipTestDir bool + assertResult func(t *testing.T, got []*accessgraphsecretsv1pb.PrivateKey) + }{ + { + name: "encrypted keys", + keysGen: writeEncryptedKeys, + }, + { + name: "unencrypted keys", + keysGen: writeUnEncryptedKeys, + }, + { + name: "encryptedKey without public key file", + keysGen: writeEncryptedKeyWithoutPubFile, + }, + { + name: "invalid keys", + keysGen: writeInvalidKeys, + }, + { + name: "skip test dir keys", + keysGen: writeUnEncryptedKeys, + skipTestDir: true, + assertResult: func(t *testing.T, got []*accessgraphsecretsv1pb.PrivateKey) { + require.Empty(t, got, "ScanPrivateKeys with skip test dir should return empty keys") + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + dir := t.TempDir() + + expect := tt.keysGen(t, dir) + + var skipPaths []string + if tt.skipTestDir { + // skip the test directory. + skipPaths = []string{filepath.Join(dir, "*")} + // the expected keys should be nil since the test directory is skipped. + expect = nil + } + + s, err := New(Config{ + Dirs: []string{dir}, + SkipPaths: skipPaths, + }) + require.NoError(t, err) + + keys := s.ScanPrivateKeys(context.Background(), deviceID) + var got []*accessgraphsecretsv1pb.PrivateKey + for _, key := range keys { + got = append(got, key.Key) + } + + // Sort the keys by name for comparison. + sortPrivateKeys(expect) + sortPrivateKeys(got) + + if tt.assertResult != nil { + tt.assertResult(t, got) + } + + diff := cmp.Diff(expect, got, protocmp.Transform()) + require.Empty(t, diff, "ScanPrivateKeys keys mismatch (-got +want)") + }) + } +} + +func sortPrivateKeys(keys []*accessgraphsecretsv1pb.PrivateKey) { + sort.Slice(keys, func(i, j int) bool { + return keys[i].Metadata.Name < keys[j].Metadata.Name + }) +} + +func writeEncryptedKeys(t *testing.T, dir string) []*accessgraphsecretsv1pb.PrivateKey { + t.Helper() + var expectedKeys []*accessgraphsecretsv1pb.PrivateKey + // Write encrypted keys to the directory. + for _, key := range scantestdata.PEMEncryptedKeys { + err := os.Mkdir(filepath.Join(dir, key.Name), 0o777) + require.NoError(t, err) + + filePath := filepath.Join(dir, key.Name, key.Name) + err = os.WriteFile(filePath, key.PEMBytes, 0o666) + require.NoError(t, err) + + s, err := ssh.ParsePrivateKeyWithPassphrase(key.PEMBytes, []byte(key.EncryptionKey)) + require.NoError(t, err) + + if !key.IncludesPublicKey { + pubFilePath := filePath + ".pub" + authorizedKeyBytes := ssh.MarshalAuthorizedKey(s.PublicKey()) + require.NoError(t, os.WriteFile(pubFilePath, authorizedKeyBytes, 0o666)) + } + + fingerprint := ssh.FingerprintSHA256(s.PublicKey()) + + mode := accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED + if !key.IncludesPublicKey { + mode = accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE + } + + key, err := accessgraph.NewPrivateKeyWithName( + privateKeyNameGen(filePath, deviceID, fingerprint), + &accessgraphsecretsv1pb.PrivateKeySpec{ + PublicKeyFingerprint: fingerprint, + DeviceId: deviceID, + PublicKeyMode: mode, + }, + ) + require.NoError(t, err) + + expectedKeys = append(expectedKeys, key) + } + + return expectedKeys +} + +func writeUnEncryptedKeys(t *testing.T, dir string) []*accessgraphsecretsv1pb.PrivateKey { + t.Helper() + var expectedKeys []*accessgraphsecretsv1pb.PrivateKey + + for name, key := range scantestdata.PEMBytes { + err := os.Mkdir(filepath.Join(dir, name), 0o777) + require.NoError(t, err) + + filePath := filepath.Join(dir, name, name) + err = os.WriteFile(filePath, key, 0o666) + require.NoError(t, err) + + s, err := ssh.ParsePrivateKey(key) + require.NoError(t, err) + + fingerprint := ssh.FingerprintSHA256(s.PublicKey()) + + key, err := accessgraph.NewPrivateKeyWithName( + privateKeyNameGen(filePath, deviceID, fingerprint), + &accessgraphsecretsv1pb.PrivateKeySpec{ + PublicKeyFingerprint: fingerprint, + DeviceId: deviceID, + PublicKeyMode: accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + }, + ) + require.NoError(t, err) + + expectedKeys = append(expectedKeys, key) + } + + return expectedKeys +} + +func writeEncryptedKeyWithoutPubFile(t *testing.T, dir string) []*accessgraphsecretsv1pb.PrivateKey { + t.Helper() + + // Write encrypted keys to the directory. + rawKey := scantestdata.PEMEncryptedKeys[0] + err := os.Mkdir(filepath.Join(dir, rawKey.Name), 0o777) + require.NoError(t, err) + + filePath := filepath.Join(dir, rawKey.Name, rawKey.Name) + err = os.WriteFile(filePath, rawKey.PEMBytes, 0o666) + require.NoError(t, err) + + key, err := accessgraph.NewPrivateKeyWithName( + privateKeyNameGen(filePath, deviceID, ""), + &accessgraphsecretsv1pb.PrivateKeySpec{ + PublicKeyFingerprint: "", + DeviceId: deviceID, + PublicKeyMode: accessgraphsecretsv1pb.PublicKeyMode_PUBLIC_KEY_MODE_PROTECTED, + }, + ) + require.NoError(t, err) + + return []*accessgraphsecretsv1pb.PrivateKey{key} +} + +func writeInvalidKeys(t *testing.T, dir string) []*accessgraphsecretsv1pb.PrivateKey { + t.Helper() + + // Write invalid keys to the directory. + for path, keyBytes := range scantestdata.InvalidKeysBytes { + err := os.Mkdir(filepath.Join(dir, path), 0o777) + require.NoError(t, err) + + filePath := filepath.Join(dir, path, path) + err = os.WriteFile(filePath, keyBytes, 0o666) + require.NoError(t, err) + } + + return nil +} diff --git a/lib/secretsscanner/scaner/testdata/invalid_keys.go b/lib/secretsscanner/scaner/testdata/invalid_keys.go new file mode 100644 index 0000000000000..b2e1b18732770 --- /dev/null +++ b/lib/secretsscanner/scaner/testdata/invalid_keys.go @@ -0,0 +1,50 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package testdata + +// InvalidKeysBytes is a map of invalid keys to their byte representation. +var InvalidKeysBytes = map[string][]byte{ + "short-file": []byte("short file"), + + "empty-file": []byte(""), + + "invalid-key": []byte(`-----BEGIN PRIVATE +KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQ7z7z7z7z7z7z +-----END OPENSSH PRIVATE KEY----- +`), + + "invalid-key-valid-headers": []byte( + `-----BEGIN OPENSSH PRIVATE KEY----- +trash +-----END OPENSSH PRIVATE KEY----- +`), + + "invalid-key-invalid-header": []byte( + `abcefg-----BEGIN OPENSSH PRIVATE KEY----- +-----END OPENSSH PRIVATE KEY----- +`), + + "valid-key-not-supported-header": []byte(`-----BEGIN RANDOM PRIVATE KEY----- +MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 +AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ +6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== +-----END EC PRIVATE KEY----- +`), +} diff --git a/lib/secretsscanner/scaner/testdata/ssh_keys.go b/lib/secretsscanner/scaner/testdata/ssh_keys.go new file mode 100644 index 0000000000000..ff35441f77581 --- /dev/null +++ b/lib/secretsscanner/scaner/testdata/ssh_keys.go @@ -0,0 +1,290 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// forked from golang.org/x/crypto@v0.24.0/ssh/testdata/keys.go + +package testdata + +var PEMBytes = map[string][]byte{ + "dsa": []byte(`-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQD6PDSEyXiI9jfNs97WuM46MSDCYlOqWw80ajN16AohtBncs1YB +lHk//dQOvCYOsYaE+gNix2jtoRjwXhDsc25/IqQbU1ahb7mB8/rsaILRGIbA5WH3 +EgFtJmXFovDz3if6F6TzvhFpHgJRmLYVR8cqsezL3hEZOvvs2iH7MorkxwIVAJHD +nD82+lxh2fb4PMsIiaXudAsBAoGAQRf7Q/iaPRn43ZquUhd6WwvirqUj+tkIu6eV +2nZWYmXLlqFQKEy4Tejl7Wkyzr2OSYvbXLzo7TNxLKoWor6ips0phYPPMyXld14r +juhT24CrhOzuLMhDduMDi032wDIZG4Y+K7ElU8Oufn8Sj5Wge8r6ANmmVgmFfynr +FhdYCngCgYEA3ucGJ93/Mx4q4eKRDxcWD3QzWyqpbRVRRV1Vmih9Ha/qC994nJFz +DQIdjxDIT2Rk2AGzMqFEB68Zc3O+Wcsmz5eWWzEwFxaTwOGWTyDqsDRLm3fD+QYj +nOwuxb0Kce+gWI8voWcqC9cyRm09jGzu2Ab3Bhtpg8JJ8L7gS3MRZK4CFEx4UAfY +Fmsr0W6fHB9nhS4/UXM8 +-----END DSA PRIVATE KEY----- +`), + "ecdsa": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINGWx0zo6fhJ/0EAfrPzVFyFC9s18lBt3cRoEDhS3ARooAoGCCqGSM49 +AwEHoUQDQgAEi9Hdw6KvZcWxfg2IDhA7UkpDtzzt6ZqJXSsFdLd+Kx4S3Sx4cVO+ +6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA== +-----END EC PRIVATE KEY----- +`), + "ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49 +AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU +qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg== +-----END EC PRIVATE KEY----- +`), + "ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS +qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43 +VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz +hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI= +-----END EC PRIVATE KEY----- +`), + "ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF +iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV +UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+ +uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn +FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ== +-----END EC PRIVATE KEY----- +`), + "rsa": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAnuozKMtcQkIImZGSe4IujS4+Lkas9jmlBivziWGU3waivkpU +vYspgJbh7vSvnHOPtKscdIJ+3UUyViDUoM73GumsmHvfeRCoA9YROZK4fQR9G0a1 +wfoRqsrJXGToCzTvr/I2KIwpUG0bRE9rUvsW+JN9xgri+cIJWtu/dGYDkILO4bkF +IxtEvHNVvhGLenyOHFhPw3hAZ7/bKq8kvKzm9D2zOllHe1wWncMkhVmEFF9Houeh +jbddmeIAAxBpRUFfzp1dD7503ADBlJdK306D4CeI4KIFiqE1VrmfcMgP8fti0S0b +4JtmvevYoPd+/wB9ItFqvhc6nyuxF0PfWH+SvwIDAQABAoIBAQCCcpNeSFjKVvRC +Q1nwIrPd1njaec+fK0CIqWl3e2++B+9trwySrvp5gOGjyp2hGsd7Mf7gsQI81oF0 +a+y+uEXlhK3WWdDey0pwI7ft/7+LeDTOQCQRQBpijaXvPzGviVu7nWLRtARx7a41 +S9A4xL5dfI0BFYyuIpaVS8+EV/1TEJIbceZ5q5RBlARA1rc+nBvjygNzYdRq9Rao +yyehvnXZ7pQrATnwofPolbZNseW2Q9sRMmtm1E60XJJ433P7nFbxXtsMAYgxWSQc +V/92iRPYeD7sN/b7qulLEgC6e8el2gLGIB9aQyG7B6KFqloqvx/ymYs07+bWIQCU +6i9y7LABAoGBANKB2Rs0lF5c+gpEE3w0AWoxGyL04TZECtl2hQ/b2jc2n8hLqLhv +zNIKN+xzEP6j0ijXajjEMLiQH10qQ6+Plv8C7o8GJC1V/Oj4u4kbPqfVV1kSxuWm +FBjz6+c8VPbEBgXq5lCMEgC2Ii8XVRoyd3iSSOh+LIMBu/Br3JEsjJq/AoGBAMFC +CvODTiThrZo8v765dRSHrLOvB4jZOPrEKLWECLaQDQpuhgzZhyWm9zFfxGB+LWE9 +R9pU6ZCFPtPfd4cRZ9cezrp+lgdrqjcUX/2ZLLMk21WXFuRaw/4KTlKNsMY6lbAK +qVkUFWIZWaCQ8bdVCP48polipRNmN9mAHsIhIwgBAoGBAM6yn1qeS11I0GAKLlPT +wNvjsfCmIQmm0DxtqwRCbUevxD7pQ5cueCB51iW/ap2OgEqIEo4A3pIrOhDB8kpN +pQdrepFHh3hYqYicy5A6B1DHJAibbl+Krss9n5KjZA4VtpBS8al/kCHQtUomD/M0 +QKlMgnh/g/dzWXYegyqtYraDAoGAGbeBH5B8iJnjcR/eYDHrq5S2XZ7QANzvISeT +RzxPsIOQyK+WdQVJX7BNOqvExRZlUYhHFH2yKwIgLy+Qh0/Aora9ycFok4o3N2cl +suh8M0aXTVdyu2Z8qESU0ZV7TZWkL63rhSgQBGLdM2m2ULAnJzXI74VJ9D/o9K+A +6FJiiAECgYEAujJ/hKxVKEUvxwloGSDhKCUH86+7UOkb/EM2zZFrlPYAz1VcCwr3 +K14r8BtmLFXuLXOlACpoH0Wf4uia+t6n8m9JK3mvpJ7fempAsptP3AdZMQFe7xUm +SXEGQBYxcyS5Q+ncwWZuPgby5wJ9D4Fd6TQH+wwG52sFugt/fGxbPug= +-----END RSA PRIVATE KEY----- +`), + "pkcs8": []byte(`-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCitzS2KiRQTccf +VApb0mbPpo1lt29JjeLBYAehXHWfQ+w8sXpd8e04n/020spx1R94yg+v0NjXyh2R +NFXNBYdhNei33VJxUeKNlExaecvW2yxfuZqka+ZxT1aI8zrAsjh3Rwc6wayAJS4R +wZuzlDv4jZitWqwD+mb/22Zwq/WSs4YX5dUHDklfdWSVnoBfue8K/00n8f5yMTdJ +vFF0qAJwf9spPEHla0lYcozJk64CO5lRkqfLor4UnsXXOiA7aRIoaUSKa+rlhiqt +1EMGYiBjblPt4SwMelGGU2UfywPb4d85gpQ/s8SBARbpPxNVs2IbHDMwj70P3uZc +74M3c4VJAgMBAAECggEAFIzY3mziGzZHgMBncoNXMsCRORh6uKpvygZr0EhSHqRA +cMXlc3n7gNxL6aGjqc7F48Z5RrY0vMQtCcq3T2Z0W6WoV5hfMiqqV0E0h3S8ds1F +hG13h26NMyBXCILXl8Cqev4Afr45IBISCHIQTRTaoiCX+MTr1rDIU2YNQQumvzkz +fMw2XiFTFTgxAtJUAgKoTqLtm7/T+az7TKw+Hesgbx7yaJoMh9DWGBh4Y61DnIDA +fcxJboAfxxnFiXvdBVmzo72pCsRXrWOsjW6WxQmCKuXHvyB1FZTmMaEFNCGSJDa6 +U+OCzA3m65loAZAE7ffFHhYgssz/h9TBaOjKO0BX1QKBgQDZiCBvu+bFh9pEodcS +VxaI+ATlsYcmGdLtnZw5pxuEdr60iNWhpEcV6lGkbdiv5aL43QaGFDLagqeHI77b ++ITFbPPdCiYNaqlk6wyiXv4pdN7V683EDmGWSQlPeC9IhUilt2c+fChK2EB/XlkO +q8c3Vk1MsC6JOxDXNgJxylNpswKBgQC/fYBTb9iD+uM2n3SzJlct/ZlPaONKnNDR +pbTOdxBFHsu2VkfY858tfnEPkmSRX0yKmjHni6e8/qIzfzLwWBY4NmxhNZE5v+qJ +qZF26ULFdrZB4oWXAOliy/1S473OpQnp2MZp2asd0LPcg/BNaMuQrz44hxHb76R7 +qWD0ebIfEwKBgQCRCIiP1pjbVGN7ZOgPS080DSC+wClahtcyI+ZYLglTvRQTLDQ7 +LFtUykCav748MIADKuJBnM/3DiuCF5wV71EejDDfS/fo9BdyuKBY1brhixFTUX+E +Ww5Hc/SoLnpgALVZ/7jvWTpIBHykLxRziqYtR/YLzl+IkX/97P2ePoZ0rwKBgHNC +/7M5Z4JJyepfIMeVFHTCaT27TNTkf20x6Rs937U7TDN8y9JzEiU4LqXI4HAAhPoI +xnExRs4kF04YCnlRDE7Zs3Lv43J3ap1iTATfcymYwyv1RaQXEGQ/lUQHgYCZJtZz +fTrJoo5XyWu6nzJ5Gc8FLNaptr5ECSXGVm3Rsr2xAoGBAJWqEEQS/ejhO05QcPqh +y4cUdLr0269ILVsvic4Ot6zgfPIntXAK6IsHGKcg57kYm6W9k1CmmlA4ENGryJnR +vxyyqA9eyTFc1CQNuc2frKFA9It49JzjXahKc0aDHEHmTR787Tmk1LbuT0/gm9kA +L4INU6g+WqF0fatJxd+IJPrp +-----END PRIVATE KEY----- +`), + "ed25519": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8DvvwAAAJhAFfkOQBX5 +DgAAAAtzc2gtZWQyNTUxOQAAACA+3f7hS7g5UWwXOGVTrMfhmxyrjqz7Sxxbx7I1j8Dvvw +AAAEAaYmXltfW6nhRo3iWGglRB48lYq0z0Q3I3KyrdutEr6j7d/uFLuDlRbBc4ZVOsx+Gb +HKuOrPtLHFvHsjWPwO+/AAAAE2dhcnRvbm1AZ2FydG9ubS14cHMBAg== +-----END OPENSSH PRIVATE KEY----- +`), + "rsa-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5l +oEuW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lz +a+yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAIQWL0H31i9B98AAAAH +c3NoLXJzYQAAAIEAwa48yfWFi3uIdqzuf9X7C2Zxfea/Iaaw0zIwHudpF8U92WVIiC5loE +uW1+OaVi3UWfIEjWMV1tHGysrHOwtwc34BPCJqJknUQO/KtDTBTJ4Pryhw1bWPC999Lza+ +yrCTdNQYBzoROXKExZgPFh9pTMi5wqpHDuOQ2qZFIEI3lT0AAAADAQABAAAAgCThyTGsT4 +IARDxVMhWl6eiB2ZrgFgWSeJm/NOqtppWgOebsIqPMMg4UVuVFsl422/lE3RkPhVkjGXgE +pWvZAdCnmLmApK8wK12vF334lZhZT7t3Z9EzJps88PWEHo7kguf285HcnUM7FlFeissJdk +kXly34y7/3X/a6Tclm+iABAAAAQE0xR/KxZ39slwfMv64Rz7WKk1PPskaryI29aHE3mKHk +pY2QA+P3QlrKxT/VWUMjHUbNNdYfJm48xu0SGNMRdKMAAABBAORh2NP/06JUV3J9W/2Hju +X1ViJuqqcQnJPVzpgSL826EC2xwOECTqoY8uvFpUdD7CtpksIxNVqRIhuNOlz0lqEAAABB +ANkaHTTaPojClO0dKJ/Zjs7pWOCGliebBYprQ/Y4r9QLBkC/XaWMS26gFIrjgC7D2Rv+rZ +wSD0v0RcmkITP1ZR0AAAAYcHF1ZXJuYUBMdWNreUh5ZHJvLmxvY2FsAQID +-----END OPENSSH PRIVATE KEY-----`), + "p256-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQSN5Ld/DFy8LJK0yrWg+Ryhq4/ifHry +QyCQeT4UXSB+UGdRct7kWA0hARbTaSCh+8U/Gs5O+IkDNoTKVsgxKUMQAAAAsO3C7nPtwu +5zAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBI3kt38MXLwskrTK +taD5HKGrj+J8evJDIJB5PhRdIH5QZ1Fy3uRYDSEBFtNpIKH7xT8azk74iQM2hMpWyDEpQx +AAAAAhAIHB48R+goZaiXndfYTrwk4BT1+MeLPC2/dwe0J5d1QDAAAAE21hcmlhbm9AZW5k +b3IubG9jYWwBAgME +-----END OPENSSH PRIVATE KEY-----`), + "p384-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS +1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTZb2VzEPs2NN/i1qHddKTVfwoIq3Tf +PeQ/kcWBvuCVJfIygvpm9MeusawEPuLSEXwiNDew+YHZ9xHIvFjCmZsLuEOzuh9t9KotwM +57H+7N+RDFzhM2j8hAaOuT5XDLKfUAAADgn/Sny5/0p8sAAAATZWNkc2Etc2hhMi1uaXN0 +cDM4NAAAAAhuaXN0cDM4NAAAAGEE2W9lcxD7NjTf4tah3XSk1X8KCKt03z3kP5HFgb7glS +XyMoL6ZvTHrrGsBD7i0hF8IjQ3sPmB2fcRyLxYwpmbC7hDs7ofbfSqLcDOex/uzfkQxc4T +No/IQGjrk+Vwyyn1AAAAMQDg0hwGKB/9Eq+e2FeTspi8QHW5xTD6prqsHDFx4cKk0ccgFV +61dhFhD/8SEbYlHzEAAAATbWFyaWFub0BlbmRvci5sb2NhbAECAwQ= +-----END OPENSSH PRIVATE KEY-----`), + "p521-openssh-format": []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS +1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQBKzI3QSp1a2e1zMulZl1uFF1Y2Dnv +LSIwEu837hOV1epYEgNveAhGNm57TuBqYtnZeVfd2pzaz7CKX6N4B33N1XABQ5Ngji7lF2 +dUbmhNqJoMh43ioIsQNBaBenhmRpYP6f5k8P/7JZMIsLhkJk2hykb8maSZ+B3PYwPMNBdS +vP+0sHQAAAEYIsr2CCLK9ggAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ +AAAIUEASsyN0EqdWtntczLpWZdbhRdWNg57y0iMBLvN+4TldXqWBIDb3gIRjZue07gamLZ +2XlX3dqc2s+wil+jeAd9zdVwAUOTYI4u5RdnVG5oTaiaDIeN4qCLEDQWgXp4ZkaWD+n+ZP +D/+yWTCLC4ZCZNocpG/Jmkmfgdz2MDzDQXUrz/tLB0AAAAQgEdeH+im6iRcP/juTAoeSHo +ExLtWhgL4JYqRwcOnzCKuLOPjEY/HSOuc+HRrbN9rbjsq+PcPHYe1NnkzXk0IW8hxQAAAB +NtYXJpYW5vQGVuZG9yLmxvY2FsAQIDBAUGBw== +-----END OPENSSH PRIVATE KEY-----`), + "user": []byte(`-----BEGIN EC PRIVATE KEY----- +MHcCAQEEILYCAeq8f7V4vSSypRw7pxy8yz3V5W4qg8kSC3zJhqpQoAoGCCqGSM49 +AwEHoUQDQgAEYcO2xNKiRUYOLEHM7VYAp57HNyKbOdYtHD83Z4hzNPVC4tM5mdGD +PLL8IEwvYu2wq+lpXfGQnNMbzYf9gspG0w== +-----END EC PRIVATE KEY----- +`), + "ca": []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAvg9dQ9IRG59lYJb+GESfKWTch4yBpr7Ydw1jkK6vvtrx9jLo +5hkA8X6+ElRPRqTAZSlN5cBm6YCAcQIOsmXDUn6Oj1lVPQAoOjTBTvsjM3NjGhvv +52kHTY0nsMsBeY9q5DTtlzmlYkVUq2a6Htgf2mNi01dIw5fJ7uTTo8EbNf7O0i3u +c9a8P19HaZl5NKiWN4EIZkfB2WdXYRJCVBsGgQj3dE/GrEmH9QINq1A+GkNvK96u +vZm8H1jjmuqzHplWa7lFeXcx8FTVTbVb/iJrZ2Lc/JvIPitKZWhqbR59yrGjpwEp +Id7bo4WhO5L3OB0fSIJYvfu+o4WYnt4f3UzecwIDAQABAoIBABRD9yHgKErVuC2Q +bA+SYZY8VvdtF/X7q4EmQFORDNRA7EPgMc03JU6awRGbQ8i4kHs46EFzPoXvWcKz +AXYsO6N0Myc900Tp22A5d9NAHATEbPC/wdje7hRq1KyZONMJY9BphFv3nZbY5apR +Dc90JBFZP5RhXjTc3n9GjvqLAKfFEKVmPRCvqxCOZunw6XR+SgIQLJo36nsIsbhW +QUXIVaCI6cXMN8bRPm8EITdBNZu06Fpu4ZHm6VaxlXN9smERCDkgBSNXNWHKxmmA +c3Glo2DByUr2/JFBOrLEe9fkYgr24KNCQkHVcSaFxEcZvTggr7StjKISVHlCNEaB +7Q+kPoECgYEA3zE9FmvFGoQCU4g4Nl3dpQHs6kaAW8vJlrmq3xsireIuaJoa2HMe +wYdIvgCnK9DIjyxd5OWnE4jXtAEYPsyGD32B5rSLQrRO96lgb3f4bESCLUb3Bsn/ +sdgeE3p1xZMA0B59htqCrvVgN9k8WxyevBxYl3/gSBm/p8OVH1RTW/ECgYEA2f9Z +95OLj0KQHQtxQXf+I3VjhCw3LkLW39QZOXVI0QrCJfqqP7uxsJXH9NYX0l0GFTcR +kRrlyoaSU1EGQosZh+n1MvplGBTkTSV47/bPsTzFpgK2NfEZuFm9RoWgltS+nYeH +Y2k4mnAN3PhReCMwuprmJz8GRLsO3Cs2s2YylKMCgYEA2UX+uO/q7jgqZ5UJW+ue +1H5+W0aMuFA3i7JtZEnvRaUVFqFGlwXin/WJ2+WY1++k/rPrJ+Rk9IBXtBUIvEGw +FC5TIfsKQsJyyWgqx/jbbtJ2g4s8+W/1qfTAuqeRNOg5d2DnRDs90wJuS4//0JaY +9HkHyVwkQyxFxhSA/AHEMJECgYA2MvyFR1O9bIk0D3I7GsA+xKLXa77Ua53MzIjw +9i4CezBGDQpjCiFli/fI8am+jY5DnAtsDknvjoG24UAzLy5L0mk6IXMdB6SzYYut +7ak5oahqW+Y9hxIj+XvLmtGQbphtxhJtLu35x75KoBpxSh6FZpmuTEccs31AVCYn +eFM/DQKBgQDOPUwbLKqVi6ddFGgrV9MrWw+SWsDa43bPuyvYppMM3oqesvyaX1Dt +qDvN7owaNxNM4OnfKcZr91z8YPVCFo4RbBif3DXRzjNNBlxEjHBtuMOikwvsmucN +vIrbeEpjTiUMTEAr6PoTiVHjsfS8WAM6MDlF5M+2PNswDsBpa2yLgA== +-----END RSA PRIVATE KEY----- +`), +} + +var PEMEncryptedKeys = []struct { + Name string + EncryptionKey string + IncludesPublicKey bool + PEMBytes []byte +}{ + 0: { + Name: "rsa-encrypted", + EncryptionKey: "r54-G0pher_t3st$", + PEMBytes: []byte(`-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,3E1714DE130BC5E81327F36564B05462 + +MqW88sud4fnWk/Jk3fkjh7ydu51ZkHLN5qlQgA4SkAXORPPMj2XvqZOv1v2LOgUV +dUevUn8PZK7a9zbZg4QShUSzwE5k6wdB7XKPyBgI39mJ79GBd2U4W3h6KT6jIdWA +goQpluxkrzr2/X602IaxLEre97FT9mpKC6zxKCLvyFWVIP9n3OSFS47cTTXyFr+l +7PdRhe60nn6jSBgUNk/Q1lAvEQ9fufdPwDYY93F1wyJ6lOr0F1+mzRrMbH67NyKs +rG8J1Fa7cIIre7ueKIAXTIne7OAWqpU9UDgQatDtZTbvA7ciqGsSFgiwwW13N+Rr +hN8MkODKs9cjtONxSKi05s206A3NDU6STtZ3KuPDjFE1gMJODotOuqSM+cxKfyFq +wxpk/CHYCDdMAVBSwxb/vraOHamylL4uCHpJdBHypzf2HABt+lS8Su23uAmL87DR +yvyCS/lmpuNTndef6qHPRkoW2EV3xqD3ovosGf7kgwGJUk2ZpCLVteqmYehKlZDK +r/Jy+J26ooI2jIg9bjvD1PZq+Mv+2dQ1RlDrPG3PB+rEixw6vBaL9x3jatCd4ej7 +XG7lb3qO9xFpLsx89tkEcvpGR+broSpUJ6Mu5LBCVmrvqHjvnDhrZVz1brMiQtU9 +iMZbgXqDLXHd6ERWygk7OTU03u+l1gs+KGMfmS0h0ZYw6KGVLgMnsoxqd6cFSKNB +8Ohk9ZTZGCiovlXBUepyu8wKat1k8YlHSfIHoRUJRhhcd7DrmojC+bcbMIZBU22T +Pl2ftVRGtcQY23lYd0NNKfebF7ncjuLWQGy+vZW+7cgfI6wPIbfYfP6g7QAutk6W +KQx0AoX5woZ6cNxtpIrymaVjSMRRBkKQrJKmRp3pC/lul5E5P2cueMs1fj4OHTbJ +lAUv88ywr+R+mRgYQlFW/XQ653f6DT4t6+njfO9oBcPrQDASZel3LjXLpjjYG/N5 ++BWnVexuJX9ika8HJiFl55oqaKb+WknfNhk5cPY+x7SDV9ywQeMiDZpr0ffeYAEP +LlwwiWRDYpO+uwXHSFF3+JjWwjhs8m8g99iFb7U93yKgBB12dCEPPa2ZeH9wUHMJ +sreYhNuq6f4iWWSXpzN45inQqtTi8jrJhuNLTT543ErW7DtntBO2rWMhff3aiXbn +Uy3qzZM1nPbuCGuBmP9L2dJ3Z5ifDWB4JmOyWY4swTZGt9AVmUxMIKdZpRONx8vz +I9u9nbVPGZBcou50Pa0qTLbkWsSL94MNXrARBxzhHC9Zs6XNEtwN7mOuii7uMkVc +adrxgknBH1J1N+NX/eTKzUwJuPvDtA+Z5ILWNN9wpZT/7ed8zEnKHPNUexyeT5g3 +uw9z9jH7ffGxFYlx87oiVPHGOrCXYZYW5uoZE31SCBkbtNuffNRJRKIFeipmpJ3P +7bpAG+kGHMelQH6b+5K1Qgsv4tpuSyKeTKpPFH9Av5nN4P1ZBm9N80tzbNWqjSJm +S7rYdHnuNEVnUGnRmEUMmVuYZnNBEVN/fP2m2SEwXcP3Uh7TiYlcWw10ygaGmOr7 +MvMLGkYgQ4Utwnd98mtqa0jr0hK2TcOSFir3AqVvXN3XJj4cVULkrXe4Im1laWgp +-----END RSA PRIVATE KEY----- +`), + }, + + 1: { + Name: "dsa-encrypted", + EncryptionKey: "qG0pher-dsa_t3st$", + PEMBytes: []byte(`-----BEGIN DSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,7CE7A6E4A647DC01AF860210B15ADE3E + +hvnBpI99Hceq/55pYRdOzBLntIEis02JFNXuLEydWL+RJBFDn7tA+vXec0ERJd6J +G8JXlSOAhmC2H4uK3q2xR8/Y3yL95n6OIcjvCBiLsV+o3jj1MYJmErxP6zRtq4w3 +JjIjGHWmaYFSxPKQ6e8fs74HEqaeMV9ONUoTtB+aISmgaBL15Fcoayg245dkBvVl +h5Kqspe7yvOBmzA3zjRuxmSCqKJmasXM7mqs3vIrMxZE3XPo1/fWKcPuExgpVQoT +HkJZEoIEIIPnPMwT2uYbFJSGgPJVMDT84xz7yvjCdhLmqrsXgs5Qw7Pw0i0c0BUJ +b7fDJ2UhdiwSckWGmIhTLlJZzr8K+JpjCDlP+REYBI5meB7kosBnlvCEHdw2EJkH +0QDc/2F4xlVrHOLbPRFyu1Oi2Gvbeoo9EsM/DThpd1hKAlb0sF5Y0y0d+owv0PnE +R/4X3HWfIdOHsDUvJ8xVWZ4BZk9Zk9qol045DcFCehpr/3hslCrKSZHakLt9GI58 +vVQJ4L0aYp5nloLfzhViZtKJXRLkySMKdzYkIlNmW1oVGl7tce5UCNI8Nok4j6yn +IiHM7GBn+0nJoKTXsOGMIBe3ulKlKVxLjEuk9yivh/8= +-----END DSA PRIVATE KEY----- +`), + }, + + 2: { + Name: "ed25519-encrypted", + EncryptionKey: "password", + IncludesPublicKey: true, + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDKj29BlC +ocEWuVhQ94/RjoAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIIw1gSurPTDwZidA +2AIjQZgoQi3IFn9jBtFdP10/Jj7DAAAAoFGkQbB2teSU7ikUsnc7ct2aH3pitM359lNVUh +7DQbJWMjbQFbrBYyDJP+ALj1/RZmP2yoIf7/wr99q53/pm28Xp1gGP5V2RGRJYCA6kgFIH +xdB6KEw1Ce7Bz8JaDIeagAGd3xtQTH3cuuleVxCZZnk9NspsPxigADKCls/RUiK7F+z3Qf +Lvs9+PH8nIuhFMYZgo3liqZbVS5z4Fqhyzyq4= +-----END OPENSSH PRIVATE KEY----- +`), + }, + + 3: { + Name: "ed25519-encrypted-cbc", + EncryptionKey: "password", + IncludesPublicKey: true, + PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABDzGKF3uX +G1gXALZKFd6Ir4AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDne4/teO42zTDdj +NwxUMNpbfmp/dxgU4ZNkC3ydgcugAAAAoJ3J/oA7+iqVOz0CIUUk9ufdP1VP4jDf2um+0s +Sgs7x6Gpyjq67Ps7wLRdSmxr/G5b+Z8dRGFYS/wUCQEe3whwuImvLyPwWjXLzkAyMzc01f +ywBGSrHnvP82ppenc2HuTI+E05Xc02i6JVyI1ShiekQL5twoqtR6pEBZnD17UonIx7cRzZ +gbDGyT3bXMQtagvCwoW+/oMTKXiZP5jCJpEO8= +-----END OPENSSH PRIVATE KEY----- +`), + }, +} diff --git a/lib/service/service.go b/lib/service/service.go index 75d609cff1ce6..55b6d035c798a 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -70,6 +70,7 @@ import ( "github.com/gravitational/teleport/api/client/webclient" "github.com/gravitational/teleport/api/constants" apidefaults "github.com/gravitational/teleport/api/defaults" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" kubeproto "github.com/gravitational/teleport/api/gen/proto/go/teleport/kube/v1" transportpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/transport/v1" @@ -140,6 +141,7 @@ import ( "github.com/gravitational/teleport/lib/resumption" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/reversetunnelclient" + secretsscannerproxy "github.com/gravitational/teleport/lib/secretsscanner/proxy" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local" @@ -4255,7 +4257,6 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { return trace.Wrap(err) } alpnRouter, reverseTunnelALPNRouter := setupALPNRouter(listeners, serverTLSConfig, cfg) - alpnAddr := "" if listeners.alpn != nil { alpnAddr = listeners.alpn.Addr().String() @@ -5109,8 +5110,10 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { grpcServerMTLS *grpc.Server ) if alpnRouter != nil { - grpcServerPublic = process.initPublicGRPCServer(proxyLimiter, conn, listeners.grpcPublic) - + grpcServerPublic, err = process.initPublicGRPCServer(proxyLimiter, conn, listeners.grpcPublic) + if err != nil { + return trace.Wrap(err) + } grpcServerMTLS, err = process.initSecureGRPCServer( initSecureGRPCServerCfg{ limiter: proxyLimiter, @@ -6459,7 +6462,7 @@ func (process *TeleportProcess) initPublicGRPCServer( limiter *limiter.Limiter, conn *Connector, listener net.Listener, -) *grpc.Server { +) (*grpc.Server, error) { server := grpc.NewServer( grpc.ChainUnaryInterceptor( interceptors.GRPCServerUnaryErrorInterceptor, @@ -6490,11 +6493,24 @@ func (process *TeleportProcess) initPublicGRPCServer( ) joinServiceServer := joinserver.NewJoinServiceGRPCServer(conn.Client) proto.RegisterJoinServiceServer(server, joinServiceServer) + + accessGraphProxySvc, err := secretsscannerproxy.New( + secretsscannerproxy.ServiceConfig{ + AuthClient: conn.Client, + Log: process.logger, + }) + if err != nil { + return nil, trace.Wrap(err) + + } + + accessgraphsecretsv1pb.RegisterSecretsScannerServiceServer(server, accessGraphProxySvc) + process.RegisterCriticalFunc("proxy.grpc.public", func() error { process.logger.InfoContext(process.ExitContext(), "Starting proxy gRPC server.", "listen_address", listener.Addr()) return trace.Wrap(server.Serve(listener)) }) - return server + return server, nil } // initSecureGRPCServer creates and registers a gRPC server that uses mTLS for diff --git a/lib/service/service_test.go b/lib/service/service_test.go index 981ca212cf528..8da052436b30a 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -1293,7 +1293,8 @@ func TestProxyGRPCServers(t *testing.T) { }) // Insecure gRPC server. - insecureGRPC := process.initPublicGRPCServer(limiter, testConnector, insecureListener) + insecureGRPC, err := process.initPublicGRPCServer(limiter, testConnector, insecureListener) + require.NoError(t, err) t.Cleanup(insecureGRPC.GracefulStop) proxyLockWatcher, err := services.NewLockWatcher(context.Background(), services.LockWatcherConfig{ diff --git a/lib/services/access_graph.go b/lib/services/access_graph.go new file mode 100644 index 0000000000000..aef36297c8128 --- /dev/null +++ b/lib/services/access_graph.go @@ -0,0 +1,82 @@ +/* + * Teleport + * Copyright (C) 2023 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package services + +import ( + "context" + + "github.com/gravitational/trace" + + accessgraphsecretspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + "github.com/gravitational/teleport/api/types/accessgraph" +) + +// AccessGraphSecretsGetter is an interface for getting access graph secrets. +type AccessGraphSecretsGetter interface { + // ListAllAuthorizedKeys lists all authorized keys stored in the backend. + ListAllAuthorizedKeys(ctx context.Context, pageSize int, pageToken string) ([]*accessgraphsecretspb.AuthorizedKey, string, error) + // ListAuthorizedKeysForServer lists all authorized keys for a given hostID. + ListAuthorizedKeysForServer(ctx context.Context, hostID string, pageSize int, pageToken string) ([]*accessgraphsecretspb.AuthorizedKey, string, error) + // ListAllPrivateKeys lists all private keys stored in the backend. + ListAllPrivateKeys(ctx context.Context, pageSize int, pageToken string) ([]*accessgraphsecretspb.PrivateKey, string, error) + // ListPrivateKeysForDevice lists all private keys for a given deviceID. + ListPrivateKeysForDevice(ctx context.Context, deviceID string, pageSize int, pageToken string) ([]*accessgraphsecretspb.PrivateKey, string, error) +} + +// MarshalAccessGraphAuthorizedKey marshals a [accessgraphsecretspb.AuthorizedKey] resource to JSON. +func MarshalAccessGraphAuthorizedKey(in *accessgraphsecretspb.AuthorizedKey, opts ...MarshalOption) ([]byte, error) { + if err := accessgraph.ValidateAuthorizedKey(in); err != nil { + return nil, trace.Wrap(err) + } + + return MarshalProtoResource(in, opts...) +} + +// UnmarshalAccessGraphAuthorizedKey unmarshals a [accessgraphsecretspb.AuthorizedKey] resource from JSON. +func UnmarshalAccessGraphAuthorizedKey(data []byte, opts ...MarshalOption) (*accessgraphsecretspb.AuthorizedKey, error) { + out, err := UnmarshalProtoResource[*accessgraphsecretspb.AuthorizedKey](data, opts...) + if err != nil { + return nil, trace.Wrap(err) + } + if err := accessgraph.ValidateAuthorizedKey(out); err != nil { + return nil, trace.Wrap(err) + } + return out, nil +} + +// MarshalAccessGraphPrivateKey marshals a [accessgraphsecretspb.PrivateKey] resource to JSON. +func MarshalAccessGraphPrivateKey(in *accessgraphsecretspb.PrivateKey, opts ...MarshalOption) ([]byte, error) { + if err := accessgraph.ValidatePrivateKey(in); err != nil { + return nil, trace.Wrap(err) + } + + return MarshalProtoResource(in, opts...) +} + +// UnmarshalAccessGraphPrivateKey unmarshals a [accessgraphsecretspb.PrivateKey] resource from JSON. +func UnmarshalAccessGraphPrivateKey(data []byte, opts ...MarshalOption) (*accessgraphsecretspb.PrivateKey, error) { + out, err := UnmarshalProtoResource[*accessgraphsecretspb.PrivateKey](data, opts...) + if err != nil { + return nil, trace.Wrap(err) + } + if err := accessgraph.ValidatePrivateKey(out); err != nil { + return nil, trace.Wrap(err) + } + return out, nil +} diff --git a/lib/services/access_graph_settings.go b/lib/services/access_graph_settings.go new file mode 100644 index 0000000000000..9454b60b4847e --- /dev/null +++ b/lib/services/access_graph_settings.go @@ -0,0 +1,37 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package services + +import ( + "github.com/gravitational/trace" + + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" +) + +// UnmarshalAccessGraphSettings unmarshals the AccessGraphSettings resource from JSON. +func UnmarshalAccessGraphSettings(data []byte, opts ...MarshalOption) (*clusterconfigpb.AccessGraphSettings, error) { + out, err := UnmarshalProtoResource[*clusterconfigpb.AccessGraphSettings](data, opts...) + return out, trace.Wrap(err) +} + +// MarshalAccessGraphSettings marshals the AccessGraphSettings resource to JSON. +func MarshalAccessGraphSettings(c *clusterconfigpb.AccessGraphSettings, opts ...MarshalOption) ([]byte, error) { + bytes, err := MarshalProtoResource(c, opts...) + return bytes, trace.Wrap(err) +} diff --git a/lib/services/configuration.go b/lib/services/configuration.go index 1f6050c4ee078..78fe24146bcdf 100644 --- a/lib/services/configuration.go +++ b/lib/services/configuration.go @@ -21,6 +21,7 @@ package services import ( "context" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" ) @@ -116,4 +117,15 @@ type ClusterConfiguration interface { UpdateClusterMaintenanceConfig(ctx context.Context, cfg types.ClusterMaintenanceConfig) error // DeleteClusterMaintenanceConfig deletes the maintenance config singleton. DeleteClusterMaintenanceConfig(ctx context.Context) error + + // GetAccessGraphSettings gets the access graph settings from the backend. + GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error) + // CreateAccessGraphSettings creates the access graph settings in the backend. + CreateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) + // UpdateAccessGraphSettings updates the access graph settings in the backend. + UpdateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) + // UpsertAccessGraphSettings creates or updates the access graph settings in the backend. + UpsertAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) + // DeleteAccessGraphSettings deletes the access graph settings from the backend. + DeleteAccessGraphSettings(context.Context) error } diff --git a/lib/services/device.go b/lib/services/device.go index 65252a91b100a..1456d39324a64 100644 --- a/lib/services/device.go +++ b/lib/services/device.go @@ -19,12 +19,21 @@ package services import ( + "context" + "github.com/gravitational/trace" + devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/utils" ) +// DevicesGetter allows to list all registered devices from storage. +type DevicesGetter interface { + ListDevices(ctx context.Context, pageSize int, pageToken string, view devicepb.DeviceView) (devices []*devicepb.Device, nextPageToken string, err error) +} + // UnmarshalDevice unmarshals a DeviceV1 resource and runs CheckAndSetDefaults. func UnmarshalDevice(raw []byte) (*types.DeviceV1, error) { dev := &types.DeviceV1{} @@ -42,3 +51,30 @@ func MarshalDevice(dev *types.DeviceV1) ([]byte, error) { } return devBytes, nil } + +var ( + // unmarshalDeviceFromBackendItemConv is a convenience function that converts + // a backend.Item to a *devicepb.Device. + // It's populated when e/lib/devicetrust/storage/ is initialized. + unmarshalDeviceFromBackendItemConv func(item backend.Item) (*devicepb.Device, error) +) + +// SetUnmarshalDeviceFromBackendItemConv allows to set a custom conversion function for +// unmarshaling a [devicepb.Device] from a [backend.Item]. +// This function must be called in the init() function of the package that owns the conversion logic. +// It's not safe to call this function concurrently. +func SetUnmarshalDeviceFromBackendItemConv(conv func(item backend.Item) (*devicepb.Device, error)) { + unmarshalDeviceFromBackendItemConv = conv +} + +// UnmarshalDeviceFromBackendItem unmarshals a devicepb.Device from a backend.Item. +// It's a convenience function that uses UnmarshalDeviceFromBackendItemConv because +// the storage package uses an internal representation of devicepb.Device when storing +// it in the backend. +func UnmarshalDeviceFromBackendItem(item backend.Item) (*devicepb.Device, error) { + if unmarshalDeviceFromBackendItemConv == nil { + return nil, trace.BadParameter("UnmarshalDeviceFromBackendItemConv is not set") + } + res, err := unmarshalDeviceFromBackendItemConv(item) + return res, trace.Wrap(err) +} diff --git a/lib/services/local/access_graph.go b/lib/services/local/access_graph.go new file mode 100644 index 0000000000000..4be7ec74ec6c3 --- /dev/null +++ b/lib/services/local/access_graph.go @@ -0,0 +1,164 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package local + +import ( + "context" + + "github.com/gravitational/trace" + + accessgraphsecretspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/local/generic" +) + +const ( + authorizedKeysPrefix = "access_graph_ssh_authorized_keys" + privateKeysPrefix = "access_graph_ssh_private_keys" +) + +// AccessGraphSecretsService manages secrets found on Teleport Nodes and +// enrolled devices. +type AccessGraphSecretsService struct { + authorizedKeysSvc *generic.ServiceWrapper[*accessgraphsecretspb.AuthorizedKey] + privateKeysSvc *generic.ServiceWrapper[*accessgraphsecretspb.PrivateKey] +} + +// NewAccessGraphSecretsService returns a new Access Graph Secrets service. +// This service in Teleport is used to keep track of secrets found in Teleport +// Nodes and on enrolled devices. Currently, it only stores secrets related with +// SSH Keys. Future implementations might extend them. +func NewAccessGraphSecretsService(backend backend.Backend) (*AccessGraphSecretsService, error) { + authorizedKeysSvc, err := generic.NewServiceWrapper( + backend, + types.KindAccessGraphSecretAuthorizedKey, + authorizedKeysPrefix, + services.MarshalAccessGraphAuthorizedKey, + services.UnmarshalAccessGraphAuthorizedKey, + ) + if err != nil { + return nil, trace.Wrap(err) + } + + privateKeysSvc, err := generic.NewServiceWrapper( + backend, + types.KindAccessGraphSecretPrivateKey, + privateKeysPrefix, + services.MarshalAccessGraphPrivateKey, + services.UnmarshalAccessGraphPrivateKey, + ) + if err != nil { + return nil, trace.Wrap(err) + } + + return &AccessGraphSecretsService{ + authorizedKeysSvc: authorizedKeysSvc, + privateKeysSvc: privateKeysSvc, + }, nil +} + +// ListAllAuthorizedKeys lists all authorized keys stored in the backend. +func (k *AccessGraphSecretsService) ListAllAuthorizedKeys(ctx context.Context, pageSize int, pageToken string) ([]*accessgraphsecretspb.AuthorizedKey, string, error) { + out, next, err := k.authorizedKeysSvc.ListResources(ctx, pageSize, pageToken) + if err != nil { + return nil, "", trace.Wrap(err) + } + return out, next, nil +} + +// ListAuthorizedKeysForServer lists all authorized keys for a given hostID. +func (k *AccessGraphSecretsService) ListAuthorizedKeysForServer(ctx context.Context, hostID string, pageSize int, pageToken string) ([]*accessgraphsecretspb.AuthorizedKey, string, error) { + if hostID == "" { + return nil, "", trace.BadParameter("server name is required") + } + svc := k.authorizedKeysSvc.WithPrefix(hostID) + out, next, err := svc.ListResources(ctx, pageSize, pageToken) + if err != nil { + return nil, "", trace.Wrap(err) + } + return out, next, nil +} + +// UpsertAuthorizedKey upserts a new authorized key. +func (k *AccessGraphSecretsService) UpsertAuthorizedKey(ctx context.Context, in *accessgraphsecretspb.AuthorizedKey) (*accessgraphsecretspb.AuthorizedKey, error) { + svc := k.authorizedKeysSvc.WithPrefix(in.Spec.HostId) + out, err := svc.UpsertResource(ctx, in) + if err != nil { + return nil, trace.Wrap(err) + } + + return out, nil +} + +// DeleteAuthorizedKey deletes a specific authorized key. +func (k *AccessGraphSecretsService) DeleteAuthorizedKey(ctx context.Context, hostID, name string) error { + svc := k.authorizedKeysSvc.WithPrefix(hostID) + return trace.Wrap(svc.DeleteResource(ctx, name)) +} + +// DeleteAllAuthorizedKeys deletes all authorized keys. +func (k *AccessGraphSecretsService) DeleteAllAuthorizedKeys(ctx context.Context) error { + return trace.Wrap(k.authorizedKeysSvc.DeleteAllResources(ctx)) +} + +// ListAllPrivateKeys lists all private keys stored in the backend. +func (k *AccessGraphSecretsService) ListAllPrivateKeys(ctx context.Context, pageSize int, pageToken string) ([]*accessgraphsecretspb.PrivateKey, string, error) { + out, next, err := k.privateKeysSvc.ListResources(ctx, pageSize, pageToken) + if err != nil { + return nil, "", trace.Wrap(err) + } + return out, next, nil +} + +// ListPrivateKeysForDevice lists all private keys for a given deviceID. +func (k *AccessGraphSecretsService) ListPrivateKeysForDevice(ctx context.Context, deviceID string, pageSize int, pageToken string) ([]*accessgraphsecretspb.PrivateKey, string, error) { + if deviceID == "" { + return nil, "", trace.BadParameter("server name is required") + } + svc := k.privateKeysSvc.WithPrefix(deviceID) + out, next, err := svc.ListResources(ctx, pageSize, pageToken) + if err != nil { + return nil, "", trace.Wrap(err) + } + return out, next, nil +} + +// UpsertPrivateKey upserts a new private key. +func (k *AccessGraphSecretsService) UpsertPrivateKey(ctx context.Context, in *accessgraphsecretspb.PrivateKey) (*accessgraphsecretspb.PrivateKey, error) { + svc := k.privateKeysSvc.WithPrefix(in.Spec.DeviceId) + out, err := svc.UpsertResource(ctx, in) + if err != nil { + return nil, trace.Wrap(err) + } + + return out, nil +} + +// DeletePrivateKey deletes a specific private key. +func (k *AccessGraphSecretsService) DeletePrivateKey(ctx context.Context, deviceID, name string) error { + svc := k.privateKeysSvc.WithPrefix(deviceID) + return trace.Wrap(svc.DeleteResource(ctx, name)) +} + +// DeleteAllPrivateKeys deletes all private keys. +func (k *AccessGraphSecretsService) DeleteAllPrivateKeys(ctx context.Context) error { + return trace.Wrap(k.privateKeysSvc.DeleteAllResources(ctx)) +} diff --git a/lib/services/local/access_graph_test.go b/lib/services/local/access_graph_test.go new file mode 100644 index 0000000000000..7dabcb1eaadd7 --- /dev/null +++ b/lib/services/local/access_graph_test.go @@ -0,0 +1,254 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package local + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + + accessgraphsecretspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types/accessgraph" + "github.com/gravitational/teleport/lib/backend/memory" +) + +func TestAccessGraphAuthorizedKeys(t *testing.T) { + backend, err := memory.New(memory.Config{}) + require.NoError(t, err) + service, err := NewAccessGraphSecretsService(backend) + require.NoError(t, err) + + ctx := context.TODO() + pageSize := 10 + pageToken := "" + + // Test case 1: Empty list + keys, nextToken, err := service.ListAllAuthorizedKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, keys) + require.Empty(t, nextToken) + + // Test case 2: Non-empty list + authorizedKeys := []*accessgraphsecretspb.AuthorizedKeySpec{ + { + HostId: "host1", + HostUser: "user1", + KeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + KeyType: "ssh-rsa", + }, + { + HostId: "host1", + HostUser: "user2", + KeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + KeyType: "ssh-rsa", + }, + { + HostId: "host2", + HostUser: "user1", + KeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + KeyType: "ssh-rsa", + }, + { + HostId: "host2", + HostUser: "user2", + KeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + KeyType: "ssh-rsa", + }, + } + var authKeys []*accessgraphsecretspb.AuthorizedKey + for _, key := range authorizedKeys { + authKey, err := accessgraph.NewAuthorizedKey(key) + require.NoError(t, err) + _, err = service.UpsertAuthorizedKey(ctx, authKey) + require.NoError(t, err) + authKeys = append(authKeys, authKey) + } + + keys, nextToken, err = service.ListAllAuthorizedKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, cmp.Diff(authKeys, keys, + protocmp.Transform(), + protocmp.IgnoreFields(&headerv1.Metadata{}, "id"), + cmpopts.SortSlices(func(a, b *accessgraphsecretspb.AuthorizedKey) bool { + return a.Metadata.Name < b.Metadata.Name + }))) + require.Empty(t, nextToken) + + // Test case 3: Pagination + pageSize = 2 + pageToken = "" + keys, nextToken, err = service.ListAllAuthorizedKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, pageSize) + require.NotEmpty(t, nextToken) + + pageToken = nextToken + keys, nextToken, err = service.ListAllAuthorizedKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, pageSize) + require.Empty(t, nextToken) + + // Test case 4: List authorized keys for server + pageToken = "" + keysHost1, nextToken, err := service.ListAuthorizedKeysForServer(ctx, "host1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 2) + require.Empty(t, nextToken) + keysHost2, nextToken, err := service.ListAuthorizedKeysForServer(ctx, "host2", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 2) + require.Empty(t, nextToken) + require.NotEqual(t, keysHost1, keysHost2) + + // Test case 5: List authorized keys for server with pagination + pageToken = "" + pageSize = 1 + keys, nextToken, err = service.ListAuthorizedKeysForServer(ctx, "host1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 1) + require.NotEmpty(t, nextToken) + + pageToken = nextToken + keys, nextToken, err = service.ListAuthorizedKeysForServer(ctx, "host1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 1) + require.Empty(t, nextToken) + + // Test case 6: Delete all + err = service.DeleteAllAuthorizedKeys(ctx) + require.NoError(t, err) + keys, nextToken, err = service.ListAllAuthorizedKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, keys) + require.Empty(t, nextToken) +} + +func TestAccessGraphPrivateKeys(t *testing.T) { + backend, err := memory.New(memory.Config{}) + require.NoError(t, err) + service, err := NewAccessGraphSecretsService(backend) + require.NoError(t, err) + + ctx := context.TODO() + pageSize := 10 + pageToken := "" + + // Test case 1: Empty list + keys, nextToken, err := service.ListAllPrivateKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, keys) + require.Empty(t, nextToken) + + // Test case 2: Non-empty list + privateKeysSpec := []*accessgraphsecretspb.PrivateKeySpec{ + { + DeviceId: "device1", + PublicKeyMode: accessgraphsecretspb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + PublicKeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + }, + { + DeviceId: "device1", + PublicKeyMode: accessgraphsecretspb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE, + PublicKeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + }, + { + DeviceId: "device2", + PublicKeyMode: accessgraphsecretspb.PublicKeyMode_PUBLIC_KEY_MODE_DERIVED, + PublicKeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + }, + { + DeviceId: "device2", + PublicKeyMode: accessgraphsecretspb.PublicKeyMode_PUBLIC_KEY_MODE_PUB_FILE, + PublicKeyFingerprint: "AAAAB3NzaC1yc2EAAAADAQABAAABAQC...", + }, + } + var authKeys []*accessgraphsecretspb.PrivateKey + for _, key := range privateKeysSpec { + name := uuid.New().String() + prvKey, err := accessgraph.NewPrivateKeyWithName(name, key) + require.NoError(t, err) + _, err = service.UpsertPrivateKey(ctx, prvKey) + require.NoError(t, err) + authKeys = append(authKeys, prvKey) + } + + keys, nextToken, err = service.ListAllPrivateKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, cmp.Diff(authKeys, keys, + protocmp.Transform(), + protocmp.IgnoreFields(&headerv1.Metadata{}, "id"), + cmpopts.SortSlices(func(a, b *accessgraphsecretspb.PrivateKey) bool { + return a.Metadata.Name < b.Metadata.Name + }))) + require.Empty(t, nextToken) + + // Test case 3: Pagination + pageSize = 2 + pageToken = "" + keys, nextToken, err = service.ListAllPrivateKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, pageSize) + require.NotEmpty(t, nextToken) + + pageToken = nextToken + keys, nextToken, err = service.ListAllPrivateKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, pageSize) + require.Empty(t, nextToken) + + // Test case 4: List private keys for device + pageToken = "" + keysHost1, nextToken, err := service.ListPrivateKeysForDevice(ctx, "device1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 2) + require.Empty(t, nextToken) + keysHost2, nextToken, err := service.ListPrivateKeysForDevice(ctx, "device2", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 2) + require.Empty(t, nextToken) + require.NotEqual(t, keysHost1, keysHost2) + + // Test case 5: List private keys for device with pagination + pageToken = "" + pageSize = 1 + keys, nextToken, err = service.ListPrivateKeysForDevice(ctx, "device1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 1) + require.NotEmpty(t, nextToken) + + pageToken = nextToken + keys, nextToken, err = service.ListPrivateKeysForDevice(ctx, "device1", pageSize, pageToken) + require.NoError(t, err) + require.Len(t, keys, 1) + require.Empty(t, nextToken) + + // Test case 6: Delete all + err = service.DeleteAllPrivateKeys(ctx) + require.NoError(t, err) + keys, nextToken, err = service.ListAllPrivateKeys(ctx, pageSize, pageToken) + require.NoError(t, err) + require.Empty(t, keys) + require.Empty(t, nextToken) +} diff --git a/lib/services/local/configuration.go b/lib/services/local/configuration.go index 117c0f49e5b85..29dc6b95f0a1a 100644 --- a/lib/services/local/configuration.go +++ b/lib/services/local/configuration.go @@ -26,6 +26,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/gravitational/teleport" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/modules" @@ -726,18 +727,112 @@ func (s *ClusterConfigurationService) DeleteClusterMaintenanceConfig(ctx context return nil } +// GetAccessGraphSettings fetches the cluster *clusterconfigpb.AccessGraphSettings from the backend and return them. +func (s *ClusterConfigurationService) GetAccessGraphSettings(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + item, err := s.Get(ctx, backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix)) + if err != nil { + if trace.IsNotFound(err) { + return nil, trace.NotFound("AccessGraphSettings preference not found") + } + return nil, trace.Wrap(err) + } + return services.UnmarshalAccessGraphSettings(item.Value, + services.WithExpires(item.Expires), services.WithRevision(item.Revision)) +} + +// CreateAccessGraphSettings creates an *clusterconfigpb.AccessGraphSettings if it does not already exist. +func (s *ClusterConfigurationService) CreateAccessGraphSettings(ctx context.Context, set *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + value, err := services.MarshalAccessGraphSettings(set) + if err != nil { + return nil, trace.Wrap(err) + } + + item := backend.Item{ + Key: backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix), + Value: value, + } + + lease, err := s.Backend.Create(ctx, item) + if err != nil { + return nil, trace.Wrap(err) + } + + set.Metadata.Revision = lease.Revision + return set, nil +} + +// UpdateAccessGraphSettings updates an existing *clusterconfigpb.AccessGraphSettings. +func (s *ClusterConfigurationService) UpdateAccessGraphSettings(ctx context.Context, set *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + rev := set.GetMetadata().GetRevision() + + value, err := services.MarshalAccessGraphSettings(set) + if err != nil { + return nil, trace.Wrap(err) + } + + item := backend.Item{ + Key: backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix), + Value: value, + Revision: rev, + } + + lease, err := s.ConditionalUpdate(ctx, item) + if err != nil { + return nil, trace.Wrap(err) + } + + set.Metadata.Revision = lease.Revision + return set, nil +} + +// UpsertAccessGraphSettings creates or overwrites an *clusterconfigpb.AccessGraphSettings. +func (s *ClusterConfigurationService) UpsertAccessGraphSettings(ctx context.Context, set *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + rev := set.GetMetadata().GetRevision() + value, err := services.MarshalAccessGraphSettings(set) + if err != nil { + return nil, trace.Wrap(err) + } + + item := backend.Item{ + Key: backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix), + Value: value, + Revision: rev, + } + + lease, err := s.Put(ctx, item) + if err != nil { + return nil, trace.Wrap(err) + } + + set.Metadata.Revision = lease.Revision + return set, nil +} + +// DeleteAccessGraphSettings deletes *clusterconfigpb.AccessGraphSettings from the backend. +func (s *ClusterConfigurationService) DeleteAccessGraphSettings(ctx context.Context) error { + err := s.Delete(ctx, backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix)) + if err != nil { + if trace.IsNotFound(err) { + return trace.NotFound("access graph settings not found") + } + return trace.Wrap(err) + } + return nil +} + const ( - clusterConfigPrefix = "cluster_configuration" - namePrefix = "name" - staticTokensPrefix = "static_tokens" - authPrefix = "authentication" - preferencePrefix = "preference" - generalPrefix = "general" - auditPrefix = "audit" - networkingPrefix = "networking" - sessionRecordingPrefix = "session_recording" - scriptsPrefix = "scripts" - uiPrefix = "ui" - installerPrefix = "installer" - maintenancePrefix = "maintenance" + clusterConfigPrefix = "cluster_configuration" + namePrefix = "name" + staticTokensPrefix = "static_tokens" + authPrefix = "authentication" + preferencePrefix = "preference" + generalPrefix = "general" + auditPrefix = "audit" + networkingPrefix = "networking" + sessionRecordingPrefix = "session_recording" + scriptsPrefix = "scripts" + uiPrefix = "ui" + installerPrefix = "installer" + maintenancePrefix = "maintenance" + accessGraphSettingsPrefix = "access_graph_settings" ) diff --git a/lib/services/local/configuration_test.go b/lib/services/local/configuration_test.go index fd1f60a402619..22adc28b16977 100644 --- a/lib/services/local/configuration_test.go +++ b/lib/services/local/configuration_test.go @@ -70,6 +70,18 @@ func TestAuthPreference(t *testing.T) { suite.AuthPreference(t) } +func TestAccessGraphSettings(t *testing.T) { + tt := setupConfigContext(context.Background(), t) + + clusterConfig, err := NewClusterConfigurationService(tt.bk) + require.NoError(t, err) + + suite := &suite.ServicesTestSuite{ + ConfigS: clusterConfig, + } + suite.AccessGraphSettings(t) +} + func TestClusterName(t *testing.T) { tt := setupConfigContext(context.Background(), t) diff --git a/lib/services/local/events.go b/lib/services/local/events.go index b9079e7d8a2de..18f00e981ca25 100644 --- a/lib/services/local/events.go +++ b/lib/services/local/events.go @@ -29,11 +29,14 @@ import ( "github.com/gravitational/teleport" apidefaults "github.com/gravitational/teleport/api/defaults" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/kubewaitingcontainer" "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/devicetrust" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local/generic" ) @@ -206,6 +209,14 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type parser = newAccessMonitoringRuleParser() case types.KindInstance: parser = newInstanceParser() + case types.KindDevice: + parser = newDeviceParser() + case types.KindAccessGraphSecretPrivateKey: + parser = newAccessGraphSecretPrivateKeyParser() + case types.KindAccessGraphSecretAuthorizedKey: + parser = newAccessGraphSecretAuthorizedKeyParser() + case types.KindAccessGraphSettings: + parser = newAccessGraphSettingsParser() default: if watch.AllowPartialSuccess { continue @@ -2173,6 +2184,138 @@ func WaitForEvent(ctx context.Context, watcher types.Watcher, m EventMatcher, cl } } +func newDeviceParser() *deviceParser { + return &deviceParser{ + baseParser: newBaseParser(backend.Key(devicetrust.DevicesIDPrefix...)), + } +} + +type deviceParser struct { + baseParser +} + +func (p *deviceParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + name, err := base(event.Item.Key, 0 /* offset */) + if err != nil { + return nil, trace.Wrap(err) + } + device := &types.DeviceV1{ + ResourceHeader: types.ResourceHeader{ + Kind: types.KindDevice, + Version: types.V1, + Metadata: types.Metadata{ + Name: string(name), + }, + }, + } + return device, nil + case types.OpPut: + device, err := services.UnmarshalDeviceFromBackendItem(event.Item) + if err != nil { + return nil, trace.Wrap(err) + } + // [devicepb.Device] doesn't satisfy types.Resource interface or Resource153 interface, + // so we need to convert it to types.DeviceV1 so it satisfy types.Resource interface. + dev := types.DeviceToResource(device) + // Set the expires and revision fields. + dev.SetExpiry(event.Item.Expires) + dev.SetRevision(event.Item.Revision) + return dev, nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + +func newAccessGraphSecretPrivateKeyParser() *accessGraphSecretPrivateKeyParser { + return &accessGraphSecretPrivateKeyParser{ + baseParser: newBaseParser(backend.Key(privateKeysPrefix)), + } +} + +type accessGraphSecretPrivateKeyParser struct { + baseParser +} + +func (p *accessGraphSecretPrivateKeyParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + deviceID, name, err := baseTwoKeys(event.Item.Key) + if err != nil { + return nil, trace.Wrap(err) + } + + privateKey := &accessgraphsecretsv1pb.PrivateKey{ + Kind: types.KindAccessGraphSecretPrivateKey, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: name, + }, + Spec: &accessgraphsecretsv1pb.PrivateKeySpec{ + DeviceId: deviceID, + }, + } + + return types.Resource153ToLegacy(privateKey), nil + case types.OpPut: + pk, err := services.UnmarshalAccessGraphPrivateKey( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision)) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(pk), nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + +func newAccessGraphSecretAuthorizedKeyParser() *accessGraphSecretAuthorizedKeyParser { + return &accessGraphSecretAuthorizedKeyParser{ + baseParser: newBaseParser(backend.Key(authorizedKeysPrefix)), + } +} + +type accessGraphSecretAuthorizedKeyParser struct { + baseParser +} + +func (p *accessGraphSecretAuthorizedKeyParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + hostID, name, err := baseTwoKeys(event.Item.Key) + if err != nil { + return nil, trace.Wrap(err) + } + + authorizedKey := &accessgraphsecretsv1pb.AuthorizedKey{ + Kind: types.KindAccessGraphSecretAuthorizedKey, + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: name, + }, + Spec: &accessgraphsecretsv1pb.AuthorizedKeySpec{ + HostId: hostID, + }, + } + + return types.Resource153ToLegacy(authorizedKey), nil + case types.OpPut: + ak, err := services.UnmarshalAccessGraphAuthorizedKey( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision)) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(ak), nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + // Match matches the specified resource event by applying itself func (r EventMatcherFunc) Match(event types.Event) (types.Resource, error) { return r(event) @@ -2208,3 +2351,37 @@ func baseTwoKeys(key []byte) (string, string, error) { } return string(parts[len(parts)-2]), string(parts[len(parts)-1]), nil } + +func newAccessGraphSettingsParser() *accessGraphSettingsParser { + return &accessGraphSettingsParser{ + baseParser: newBaseParser(backend.Key(clusterConfigPrefix, accessGraphSettingsPrefix)), + } +} + +type accessGraphSettingsParser struct { + baseParser +} + +func (p *accessGraphSettingsParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + h, err := resourceHeader(event, types.KindAccessGraphSettings, types.V1, 0) + if err != nil { + return nil, trace.Wrap(err) + } + h.SetName(types.MetaNameAccessGraphSettings) + return h, nil + case types.OpPut: + settings, err := services.UnmarshalAccessGraphSettings( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision), + ) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(settings), nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} diff --git a/lib/services/local/generic/generic.go b/lib/services/local/generic/generic.go index 8b64a5f02d036..72a10b8b71c0b 100644 --- a/lib/services/local/generic/generic.go +++ b/lib/services/local/generic/generic.go @@ -78,7 +78,6 @@ func (c *ServiceConfig[T]) CheckAndSetDefaults() error { if c.UnmarshalFunc == nil { return trace.BadParameter("unmarshal func is missing") } - return nil } @@ -167,17 +166,17 @@ func (s *Service[T]) GetResources(ctx context.Context) ([]T, error) { // ListResources returns a paginated list of resources. func (s *Service[T]) ListResources(ctx context.Context, pageSize int, pageToken string) ([]T, string, error) { - resources, next, err := s.ListResourcesReturnNextResource(ctx, pageSize, pageToken) - var nextKey string - if next != nil { - nextKey = backend.GetPaginationKey(*next) - } + resources, _, nextKey, err := s.listResourcesReturnNextResourceWithKey(ctx, pageSize, pageToken) return resources, nextKey, trace.Wrap(err) } // ListResourcesReturnNextResource returns a paginated list of resources. The next resource is returned, which allows consumers to construct // the next pagination key as appropriate. func (s *Service[T]) ListResourcesReturnNextResource(ctx context.Context, pageSize int, pageToken string) ([]T, *T, error) { + resources, next, _, err := s.listResourcesReturnNextResourceWithKey(ctx, pageSize, pageToken) + return resources, next, trace.Wrap(err) +} +func (s *Service[T]) listResourcesReturnNextResourceWithKey(ctx context.Context, pageSize int, pageToken string) ([]T, *T, string, error) { rangeStart := backend.Key(s.backendPrefix, pageToken) rangeEnd := backend.RangeEnd(backend.ExactKey(s.backendPrefix)) @@ -191,26 +190,32 @@ func (s *Service[T]) ListResourcesReturnNextResource(ctx context.Context, pageSi // no filter provided get the range directly result, err := s.backend.GetRange(ctx, rangeStart, rangeEnd, limit) if err != nil { - return nil, nil, trace.Wrap(err) + return nil, nil, "", trace.Wrap(err) } out := make([]T, 0, len(result.Items)) + var lastKey []byte for _, item := range result.Items { resource, err := s.unmarshalFunc(item.Value, services.WithRevision(item.Revision), services.WithResourceID(item.ID)) if err != nil { - return nil, nil, trace.Wrap(err) + return nil, nil, "", trace.Wrap(err) } out = append(out, resource) + lastKey = item.Key } - var next *T + var ( + next *T + nextKey string + ) if len(out) > pageSize { next = &out[pageSize] // Truncate the last item that was used to determine next row existence. out = out[:pageSize] + nextKey = trimLastKey(string(lastKey), s.backendPrefix) } - return out, next, nil + return out, next, nextKey, nil } // ListResourcesWithFilter returns a paginated list of resources that match the given filter. @@ -226,6 +231,7 @@ func (s *Service[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, limit := pageSize + 1 var resources []T + var lastKey []byte if err := backend.IterateRange( ctx, s.backend, @@ -239,6 +245,7 @@ func (s *Service[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, return false, trace.Wrap(err) } if matcher(resource) { + lastKey = item.Key resources = append(resources, resource) } if len(resources) == pageSize { @@ -252,7 +259,7 @@ func (s *Service[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, var nextKey string if len(resources) > pageSize { - nextKey = backend.GetPaginationKey(resources[pageSize]) + nextKey = trimLastKey(string(lastKey), s.backendPrefix) // Truncate the last item that was used to determine next row existence. resources = resources[:pageSize] } @@ -460,3 +467,13 @@ func (s *Service[T]) RunWhileLocked(ctx context.Context, lockName string, ttl ti return fn(ctx, s.backend) })) } + +func trimLastKey(lastKey, prefix string) string { + if !strings.HasSuffix(prefix, string(backend.Separator)) { + prefix += string(backend.Separator) + } + if !strings.HasPrefix(prefix, string(backend.Separator)) { + prefix = string(backend.Separator) + prefix + } + return strings.TrimPrefix(lastKey, prefix) +} diff --git a/lib/services/local/generic/generic_test.go b/lib/services/local/generic/generic_test.go index 2efc4dcc3bbe6..c6abf2863af20 100644 --- a/lib/services/local/generic/generic_test.go +++ b/lib/services/local/generic/generic_test.go @@ -333,6 +333,65 @@ func TestGenericListResourcesReturnNextResource(t *testing.T) { require.Nil(t, next) } +func TestGenericListResourcesWithMultiplePrefixes(t *testing.T) { + ctx := context.Background() + + memBackend, err := memory.New(memory.Config{ + Context: ctx, + Clock: clockwork.NewFakeClock(), + }) + require.NoError(t, err) + + service, err := NewService(&ServiceConfig[*testResource]{ + Backend: memBackend, + ResourceKind: "generic resource", + PageLimit: 200, + BackendPrefix: "generic_prefix", + UnmarshalFunc: unmarshalResource, + MarshalFunc: marshalResource, + }) + require.NoError(t, err) + + // Create a couple test resources. + r1 := newTestResource("r1") + r2 := newTestResource("r2") + + _, err = service.WithPrefix("a-unique-prefix").UpsertResource(ctx, r1) + require.NoError(t, err) + _, err = service.WithPrefix("another-unique-prefix").UpsertResource(ctx, r2) + require.NoError(t, err) + + page, next, err := service.ListResources(ctx, 1, "") + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r1}, page, + cmpopts.IgnoreFields(types.Metadata{}, "Revision", "ID"), + )) + require.Equal(t, next, "another-unique-prefix"+string(backend.Separator)+r2.GetName()) + + page, next, err = service.ListResources(ctx, 1, next) + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r2}, page, + cmpopts.IgnoreFields(types.Metadata{}, "Revision", "ID"), + )) + require.Empty(t, next) + + _, err = service.WithPrefix("a-unique-prefix").UpsertResource(ctx, r2) + require.NoError(t, err) + page, next, err = service.WithPrefix("a-unique-prefix").ListResources(ctx, 1, "") + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r1}, page, + cmpopts.IgnoreFields(types.Metadata{}, "Revision", "ID"), + )) + require.Equal(t, next, r2.GetName()) + + page, next, err = service.WithPrefix("a-unique-prefix").ListResources(ctx, 1, next) + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r2}, page, + cmpopts.IgnoreFields(types.Metadata{}, "Revision", "ID"), + )) + require.Empty(t, next) +} + func TestGenericListResourcesWithFilter(t *testing.T) { ctx := context.Background() diff --git a/lib/services/local/generic/generic_wrapper.go b/lib/services/local/generic/generic_wrapper.go index 3fa6fc1c1c418..6ccb9aafb40de 100644 --- a/lib/services/local/generic/generic_wrapper.go +++ b/lib/services/local/generic/generic_wrapper.go @@ -33,8 +33,8 @@ func NewServiceWrapper[T types.ResourceMetadata]( resourceKind string, backendPrefix string, marshalFunc MarshalFunc[T], - unmarshalFunc UnmarshalFunc[T]) (*ServiceWrapper[T], error) { - + unmarshalFunc UnmarshalFunc[T], +) (*ServiceWrapper[T], error) { cfg := &ServiceConfig[resourceMetadataAdapter[T]]{ Backend: backend, ResourceKind: resourceKind, diff --git a/lib/services/presets.go b/lib/services/presets.go index 1d7992d1bea3a..1dc9874f5fc5e 100644 --- a/lib/services/presets.go +++ b/lib/services/presets.go @@ -176,6 +176,7 @@ func NewPresetEditorRole() types.Role { types.NewRule(types.KindServerInfo, RW()), types.NewRule(types.KindAppServer, RW()), types.NewRule(types.KindAccessMonitoringRule, RW()), + types.NewRule(types.KindAccessGraphSettings, RW()), }, }, }, diff --git a/lib/services/readonly/cache.go b/lib/services/readonly/cache.go index 503018f75b553..f553ba2089196 100644 --- a/lib/services/readonly/cache.go +++ b/lib/services/readonly/cache.go @@ -24,6 +24,7 @@ import ( "github.com/gravitational/trace" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/utils" ) @@ -33,6 +34,7 @@ type Upstream interface { GetAuthPreference(ctx context.Context) (types.AuthPreference, error) GetClusterNetworkingConfig(ctx context.Context) (types.ClusterNetworkingConfig, error) GetSessionRecordingConfig(ctx context.Context) (types.SessionRecordingConfig, error) + GetAccessGraphSettings(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) } // Cache provides simple ttl-based in-memory caching for select resources that are frequently accessed @@ -123,3 +125,16 @@ func (c *Cache) GetReadOnlySessionRecordingConfig(ctx context.Context) (SessionR }) return cfg, trace.Wrap(err) } + +// GetReadOnlyAccessGraphSettings returns a read-only shared reference to the dynamic access graph settings resource. +func (c *Cache) GetReadOnlyAccessGraphSettings(ctx context.Context) (AccessGraphSettings, error) { + if c.cfg.Disabled { + cfg, err := c.cfg.Upstream.GetAccessGraphSettings(ctx) + return sealAccessGraphSettings(cfg), trace.Wrap(err) + } + cfg, err := utils.FnCacheGet(ctx, c.ttlCache, ttlCacheKey{kind: types.KindAccessGraphSettings}, func(ctx context.Context) (AccessGraphSettings, error) { + cfg, err := c.cfg.Upstream.GetAccessGraphSettings(ctx) + return sealAccessGraphSettings(cfg), trace.Wrap(err) + }) + return cfg, trace.Wrap(err) +} diff --git a/lib/services/readonly/readonly.go b/lib/services/readonly/readonly.go index 71462dd9f01b7..47e60ec9c4daf 100644 --- a/lib/services/readonly/readonly.go +++ b/lib/services/readonly/readonly.go @@ -21,7 +21,10 @@ package readonly import ( "time" + protobuf "google.golang.org/protobuf/proto" + "github.com/gravitational/teleport/api/constants" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/keys" ) @@ -103,3 +106,32 @@ func sealSessionRecordingConfig(c SessionRecordingConfig) SessionRecordingConfig } return sealedSessionRecordingConfig{SessionRecordingConfig: c} } + +// AccessGraphSettings is a read-only subset of clusterconfigpb.AccessGraphSettings used on certain hot paths +// to ensure that we do not modify the underlying AccessGraphSettings as it may be shared across +// multiple goroutines. +type AccessGraphSettings interface { + SecretsScanConfig() clusterconfigpb.AccessGraphSecretsScanConfig + Clone() *clusterconfigpb.AccessGraphSettings +} + +type sealedAccessGraphSettings struct { + *clusterconfigpb.AccessGraphSettings +} + +// sealAccessGraphSettings returns a read-only version of the SessionRecordingConfig. +func sealAccessGraphSettings(c *clusterconfigpb.AccessGraphSettings) AccessGraphSettings { + if c == nil { + // preserving nils simplifies error flow-control + return nil + } + return sealedAccessGraphSettings{c} +} + +func (a sealedAccessGraphSettings) SecretsScanConfig() clusterconfigpb.AccessGraphSecretsScanConfig { + return a.GetSpec().GetSecretsScanConfig() +} + +func (a sealedAccessGraphSettings) Clone() *clusterconfigpb.AccessGraphSettings { + return protobuf.Clone(a.AccessGraphSettings).(*clusterconfigpb.AccessGraphSettings) +} diff --git a/lib/services/readonly/readonly_test.go b/lib/services/readonly/readonly_test.go index 8876f27a7b64b..61bd34c346955 100644 --- a/lib/services/readonly/readonly_test.go +++ b/lib/services/readonly/readonly_test.go @@ -24,14 +24,18 @@ import ( "time" "github.com/stretchr/testify/require" + protobuf "google.golang.org/protobuf/proto" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" "github.com/gravitational/teleport/api/types" ) type testUpstream struct { - auth types.AuthPreference - networking types.ClusterNetworkingConfig - recording types.SessionRecordingConfig + auth types.AuthPreference + networking types.ClusterNetworkingConfig + recording types.SessionRecordingConfig + accessGraphSettings *clusterconfigpb.AccessGraphSettings } func (u *testUpstream) GetAuthPreference(ctx context.Context) (types.AuthPreference, error) { @@ -46,6 +50,10 @@ func (u *testUpstream) GetSessionRecordingConfig(ctx context.Context) (types.Ses return u.recording.Clone(), nil } +func (u *testUpstream) GetAccessGraphSettings(ctx context.Context) (*clusterconfigpb.AccessGraphSettings, error) { + return protobuf.Clone(u.accessGraphSettings).(*clusterconfigpb.AccessGraphSettings), nil +} + // TestAuthPreference tests the GetReadOnlyAuthPreference method and verifies the read-only protections // on the returned resource. func TestAuthPreference(t *testing.T) { @@ -141,6 +149,38 @@ func TestCloneBreaksEquality(t *testing.T) { require.False(t, pointersEqual(recording, recording.Clone())) } +func TestAccessGraphSettings(t *testing.T) { + // Create a new cache instance. + cache, err := NewCache(CacheConfig{ + Upstream: &testUpstream{ + accessGraphSettings: &clusterconfigpb.AccessGraphSettings{ + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: "access-graph-settings", + }, + }, + }, + TTL: time.Hour, + }) + require.NoError(t, err) + + // Get the session recording config resource. + ag, err := cache.GetReadOnlyAccessGraphSettings(context.Background()) + require.NoError(t, err) + + // Verify that the access graph settings resource cannot be cast back to a write-supporting interface. + // We do this by checking if the resource is of the sealedAccessGraphSettings type, which is a read-only + // wrapper around the original resource and should not be directly castable back to the original type. + _, ok := ag.(sealedAccessGraphSettings) + require.True(t, ok) + + ag2, err := cache.GetReadOnlyAccessGraphSettings(context.Background()) + require.NoError(t, err) + + // verify pointer equality (i.e. that subsequent reads return the same shared resource). + require.True(t, pointersEqual(ag, ag2)) +} + // pointersEqual is a helper function that compares two pointers for equality. used to improve readability // and avoid incorrect lints. func pointersEqual(a, b interface{}) bool { diff --git a/lib/services/resource.go b/lib/services/resource.go index aeba9adb6131a..411264c716c9c 100644 --- a/lib/services/resource.go +++ b/lib/services/resource.go @@ -246,6 +246,8 @@ func ParseShortcut(in string) (string, error) { return types.KindAccessRequest, nil case types.KindPlugin, types.KindPlugin + "s": return types.KindPlugin, nil + case types.KindAccessGraphSettings, "ags": + return types.KindAccessGraphSettings, nil } return "", trace.BadParameter("unsupported resource: %q - resources should be expressed as 'type/name', for example 'connector/github'", in) } diff --git a/lib/services/suite/suite.go b/lib/services/suite/suite.go index f6660a4100348..a0fba991c6608 100644 --- a/lib/services/suite/suite.go +++ b/lib/services/suite/suite.go @@ -38,11 +38,15 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/crypto/bcrypt" "golang.org/x/crypto/ssh" + protobuf "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/testing/protocmp" "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/constants" apidefaults "github.com/gravitational/teleport/api/defaults" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/clusterconfig" "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/auth/testauthority" "github.com/gravitational/teleport/lib/backend" @@ -1253,6 +1257,39 @@ func (s *ServicesTestSuite) AuthPreference(t *testing.T) { require.Empty(t, cmp.Diff(upserted, gotAP), cmpopts.IgnoreFields(types.Metadata{}, "ID", "Revision")) } +// AccessGraphSettings tests access graph settings service +func (s *ServicesTestSuite) AccessGraphSettings(t *testing.T) { + ctx := context.Background() + ap, err := clusterconfig.NewAccessGraphSettings( + &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + ) + require.NoError(t, err) + + created, err := s.ConfigS.CreateAccessGraphSettings(ctx, ap) + require.NoError(t, err) + require.NotEmpty(t, created.GetMetadata().GetRevision()) + + // Validate the created preference matches the retrieve preference. + got, err := s.ConfigS.GetAccessGraphSettings(ctx) + require.NoError(t, err) + require.Empty(t, cmp.Diff(ap, got, protocmp.Transform())) + + // Validate that update only works if the revision matches. + got.Metadata.Revision = "123" + _, err = s.ConfigS.UpdateAccessGraphSettings(ctx, got) + require.True(t, trace.IsCompareFailed(err)) + + // Validate that upserting overwrites the value regardless of the revision. + upserted, err := s.ConfigS.UpsertAccessGraphSettings(ctx, protobuf.Clone(got).(*clusterconfigpb.AccessGraphSettings)) + require.NoError(t, err) + require.NotEmpty(t, upserted.GetMetadata().GetRevision()) + upserted.Metadata.Revision = "" + got.Metadata.Revision = "" + require.Empty(t, cmp.Diff(upserted, got, protocmp.Transform())) +} + // SessionRecordingConfig tests session recording configuration. func (s *ServicesTestSuite) SessionRecordingConfig(t *testing.T) { ctx := context.Background() diff --git a/lib/srv/regular/sshserver.go b/lib/srv/regular/sshserver.go index cb08c3c15d9b1..978d2ca96a8f7 100644 --- a/lib/srv/regular/sshserver.go +++ b/lib/srv/regular/sshserver.go @@ -26,6 +26,7 @@ import ( "errors" "fmt" "io" + "log/slog" "maps" "net" "os" @@ -62,6 +63,7 @@ import ( "github.com/gravitational/teleport/lib/proxy" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/reversetunnelclient" + authorizedkeysreporter "github.com/gravitational/teleport/lib/secretsscanner/authorizedkeys" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/srv" @@ -880,6 +882,12 @@ func New( } s.srv = server + if !s.proxyMode { + if err := s.startAuthorizedKeysManager(ctx, auth); err != nil { + log.WithError(err).Infof("Failed to start authorized keys manager.") + } + } + var heartbeatMode srv.HeartbeatMode if s.proxyMode { heartbeatMode = srv.HeartbeatModeProxy @@ -934,6 +942,31 @@ func (s *Server) tunnelWithAccessChecker(ctx *srv.ServerContext) (reversetunnelc return reversetunnelclient.NewTunnelWithRoles(s.proxyTun, clusterName.GetClusterName(), ctx.Identity.AccessChecker, s.proxyAccessPoint), nil } +// startAuthorizedKeysManager starts the authorized keys manager. +func (s *Server) startAuthorizedKeysManager(ctx context.Context, auth authclient.ClientI) error { + authorizedKeysWatcher, err := authorizedkeysreporter.NewWatcher( + ctx, + authorizedkeysreporter.WatcherConfig{ + Client: auth, + Logger: slog.Default(), + HostID: s.uuid, + Clock: s.clock, + }, + ) + if errors.Is(err, authorizedkeysreporter.ErrUnsupportedPlatform) { + return nil + } else if err != nil { + return trace.Wrap(err) + } + + go func() { + if err := authorizedKeysWatcher.Run(ctx); err != nil { + s.Warningf("Failed to start authorized keys watcher: %v", err) + } + }() + return nil +} + // Context returns server shutdown context func (s *Server) Context() context.Context { return s.ctx diff --git a/proto/accessgraph/v1alpha/resources.proto b/proto/accessgraph/v1alpha/resources.proto index 677034afda0b8..480299cf65162 100644 --- a/proto/accessgraph/v1alpha/resources.proto +++ b/proto/accessgraph/v1alpha/resources.proto @@ -20,8 +20,11 @@ syntax = "proto3"; package accessgraph.v1alpha; +import "teleport/access_graph/v1/authorized_key.proto"; +import "teleport/access_graph/v1/private_key.proto"; import "teleport/accesslist/v1/accesslist.proto"; import "teleport/crownjewel/v1/crownjewel.proto"; +import "teleport/devicetrust/v1/device.proto"; import "teleport/legacy/types/types.proto"; option go_package = "github.com/gravitational/teleport/gen/proto/go/accessgraph/v1alpha;accessgraphv1alpha"; @@ -76,5 +79,11 @@ message ResourceEntry { teleport.accesslist.v1.AccessList access_list = 9; // crown_jewel is a resource for crown jewels. teleport.crownjewel.v1.CrownJewel crown_jewel = 10; + // device is a device trust resource. + teleport.devicetrust.v1.Device device = 12; + // private_key represents a private key resource found in user's laptops. + teleport.access_graph.v1.PrivateKey private_key = 13; + // authorized_key represents a authorized key for a server. + teleport.access_graph.v1.AuthorizedKey authorized_key = 14; } } diff --git a/tool/tctl/common/clusterconfig/accessgraphsettings.go b/tool/tctl/common/clusterconfig/accessgraphsettings.go new file mode 100644 index 0000000000000..939b8ae23efc0 --- /dev/null +++ b/tool/tctl/common/clusterconfig/accessgraphsettings.go @@ -0,0 +1,148 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package clusterconfig + +import ( + "github.com/gravitational/trace" + + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/header/convert/legacy" + headerv1 "github.com/gravitational/teleport/api/types/header/convert/v1" + "github.com/gravitational/teleport/lib/utils" +) + +// AccessGraphSettings is a type to represent [clusterconfigpb.AcccessGraphSettings] +// which implements types.Resource and custom YAML (un)marshaling. +// This satisfies the expected YAML format for // the resource, which would be +// hard/impossible to do for the proto resource directly +type AccessGraphSettings struct { + // ResourceHeader is embedded to implement types.Resource + types.ResourceHeader + // Spec is the specification + Spec accessGraphSettingsSpec `json:"spec"` +} + +// accessGraphSettingsSpec holds the AccessGraphSettings properties. +type accessGraphSettingsSpec struct { + SecretsScanConfig string `json:"secrets_scan_config"` +} + +// CheckAndSetDefaults sanity checks AccessGraphSettings fields to catch simple errors, and +// sets default values for all fields with defaults. +func (r *AccessGraphSettings) CheckAndSetDefaults() error { + if err := r.Metadata.CheckAndSetDefaults(); err != nil { + return trace.Wrap(err) + } + if r.Kind == "" { + r.Kind = types.KindAccessGraphSettings + } else if r.Kind != types.KindAccessGraphSettings { + return trace.BadParameter("unexpected resource kind %q, must be %q", r.Kind, types.KindAccessGraphSettings) + } + if r.Version == "" { + r.Version = types.V1 + } else if r.Version != types.V1 { + return trace.BadParameter("unsupported resource version %q, %q is currently the only supported version", r.Version, types.V1) + } + if r.Metadata.Name == "" { + r.Metadata.Name = types.MetaNameAccessGraphSettings + } else if r.Metadata.Name != types.MetaNameAccessGraphSettings { + return trace.BadParameter("access graph settings must have a name %q", types.MetaNameAccessGraphSettings) + } + + if _, err := stringToSecretsScanConfig(r.Spec.SecretsScanConfig); err != nil { + return trace.BadParameter("secrets_scan_config must be one of [enabled, disabled]") + } + + return nil +} + +// UnmarshalAccessGraphSettings parses a [*clusterconfigpb.AccessGraphSettings] in the [AccessGraphSettings] +// format which matches the expected YAML format for Teleport resources, sets default values, and +// converts to [*clusterconfigpb.AccessGraphSettings]. +func UnmarshalAccessGraphSettings(raw []byte) (*clusterconfigpb.AccessGraphSettings, error) { + var resource AccessGraphSettings + if err := utils.FastUnmarshal(raw, &resource); err != nil { + return nil, trace.Wrap(err) + } + if err := resource.CheckAndSetDefaults(); err != nil { + return nil, trace.Wrap(err) + } + rec, err := resourceToProto(&resource) + return rec, trace.Wrap(err) +} + +// ProtoToResource converts a [*clusterconfigpb.AccessGraphSettings] into a [*AccessGraphSettings] which +// implements types.Resource and can be marshaled to YAML or JSON in a +// human-friendly format. +func ProtoToResource(set *clusterconfigpb.AccessGraphSettings) (*AccessGraphSettings, error) { + conf, err := secretsScanConfigToString(set.Spec.SecretsScanConfig) + if err != nil { + return nil, trace.Wrap(err) + } + r := &AccessGraphSettings{ + ResourceHeader: types.ResourceHeader{ + Kind: set.Kind, + Version: set.Version, + Metadata: legacy.FromHeaderMetadata(headerv1.FromMetadataProto(set.Metadata)), + }, + Spec: accessGraphSettingsSpec{ + SecretsScanConfig: conf, + }, + } + return r, nil +} + +func resourceToProto(r *AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error) { + secretsScanConfig, err := stringToSecretsScanConfig(r.Spec.SecretsScanConfig) + if err != nil { + return nil, trace.Wrap(err) + } + return &clusterconfigpb.AccessGraphSettings{ + Kind: r.Kind, + SubKind: r.SubKind, + Version: r.Version, + Metadata: headerv1.ToMetadataProto(legacy.ToHeaderMetadata(r.Metadata)), + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: secretsScanConfig, + }, + }, nil +} + +func secretsScanConfigToString(secretsScanConfig clusterconfigpb.AccessGraphSecretsScanConfig) (string, error) { + switch secretsScanConfig { + case clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED: + return "disabled", nil + case clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED: + return "enabled", nil + default: + return "", trace.BadParameter("unexpected secrets scan config %q", secretsScanConfig) + } +} + +func stringToSecretsScanConfig(secretsScanConfig string) (clusterconfigpb.AccessGraphSecretsScanConfig, error) { + switch secretsScanConfig { + case "disabled", "off": + return clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, nil + case "enabled", "on": + return clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, nil + default: + return clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_UNSPECIFIED, trace.BadParameter("secrets scan config must be one of [enabled, disabled]") + } +} diff --git a/tool/tctl/common/clusterconfig/accessgraphsettings_test.go b/tool/tctl/common/clusterconfig/accessgraphsettings_test.go new file mode 100644 index 0000000000000..01a1a7e3f4366 --- /dev/null +++ b/tool/tctl/common/clusterconfig/accessgraphsettings_test.go @@ -0,0 +1,269 @@ +/* + * Teleport + * Copyright (C) 2023 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package clusterconfig + +import ( + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/testing/protocmp" + kyaml "k8s.io/apimachinery/pkg/util/yaml" + + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/services" +) + +func TestUnmarshalAccessGraphSettings(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + desc string + input string + errorContains string + expected *clusterconfigpb.AccessGraphSettings + }{ + { + desc: "disabled", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "disabled" +`, + expected: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + }, + }, + { + desc: "off", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "off" +`, + expected: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + }, + }, + { + desc: "enabled", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "enabled" +`, + expected: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + }, + }, + { + desc: "on", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "on" +`, + expected: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + }, + }, + { + desc: "invalid settings", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "invalidasd" +`, + errorContains: "secrets_scan_config must be one of [enabled, disabled]", + }, + { + desc: "wrong name", + input: `--- +kind: access_graph_settings +version: v1 +metadata: + name: access +spec: + secrets_scan_config: "on" +`, + errorContains: "access graph settings must have a name \"access-graph-settings\"", + }, + { + desc: "wrong version", + input: `--- +kind: access_graph_settings +version: v2 +metadata: + name: access-graph-settings +spec: + secrets_scan_config: "on" +`, + errorContains: "unsupported resource version", + }, + } { + t.Run(tc.desc, func(t *testing.T) { + // Mimic tctl resource command by using the same decoder and + // initially unmarshalling into services.UnknownResource + reader := strings.NewReader(tc.input) + decoder := kyaml.NewYAMLOrJSONDecoder(reader, defaults.LookaheadBufSize) + var raw services.UnknownResource + err := decoder.Decode(&raw) + require.NoError(t, err) + require.Equal(t, types.KindAccessGraphSettings, raw.Kind) + + out, err := UnmarshalAccessGraphSettings(raw.Raw) + if tc.errorContains != "" { + require.ErrorContains(t, err, tc.errorContains, "error from UnmarshalAccessGraphSettings does not contain the expected string") + return + } + require.NoError(t, err, "UnmarshalAccessGraphSettings returned unexpected error") + + require.Empty(t, cmp.Diff(tc.expected, out, protocmp.Transform()), "unmarshalled data does not match what was expected") + }) + } +} + +func TestProtoToResource(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + desc string + expected *AccessGraphSettings + errorContains string + input *clusterconfigpb.AccessGraphSettings + }{ + { + desc: "disabled", + expected: &AccessGraphSettings{ + ResourceHeader: types.ResourceHeader{ + Kind: types.KindAccessGraphSettings, + Version: types.V1, + Metadata: types.Metadata{Name: types.MetaNameAccessGraphSettings}, + }, + Spec: accessGraphSettingsSpec{ + SecretsScanConfig: "disabled", + }, + }, + input: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED, + }, + }, + }, + { + desc: "enabled", + expected: &AccessGraphSettings{ + ResourceHeader: types.ResourceHeader{ + Kind: types.KindAccessGraphSettings, + Version: types.V1, + Metadata: types.Metadata{Name: types.MetaNameAccessGraphSettings}, + }, + Spec: accessGraphSettingsSpec{ + SecretsScanConfig: "enabled", + }, + }, + input: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED, + }, + }, + }, + { + desc: "incorrect data", + errorContains: "unexpected secrets scan config", + input: &clusterconfigpb.AccessGraphSettings{ + Version: types.V1, + Kind: types.KindAccessGraphSettings, + Metadata: &headerv1.Metadata{ + Name: types.MetaNameAccessGraphSettings, + }, + Spec: &clusterconfigpb.AccessGraphSettingsSpec{ + SecretsScanConfig: 5, + }, + }, + }, + } { + t.Run(tc.desc, func(t *testing.T) { + + out, err := ProtoToResource(tc.input) + if tc.errorContains != "" { + require.ErrorContains(t, err, tc.errorContains, "error from ProtoToResource does not contain the expected string") + return + } + require.NoError(t, err, "ProtoToResource returned unexpected error") + + require.Empty(t, cmp.Diff(tc.expected, out, protocmp.Transform())) + }) + } +} diff --git a/tool/tctl/common/collection.go b/tool/tctl/common/collection.go index 3ed204084af06..f1863230fcb0b 100644 --- a/tool/tctl/common/collection.go +++ b/tool/tctl/common/collection.go @@ -48,6 +48,7 @@ import ( "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/tool/common" + clusterconfigrec "github.com/gravitational/teleport/tool/tctl/common/clusterconfig" "github.com/gravitational/teleport/tool/tctl/common/databaseobject" "github.com/gravitational/teleport/tool/tctl/common/databaseobjectimportrule" "github.com/gravitational/teleport/tool/tctl/common/loginrule" @@ -1466,6 +1467,23 @@ func (c *accessListCollection) writeText(w io.Writer, verbose bool) error { return trace.Wrap(err) } +type accessGraphSettings struct { + accessGraphSettings *clusterconfigrec.AccessGraphSettings +} + +func (c *accessGraphSettings) resources() []types.Resource { + return []types.Resource{c.accessGraphSettings} +} + +func (c *accessGraphSettings) writeText(w io.Writer, verbose bool) error { + t := asciitable.MakeTable([]string{"SSH Keys Scan"}) + t.AddRow([]string{ + c.accessGraphSettings.Spec.SecretsScanConfig, + }) + _, err := t.AsBuffer().WriteTo(w) + return trace.Wrap(err) +} + type accessRequestCollection struct { accessRequests []types.AccessRequest } diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go index e985f3686fff4..f3083fa3d114a 100644 --- a/tool/tctl/common/resource_command.go +++ b/tool/tctl/common/resource_command.go @@ -42,6 +42,7 @@ import ( apiclient "github.com/gravitational/teleport/api/client" "github.com/gravitational/teleport/api/client/proto" apidefaults "github.com/gravitational/teleport/api/defaults" + clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" dbobjectimportrulev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobjectimportrule/v1" @@ -64,6 +65,7 @@ import ( "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" + clusterconfigrec "github.com/gravitational/teleport/tool/tctl/common/clusterconfig" "github.com/gravitational/teleport/tool/tctl/common/databaseobject" "github.com/gravitational/teleport/tool/tctl/common/databaseobjectimportrule" "github.com/gravitational/teleport/tool/tctl/common/loginrule" @@ -159,6 +161,7 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *servicec types.KindDatabaseObject: rc.createDatabaseObject, types.KindAccessMonitoringRule: rc.createAccessMonitoringRule, types.KindCrownJewel: rc.createCrownJewel, + types.KindAccessGraphSettings: rc.upsertAccessGraphSettings, types.KindPlugin: rc.createPlugin, } rc.UpdateHandlers = map[ResourceKind]ResourceCreateHandler{ @@ -172,6 +175,7 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *servicec types.KindSessionRecordingConfig: rc.updateSessionRecordingConfig, types.KindAccessMonitoringRule: rc.updateAccessMonitoringRule, types.KindCrownJewel: rc.updateCrownJewel, + types.KindAccessGraphSettings: rc.updateAccessGraphSettings, types.KindPlugin: rc.updatePlugin, } rc.config = config @@ -2814,6 +2818,16 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient startKey = resp.NextKey } return &pluginCollection{plugins: plugins}, nil + case types.KindAccessGraphSettings: + settings, err := client.ClusterConfigClient().GetAccessGraphSettings(ctx, &clusterconfigpb.GetAccessGraphSettingsRequest{}) + if err != nil { + return nil, trace.Wrap(err) + } + rec, err := clusterconfigrec.ProtoToResource(settings) + if err != nil { + return nil, trace.Wrap(err) + } + return &accessGraphSettings{accessGraphSettings: rec}, nil } return nil, trace.BadParameter("getting %q is not supported", rc.ref.String()) } @@ -3101,3 +3115,30 @@ func (rc *ResourceCommand) createPlugin(ctx context.Context, client *authclient. fmt.Printf("plugin %q has been updated\n", item.GetName()) return nil } + +func (rc *ResourceCommand) upsertAccessGraphSettings(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error { + settings, err := clusterconfigrec.UnmarshalAccessGraphSettings(raw.Raw) + if err != nil { + return trace.Wrap(err) + } + + if _, err = client.ClusterConfigClient().UpsertAccessGraphSettings(ctx, &clusterconfigpb.UpsertAccessGraphSettingsRequest{AccessGraphSettings: settings}); err != nil { + return trace.Wrap(err) + } + + fmt.Println("access_graph_settings has been upserted") + return nil +} + +func (rc *ResourceCommand) updateAccessGraphSettings(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error { + settings, err := clusterconfigrec.UnmarshalAccessGraphSettings(raw.Raw) + if err != nil { + return trace.Wrap(err) + } + + if _, err = client.ClusterConfigClient().UpdateAccessGraphSettings(ctx, &clusterconfigpb.UpdateAccessGraphSettingsRequest{AccessGraphSettings: settings}); err != nil { + return trace.Wrap(err) + } + fmt.Println("access_graph_settings has been updated") + return nil +} diff --git a/tool/tsh/common/scan.go b/tool/tsh/common/scan.go new file mode 100644 index 0000000000000..f96eff417b468 --- /dev/null +++ b/tool/tsh/common/scan.go @@ -0,0 +1,170 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package common + +import ( + "fmt" + "log/slog" + "runtime" + "strings" + + "github.com/alecthomas/kingpin/v2" + "github.com/gravitational/trace" + + "github.com/gravitational/teleport/api/constants" + accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" + "github.com/gravitational/teleport/api/types/accessgraph" + "github.com/gravitational/teleport/lib/devicetrust/assert" + dtnative "github.com/gravitational/teleport/lib/devicetrust/native" + secretsscannerclient "github.com/gravitational/teleport/lib/secretsscanner/client" + secretsreporter "github.com/gravitational/teleport/lib/secretsscanner/reporter" + secretsscanner "github.com/gravitational/teleport/lib/secretsscanner/scaner" +) + +type scanCommand struct { + keys *scanKeysCommand +} + +func newScanCommand(app *kingpin.Application) scanCommand { + scan := app.Command("scan", "Scan the local machine for Secrets and report findings to Teleport") + cmd := scanCommand{ + keys: newScanKeysCommand(scan), + } + return cmd +} + +type scanKeysCommand struct { + *kingpin.CmdClause + dirs []string + skipPaths []string +} + +func newScanKeysCommand(parent *kingpin.CmdClause) *scanKeysCommand { + c := &scanKeysCommand{CmdClause: parent.Command("keys", "Scan the local machine for SSH private keys and report findings to Teleport")} + c.Flag("dirs", "Directories to scan.").Default(defaultDirValues()).StringsVar(&c.dirs) + c.Flag("skip-paths", "Paths to directories or files to skip. Supports for matching patterns.").StringsVar(&c.skipPaths) + return c +} + +func defaultDirValues() string { + switch runtime.GOOS { + case constants.LinuxOS: + return "/home/" + case constants.DarwinOS: + return "/Users/" + case constants.WindowsOS: + return "C:\\Users\\" + default: + return "/" + } +} + +func (c *scanKeysCommand) run(cf *CLIConf) error { + if len(c.dirs) == 0 { + return trace.BadParameter("no directories to scan") + } + + if cf.Proxy == "" { + return trace.BadParameter("proxy address is required") + } + + ctx := cf.Context + + deviceCred, err := dtnative.GetDeviceCredential() + if err != nil { + return trace.Wrap(err, "device not enrolled") + } + + fmt.Printf("Device trust credentials found.\nScanning %s.\n", strings.Join(c.dirs, ", ")) + + scanner, err := secretsscanner.New(secretsscanner.Config{ + Dirs: c.dirs, + SkipPaths: c.skipPaths, + Log: slog.Default(), + }) + if err != nil { + return trace.Wrap(err, "failed to create scanner") + } + + privateKeys := scanner.ScanPrivateKeys( + ctx, + deviceCred.Id, + ) + + printPrivateKeys(privateKeys) + + client, err := secretsscannerclient.NewSecretsScannerServiceClient( + ctx, + secretsscannerclient.ClientConfig{ + ProxyServer: cf.Proxy, + Insecure: cf.InsecureSkipVerify, + Log: slog.Default(), + }) + if err != nil { + return trace.Wrap(err, "failed to create client") + } + + reporter, err := secretsreporter.New( + secretsreporter.Config{ + Client: client, + Log: slog.Default(), + AssertCeremonyBuilder: func() (*assert.Ceremony, error) { + return assert.NewCeremony() + }, + }, + ) + if err != nil { + return trace.Wrap(err, "failed to create reporter") + } + + if err := reporter.ReportPrivateKeys(ctx, collectPrivateKeys(privateKeys)); trace.IsNotImplemented(err) { + return handleUnimplementedError(ctx, err, *cf) + } else if err != nil { + return trace.Wrap(err, "failed to report private keys") + } + + fmt.Printf("Reported %d SSH fingerprints to Teleport.\n", len(privateKeys)) + + return nil +} + +func printPrivateKeys(privateKeys []secretsscanner.SSHPrivateKey) { + if len(privateKeys) == 0 { + fmt.Println("No SSH private keys found.") + return + } + + fmt.Println("SSH private keys found:") + for _, pk := range privateKeys { + path, key := pk.Path, pk.Key + fmt.Printf("- SHA256 fingerprint: %q (mode: %s) at %s\n", + key.Spec.PublicKeyFingerprint, + accessgraph.DescribePublicKeyMode(key.Spec.PublicKeyMode), + path, + ) + } +} + +func collectPrivateKeys(privateKeys []secretsscanner.SSHPrivateKey) []*accessgraphsecretsv1pb.PrivateKey { + keys := make([]*accessgraphsecretsv1pb.PrivateKey, 0, len(privateKeys)) + for _, pk := range privateKeys { + keys = append(keys, pk.Key) + } + return keys +} diff --git a/tool/tsh/common/tsh.go b/tool/tsh/common/tsh.go index 4927e609a4baa..ba4b5bcc4cf70 100644 --- a/tool/tsh/common/tsh.go +++ b/tool/tsh/common/tsh.go @@ -1165,6 +1165,8 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error { kube := newKubeCommand(app) // MFA subcommands. mfa := newMFACommand(app) + // SCAN subcommands. + scan := newScanCommand(app) config := app.Command("config", "Print OpenSSH configuration details.") config.Flag("port", "SSH port on a remote host").Short('p').Int32Var(&cf.NodePort) @@ -1459,7 +1461,8 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error { err = kube.exec.run(&cf) case kube.join.FullCommand(): err = kube.join.run(&cf) - + case scan.keys.FullCommand(): + err = scan.keys.run(&cf) case proxySSH.FullCommand(): err = onProxyCommandSSH(&cf) case proxyDB.FullCommand():