From b197b3ec47cde7e9d8d5983e9ba80168c59e9584 Mon Sep 17 00:00:00 2001 From: Gavin Frazar Date: Mon, 29 Jul 2024 15:07:40 -0700 Subject: [PATCH] add ListVPCs to AWS OIDC integration service (#44708) * add ListVPCs to AWS OIDC integration service * add databasevpcs endpoint for AWS OIDC integration * set DescribeVpcs page size to 100 --- .../integration/v1/awsoidc_service.pb.go | 897 +++++++++++------- .../integration/v1/awsoidc_service_grpc.pb.go | 43 + .../integration/v1/awsoidc_service.proto | 37 +- lib/auth/integration/integrationv1/awsoidc.go | 42 + .../integration/integrationv1/awsoidc_test.go | 425 +++------ .../awsoidc/deploydatabaseservice.go | 28 +- .../awsoidc/deploydatabaseservice_test.go | 53 ++ lib/integrations/awsoidc/list_subnets.go | 9 +- lib/integrations/awsoidc/list_vpcs.go | 122 +++ lib/integrations/awsoidc/list_vpcs_test.go | 214 +++++ lib/web/apiserver.go | 1 + lib/web/integrations_awsoidc.go | 175 +++- lib/web/ui/integration.go | 33 + 13 files changed, 1432 insertions(+), 647 deletions(-) create mode 100644 lib/integrations/awsoidc/list_vpcs.go create mode 100644 lib/integrations/awsoidc/list_vpcs_test.go diff --git a/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go b/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go index 19b748e2b04f1..a5ab858bad303 100644 --- a/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go @@ -1085,7 +1085,7 @@ type Subnet struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Name is the subnet name. + // Name is the subnet name. Can be empty. Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // ID is the subnet ID. Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` @@ -1205,6 +1205,193 @@ func (x *ListSubnetsResponse) GetNextToken() string { return "" } +// ListVPCsRequest is a request for a paginated list of AWS VPCs. +type ListVPCsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Integration is the AWS OIDC Integration name. + // Required. + Integration string `protobuf:"bytes,1,opt,name=integration,proto3" json:"integration,omitempty"` + // Region is the AWS Region + // Required. + Region string `protobuf:"bytes,2,opt,name=region,proto3" json:"region,omitempty"` + // NextToken is the token to be used to fetch the next page. + // If empty, the first page is fetched. + NextToken string `protobuf:"bytes,3,opt,name=next_token,json=nextToken,proto3" json:"next_token,omitempty"` +} + +func (x *ListVPCsRequest) Reset() { + *x = ListVPCsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListVPCsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListVPCsRequest) ProtoMessage() {} + +func (x *ListVPCsRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_integration_v1_awsoidc_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 ListVPCsRequest.ProtoReflect.Descriptor instead. +func (*ListVPCsRequest) Descriptor() ([]byte, []int) { + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{16} +} + +func (x *ListVPCsRequest) GetIntegration() string { + if x != nil { + return x.Integration + } + return "" +} + +func (x *ListVPCsRequest) GetRegion() string { + if x != nil { + return x.Region + } + return "" +} + +func (x *ListVPCsRequest) GetNextToken() string { + if x != nil { + return x.NextToken + } + return "" +} + +// VPC is a representation of an AWS VPC. +type VPC struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Name is the VPC name. Can be empty. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // ID is the VPC ID. + Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *VPC) Reset() { + *x = VPC{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VPC) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VPC) ProtoMessage() {} + +func (x *VPC) ProtoReflect() protoreflect.Message { + mi := &file_teleport_integration_v1_awsoidc_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 VPC.ProtoReflect.Descriptor instead. +func (*VPC) Descriptor() ([]byte, []int) { + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{17} +} + +func (x *VPC) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VPC) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +// ListVPCsResponse contains a page of AWS VPCs. +type ListVPCsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // VPCs contains the page of VPCs. + Vpcs []*VPC `protobuf:"bytes,1,rep,name=vpcs,proto3" json:"vpcs,omitempty"` + // NextToken is used for pagination. + // If non-empty, it can be used to request the next page. + NextToken string `protobuf:"bytes,2,opt,name=next_token,json=nextToken,proto3" json:"next_token,omitempty"` +} + +func (x *ListVPCsResponse) Reset() { + *x = ListVPCsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListVPCsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListVPCsResponse) ProtoMessage() {} + +func (x *ListVPCsResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_integration_v1_awsoidc_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 ListVPCsResponse.ProtoReflect.Descriptor instead. +func (*ListVPCsResponse) Descriptor() ([]byte, []int) { + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{18} +} + +func (x *ListVPCsResponse) GetVpcs() []*VPC { + if x != nil { + return x.Vpcs + } + return nil +} + +func (x *ListVPCsResponse) GetNextToken() string { + if x != nil { + return x.NextToken + } + return "" +} + // DeployDatabaseServiceRequest is a request to deploy . type DeployDatabaseServiceRequest struct { state protoimpl.MessageState @@ -1236,7 +1423,7 @@ type DeployDatabaseServiceRequest struct { func (x *DeployDatabaseServiceRequest) Reset() { *x = DeployDatabaseServiceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[16] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1249,7 +1436,7 @@ func (x *DeployDatabaseServiceRequest) String() string { func (*DeployDatabaseServiceRequest) ProtoMessage() {} func (x *DeployDatabaseServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[16] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1262,7 +1449,7 @@ func (x *DeployDatabaseServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployDatabaseServiceRequest.ProtoReflect.Descriptor instead. func (*DeployDatabaseServiceRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{16} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{19} } func (x *DeployDatabaseServiceRequest) GetIntegration() string { @@ -1331,7 +1518,7 @@ type DeployDatabaseServiceDeployment struct { func (x *DeployDatabaseServiceDeployment) Reset() { *x = DeployDatabaseServiceDeployment{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[17] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1344,7 +1531,7 @@ func (x *DeployDatabaseServiceDeployment) String() string { func (*DeployDatabaseServiceDeployment) ProtoMessage() {} func (x *DeployDatabaseServiceDeployment) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[17] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1357,7 +1544,7 @@ func (x *DeployDatabaseServiceDeployment) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployDatabaseServiceDeployment.ProtoReflect.Descriptor instead. func (*DeployDatabaseServiceDeployment) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{17} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{20} } func (x *DeployDatabaseServiceDeployment) GetTeleportConfigString() string { @@ -1403,7 +1590,7 @@ type DeployDatabaseServiceResponse struct { func (x *DeployDatabaseServiceResponse) Reset() { *x = DeployDatabaseServiceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[18] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1416,7 +1603,7 @@ func (x *DeployDatabaseServiceResponse) String() string { func (*DeployDatabaseServiceResponse) ProtoMessage() {} func (x *DeployDatabaseServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[18] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1429,7 +1616,7 @@ func (x *DeployDatabaseServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployDatabaseServiceResponse.ProtoReflect.Descriptor instead. func (*DeployDatabaseServiceResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{18} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{21} } func (x *DeployDatabaseServiceResponse) GetClusterArn() string { @@ -1488,7 +1675,7 @@ type DeployServiceRequest struct { func (x *DeployServiceRequest) Reset() { *x = DeployServiceRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[19] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1501,7 +1688,7 @@ func (x *DeployServiceRequest) String() string { func (*DeployServiceRequest) ProtoMessage() {} func (x *DeployServiceRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[19] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1514,7 +1701,7 @@ func (x *DeployServiceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployServiceRequest.ProtoReflect.Descriptor instead. func (*DeployServiceRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{19} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{22} } func (x *DeployServiceRequest) GetIntegration() string { @@ -1599,7 +1786,7 @@ type DeployServiceResponse struct { func (x *DeployServiceResponse) Reset() { *x = DeployServiceResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[20] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1612,7 +1799,7 @@ func (x *DeployServiceResponse) String() string { func (*DeployServiceResponse) ProtoMessage() {} func (x *DeployServiceResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[20] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1625,7 +1812,7 @@ func (x *DeployServiceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeployServiceResponse.ProtoReflect.Descriptor instead. func (*DeployServiceResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{20} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{23} } func (x *DeployServiceResponse) GetClusterArn() string { @@ -1681,7 +1868,7 @@ type EnrollEKSClustersRequest struct { func (x *EnrollEKSClustersRequest) Reset() { *x = EnrollEKSClustersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[21] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1694,7 +1881,7 @@ func (x *EnrollEKSClustersRequest) String() string { func (*EnrollEKSClustersRequest) ProtoMessage() {} func (x *EnrollEKSClustersRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[21] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1707,7 +1894,7 @@ func (x *EnrollEKSClustersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EnrollEKSClustersRequest.ProtoReflect.Descriptor instead. func (*EnrollEKSClustersRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{21} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{24} } func (x *EnrollEKSClustersRequest) GetIntegration() string { @@ -1762,7 +1949,7 @@ type EnrollEKSClusterResult struct { func (x *EnrollEKSClusterResult) Reset() { *x = EnrollEKSClusterResult{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[22] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1775,7 +1962,7 @@ func (x *EnrollEKSClusterResult) String() string { func (*EnrollEKSClusterResult) ProtoMessage() {} func (x *EnrollEKSClusterResult) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[22] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1788,7 +1975,7 @@ func (x *EnrollEKSClusterResult) ProtoReflect() protoreflect.Message { // Deprecated: Use EnrollEKSClusterResult.ProtoReflect.Descriptor instead. func (*EnrollEKSClusterResult) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{22} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{25} } func (x *EnrollEKSClusterResult) GetEksClusterName() string { @@ -1825,7 +2012,7 @@ type EnrollEKSClustersResponse struct { func (x *EnrollEKSClustersResponse) Reset() { *x = EnrollEKSClustersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[23] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1838,7 +2025,7 @@ func (x *EnrollEKSClustersResponse) String() string { func (*EnrollEKSClustersResponse) ProtoMessage() {} func (x *EnrollEKSClustersResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[23] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1851,7 +2038,7 @@ func (x *EnrollEKSClustersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EnrollEKSClustersResponse.ProtoReflect.Descriptor instead. func (*EnrollEKSClustersResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{23} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{26} } func (x *EnrollEKSClustersResponse) GetResults() []*EnrollEKSClusterResult { @@ -1881,7 +2068,7 @@ type ListEC2Request struct { func (x *ListEC2Request) Reset() { *x = ListEC2Request{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[24] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1894,7 +2081,7 @@ func (x *ListEC2Request) String() string { func (*ListEC2Request) ProtoMessage() {} func (x *ListEC2Request) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[24] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1907,7 +2094,7 @@ func (x *ListEC2Request) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEC2Request.ProtoReflect.Descriptor instead. func (*ListEC2Request) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{24} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{27} } func (x *ListEC2Request) GetIntegration() string { @@ -1947,7 +2134,7 @@ type ListEC2Response struct { func (x *ListEC2Response) Reset() { *x = ListEC2Response{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[25] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1960,7 +2147,7 @@ func (x *ListEC2Response) String() string { func (*ListEC2Response) ProtoMessage() {} func (x *ListEC2Response) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[25] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1973,7 +2160,7 @@ func (x *ListEC2Response) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEC2Response.ProtoReflect.Descriptor instead. func (*ListEC2Response) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{25} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{28} } func (x *ListEC2Response) GetServers() []*types.ServerV2 { @@ -2010,7 +2197,7 @@ type ListEKSClustersRequest struct { func (x *ListEKSClustersRequest) Reset() { *x = ListEKSClustersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[26] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2023,7 +2210,7 @@ func (x *ListEKSClustersRequest) String() string { func (*ListEKSClustersRequest) ProtoMessage() {} func (x *ListEKSClustersRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[26] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2036,7 +2223,7 @@ func (x *ListEKSClustersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEKSClustersRequest.ProtoReflect.Descriptor instead. func (*ListEKSClustersRequest) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{26} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{29} } func (x *ListEKSClustersRequest) GetIntegration() string { @@ -2086,7 +2273,7 @@ type EKSCluster struct { func (x *EKSCluster) Reset() { *x = EKSCluster{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[27] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2099,7 +2286,7 @@ func (x *EKSCluster) String() string { func (*EKSCluster) ProtoMessage() {} func (x *EKSCluster) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[27] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2112,7 +2299,7 @@ func (x *EKSCluster) ProtoReflect() protoreflect.Message { // Deprecated: Use EKSCluster.ProtoReflect.Descriptor instead. func (*EKSCluster) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{27} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{30} } func (x *EKSCluster) GetName() string { @@ -2173,7 +2360,7 @@ type ListEKSClustersResponse struct { func (x *ListEKSClustersResponse) Reset() { *x = ListEKSClustersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[28] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2186,7 +2373,7 @@ func (x *ListEKSClustersResponse) String() string { func (*ListEKSClustersResponse) ProtoMessage() {} func (x *ListEKSClustersResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[28] + mi := &file_teleport_integration_v1_awsoidc_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2199,7 +2386,7 @@ func (x *ListEKSClustersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEKSClustersResponse.ProtoReflect.Descriptor instead. func (*ListEKSClustersResponse) Descriptor() ([]byte, []int) { - return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{28} + return file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP(), []int{31} } func (x *ListEKSClustersResponse) GetClusters() []*EKSCluster { @@ -2370,240 +2557,262 @@ var file_teleport_integration_v1_awsoidc_service_proto_rawDesc = []byte{ 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xc0, - 0x02, 0x0a, 0x1c, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x61, 0x73, - 0x6b, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x72, 0x6e, 0x12, 0x29, 0x0a, - 0x10, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5a, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x76, - 0x70, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x70, 0x63, - 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, - 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, - 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x74, 0x0a, 0x1d, 0x44, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x72, 0x6e, 0x12, 0x32, 0x0a, 0x15, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x72, 0x6c, - 0x22, 0x83, 0x03, 0x0a, 0x14, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, - 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, - 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, - 0x74, 0x49, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x6f, 0x6c, - 0x65, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x73, - 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x72, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x34, 0x0a, 0x16, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x22, 0xbd, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x72, - 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, - 0x72, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x74, 0x61, 0x73, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x41, - 0x72, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, - 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x13, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x55, 0x72, 0x6c, 0x22, 0xd7, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x72, 0x6f, 0x6c, - 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, - 0x11, 0x65, 0x6b, 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x6b, 0x73, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, - 0x70, 0x70, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x22, 0x79, 0x0a, 0x16, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x6b, - 0x73, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x6b, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x66, 0x0a, 0x19, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x22, 0x69, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, - 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x5b, - 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x29, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x56, 0x32, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, - 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x71, 0x0a, 0x16, 0x4c, - 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x6a, + 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x29, 0x0a, 0x03, 0x56, 0x50, + 0x43, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x63, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x76, 0x70, 0x63, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x56, 0x50, 0x43, 0x52, 0x04, 0x76, 0x70, 0x63, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xc0, 0x02, 0x0a, 0x1c, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x6f, + 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, + 0x73, 0x6b, 0x52, 0x6f, 0x6c, 0x65, 0x41, 0x72, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x5a, 0x0a, 0x0b, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x0b, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xb6, 0x01, + 0x0a, 0x1f, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x12, 0x34, 0x0a, 0x16, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x15, 0x0a, 0x06, 0x76, 0x70, 0x63, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x70, 0x63, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x22, 0x74, 0x0a, 0x1d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x72, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, 0x72, 0x6c, 0x22, 0x83, 0x03, 0x0a, + 0x14, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, - 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xfb, - 0x02, 0x0a, 0x0a, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x6e, 0x12, 0x47, 0x0a, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, - 0x62, 0x65, 0x6c, 0x73, 0x12, 0x54, 0x0a, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4a, - 0x6f, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, - 0x6a, 0x6f, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, - 0x0f, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x79, 0x0a, 0x17, - 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, + 0x27, 0x0a, 0x0f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x49, 0x64, 0x73, + 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x61, 0x72, + 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x73, 0x6b, 0x52, 0x6f, 0x6c, + 0x65, 0x41, 0x72, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x3b, 0x0a, 0x1a, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6a, 0x6f, + 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x17, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4a, + 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x16, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x22, 0xbd, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x72, 0x6e, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x72, 0x6e, 0x12, 0x2e, + 0x0a, 0x13, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x74, 0x61, 0x73, + 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x6e, 0x12, 0x32, + 0x0a, 0x15, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x55, + 0x72, 0x6c, 0x22, 0xd7, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x6b, 0x73, + 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x6b, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x61, 0x70, 0x70, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, 0x70, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x79, 0x0a, 0x16, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x65, 0x6b, 0x73, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x65, 0x6b, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x66, 0x0a, 0x19, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, + 0x69, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x5b, 0x0a, 0x0f, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, + 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x52, + 0x07, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, - 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xfa, 0x08, 0x0a, 0x0e, 0x41, 0x57, 0x53, 0x4f, - 0x49, 0x44, 0x43, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, - 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x71, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x45, + 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xfb, 0x02, 0x0a, 0x0a, 0x45, + 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x6e, 0x12, 0x47, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x12, 0x54, 0x0a, 0x0b, 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x6a, 0x6f, 0x69, 0x6e, + 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x39, + 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3d, 0x0a, 0x0f, 0x4a, 0x6f, 0x69, + 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x79, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x32, 0xdb, 0x09, 0x0a, 0x0e, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, + 0x43, 0x45, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, - 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x74, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x45, 0x49, 0x43, 0x45, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, + 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x12, + 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, + 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x74, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, + 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x68, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, - 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x56, + 0x50, 0x43, 0x73, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, - 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x15, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, - 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x11, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, - 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6e, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7a, 0x0a, 0x11, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5c, 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x12, 0x27, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, - 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, - 0x73, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, + 0x07, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, - 0x76, 0x31, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x0f, 0x4c, + 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, + 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x3b, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2618,7 +2827,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_rawDescGZIP() []byte { return file_teleport_integration_v1_awsoidc_service_proto_rawDescData } -var file_teleport_integration_v1_awsoidc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_teleport_integration_v1_awsoidc_service_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_teleport_integration_v1_awsoidc_service_proto_goTypes = []interface{}{ (*ListEICERequest)(nil), // 0: teleport.integration.v1.ListEICERequest (*EC2InstanceConnectEndpoint)(nil), // 1: teleport.integration.v1.EC2InstanceConnectEndpoint @@ -2636,65 +2845,71 @@ var file_teleport_integration_v1_awsoidc_service_proto_goTypes = []interface{}{ (*ListSubnetsRequest)(nil), // 13: teleport.integration.v1.ListSubnetsRequest (*Subnet)(nil), // 14: teleport.integration.v1.Subnet (*ListSubnetsResponse)(nil), // 15: teleport.integration.v1.ListSubnetsResponse - (*DeployDatabaseServiceRequest)(nil), // 16: teleport.integration.v1.DeployDatabaseServiceRequest - (*DeployDatabaseServiceDeployment)(nil), // 17: teleport.integration.v1.DeployDatabaseServiceDeployment - (*DeployDatabaseServiceResponse)(nil), // 18: teleport.integration.v1.DeployDatabaseServiceResponse - (*DeployServiceRequest)(nil), // 19: teleport.integration.v1.DeployServiceRequest - (*DeployServiceResponse)(nil), // 20: teleport.integration.v1.DeployServiceResponse - (*EnrollEKSClustersRequest)(nil), // 21: teleport.integration.v1.EnrollEKSClustersRequest - (*EnrollEKSClusterResult)(nil), // 22: teleport.integration.v1.EnrollEKSClusterResult - (*EnrollEKSClustersResponse)(nil), // 23: teleport.integration.v1.EnrollEKSClustersResponse - (*ListEC2Request)(nil), // 24: teleport.integration.v1.ListEC2Request - (*ListEC2Response)(nil), // 25: teleport.integration.v1.ListEC2Response - (*ListEKSClustersRequest)(nil), // 26: teleport.integration.v1.ListEKSClustersRequest - (*EKSCluster)(nil), // 27: teleport.integration.v1.EKSCluster - (*ListEKSClustersResponse)(nil), // 28: teleport.integration.v1.ListEKSClustersResponse - nil, // 29: teleport.integration.v1.EKSCluster.LabelsEntry - nil, // 30: teleport.integration.v1.EKSCluster.JoinLabelsEntry - (*types.DatabaseV3)(nil), // 31: types.DatabaseV3 - (*types.ServerV2)(nil), // 32: types.ServerV2 + (*ListVPCsRequest)(nil), // 16: teleport.integration.v1.ListVPCsRequest + (*VPC)(nil), // 17: teleport.integration.v1.VPC + (*ListVPCsResponse)(nil), // 18: teleport.integration.v1.ListVPCsResponse + (*DeployDatabaseServiceRequest)(nil), // 19: teleport.integration.v1.DeployDatabaseServiceRequest + (*DeployDatabaseServiceDeployment)(nil), // 20: teleport.integration.v1.DeployDatabaseServiceDeployment + (*DeployDatabaseServiceResponse)(nil), // 21: teleport.integration.v1.DeployDatabaseServiceResponse + (*DeployServiceRequest)(nil), // 22: teleport.integration.v1.DeployServiceRequest + (*DeployServiceResponse)(nil), // 23: teleport.integration.v1.DeployServiceResponse + (*EnrollEKSClustersRequest)(nil), // 24: teleport.integration.v1.EnrollEKSClustersRequest + (*EnrollEKSClusterResult)(nil), // 25: teleport.integration.v1.EnrollEKSClusterResult + (*EnrollEKSClustersResponse)(nil), // 26: teleport.integration.v1.EnrollEKSClustersResponse + (*ListEC2Request)(nil), // 27: teleport.integration.v1.ListEC2Request + (*ListEC2Response)(nil), // 28: teleport.integration.v1.ListEC2Response + (*ListEKSClustersRequest)(nil), // 29: teleport.integration.v1.ListEKSClustersRequest + (*EKSCluster)(nil), // 30: teleport.integration.v1.EKSCluster + (*ListEKSClustersResponse)(nil), // 31: teleport.integration.v1.ListEKSClustersResponse + nil, // 32: teleport.integration.v1.EKSCluster.LabelsEntry + nil, // 33: teleport.integration.v1.EKSCluster.JoinLabelsEntry + (*types.DatabaseV3)(nil), // 34: types.DatabaseV3 + (*types.ServerV2)(nil), // 35: types.ServerV2 } var file_teleport_integration_v1_awsoidc_service_proto_depIdxs = []int32{ 1, // 0: teleport.integration.v1.ListEICEResponse.ec2ices:type_name -> teleport.integration.v1.EC2InstanceConnectEndpoint 4, // 1: teleport.integration.v1.CreateEICERequest.endpoints:type_name -> teleport.integration.v1.EC2ICEndpoint 4, // 2: teleport.integration.v1.CreateEICEResponse.created_endpoints:type_name -> teleport.integration.v1.EC2ICEndpoint - 31, // 3: teleport.integration.v1.ListDatabasesResponse.databases:type_name -> types.DatabaseV3 + 34, // 3: teleport.integration.v1.ListDatabasesResponse.databases:type_name -> types.DatabaseV3 9, // 4: teleport.integration.v1.SecurityGroupRule.cidrs:type_name -> teleport.integration.v1.SecurityGroupRuleCIDR 10, // 5: teleport.integration.v1.SecurityGroup.inbound_rules:type_name -> teleport.integration.v1.SecurityGroupRule 10, // 6: teleport.integration.v1.SecurityGroup.outbound_rules:type_name -> teleport.integration.v1.SecurityGroupRule 11, // 7: teleport.integration.v1.ListSecurityGroupsResponse.security_groups:type_name -> teleport.integration.v1.SecurityGroup 14, // 8: teleport.integration.v1.ListSubnetsResponse.subnets:type_name -> teleport.integration.v1.Subnet - 17, // 9: teleport.integration.v1.DeployDatabaseServiceRequest.deployments:type_name -> teleport.integration.v1.DeployDatabaseServiceDeployment - 22, // 10: teleport.integration.v1.EnrollEKSClustersResponse.results:type_name -> teleport.integration.v1.EnrollEKSClusterResult - 32, // 11: teleport.integration.v1.ListEC2Response.servers:type_name -> types.ServerV2 - 29, // 12: teleport.integration.v1.EKSCluster.labels:type_name -> teleport.integration.v1.EKSCluster.LabelsEntry - 30, // 13: teleport.integration.v1.EKSCluster.join_labels:type_name -> teleport.integration.v1.EKSCluster.JoinLabelsEntry - 27, // 14: teleport.integration.v1.ListEKSClustersResponse.clusters:type_name -> teleport.integration.v1.EKSCluster - 0, // 15: teleport.integration.v1.AWSOIDCService.ListEICE:input_type -> teleport.integration.v1.ListEICERequest - 3, // 16: teleport.integration.v1.AWSOIDCService.CreateEICE:input_type -> teleport.integration.v1.CreateEICERequest - 6, // 17: teleport.integration.v1.AWSOIDCService.ListDatabases:input_type -> teleport.integration.v1.ListDatabasesRequest - 8, // 18: teleport.integration.v1.AWSOIDCService.ListSecurityGroups:input_type -> teleport.integration.v1.ListSecurityGroupsRequest - 13, // 19: teleport.integration.v1.AWSOIDCService.ListSubnets:input_type -> teleport.integration.v1.ListSubnetsRequest - 16, // 20: teleport.integration.v1.AWSOIDCService.DeployDatabaseService:input_type -> teleport.integration.v1.DeployDatabaseServiceRequest - 19, // 21: teleport.integration.v1.AWSOIDCService.DeployService:input_type -> teleport.integration.v1.DeployServiceRequest - 21, // 22: teleport.integration.v1.AWSOIDCService.EnrollEKSClusters:input_type -> teleport.integration.v1.EnrollEKSClustersRequest - 24, // 23: teleport.integration.v1.AWSOIDCService.ListEC2:input_type -> teleport.integration.v1.ListEC2Request - 26, // 24: teleport.integration.v1.AWSOIDCService.ListEKSClusters:input_type -> teleport.integration.v1.ListEKSClustersRequest - 2, // 25: teleport.integration.v1.AWSOIDCService.ListEICE:output_type -> teleport.integration.v1.ListEICEResponse - 5, // 26: teleport.integration.v1.AWSOIDCService.CreateEICE:output_type -> teleport.integration.v1.CreateEICEResponse - 7, // 27: teleport.integration.v1.AWSOIDCService.ListDatabases:output_type -> teleport.integration.v1.ListDatabasesResponse - 12, // 28: teleport.integration.v1.AWSOIDCService.ListSecurityGroups:output_type -> teleport.integration.v1.ListSecurityGroupsResponse - 15, // 29: teleport.integration.v1.AWSOIDCService.ListSubnets:output_type -> teleport.integration.v1.ListSubnetsResponse - 18, // 30: teleport.integration.v1.AWSOIDCService.DeployDatabaseService:output_type -> teleport.integration.v1.DeployDatabaseServiceResponse - 20, // 31: teleport.integration.v1.AWSOIDCService.DeployService:output_type -> teleport.integration.v1.DeployServiceResponse - 23, // 32: teleport.integration.v1.AWSOIDCService.EnrollEKSClusters:output_type -> teleport.integration.v1.EnrollEKSClustersResponse - 25, // 33: teleport.integration.v1.AWSOIDCService.ListEC2:output_type -> teleport.integration.v1.ListEC2Response - 28, // 34: teleport.integration.v1.AWSOIDCService.ListEKSClusters:output_type -> teleport.integration.v1.ListEKSClustersResponse - 25, // [25:35] is the sub-list for method output_type - 15, // [15:25] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 17, // 9: teleport.integration.v1.ListVPCsResponse.vpcs:type_name -> teleport.integration.v1.VPC + 20, // 10: teleport.integration.v1.DeployDatabaseServiceRequest.deployments:type_name -> teleport.integration.v1.DeployDatabaseServiceDeployment + 25, // 11: teleport.integration.v1.EnrollEKSClustersResponse.results:type_name -> teleport.integration.v1.EnrollEKSClusterResult + 35, // 12: teleport.integration.v1.ListEC2Response.servers:type_name -> types.ServerV2 + 32, // 13: teleport.integration.v1.EKSCluster.labels:type_name -> teleport.integration.v1.EKSCluster.LabelsEntry + 33, // 14: teleport.integration.v1.EKSCluster.join_labels:type_name -> teleport.integration.v1.EKSCluster.JoinLabelsEntry + 30, // 15: teleport.integration.v1.ListEKSClustersResponse.clusters:type_name -> teleport.integration.v1.EKSCluster + 0, // 16: teleport.integration.v1.AWSOIDCService.ListEICE:input_type -> teleport.integration.v1.ListEICERequest + 3, // 17: teleport.integration.v1.AWSOIDCService.CreateEICE:input_type -> teleport.integration.v1.CreateEICERequest + 6, // 18: teleport.integration.v1.AWSOIDCService.ListDatabases:input_type -> teleport.integration.v1.ListDatabasesRequest + 8, // 19: teleport.integration.v1.AWSOIDCService.ListSecurityGroups:input_type -> teleport.integration.v1.ListSecurityGroupsRequest + 13, // 20: teleport.integration.v1.AWSOIDCService.ListSubnets:input_type -> teleport.integration.v1.ListSubnetsRequest + 16, // 21: teleport.integration.v1.AWSOIDCService.ListVPCs:input_type -> teleport.integration.v1.ListVPCsRequest + 19, // 22: teleport.integration.v1.AWSOIDCService.DeployDatabaseService:input_type -> teleport.integration.v1.DeployDatabaseServiceRequest + 22, // 23: teleport.integration.v1.AWSOIDCService.DeployService:input_type -> teleport.integration.v1.DeployServiceRequest + 24, // 24: teleport.integration.v1.AWSOIDCService.EnrollEKSClusters:input_type -> teleport.integration.v1.EnrollEKSClustersRequest + 27, // 25: teleport.integration.v1.AWSOIDCService.ListEC2:input_type -> teleport.integration.v1.ListEC2Request + 29, // 26: teleport.integration.v1.AWSOIDCService.ListEKSClusters:input_type -> teleport.integration.v1.ListEKSClustersRequest + 2, // 27: teleport.integration.v1.AWSOIDCService.ListEICE:output_type -> teleport.integration.v1.ListEICEResponse + 5, // 28: teleport.integration.v1.AWSOIDCService.CreateEICE:output_type -> teleport.integration.v1.CreateEICEResponse + 7, // 29: teleport.integration.v1.AWSOIDCService.ListDatabases:output_type -> teleport.integration.v1.ListDatabasesResponse + 12, // 30: teleport.integration.v1.AWSOIDCService.ListSecurityGroups:output_type -> teleport.integration.v1.ListSecurityGroupsResponse + 15, // 31: teleport.integration.v1.AWSOIDCService.ListSubnets:output_type -> teleport.integration.v1.ListSubnetsResponse + 18, // 32: teleport.integration.v1.AWSOIDCService.ListVPCs:output_type -> teleport.integration.v1.ListVPCsResponse + 21, // 33: teleport.integration.v1.AWSOIDCService.DeployDatabaseService:output_type -> teleport.integration.v1.DeployDatabaseServiceResponse + 23, // 34: teleport.integration.v1.AWSOIDCService.DeployService:output_type -> teleport.integration.v1.DeployServiceResponse + 26, // 35: teleport.integration.v1.AWSOIDCService.EnrollEKSClusters:output_type -> teleport.integration.v1.EnrollEKSClustersResponse + 28, // 36: teleport.integration.v1.AWSOIDCService.ListEC2:output_type -> teleport.integration.v1.ListEC2Response + 31, // 37: teleport.integration.v1.AWSOIDCService.ListEKSClusters:output_type -> teleport.integration.v1.ListEKSClustersResponse + 27, // [27:38] is the sub-list for method output_type + 16, // [16:27] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_teleport_integration_v1_awsoidc_service_proto_init() } @@ -2896,7 +3111,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeployDatabaseServiceRequest); i { + switch v := v.(*ListVPCsRequest); i { case 0: return &v.state case 1: @@ -2908,7 +3123,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeployDatabaseServiceDeployment); i { + switch v := v.(*VPC); i { case 0: return &v.state case 1: @@ -2920,7 +3135,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeployDatabaseServiceResponse); i { + switch v := v.(*ListVPCsResponse); i { case 0: return &v.state case 1: @@ -2932,7 +3147,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeployServiceRequest); i { + switch v := v.(*DeployDatabaseServiceRequest); i { case 0: return &v.state case 1: @@ -2944,7 +3159,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeployServiceResponse); i { + switch v := v.(*DeployDatabaseServiceDeployment); i { case 0: return &v.state case 1: @@ -2956,7 +3171,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnrollEKSClustersRequest); i { + switch v := v.(*DeployDatabaseServiceResponse); i { case 0: return &v.state case 1: @@ -2968,7 +3183,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnrollEKSClusterResult); i { + switch v := v.(*DeployServiceRequest); i { case 0: return &v.state case 1: @@ -2980,7 +3195,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EnrollEKSClustersResponse); i { + switch v := v.(*DeployServiceResponse); i { case 0: return &v.state case 1: @@ -2992,7 +3207,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEC2Request); i { + switch v := v.(*EnrollEKSClustersRequest); i { case 0: return &v.state case 1: @@ -3004,7 +3219,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEC2Response); i { + switch v := v.(*EnrollEKSClusterResult); i { case 0: return &v.state case 1: @@ -3016,7 +3231,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEKSClustersRequest); i { + switch v := v.(*EnrollEKSClustersResponse); i { case 0: return &v.state case 1: @@ -3028,7 +3243,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EKSCluster); i { + switch v := v.(*ListEC2Request); i { case 0: return &v.state case 1: @@ -3040,6 +3255,42 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { } } file_teleport_integration_v1_awsoidc_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEC2Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_integration_v1_awsoidc_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEKSClustersRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_integration_v1_awsoidc_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EKSCluster); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_integration_v1_awsoidc_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListEKSClustersResponse); i { case 0: return &v.state @@ -3058,7 +3309,7 @@ func file_teleport_integration_v1_awsoidc_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_integration_v1_awsoidc_service_proto_rawDesc, NumEnums: 0, - NumMessages: 31, + NumMessages: 34, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/teleport/integration/v1/awsoidc_service_grpc.pb.go b/api/gen/proto/go/teleport/integration/v1/awsoidc_service_grpc.pb.go index ec6adcc91dc40..919e843d5d59b 100644 --- a/api/gen/proto/go/teleport/integration/v1/awsoidc_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/awsoidc_service_grpc.pb.go @@ -38,6 +38,7 @@ const ( AWSOIDCService_ListDatabases_FullMethodName = "/teleport.integration.v1.AWSOIDCService/ListDatabases" AWSOIDCService_ListSecurityGroups_FullMethodName = "/teleport.integration.v1.AWSOIDCService/ListSecurityGroups" AWSOIDCService_ListSubnets_FullMethodName = "/teleport.integration.v1.AWSOIDCService/ListSubnets" + AWSOIDCService_ListVPCs_FullMethodName = "/teleport.integration.v1.AWSOIDCService/ListVPCs" AWSOIDCService_DeployDatabaseService_FullMethodName = "/teleport.integration.v1.AWSOIDCService/DeployDatabaseService" AWSOIDCService_DeployService_FullMethodName = "/teleport.integration.v1.AWSOIDCService/DeployService" AWSOIDCService_EnrollEKSClusters_FullMethodName = "/teleport.integration.v1.AWSOIDCService/EnrollEKSClusters" @@ -71,6 +72,10 @@ type AWSOIDCServiceClient interface { // It uses the following API: // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html ListSubnets(ctx context.Context, in *ListSubnetsRequest, opts ...grpc.CallOption) (*ListSubnetsResponse, error) + // ListVPCs returns a list of AWS VPCs. + // It uses the following API: + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html + ListVPCs(ctx context.Context, in *ListVPCsRequest, opts ...grpc.CallOption) (*ListVPCsResponse, error) // DeployDatabaseService deploys a Database Services to Amazon ECS. DeployDatabaseService(ctx context.Context, in *DeployDatabaseServiceRequest, opts ...grpc.CallOption) (*DeployDatabaseServiceResponse, error) // DeployService deploys an ECS Service to Amazon ECS. @@ -141,6 +146,15 @@ func (c *aWSOIDCServiceClient) ListSubnets(ctx context.Context, in *ListSubnetsR return out, nil } +func (c *aWSOIDCServiceClient) ListVPCs(ctx context.Context, in *ListVPCsRequest, opts ...grpc.CallOption) (*ListVPCsResponse, error) { + out := new(ListVPCsResponse) + err := c.cc.Invoke(ctx, AWSOIDCService_ListVPCs_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *aWSOIDCServiceClient) DeployDatabaseService(ctx context.Context, in *DeployDatabaseServiceRequest, opts ...grpc.CallOption) (*DeployDatabaseServiceResponse, error) { out := new(DeployDatabaseServiceResponse) err := c.cc.Invoke(ctx, AWSOIDCService_DeployDatabaseService_FullMethodName, in, out, opts...) @@ -212,6 +226,10 @@ type AWSOIDCServiceServer interface { // It uses the following API: // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html ListSubnets(context.Context, *ListSubnetsRequest) (*ListSubnetsResponse, error) + // ListVPCs returns a list of AWS VPCs. + // It uses the following API: + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html + ListVPCs(context.Context, *ListVPCsRequest) (*ListVPCsResponse, error) // DeployDatabaseService deploys a Database Services to Amazon ECS. DeployDatabaseService(context.Context, *DeployDatabaseServiceRequest) (*DeployDatabaseServiceResponse, error) // DeployService deploys an ECS Service to Amazon ECS. @@ -249,6 +267,9 @@ func (UnimplementedAWSOIDCServiceServer) ListSecurityGroups(context.Context, *Li func (UnimplementedAWSOIDCServiceServer) ListSubnets(context.Context, *ListSubnetsRequest) (*ListSubnetsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListSubnets not implemented") } +func (UnimplementedAWSOIDCServiceServer) ListVPCs(context.Context, *ListVPCsRequest) (*ListVPCsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListVPCs not implemented") +} func (UnimplementedAWSOIDCServiceServer) DeployDatabaseService(context.Context, *DeployDatabaseServiceRequest) (*DeployDatabaseServiceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeployDatabaseService not implemented") } @@ -367,6 +388,24 @@ func _AWSOIDCService_ListSubnets_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _AWSOIDCService_ListVPCs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListVPCsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AWSOIDCServiceServer).ListVPCs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AWSOIDCService_ListVPCs_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AWSOIDCServiceServer).ListVPCs(ctx, req.(*ListVPCsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _AWSOIDCService_DeployDatabaseService_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DeployDatabaseServiceRequest) if err := dec(in); err != nil { @@ -484,6 +523,10 @@ var AWSOIDCService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListSubnets", Handler: _AWSOIDCService_ListSubnets_Handler, }, + { + MethodName: "ListVPCs", + Handler: _AWSOIDCService_ListVPCs_Handler, + }, { MethodName: "DeployDatabaseService", Handler: _AWSOIDCService_DeployDatabaseService_Handler, diff --git a/api/proto/teleport/integration/v1/awsoidc_service.proto b/api/proto/teleport/integration/v1/awsoidc_service.proto index adc4f17ed4953..0c0813df5ad7f 100644 --- a/api/proto/teleport/integration/v1/awsoidc_service.proto +++ b/api/proto/teleport/integration/v1/awsoidc_service.proto @@ -49,6 +49,11 @@ service AWSOIDCService { // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html rpc ListSubnets(ListSubnetsRequest) returns (ListSubnetsResponse); + // ListVPCs returns a list of AWS VPCs. + // It uses the following API: + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html + rpc ListVPCs(ListVPCsRequest) returns (ListVPCsResponse); + // DeployDatabaseService deploys a Database Services to Amazon ECS. rpc DeployDatabaseService(DeployDatabaseServiceRequest) returns (DeployDatabaseServiceResponse); @@ -262,7 +267,7 @@ message ListSubnetsRequest { // Subnet is a representation of an AWS VPC subnet. message Subnet { - // Name is the subnet name. + // Name is the subnet name. Can be empty. string name = 1; // ID is the subnet ID. string id = 2; @@ -279,6 +284,36 @@ message ListSubnetsResponse { string next_token = 2; } +// ListVPCsRequest is a request for a paginated list of AWS VPCs. +message ListVPCsRequest { + // Integration is the AWS OIDC Integration name. + // Required. + string integration = 1; + // Region is the AWS Region + // Required. + string region = 2; + // NextToken is the token to be used to fetch the next page. + // If empty, the first page is fetched. + string next_token = 3; +} + +// VPC is a representation of an AWS VPC. +message VPC { + // Name is the VPC name. Can be empty. + string name = 1; + // ID is the VPC ID. + string id = 2; +} + +// ListVPCsResponse contains a page of AWS VPCs. +message ListVPCsResponse { + // VPCs contains the page of VPCs. + repeated VPC vpcs = 1; + // NextToken is used for pagination. + // If non-empty, it can be used to request the next page. + string next_token = 2; +} + // DeployDatabaseServiceRequest is a request to deploy . message DeployDatabaseServiceRequest { // Integration is the AWS OIDC Integration name. diff --git a/lib/auth/integration/integrationv1/awsoidc.go b/lib/auth/integration/integrationv1/awsoidc.go index ab3a0277c182f..ad74145be366f 100644 --- a/lib/auth/integration/integrationv1/awsoidc.go +++ b/lib/auth/integration/integrationv1/awsoidc.go @@ -716,3 +716,45 @@ func (s *AWSOIDCService) ListSubnets(ctx context.Context, req *integrationpb.Lis NextToken: resp.NextToken, }, nil } + +// ListVPCs returns a list of AWS VPCs. +func (s *AWSOIDCService) ListVPCs(ctx context.Context, req *integrationpb.ListVPCsRequest) (*integrationpb.ListVPCsResponse, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindIntegration, types.VerbUse); err != nil { + return nil, trace.Wrap(err) + } + + awsClientReq, err := s.awsClientReq(ctx, req.Integration, req.Region) + if err != nil { + return nil, trace.Wrap(err) + } + + awsClient, err := awsoidc.NewListVPCsClient(ctx, awsClientReq) + if err != nil { + return nil, trace.Wrap(err) + } + + resp, err := awsoidc.ListVPCs(ctx, awsClient, awsoidc.ListVPCsRequest{ + NextToken: req.NextToken, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + vpcs := make([]*integrationpb.VPC, 0, len(resp.VPCs)) + for _, s := range resp.VPCs { + vpcs = append(vpcs, &integrationpb.VPC{ + Name: s.Name, + Id: s.ID, + }) + } + + return &integrationpb.ListVPCsResponse{ + Vpcs: vpcs, + NextToken: resp.NextToken, + }, nil +} diff --git a/lib/auth/integration/integrationv1/awsoidc_test.go b/lib/auth/integration/integrationv1/awsoidc_test.go index 84c06dc544879..ef22596ad414a 100644 --- a/lib/auth/integration/integrationv1/awsoidc_test.go +++ b/lib/auth/integration/integrationv1/awsoidc_test.go @@ -215,7 +215,7 @@ func TestConvertSecurityGroupRulesToProto(t *testing.T) { } } -func TestListEICE(t *testing.T) { +func TestRBAC(t *testing.T) { t.Parallel() clusterName := "test-cluster" @@ -243,141 +243,10 @@ func TestListEICE(t *testing.T) { }) require.NoError(t, err) - t.Run("fails when user doesn't have access to integration.use", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead}, - }}}, - } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsoidService.ListEICE(userCtx, &integrationv1.ListEICERequest{ - Integration: integrationName, - Region: "my-region", - VpcIds: []string{"vpc-123"}, - NextToken: "", - }) - require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) - }) - t.Run("calls awsoidc package when user has access to integration.use/read", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead, types.VerbUse}, - }}}, - } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsoidService.ListEICE(userCtx, &integrationv1.ListEICERequest{ - Integration: integrationName, - Region: "", - VpcIds: []string{"vpc-123"}, - NextToken: "", - }) - require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) - }) -} - -func TestListDatabases(t *testing.T) { - t.Parallel() - - clusterName := "test-cluster" - proxyPublicAddr := "127.0.0.1.nip.io" - integrationName := "my-awsoidc-integration" - ig, err := types.NewIntegrationAWSOIDC( - types.Metadata{Name: integrationName}, - &types.AWSOIDCIntegrationSpecV1{ - RoleARN: "arn:aws:iam::123456789012:role/OpsTeam", - }, - ) - require.NoError(t, err) - - ca := newCertAuthority(t, types.HostCA, clusterName) - ctx, localClient, integrationSvc := initSvc(t, ca, clusterName, proxyPublicAddr) - - _, err = localClient.CreateIntegration(ctx, ig) - require.NoError(t, err) - - awsSvc, err := NewAWSOIDCService(&AWSOIDCServiceConfig{ - IntegrationService: integrationSvc, - Authorizer: integrationSvc.authorizer, - ProxyPublicAddrGetter: func() string { return "128.0.0.1" }, - Cache: &mockCache{}, - }) - require.NoError(t, err) - - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead}, - }}}, + type endpointSubtest struct { + name string + fn func() error } - - t.Run("fails when user doesn't have access to integration.use", func(t *testing.T) { - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - _, err = awsSvc.ListDatabases(userCtx, &integrationv1.ListDatabasesRequest{ - Integration: integrationName, - Region: "", - RdsType: "", - Engines: []string{}, - NextToken: "", - VpcId: "vpc-123", - }) - require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) - }) - t.Run("calls awsoidc package when user has access to integration.use/read", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead, types.VerbUse}, - }}}, - } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsSvc.ListDatabases(userCtx, &integrationv1.ListDatabasesRequest{ - Integration: integrationName, - Region: "", - RdsType: "", - Engines: []string{}, - NextToken: "", - VpcId: "vpc-123", - }) - require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) - }) -} - -func TestEnrollEKSClusters(t *testing.T) { - t.Parallel() - - clusterName := "test-cluster" - proxyPublicAddr := "127.0.0.1" - integrationName := "my-awsoidc-integration" - ig, err := types.NewIntegrationAWSOIDC( - types.Metadata{Name: integrationName}, - &types.AWSOIDCIntegrationSpecV1{ - RoleARN: "arn:aws:iam::123456789012:role/OpsTeam", - }, - ) - require.NoError(t, err) - - ca := newCertAuthority(t, types.HostCA, clusterName) - ctx, localClient, resourceSvc := initSvc(t, ca, clusterName, proxyPublicAddr) - - _, err = localClient.CreateIntegration(ctx, ig) - require.NoError(t, err) - - awsoidService, err := NewAWSOIDCService(&AWSOIDCServiceConfig{ - IntegrationService: resourceSvc, - Authorizer: resourceSvc.authorizer, - ProxyPublicAddrGetter: func() string { return "128.0.0.1" }, - Cache: &mockCache{}, - }) - require.NoError(t, err) - t.Run("fails when user doesn't have access to integration.use", func(t *testing.T) { role := types.RoleSpecV6{ Allow: types.RoleConditions{Rules: []types.Rule{{ @@ -388,77 +257,84 @@ func TestEnrollEKSClusters(t *testing.T) { userCtx := authorizerForDummyUser(t, ctx, role, localClient) - _, err = awsoidService.EnrollEKSClusters(userCtx, &integrationv1.EnrollEKSClustersRequest{ - Integration: integrationName, - Region: "my-region", - EksClusterNames: []string{"EKS1"}, - AgentVersion: "10.0.0", - }) - require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) - }) - t.Run("calls awsoidc package when user has access to integration.use/read", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead, types.VerbUse}, - }}}, + for _, tt := range []endpointSubtest{ + { + name: "ListEICE", + fn: func() error { + _, err := awsoidService.ListEICE(userCtx, &integrationv1.ListEICERequest{ + Integration: integrationName, + Region: "my-region", + VpcIds: []string{"vpc-123"}, + NextToken: "", + }) + return err + }, + }, + { + name: "ListDatabases", + fn: func() error { + _, err := awsoidService.ListDatabases(userCtx, &integrationv1.ListDatabasesRequest{ + Integration: integrationName, + Region: "", + RdsType: "", + Engines: []string{}, + NextToken: "", + VpcId: "vpc-123", + }) + return err + }, + }, + { + name: "EnrollEKSClusters", + fn: func() error { + _, err := awsoidService.EnrollEKSClusters(userCtx, &integrationv1.EnrollEKSClustersRequest{ + Integration: integrationName, + Region: "my-region", + EksClusterNames: []string{"EKS1"}, + AgentVersion: "10.0.0", + }) + return err + }, + }, + { + name: "DeployService", + fn: func() error { + _, err = awsoidService.DeployService(userCtx, &integrationv1.DeployServiceRequest{ + Integration: integrationName, + Region: "my-region", + }) + return err + }, + }, + { + name: "ListSubnets", + fn: func() error { + _, err := awsoidService.ListSubnets(userCtx, &integrationv1.ListSubnetsRequest{ + Integration: integrationName, + Region: "my-region", + VpcId: "vpc-1", + }) + return err + }, + }, + { + name: "ListVPCs", + fn: func() error { + _, err := awsoidService.ListVPCs(userCtx, &integrationv1.ListVPCsRequest{ + Integration: integrationName, + Region: "my-region", + }) + return err + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.fn() + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) + }) } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err := awsoidService.EnrollEKSClusters(userCtx, &integrationv1.EnrollEKSClustersRequest{ - Integration: integrationName, - Region: "my-region", - EksClusterNames: []string{"EKS1"}, - }) - require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) }) -} -func TestDeployService(t *testing.T) { - t.Parallel() - - clusterName := "test-cluster" - proxyPublicAddr := "127.0.0.1.nip.io" - integrationName := "my-awsoidc-integration" - ig, err := types.NewIntegrationAWSOIDC( - types.Metadata{Name: integrationName}, - &types.AWSOIDCIntegrationSpecV1{ - RoleARN: "arn:aws:iam::123456789012:role/OpsTeam", - }, - ) - require.NoError(t, err) - - ca := newCertAuthority(t, types.HostCA, clusterName) - ctx, localClient, resourceSvc := initSvc(t, ca, clusterName, proxyPublicAddr) - - _, err = localClient.CreateIntegration(ctx, ig) - require.NoError(t, err) - - awsoidService, err := NewAWSOIDCService(&AWSOIDCServiceConfig{ - IntegrationService: resourceSvc, - Authorizer: resourceSvc.authorizer, - ProxyPublicAddrGetter: func() string { return "128.0.0.1" }, - Cache: &mockCache{}, - }) - require.NoError(t, err) - - t.Run("fails when user doesn't have access to integration.use", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead}, - }}}, - } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsoidService.DeployService(userCtx, &integrationv1.DeployServiceRequest{ - Integration: integrationName, - Region: "my-region", - }) - require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) - }) t.Run("calls awsoidc package when user has access to integration.use/read", func(t *testing.T) { role := types.RoleSpecV6{ Allow: types.RoleConditions{Rules: []types.Rule{{ @@ -469,74 +345,81 @@ func TestDeployService(t *testing.T) { userCtx := authorizerForDummyUser(t, ctx, role, localClient) - _, err = awsoidService.DeployService(userCtx, &integrationv1.DeployServiceRequest{ - Integration: integrationName, - Region: "my-region", - }) - require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) - }) -} - -func TestListSubnets(t *testing.T) { - t.Parallel() - - clusterName := "test-cluster" - proxyPublicAddr := "127.0.0.1.nip.io" - integrationName := "my-awsoidc-integration" - ig, err := types.NewIntegrationAWSOIDC( - types.Metadata{Name: integrationName}, - &types.AWSOIDCIntegrationSpecV1{ - RoleARN: "arn:aws:iam::123456789012:role/OpsTeam", - }, - ) - require.NoError(t, err) - - ca := newCertAuthority(t, types.HostCA, clusterName) - ctx, localClient, resourceSvc := initSvc(t, ca, clusterName, proxyPublicAddr) - - _, err = localClient.CreateIntegration(ctx, ig) - require.NoError(t, err) - - awsoidService, err := NewAWSOIDCService(&AWSOIDCServiceConfig{ - IntegrationService: resourceSvc, - Authorizer: resourceSvc.authorizer, - ProxyPublicAddrGetter: func() string { return "128.0.0.1" }, - Cache: &mockCache{}, - }) - require.NoError(t, err) - - t.Run("fails when user doesn't have access to integration.use", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead}, - }}}, - } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsoidService.ListSubnets(userCtx, &integrationv1.ListSubnetsRequest{ - Integration: integrationName, - Region: "my-region", - VpcId: "vpc-1", - }) - require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, but got %T", err) - }) - t.Run("calls awsoidc package when user has access to integration.use/read", func(t *testing.T) { - role := types.RoleSpecV6{ - Allow: types.RoleConditions{Rules: []types.Rule{{ - Resources: []string{types.KindIntegration}, - Verbs: []string{types.VerbRead, types.VerbUse}, - }}}, + for _, tt := range []endpointSubtest{ + { + name: "ListEICE", + fn: func() error { + _, err := awsoidService.ListEICE(userCtx, &integrationv1.ListEICERequest{ + Integration: integrationName, + Region: "my-region", + VpcIds: []string{"vpc-123"}, + NextToken: "", + }) + return err + }, + }, + { + name: "ListDatabases", + fn: func() error { + _, err := awsoidService.ListDatabases(userCtx, &integrationv1.ListDatabasesRequest{ + Integration: integrationName, + Region: "", + RdsType: "", + Engines: []string{}, + NextToken: "", + VpcId: "vpc-123", + }) + return err + }, + }, + { + name: "EnrollEKSClusters", + fn: func() error { + _, err := awsoidService.EnrollEKSClusters(userCtx, &integrationv1.EnrollEKSClustersRequest{ + Integration: integrationName, + Region: "my-region", + EksClusterNames: []string{"EKS1"}, + AgentVersion: "10.0.0", + }) + return err + }, + }, + { + name: "DeployService", + fn: func() error { + _, err = awsoidService.DeployService(userCtx, &integrationv1.DeployServiceRequest{ + Integration: integrationName, + Region: "my-region", + }) + return err + }, + }, + { + name: "ListSubnets", + fn: func() error { + _, err := awsoidService.ListSubnets(userCtx, &integrationv1.ListSubnetsRequest{ + Integration: integrationName, + Region: "my-region", + VpcId: "vpc-1", + }) + return err + }, + }, + { + name: "ListVPCs", + fn: func() error { + _, err := awsoidService.ListVPCs(userCtx, &integrationv1.ListVPCsRequest{ + Integration: integrationName, + Region: "my-region", + }) + return err + }, + }, + } { + t.Run(tt.name, func(t *testing.T) { + err := tt.fn() + require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) + }) } - - userCtx := authorizerForDummyUser(t, ctx, role, localClient) - - _, err = awsoidService.ListSubnets(userCtx, &integrationv1.ListSubnetsRequest{ - Integration: integrationName, - Region: "my-region", - VpcId: "", - }) - require.True(t, trace.IsBadParameter(err), "expected BadParameter error, but got %T", err) }) } diff --git a/lib/integrations/awsoidc/deploydatabaseservice.go b/lib/integrations/awsoidc/deploydatabaseservice.go index f17552d62c79c..d6d35ef91585c 100644 --- a/lib/integrations/awsoidc/deploydatabaseservice.go +++ b/lib/integrations/awsoidc/deploydatabaseservice.go @@ -259,11 +259,9 @@ func DeployDatabaseService(ctx context.Context, clt DeployServiceClient, req Dep } } - clusterDashboardURL := fmt.Sprintf("https://%s.console.aws.amazon.com/ecs/v2/clusters/%s/services", req.Region, aws.ToString(cluster.ClusterName)) - return &DeployDatabaseServiceResponse{ ClusterARN: aws.ToString(cluster.ClusterArn), - ClusterDashboardURL: clusterDashboardURL, + ClusterDashboardURL: ecsClusterDashboardURL(req.Region, aws.ToString(cluster.ClusterName)), }, nil } @@ -276,3 +274,27 @@ func ecsTaskName(teleportClusterName, deploymentMode, vpcid string) string { func ecsServiceName(deploymentMode, vpcid string) string { return normalizeECSResourceName(fmt.Sprintf("%s-%s", deploymentMode, vpcid)) } + +// ecsClusterDashboardURL returns the ECS cluster dashboard URL for a given +// region and ECS cluster. +func ecsClusterDashboardURL(region, ecsClusterName string) string { + return fmt.Sprintf("https://%s.console.aws.amazon.com/ecs/v2/clusters/%s/services", region, ecsClusterName) +} + +// ECSDatabaseServiceDashboardURL returns the ECS service dashboard URL for +// a deployed database service. +func ECSDatabaseServiceDashboardURL(region, teleportClusterName, vpcID string) (string, error) { + if region == "" { + return "", trace.BadParameter("empty region") + } + if teleportClusterName == "" { + return "", trace.BadParameter("empty cluster name") + } + if vpcID == "" { + return "", trace.BadParameter("empty VPC ID") + } + ecsClusterName := normalizeECSClusterName(teleportClusterName) + ecsClusterDashboard := ecsClusterDashboardURL(region, ecsClusterName) + serviceName := ecsServiceName(DatabaseServiceDeploymentMode, vpcID) + return fmt.Sprintf("%s/%s", ecsClusterDashboard, serviceName), nil +} diff --git a/lib/integrations/awsoidc/deploydatabaseservice_test.go b/lib/integrations/awsoidc/deploydatabaseservice_test.go index a61309f9c8325..ec871eaf092ac 100644 --- a/lib/integrations/awsoidc/deploydatabaseservice_test.go +++ b/lib/integrations/awsoidc/deploydatabaseservice_test.go @@ -554,3 +554,56 @@ func TestDeployDatabaseService(t *testing.T) { require.Equal(t, "ARNcluster-name-teleport", resp.ClusterARN) }) } + +func TestECSDatabaseServiceDashboardURL(t *testing.T) { + tests := []struct { + name string + region string + teleportClusterName string + vpcID string + wantURL string + wantErrContains string + }{ + { + name: "valid params", + region: "us-west-1", + teleportClusterName: "foo.bar.com", + vpcID: "vpc-123", + wantURL: "https://us-west-1.console.aws.amazon.com/ecs/v2/clusters/foo_bar_com-teleport/services/database-service-vpc-123", + }, + { + name: "empty region is an error", + region: "", + teleportClusterName: "foo.bar.com", + vpcID: "vpc-123", + wantErrContains: "empty region", + }, + { + name: "empty cluster name is an error", + region: "us-west-1", + teleportClusterName: "", + vpcID: "vpc-123", + wantErrContains: "empty cluster name", + }, + { + name: "empty VPC ID is an error", + region: "us-west-1", + teleportClusterName: "foo.bar.com", + vpcID: "", + wantErrContains: "empty VPC", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ECSDatabaseServiceDashboardURL(tt.region, tt.teleportClusterName, tt.vpcID) + if tt.wantErrContains != "" { + require.Error(t, err) + require.ErrorContains(t, err, tt.wantErrContains) + return + } + require.NoError(t, err) + require.Equal(t, tt.wantURL, got) + }) + } +} diff --git a/lib/integrations/awsoidc/list_subnets.go b/lib/integrations/awsoidc/list_subnets.go index 6cbaf3c7a62cd..2a77cd102db52 100644 --- a/lib/integrations/awsoidc/list_subnets.go +++ b/lib/integrations/awsoidc/list_subnets.go @@ -126,15 +126,8 @@ func ListSubnets(ctx context.Context, clt ListSubnetsClient, req ListSubnetsRequ func convertAWSSubnets(subnets []ec2Types.Subnet) []Subnet { ret := make([]Subnet, 0, len(subnets)) for _, s := range subnets { - var name string - for _, tag := range s.Tags { - if aws.ToString(tag.Key) == "Name" { - name = aws.ToString(tag.Value) - break - } - } ret = append(ret, Subnet{ - Name: name, + Name: nameFromEC2Tags(s.Tags), ID: aws.ToString(s.SubnetId), AvailabilityZone: aws.ToString(s.AvailabilityZone), }) diff --git a/lib/integrations/awsoidc/list_vpcs.go b/lib/integrations/awsoidc/list_vpcs.go new file mode 100644 index 0000000000000..2a6b022413bc9 --- /dev/null +++ b/lib/integrations/awsoidc/list_vpcs.go @@ -0,0 +1,122 @@ +/* + * 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 awsoidc + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/gravitational/trace" +) + +// ListVPCsRequest contains the required fields to list AWS VPCs. +type ListVPCsRequest struct { + // NextToken is the token to be used to fetch the next page. + // If empty, the first page is fetched. + NextToken string +} + +// VPC is the Teleport representation of an AWS VPC. +type VPC struct { + // Name is the VPC name. + // This is just a friendly name and should not be used for further API calls. + // It can be empty if the VPC was not given a "Name" tag. + Name string `json:"name"` + + // ID is the VPC ID, for example "vpc-0ee975135dEXAMPLE". + // This is the value that should be used when doing further API calls. + ID string `json:"id"` +} + +// ListVPCsResponse contains a page of VPCs. +type ListVPCsResponse struct { + // VPCs contains the page of VPCs. + VPCs []VPC `json:"vpcs"` + + // NextToken is used for pagination. + // If non-empty, it can be used to request the next page. + NextToken string `json:"nextToken"` +} + +// ListVPCsClient describes the required methods to list AWS VPCs. +type ListVPCsClient interface { + // DescribeVpcs describes VPCs. + DescribeVpcs(ctx context.Context, params *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) +} + +type defaultListVPCsClient struct { + *ec2.Client +} + +// NewListVPCsClient creates a new ListVPCsClient using an AWSClientRequest. +func NewListVPCsClient(ctx context.Context, req *AWSClientRequest) (ListVPCsClient, error) { + ec2Client, err := newEC2Client(ctx, req) + if err != nil { + return nil, trace.Wrap(err) + } + + return &defaultListVPCsClient{ + Client: ec2Client, + }, nil +} + +// ListVPCs calls the following AWS API: +// https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html +// It returns a list of VPCs and an optional NextToken that can be used to fetch the next page. +func ListVPCs(ctx context.Context, clt ListVPCsClient, req ListVPCsRequest) (*ListVPCsResponse, error) { + describeVPCsInput := &ec2.DescribeVpcsInput{MaxResults: aws.Int32(100)} + if req.NextToken != "" { + describeVPCsInput.NextToken = &req.NextToken + } + + resp, err := clt.DescribeVpcs(ctx, describeVPCsInput) + if err != nil { + return nil, trace.Wrap(err) + } + + return &ListVPCsResponse{ + NextToken: aws.ToString(resp.NextToken), + VPCs: convertAWSVPCs(resp.Vpcs), + }, nil +} + +func convertAWSVPCs(vpcs []ec2Types.Vpc) []VPC { + ret := make([]VPC, 0, len(vpcs)) + for _, v := range vpcs { + ret = append(ret, VPC{ + Name: nameFromEC2Tags(v.Tags), + ID: aws.ToString(v.VpcId), + }) + } + return ret +} + +// nameFromEC2Tags is a helper to find the display name of an ec2 resource based +// on the "Name" tag, if it exists. +// Returns an empty string if there is no "Name" tag. +func nameFromEC2Tags(tags []ec2Types.Tag) string { + for _, tag := range tags { + if aws.ToString(tag.Key) == "Name" { + return aws.ToString(tag.Value) + } + } + return "" +} diff --git a/lib/integrations/awsoidc/list_vpcs_test.go b/lib/integrations/awsoidc/list_vpcs_test.go new file mode 100644 index 0000000000000..dd34de093f8a9 --- /dev/null +++ b/lib/integrations/awsoidc/list_vpcs_test.go @@ -0,0 +1,214 @@ +/* + * 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 awsoidc + +import ( + "context" + "fmt" + "strconv" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/google/go-cmp/cmp" + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" +) + +var _ ListVPCsClient = (*mockListVPCsClient)(nil) + +type mockListVPCsClient struct { + pageSize int + vpcs []ec2Types.Vpc +} + +// Returns information about AWS VPCs. +// This API supports pagination. +func (m mockListVPCsClient) DescribeVpcs(ctx context.Context, params *ec2.DescribeVpcsInput, optFns ...func(*ec2.Options)) (*ec2.DescribeVpcsOutput, error) { + requestedPage := 1 + + totalVPCs := len(m.vpcs) + + if params.NextToken != nil { + currentMarker, err := strconv.Atoi(*params.NextToken) + if err != nil { + return nil, trace.Wrap(err) + } + requestedPage = currentMarker + } + + sliceStart := m.pageSize * (requestedPage - 1) + sliceEnd := m.pageSize * requestedPage + if sliceEnd > totalVPCs { + sliceEnd = totalVPCs + } + + ret := &ec2.DescribeVpcsOutput{ + Vpcs: m.vpcs[sliceStart:sliceEnd], + } + + if sliceEnd < totalVPCs { + nextToken := strconv.Itoa(requestedPage + 1) + ret.NextToken = &nextToken + } + + return ret, nil +} + +func TestListVPCs(t *testing.T) { + ctx := context.Background() + + noErrorFunc := func(err error) bool { + return err == nil + } + + const pageSize = 100 + t.Run("pagination", func(t *testing.T) { + totalVPCs := 203 + + VPCs := make([]ec2Types.Vpc, 0, totalVPCs) + for i := 0; i < totalVPCs; i++ { + VPCs = append(VPCs, ec2Types.Vpc{ + VpcId: aws.String(fmt.Sprintf("VPC-%d", i)), + Tags: makeNameTags(fmt.Sprintf("MyVPC-%d", i)), + }) + } + + mockListClient := &mockListVPCsClient{ + pageSize: pageSize, + vpcs: VPCs, + } + + // First page must return pageSize number of VPCs + resp, err := ListVPCs(ctx, mockListClient, ListVPCsRequest{ + NextToken: "", + }) + require.NoError(t, err) + require.NotEmpty(t, resp.NextToken) + require.Len(t, resp.VPCs, pageSize) + nextPageToken := resp.NextToken + require.Equal(t, "VPC-0", resp.VPCs[0].ID) + require.Equal(t, "MyVPC-0", resp.VPCs[0].Name) + + // Second page must return pageSize number of Endpoints + resp, err = ListVPCs(ctx, mockListClient, ListVPCsRequest{ + NextToken: nextPageToken, + }) + require.NoError(t, err) + require.NotEmpty(t, resp.NextToken) + require.Len(t, resp.VPCs, pageSize) + nextPageToken = resp.NextToken + require.Equal(t, "VPC-100", resp.VPCs[0].ID) + require.Equal(t, "MyVPC-100", resp.VPCs[0].Name) + + // Third page must return only the remaining Endpoints and an empty nextToken + resp, err = ListVPCs(ctx, mockListClient, ListVPCsRequest{ + NextToken: nextPageToken, + }) + require.NoError(t, err) + require.Empty(t, resp.NextToken) + require.Len(t, resp.VPCs, 3) + require.Equal(t, "VPC-200", resp.VPCs[0].ID) + require.Equal(t, "MyVPC-200", resp.VPCs[0].Name) + }) + + for _, tt := range []struct { + name string + req ListVPCsRequest + mockVPCs []ec2Types.Vpc + errCheck func(error) bool + respCheck func(*testing.T, *ListVPCsResponse) + }{ + { + name: "valid for listing VPCs", + req: ListVPCsRequest{ + NextToken: "", + }, + mockVPCs: []ec2Types.Vpc{{ + VpcId: aws.String("VPC-123"), + Tags: makeNameTags("MyVPC-123"), + }}, + respCheck: func(t *testing.T, ldr *ListVPCsResponse) { + require.Len(t, ldr.VPCs, 1) + require.Empty(t, ldr.NextToken, "there is only 1 page of VPCs") + + want := VPC{ + ID: "VPC-123", + Name: "MyVPC-123", + } + require.Empty(t, cmp.Diff(want, ldr.VPCs[0])) + }, + errCheck: noErrorFunc, + }, + } { + t.Run(tt.name, func(t *testing.T) { + mockListClient := &mockListVPCsClient{ + pageSize: pageSize, + vpcs: tt.mockVPCs, + } + resp, err := ListVPCs(ctx, mockListClient, tt.req) + require.True(t, tt.errCheck(err), "unexpected err: %v", err) + if tt.respCheck != nil { + tt.respCheck(t, resp) + } + }) + } +} + +func TestConvertVPC(t *testing.T) { + for _, tt := range []struct { + name string + input []ec2Types.Vpc + expected []VPC + }{ + { + name: "no name tag", + input: []ec2Types.Vpc{{ + VpcId: aws.String("VPC-abc"), + Tags: []ec2Types.Tag{ + {Key: aws.String("foo"), Value: aws.String("bar")}, + }, + }}, + expected: []VPC{{ + Name: "", + ID: "VPC-abc", + }}, + }, + { + name: "with name tag", + input: []ec2Types.Vpc{{ + VpcId: aws.String("VPC-abc"), + Tags: []ec2Types.Tag{ + {Key: aws.String("foo"), Value: aws.String("bar")}, + {Key: aws.String("Name"), Value: aws.String("llama")}, + {Key: aws.String("baz"), Value: aws.String("qux")}, + }, + }}, + expected: []VPC{{ + Name: "llama", + ID: "VPC-abc", + }}, + }, + } { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.expected, convertAWSVPCs(tt.input)) + }) + } +} diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index 3317353bf62e7..e209675939a65 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -891,6 +891,7 @@ func (h *Handler) bindDefaultEndpoints() { h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/ec2ice", h.WithClusterAuth(h.awsOIDCListEC2ICE)) h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/deployec2ice", h.WithClusterAuth(h.awsOIDCDeployEC2ICE)) h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/securitygroups", h.WithClusterAuth(h.awsOIDCListSecurityGroups)) + h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/databasevpcs", h.WithClusterAuth(h.awsOIDCListDatabaseVPCs)) h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/subnets", h.WithClusterAuth(h.awsOIDCListSubnets)) h.POST("/webapi/sites/:site/integrations/aws-oidc/:name/requireddatabasesvpcs", h.WithClusterAuth(h.awsOIDCRequiredDatabasesVPCS)) h.GET("/webapi/scripts/integrations/configure/eice-iam.sh", h.WithLimiter(h.awsOIDCConfigureEICEIAM)) diff --git a/lib/web/integrations_awsoidc.go b/lib/web/integrations_awsoidc.go index 262798544f905..cd70b482fa7ad 100644 --- a/lib/web/integrations_awsoidc.go +++ b/lib/web/integrations_awsoidc.go @@ -752,24 +752,9 @@ func awsOIDCListAllDatabases(ctx context.Context, clt authclient.ClientI, integr func awsOIDCRequiredVPCSHelper(ctx context.Context, clt authclient.ClientI, req ui.AWSOIDCRequiredVPCSRequest, fetchedRDSs []*types.DatabaseV3) (*ui.AWSOIDCRequiredVPCSResponse, error) { // Get all database services with ecs/fargate metadata label. - nextToken := "" - fetchedDbSvcs := []types.DatabaseService{} - for { - page, err := client.GetResourcePage[types.DatabaseService](ctx, clt, &proto.ListResourcesRequest{ - ResourceType: types.KindDatabaseService, - Limit: defaults.MaxIterationLimit, - StartKey: nextToken, - Labels: map[string]string{types.AWSOIDCAgentLabel: types.True}, - }) - if err != nil { - return nil, trace.Wrap(err) - } - - fetchedDbSvcs = append(fetchedDbSvcs, page.Resources...) - nextToken = page.NextKey - if len(nextToken) == 0 { - break - } + fetchedDbSvcs, err := fetchAWSOIDCDatabaseServices(ctx, clt) + if err != nil { + return nil, trace.Wrap(err) } // Construct map of VPCs and its subnets. @@ -786,29 +771,10 @@ func awsOIDCRequiredVPCSHelper(ctx context.Context, clt authclient.ClientI, req } for _, svc := range fetchedDbSvcs { - if len(svc.GetResourceMatchers()) != 1 || svc.GetResourceMatchers()[0].Labels == nil { - continue + vpcID := getDBServiceVPC(svc, req.AccountID, req.Region) + if vpcID != "" { + delete(vpcLookup, vpcID) } - - // Database services deployed by Teleport have known configurations where - // we will only define a single resource matcher. - labelMatcher := *svc.GetResourceMatchers()[0].Labels - - // We check for length 3, because we are only - // wanting/checking for 3 discovery labels. - if len(labelMatcher) != 3 { - continue - } - if slices.Compare(labelMatcher[types.DiscoveryLabelAccountID], []string{req.AccountID}) != 0 { - continue - } - if slices.Compare(labelMatcher[types.DiscoveryLabelRegion], []string{req.Region}) != 0 { - continue - } - if len(labelMatcher[types.DiscoveryLabelVPCID]) != 1 { - continue - } - delete(vpcLookup, labelMatcher[types.DiscoveryLabelVPCID][0]) } return &ui.AWSOIDCRequiredVPCSResponse{ @@ -1185,7 +1151,7 @@ func (h *Handler) accessGraphCloudSyncOIDC(w http.ResponseWriter, r *http.Reques } } -func (h *Handler) awsAccessGraphOIDCSync(w http.ResponseWriter, r *http.Request, p httprouter.Params) (any, error) { +func (h *Handler) awsAccessGraphOIDCSync(w http.ResponseWriter, r *http.Request, _ httprouter.Params) (any, error) { queryParams := r.URL.Query() role := queryParams.Get("role") if err := aws.IsValidIAMRoleName(role); err != nil { @@ -1255,3 +1221,130 @@ func (h *Handler) awsOIDCListSubnets(w http.ResponseWriter, r *http.Request, p h Subnets: subnets, }, nil } + +// awsOIDCListDatabaseVPCs returns a list of VPCs using the ListVpcs action +// of the AWS OIDC Integration, and includes a link to the ECS service if +// a database service has been deployed for each VPC. +func (h *Handler) awsOIDCListDatabaseVPCs(w http.ResponseWriter, r *http.Request, p httprouter.Params, sctx *SessionContext, site reversetunnelclient.RemoteSite) (any, error) { + ctx := r.Context() + + var req ui.AWSOIDCListVPCsRequest + if err := httplib.ReadJSON(r, &req); err != nil { + return nil, trace.Wrap(err) + } + + integrationName := p.ByName("name") + if integrationName == "" { + return nil, trace.BadParameter("an integration name is required") + } + + clt, err := sctx.GetUserClient(ctx, site) + if err != nil { + return nil, trace.Wrap(err) + } + + listResp, err := clt.IntegrationAWSOIDCClient().ListVPCs(ctx, &integrationv1.ListVPCsRequest{ + Integration: integrationName, + Region: req.Region, + NextToken: req.NextToken, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + dbServices, err := fetchAWSOIDCDatabaseServices(ctx, clt) + if err != nil { + return nil, trace.Wrap(err) + } + + serviceURLByVPC, err := getServiceURLs(dbServices, req.AccountID, req.Region, h.auth.clusterName) + if err != nil { + return nil, trace.Wrap(err) + } + + vpcs := make([]ui.DatabaseEnrollmentVPC, 0, len(listResp.Vpcs)) + for _, vpc := range listResp.Vpcs { + vpcs = append(vpcs, ui.DatabaseEnrollmentVPC{ + VPC: awsoidc.VPC{ + Name: vpc.Name, + ID: vpc.Id, + }, + ECSServiceDashboardURL: serviceURLByVPC[vpc.Id], + }) + } + + return ui.AWSOIDCDatabaseVPCsResponse{ + NextToken: listResp.NextToken, + VPCs: vpcs, + }, nil +} + +func fetchAWSOIDCDatabaseServices(ctx context.Context, clt client.GetResourcesClient) ([]types.DatabaseService, error) { + // Get all database services with the AWS OIDC agent metadata label. + var nextToken string + var fetchedDbSvcs []types.DatabaseService + for { + page, err := client.GetResourcePage[types.DatabaseService](ctx, clt, &proto.ListResourcesRequest{ + ResourceType: types.KindDatabaseService, + Limit: defaults.MaxIterationLimit, + StartKey: nextToken, + Labels: map[string]string{types.AWSOIDCAgentLabel: types.True}, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + fetchedDbSvcs = append(fetchedDbSvcs, page.Resources...) + nextToken = page.NextKey + if len(nextToken) == 0 { + return fetchedDbSvcs, nil + } + } +} + +// getDBServiceVPC returns the database service's VPC ID selector value if the +// database service was deployed by the AWS OIDC integration, otherwise it +// returns an empty string. +func getDBServiceVPC(svc types.DatabaseService, accountID, region string) string { + if len(svc.GetResourceMatchers()) != 1 || svc.GetResourceMatchers()[0].Labels == nil { + return "" + } + + // Database services deployed by Teleport have known configurations where + // we will only define a single resource matcher. + labelMatcher := *svc.GetResourceMatchers()[0].Labels + + // We check for length 3, because we are only + // wanting/checking for 3 discovery labels. + if len(labelMatcher) != 3 { + return "" + } + if slices.Compare(labelMatcher[types.DiscoveryLabelAccountID], []string{accountID}) != 0 { + return "" + } + if slices.Compare(labelMatcher[types.DiscoveryLabelRegion], []string{region}) != 0 { + return "" + } + if len(labelMatcher[types.DiscoveryLabelVPCID]) != 1 { + return "" + } + return labelMatcher[types.DiscoveryLabelVPCID][0] +} + +// getServiceURLs returns a map vpcID -> service URL for ECS services deployed +// by the OIDC integration in the given account and region. +func getServiceURLs(dbServices []types.DatabaseService, accountID, region, teleportClusterName string) (map[string]string, error) { + serviceURLByVPC := make(map[string]string) + for _, svc := range dbServices { + vpcID := getDBServiceVPC(svc, accountID, region) + if vpcID == "" { + continue + } + svcURL, err := awsoidc.ECSDatabaseServiceDashboardURL(region, teleportClusterName, vpcID) + if err != nil { + return nil, trace.Wrap(err) + } + serviceURLByVPC[vpcID] = svcURL + } + return serviceURLByVPC, nil +} diff --git a/lib/web/ui/integration.go b/lib/web/ui/integration.go index f8f00c4142519..3de8c7bbce860 100644 --- a/lib/web/ui/integration.go +++ b/lib/web/ui/integration.go @@ -379,6 +379,39 @@ type AWSOIDCListSubnetsResponse struct { NextToken string `json:"nextToken,omitempty"` } +// AWSOIDCRequiredVPCSRequest is a request to list VPCs. +type AWSOIDCListVPCsRequest struct { + // Region is the AWS Region. + Region string `json:"region"` + // AccountID is the AWS Account ID. + AccountID string `json:"accountId"` + // NextToken is the token to be used to fetch the next page. + // If empty, the first page is fetched. + NextToken string `json:"nextToken"` +} + +// DatabaseEnrollmentVPC is a wrapper around [awsoidc.VPC] that also includes +// a link to the ECS service for a deployed Teleport database service in that +// VPC, if one exists. +type DatabaseEnrollmentVPC struct { + awsoidc.VPC + // ECSServiceDashboardURL is a link to the ECS service deployed for this + // VPC, if one exists. Can be empty. + ECSServiceDashboardURL string `json:"ecsServiceDashboardURL"` +} + +// AWSOIDCDatabaseVPCsResponse contains a list of VPCs, including a link to +// an existing db service deployment if one exists, and a next token if more +// pages are available. +type AWSOIDCDatabaseVPCsResponse struct { + // VPCs contains a page of VPCs. + VPCs []DatabaseEnrollmentVPC `json:"vpcs"` + + // NextToken is used for pagination. + // If non-empty, it can be used to request the next page. + NextToken string `json:"nextToken,omitempty"` +} + // AWSOIDCRequiredVPCSRequest is a request to get required (missing) VPC's and its subnets. type AWSOIDCRequiredVPCSRequest struct { // Region is the AWS Region.