From c7a11477ee6d377031782e09dc92e7e011fae79d Mon Sep 17 00:00:00 2001 From: Lisa Kim Date: Fri, 3 Feb 2023 11:30:56 -0800 Subject: [PATCH] [Web:Discover] Report events (#20581) * Define event types * Define event names for each flow * Report events upon start, exiting, and next steps * Update json property name change * Emit user skipped event * Emit error events * Handle unloading event for 'completed' step * Move updating event state into hook * Finish emitting events for desktop * Address CR: rename DiscoverDesktop to DiscoverResources * Various changes: - address CR: remove use of ref - diagnostic traces can also be a success, only emit event on failed traces - add mysql to discover events - consistent naming on exit prompt * Update and add new event names * Update tests * Emit events for unimplemented flows (apps and other dbs) * Redo emitting events for test connection Send event for EACH test connection failure or success. If a user does not do any testing, send a skipped event. --- .../proto/go/usageevents/v1/usageevents.pb.go | 287 ++++++++++-------- .../teleport/usageevents/v1/usageevents.proto | 7 + gen/proto/go/prehog/v1alpha/teleport.pb.go | 146 +++++---- gen/proto/js/prehog/v1alpha/teleport_pb.d.ts | 7 + gen/proto/js/prehog/v1alpha/teleport_pb.js | 9 +- lib/web/userevent.go | 12 +- proto/prehog/v1alpha/teleport.proto | 7 + .../CreateDatabase/useCreateDatabase.ts | 9 +- .../DownloadScript/DownloadScript.story.tsx | 30 +- .../DownloadScript/DownloadScript.tsx | 8 +- .../Database/IamPolicy/useIamPolicy.ts | 6 + .../Database/MutualTls/useMutualTls.ts | 13 +- .../teleport/src/Discover/Database/index.tsx | 12 + .../ConnectTeleport/ConnectTeleport.tsx | 15 +- .../DiscoverDesktops/DiscoverDesktops.tsx | 16 +- .../teleport/src/Discover/Desktop/index.tsx | 9 + .../teleport/src/Discover/Discover.test.tsx | 16 +- .../teleport/src/Discover/Discover.tsx | 2 +- .../Kubernetes/HelmChart/HelmChart.story.tsx | 30 +- .../src/Discover/Kubernetes/index.tsx | 7 + .../SelectResource/SelectResource.test.tsx | 12 +- .../SelectResource/SelectResource.tsx | 17 +- .../DownloadScript/DownloadScript.story.tsx | 30 +- .../teleport/src/Discover/Server/index.tsx | 7 + .../useConnectionDiagnostic.ts | 43 ++- .../src/Discover/Shared/JoinTokenContext.tsx | 22 +- .../Discover/Shared/PingTeleportContext.tsx | 5 + .../src/Discover/Shared/ResourceKind.ts | 71 +++++ .../Shared/SetupAccess/useUserTraits.test.tsx | 33 +- .../Shared/SetupAccess/useUserTraits.ts | 46 +-- web/packages/teleport/src/Discover/flow.tsx | 7 + .../src/Discover/useDiscover.test.tsx | 271 +++++++++++++++++ .../teleport/src/Discover/useDiscover.tsx | 226 +++++++++++++- web/packages/teleport/src/mocks/handlers.ts | 3 + .../teleport/src/services/agents/make.ts | 2 +- .../teleport/src/services/userEvent/types.ts | 77 +++++ .../src/services/userEvent/userEvent.ts | 22 +- 37 files changed, 1264 insertions(+), 278 deletions(-) create mode 100644 web/packages/teleport/src/Discover/useDiscover.test.tsx diff --git a/api/gen/proto/go/usageevents/v1/usageevents.pb.go b/api/gen/proto/go/usageevents/v1/usageevents.pb.go index c4d0e4c7953..5fba2446490 100644 --- a/api/gen/proto/go/usageevents/v1/usageevents.pb.go +++ b/api/gen/proto/go/usageevents/v1/usageevents.pb.go @@ -26,17 +26,24 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type DiscoverResource int32 const ( - DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0 - DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1 - DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7 - DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8 - DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9 - DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10 + DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0 + DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1 + DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7 + DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8 + DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9 + DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS DiscoverResource = 11 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT DiscoverResource = 12 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED DiscoverResource = 13 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED DiscoverResource = 14 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP DiscoverResource = 15 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_GCP DiscoverResource = 16 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP DiscoverResource = 17 ) var DiscoverResource_name = map[int32]string{ @@ -51,20 +58,34 @@ var DiscoverResource_name = map[int32]string{ 8: "DISCOVER_RESOURCE_APPLICATION_HTTP", 9: "DISCOVER_RESOURCE_APPLICATION_TCP", 10: "DISCOVER_RESOURCE_WINDOWS_DESKTOP", + 11: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS", + 12: "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT", + 13: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED", + 14: "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED", + 15: "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP", + 16: "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP", + 17: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP", } var DiscoverResource_value = map[string]int32{ - "DISCOVER_RESOURCE_UNSPECIFIED": 0, - "DISCOVER_RESOURCE_SERVER": 1, - "DISCOVER_RESOURCE_KUBERNETES": 2, - "DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3, - "DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4, - "DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5, - "DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6, - "DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7, - "DISCOVER_RESOURCE_APPLICATION_HTTP": 8, - "DISCOVER_RESOURCE_APPLICATION_TCP": 9, - "DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10, + "DISCOVER_RESOURCE_UNSPECIFIED": 0, + "DISCOVER_RESOURCE_SERVER": 1, + "DISCOVER_RESOURCE_KUBERNETES": 2, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3, + "DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4, + "DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6, + "DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7, + "DISCOVER_RESOURCE_APPLICATION_HTTP": 8, + "DISCOVER_RESOURCE_APPLICATION_TCP": 9, + "DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS": 11, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT": 12, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED": 13, + "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED": 14, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP": 15, + "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP": 16, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP": 17, } func (x DiscoverResource) String() string { @@ -1894,115 +1915,119 @@ func init() { } var fileDescriptor_94cf2ca1c69fd564 = []byte{ - // 1722 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x99, 0xcf, 0x8f, 0xe3, 0x48, - 0x15, 0xc7, 0xed, 0xf4, 0xfc, 0xe8, 0x79, 0xcb, 0xf6, 0x04, 0xb3, 0x3b, 0x93, 0x61, 0xba, 0x7b, - 0x7a, 0x32, 0x33, 0x3d, 0xdd, 0x3d, 0x28, 0xa1, 0x77, 0xf9, 0xb1, 0xb0, 0x0b, 0xa3, 0xc4, 0x71, - 0xb7, 0xb3, 0xd3, 0xdd, 0x09, 0x65, 0x67, 0x57, 0x70, 0x29, 0xb9, 0xed, 0xea, 0x8c, 0x35, 0x8e, - 0x2b, 0xb2, 0xcb, 0xbd, 0x44, 0x08, 0x21, 0x10, 0x42, 0x48, 0x23, 0x21, 0xb8, 0x21, 0x21, 0x71, - 0x81, 0x03, 0x07, 0xee, 0x9c, 0xb9, 0x71, 0xe4, 0x1f, 0x40, 0x42, 0xf3, 0x1f, 0x70, 0xe0, 0x00, - 0x02, 0x81, 0x52, 0xfe, 0x99, 0x9f, 0x36, 0x23, 0x4e, 0xd9, 0x5b, 0xe2, 0x7a, 0xf5, 0xde, 0xe7, - 0xbd, 0x2a, 0xdb, 0xf5, 0x7d, 0x86, 0x7d, 0x46, 0x1c, 0x32, 0xa4, 0x1e, 0xab, 0x07, 0xbe, 0xd1, - 0x27, 0xe4, 0x92, 0xb8, 0xcc, 0xaf, 0x5f, 0x1e, 0x66, 0xff, 0xd6, 0x86, 0x1e, 0x65, 0x54, 0xba, - 0x1d, 0x9b, 0xd6, 0xb2, 0x63, 0x97, 0x87, 0xd5, 0x03, 0x90, 0x7a, 0xed, 0xa6, 0xe1, 0xba, 0xc4, - 0x93, 0x1d, 0xdb, 0x7c, 0xa1, 0x8c, 0x47, 0xa4, 0xb7, 0xe0, 0xaa, 0xe1, 0x10, 0x8f, 0x55, 0xc4, - 0x1d, 0x71, 0xef, 0x06, 0x0a, 0xff, 0x54, 0x8f, 0x60, 0xaf, 0xd7, 0xee, 0xb8, 0xe7, 0xd4, 0xf0, - 0x2c, 0x99, 0x0e, 0x86, 0x0e, 0x61, 0xe4, 0x98, 0xea, 0xb4, 0x65, 0xf8, 0xcf, 0xc3, 0x8b, 0xa9, - 0x87, 0xcf, 0xc3, 0x7a, 0xe0, 0x13, 0xcf, 0x35, 0x06, 0x24, 0x72, 0x92, 0xfc, 0xaf, 0x3e, 0x82, - 0x07, 0x89, 0x9f, 0x86, 0x65, 0x1d, 0xd9, 0x9e, 0xcf, 0x10, 0xf1, 0x69, 0xe0, 0x99, 0x24, 0x75, - 0x51, 0x3d, 0xc8, 0x84, 0x9b, 0x36, 0x3b, 0x31, 0x58, 0x16, 0xb8, 0xfa, 0x14, 0xee, 0x27, 0xb6, - 0x1a, 0x61, 0xb2, 0x47, 0x2c, 0xe2, 0x32, 0xdb, 0x70, 0xb4, 0xe0, 0x7c, 0x60, 0xb3, 0x7c, 0xa6, - 0xef, 0xc3, 0xa3, 0xc4, 0x01, 0x22, 0x7d, 0xdb, 0x1f, 0xfb, 0x7f, 0x6e, 0x38, 0x0e, 0x71, 0xfb, - 0xa4, 0xa0, 0x13, 0xe9, 0x0e, 0xac, 0x0f, 0x2e, 0x0c, 0xcc, 0x46, 0x43, 0x52, 0x29, 0xf1, 0xb1, - 0xeb, 0x83, 0x0b, 0x43, 0x1f, 0x0d, 0x89, 0xb4, 0x05, 0xe0, 0xd0, 0xbe, 0xed, 0xe2, 0x0b, 0x87, - 0x7e, 0x52, 0x59, 0xe3, 0x83, 0x37, 0xf8, 0x95, 0x23, 0x87, 0x7e, 0x12, 0xf2, 0x23, 0x62, 0xd2, - 0x4b, 0xe2, 0x8d, 0x64, 0x6a, 0x11, 0x5f, 0xa6, 0x2e, 0xb3, 0xdd, 0x80, 0x14, 0xac, 0xe9, 0xfb, - 0xb0, 0x35, 0xe3, 0x60, 0x38, 0x2a, 0x38, 0xf9, 0x03, 0xd8, 0x9e, 0x9a, 0xdc, 0xf5, 0x6c, 0x97, - 0x15, 0x9c, 0x5d, 0x85, 0x72, 0xcb, 0xf6, 0xf9, 0xe4, 0x53, 0xc2, 0x0c, 0xcb, 0x60, 0x86, 0xb4, - 0x01, 0x25, 0xdb, 0x8a, 0x2c, 0x4b, 0xb6, 0x55, 0x35, 0xa0, 0x12, 0xdb, 0xc4, 0x4b, 0x98, 0xd8, - 0x2a, 0xb0, 0xee, 0x45, 0xd7, 0xf8, 0x8c, 0x8d, 0x77, 0xf6, 0x6b, 0x0b, 0xb6, 0x6b, 0x6d, 0xda, - 0x09, 0x4a, 0xa6, 0x56, 0x5f, 0x80, 0x14, 0x8f, 0x6a, 0x8c, 0x0c, 0x35, 0x66, 0xb0, 0xc0, 0x97, - 0x9e, 0xc2, 0x35, 0x9f, 0xff, 0x8a, 0x5c, 0x3f, 0xce, 0x75, 0x1d, 0x4e, 0x44, 0xd1, 0xb4, 0xf1, - 0xad, 0x40, 0x3c, 0x8f, 0x7a, 0xd1, 0x82, 0x86, 0x7f, 0xaa, 0xbf, 0x15, 0xe1, 0x56, 0xaf, 0x9d, - 0x99, 0xe2, 0x31, 0x62, 0x85, 0xa5, 0x52, 0x60, 0x7d, 0x10, 0xa5, 0xc6, 0x63, 0xbe, 0x51, 0x20, - 0x9d, 0xb8, 0x16, 0x28, 0x99, 0x2a, 0xc9, 0x09, 0x78, 0x89, 0x3b, 0x79, 0x52, 0x00, 0x3c, 0xce, - 0x3a, 0x86, 0xaf, 0xfe, 0x5b, 0x84, 0x9d, 0x14, 0x33, 0x2e, 0x9a, 0x46, 0x1c, 0x62, 0x32, 0x9b, - 0xba, 0xff, 0x57, 0xe0, 0xd3, 0xcc, 0x32, 0x86, 0xc8, 0x87, 0x85, 0x97, 0x31, 0x75, 0x17, 0xbb, - 0xc8, 0xe4, 0xbf, 0xf6, 0xfa, 0xf9, 0xff, 0x43, 0x84, 0xcd, 0x34, 0xff, 0x16, 0x19, 0x3a, 0x74, - 0xa4, 0x11, 0xef, 0xd2, 0x36, 0xc9, 0xca, 0xe7, 0xfe, 0x2f, 0x11, 0xee, 0x65, 0x72, 0x37, 0x98, - 0x71, 0x6e, 0xf8, 0x24, 0x7e, 0xb6, 0xad, 0x7c, 0xfa, 0x3f, 0x2c, 0xc1, 0xc3, 0xd9, 0xf4, 0x65, - 0xea, 0x5e, 0xd8, 0xfd, 0xc0, 0x23, 0xa7, 0xfa, 0x89, 0xb6, 0xf2, 0x35, 0xf8, 0x59, 0x09, 0x0e, - 0xb3, 0xdb, 0xdf, 0x7f, 0xc1, 0xe8, 0xb0, 0x61, 0x32, 0xfb, 0x92, 0xb4, 0x6c, 0x8f, 0x98, 0x8c, - 0x7a, 0x23, 0x9d, 0x52, 0xc7, 0x6f, 0xbb, 0x3e, 0x33, 0x1c, 0x67, 0xe5, 0x0b, 0xf2, 0xb2, 0x04, - 0xb5, 0xbc, 0x82, 0x24, 0x5b, 0x64, 0xe5, 0xab, 0xf1, 0xfb, 0x12, 0xec, 0xa6, 0xd5, 0x68, 0x04, - 0x8c, 0xc6, 0xbf, 0x89, 0x15, 0xc7, 0xf6, 0x57, 0xbd, 0x0a, 0xd2, 0x63, 0xb8, 0x19, 0x3b, 0xf4, - 0xb1, 0x49, 0x03, 0x97, 0x55, 0xae, 0xec, 0x88, 0x7b, 0x6b, 0x68, 0x23, 0xb9, 0x2c, 0x8f, 0xaf, - 0x56, 0x7f, 0x52, 0x82, 0xfd, 0x25, 0x4f, 0x94, 0x76, 0xe3, 0xb4, 0x4b, 0x1d, 0xdb, 0x1c, 0xad, - 0xfc, 0xbe, 0xf9, 0x8f, 0x08, 0xd5, 0xb4, 0x10, 0xe3, 0xa3, 0xa2, 0x69, 0x0f, 0x0d, 0xc7, 0xff, - 0xf4, 0xdc, 0x39, 0xff, 0x14, 0xc7, 0xc7, 0xed, 0xd8, 0x40, 0x27, 0x3e, 0x93, 0xa9, 0xeb, 0x7e, - 0x4a, 0x0e, 0x55, 0x7f, 0x17, 0xa1, 0x92, 0x26, 0x1f, 0x0b, 0x41, 0x6b, 0xe5, 0xf3, 0xfe, 0xdb, - 0x6d, 0xb8, 0xd9, 0x1b, 0x5b, 0xf3, 0x4c, 0x3b, 0x2e, 0xe9, 0x5c, 0x48, 0x3d, 0xb8, 0x19, 0xd8, - 0xf8, 0x9c, 0xeb, 0x67, 0x6c, 0x8e, 0xf5, 0x52, 0x94, 0xf5, 0xe2, 0x08, 0xb3, 0x72, 0x5b, 0x15, - 0xd0, 0x9b, 0x81, 0x9d, 0xb9, 0x2a, 0xfd, 0x4a, 0x84, 0xfd, 0xc0, 0xc6, 0x34, 0xd4, 0xa3, 0xd8, - 0x8c, 0x6a, 0x8c, 0xfb, 0x14, 0x33, 0x8a, 0xad, 0x58, 0x6f, 0x47, 0x11, 0xc3, 0x9c, 0x1a, 0x4b, - 0x22, 0x16, 0x13, 0xed, 0xaa, 0x80, 0x1e, 0x04, 0x76, 0xae, 0xad, 0xf4, 0x52, 0x84, 0x07, 0x19, - 0x3a, 0xc3, 0xb2, 0xf0, 0xc5, 0x58, 0x9c, 0xe3, 0xb8, 0xde, 0x11, 0xd7, 0x15, 0xce, 0xf5, 0x41, - 0x3e, 0xd7, 0xe2, 0x26, 0x80, 0x2a, 0xa0, 0xed, 0x04, 0x69, 0xae, 0xd9, 0x74, 0xad, 0xe6, 0xd0, - 0x38, 0x06, 0x4b, 0x56, 0xe7, 0x6a, 0xd1, 0x5a, 0xe5, 0x74, 0x1c, 0x26, 0x6a, 0xb5, 0xd8, 0x56, - 0xfa, 0xb1, 0x08, 0x3b, 0x19, 0x3a, 0x9f, 0x30, 0x6c, 0x26, 0xcd, 0x09, 0xec, 0xf3, 0xc6, 0x42, - 0xe5, 0x1a, 0x87, 0xfa, 0x7a, 0x3e, 0xd4, 0xa2, 0xd6, 0x86, 0x2a, 0xa0, 0xcd, 0x84, 0x66, 0x8e, - 0x91, 0xf4, 0x73, 0x11, 0x1e, 0x66, 0x30, 0xbc, 0x48, 0x05, 0x60, 0x33, 0x6e, 0x71, 0xc4, 0x28, - 0xd7, 0x39, 0xca, 0x37, 0xf3, 0x51, 0x96, 0x35, 0x49, 0x54, 0x01, 0xed, 0x24, 0x38, 0x0b, 0x0c, - 0xe3, 0xca, 0x78, 0x51, 0xdb, 0x01, 0x9b, 0xd4, 0xe2, 0x2f, 0xe0, 0xb0, 0xed, 0x11, 0x2d, 0xd7, - 0x7a, 0x6e, 0x65, 0x72, 0x9a, 0x26, 0x61, 0x65, 0x16, 0x1b, 0x49, 0xdf, 0x85, 0xcd, 0x79, 0x14, - 0xc3, 0x51, 0x44, 0x70, 0x83, 0x13, 0x7c, 0xa5, 0x38, 0x41, 0xb6, 0xeb, 0xa2, 0x0a, 0xa8, 0x32, - 0x13, 0x3d, 0x32, 0x90, 0xbe, 0x07, 0x5b, 0xb3, 0x91, 0x87, 0x9e, 0xed, 0xb2, 0x28, 0x34, 0xf0, - 0xd0, 0x5f, 0x2d, 0x1a, 0x7a, 0xaa, 0x67, 0xa3, 0x0a, 0xe8, 0xce, 0x54, 0xec, 0xd4, 0x42, 0x72, - 0xe0, 0x4e, 0x60, 0x63, 0x2b, 0x7a, 0xda, 0x61, 0x3f, 0xec, 0x60, 0x60, 0xee, 0xbc, 0xf2, 0x06, - 0x0f, 0x5c, 0x5f, 0x12, 0x78, 0x5e, 0xe7, 0x43, 0x15, 0xd0, 0xad, 0xc0, 0x9e, 0xdb, 0x13, 0x79, - 0x19, 0x6e, 0xbf, 0x24, 0x5c, 0x72, 0x6b, 0xfa, 0x71, 0x2b, 0x22, 0x8a, 0xfc, 0x19, 0x1e, 0xf9, - 0x6b, 0x05, 0x22, 0xcf, 0x6f, 0x66, 0x84, 0x3b, 0x2f, 0xa7, 0xe1, 0xf1, 0x03, 0xbe, 0xf1, 0x12, - 0x18, 0x8b, 0xb7, 0x05, 0xb0, 0x1f, 0xf6, 0x05, 0x22, 0x90, 0x37, 0x39, 0xc8, 0x97, 0x0b, 0x80, - 0xcc, 0x76, 0x15, 0xc2, 0x3d, 0xb7, 0xa4, 0xeb, 0xf0, 0xd3, 0xf0, 0x01, 0x9a, 0x12, 0x44, 0x67, - 0xc9, 0xf4, 0xbe, 0x0c, 0x21, 0x36, 0x38, 0xc4, 0x7b, 0x45, 0x20, 0xe6, 0xc9, 0x7b, 0x55, 0x40, - 0xf7, 0x32, 0x1c, 0x73, 0x3b, 0x00, 0xbf, 0x0c, 0x9f, 0x9e, 0xb3, 0x28, 0x66, 0x7c, 0x98, 0xc3, - 0x03, 0xe6, 0xf8, 0x11, 0xd0, 0x4d, 0x0e, 0xf4, 0x8d, 0xff, 0x01, 0x68, 0x56, 0x70, 0xab, 0x02, - 0x7a, 0x38, 0x4b, 0x95, 0xda, 0x31, 0x27, 0xd2, 0x1c, 0x7f, 0x14, 0xe1, 0xbd, 0xc9, 0x75, 0xe2, - 0x72, 0x0d, 0x1b, 0x5c, 0xaf, 0x61, 0x2b, 0x16, 0x6c, 0x98, 0x8d, 0x25, 0x2c, 0xb6, 0x43, 0x0d, - 0x1b, 0x91, 0x96, 0x39, 0xe9, 0x87, 0x85, 0xd6, 0xaf, 0x90, 0x2c, 0x56, 0x05, 0x74, 0x98, 0x5d, - 0xd4, 0x62, 0x5a, 0xfa, 0x0f, 0x22, 0x7c, 0xa9, 0x50, 0x0e, 0x69, 0xb9, 0x43, 0xfe, 0xcf, 0x72, - 0xfe, 0xe3, 0xd7, 0xe6, 0x9f, 0x3c, 0x8b, 0xab, 0x02, 0xaa, 0xe5, 0xc1, 0x4f, 0x9d, 0xde, 0x7f, - 0x2d, 0xc2, 0x93, 0x2c, 0xb9, 0x11, 0x8c, 0x4f, 0x1e, 0x89, 0x3e, 0xc4, 0xa9, 0x66, 0x0a, 0x81, - 0x25, 0x0e, 0xfc, 0xb4, 0x00, 0xf0, 0x32, 0xa1, 0xa9, 0x0a, 0x68, 0x37, 0x05, 0x5d, 0x2a, 0x49, - 0x7f, 0x27, 0x42, 0x3d, 0x67, 0xe7, 0xda, 0xc6, 0x00, 0x0f, 0xb9, 0x26, 0x8b, 0x20, 0x3f, 0xc7, - 0x21, 0x9b, 0xaf, 0xb3, 0x7f, 0x27, 0xe5, 0x9d, 0x2a, 0xa0, 0xfd, 0x25, 0x9b, 0xb8, 0x6d, 0x0c, - 0xb2, 0x5a, 0xf0, 0x17, 0x22, 0xec, 0x66, 0x51, 0x87, 0x89, 0x64, 0x9a, 0x59, 0xf7, 0xb7, 0x38, - 0xe1, 0xfb, 0x05, 0x08, 0x17, 0xe9, 0x2e, 0x55, 0x40, 0xd5, 0x14, 0x6d, 0xa1, 0x3a, 0xfb, 0x91, - 0x08, 0xf7, 0xb3, 0x4c, 0x8c, 0xf8, 0x6c, 0x4c, 0xe3, 0x4e, 0x3c, 0x8f, 0xdf, 0xce, 0x7d, 0xfb, - 0x2d, 0x11, 0x41, 0xaa, 0x80, 0xb6, 0x52, 0x92, 0x79, 0x2a, 0xc9, 0x83, 0xbb, 0x59, 0x86, 0xf8, - 0x9c, 0x1b, 0xbf, 0x87, 0x6e, 0xe5, 0x9c, 0xfc, 0x17, 0xa9, 0x90, 0xf0, 0xb5, 0x3b, 0x7f, 0xac, - 0x79, 0x1d, 0xae, 0x72, 0x0f, 0x1f, 0x5e, 0x59, 0x2f, 0x95, 0xd7, 0xc6, 0x4f, 0xea, 0xe4, 0x58, - 0xd4, 0x27, 0x2c, 0x79, 0x13, 0xf2, 0x57, 0xf0, 0xc1, 0x5f, 0xd6, 0xd2, 0x8f, 0x1b, 0xf1, 0xfe, - 0x93, 0xee, 0xc3, 0x56, 0xab, 0xad, 0xc9, 0x9d, 0x8f, 0x14, 0x84, 0x91, 0xa2, 0x75, 0x7a, 0x48, - 0x56, 0x70, 0xef, 0x4c, 0xeb, 0x2a, 0x72, 0xfb, 0xa8, 0xad, 0xb4, 0xca, 0x82, 0xb4, 0x09, 0x95, - 0x59, 0x13, 0x4d, 0x41, 0x1f, 0x29, 0xa8, 0x2c, 0x4a, 0x3b, 0xb0, 0x39, 0x3b, 0xfa, 0xac, 0xd7, - 0x54, 0xd0, 0x99, 0xa2, 0x2b, 0x5a, 0xb9, 0x24, 0xbd, 0x0b, 0xf5, 0x59, 0x8b, 0x56, 0x43, 0x6f, - 0x34, 0x1b, 0x9a, 0x82, 0xbb, 0x1d, 0x4d, 0x3f, 0x46, 0x8a, 0x86, 0x35, 0xe5, 0xe4, 0x08, 0xab, - 0x1d, 0x4d, 0x57, 0x5a, 0xe5, 0x35, 0xe9, 0x8b, 0xf0, 0x85, 0x25, 0x93, 0x4e, 0xbf, 0xad, 0x7d, - 0xeb, 0x64, 0x62, 0xc6, 0x15, 0xe9, 0x1d, 0xa8, 0x2d, 0x9b, 0xd1, 0x39, 0x3b, 0xee, 0xb4, 0x9a, - 0x13, 0x73, 0xae, 0x4a, 0x4f, 0xe0, 0x71, 0x11, 0x34, 0xd4, 0xd2, 0xca, 0xd7, 0xa4, 0x3d, 0x78, - 0x98, 0x8b, 0x34, 0xb6, 0xbc, 0x2e, 0xed, 0x42, 0x75, 0xd6, 0xb2, 0xd1, 0xed, 0x9e, 0xb4, 0xe5, - 0x86, 0xde, 0xee, 0x9c, 0x61, 0x55, 0xd7, 0xbb, 0xe5, 0x75, 0xe9, 0x11, 0xdc, 0x5f, 0x6e, 0xa7, - 0xcb, 0xdd, 0xf2, 0x8d, 0xf9, 0x66, 0x1f, 0xb7, 0xcf, 0x5a, 0x9d, 0x8f, 0x35, 0xdc, 0x52, 0xb4, - 0x67, 0x7a, 0xa7, 0x5b, 0x86, 0x83, 0xdf, 0x88, 0xb0, 0x31, 0xf9, 0xe1, 0x47, 0xba, 0x07, 0x77, - 0x93, 0x99, 0x9a, 0xde, 0xd0, 0x7b, 0xda, 0xd4, 0xda, 0xde, 0x85, 0xdb, 0xd3, 0x06, 0x5a, 0x4f, - 0x96, 0x15, 0x4d, 0x2b, 0x8b, 0x73, 0x07, 0x9f, 0xb5, 0xbb, 0x5d, 0xa5, 0x55, 0x2e, 0x49, 0x77, - 0xe0, 0xed, 0xe9, 0x41, 0x05, 0xa1, 0x0e, 0x2a, 0xaf, 0xcd, 0x9b, 0xd7, 0x68, 0x76, 0x10, 0x5f, - 0xa6, 0x66, 0xe7, 0x4f, 0xaf, 0xb6, 0xc5, 0x3f, 0xbf, 0xda, 0x16, 0xff, 0xfa, 0x6a, 0x5b, 0xfc, - 0x4e, 0xa3, 0x6f, 0xb3, 0xe7, 0xc1, 0x79, 0xcd, 0xa4, 0x83, 0x7a, 0xdf, 0x33, 0x2e, 0x6d, 0x66, - 0x8c, 0xef, 0x28, 0xc3, 0xa9, 0x27, 0xdf, 0x83, 0x8d, 0xa1, 0x5d, 0xef, 0x13, 0xb7, 0xce, 0x3f, - 0xfe, 0xd6, 0xfb, 0x74, 0xea, 0x03, 0xf1, 0xf9, 0x35, 0x3e, 0xf0, 0xee, 0x7f, 0x03, 0x00, 0x00, - 0xff, 0xff, 0xf6, 0xfc, 0x2b, 0x45, 0x42, 0x1e, 0x00, 0x00, + // 1784 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x99, 0xcf, 0x6f, 0xe4, 0x48, + 0x15, 0xc7, 0xdb, 0x9d, 0x99, 0x4c, 0xe6, 0xcd, 0x4e, 0xe2, 0x2d, 0x76, 0x67, 0x7a, 0x98, 0x24, + 0x93, 0xe9, 0xf9, 0x95, 0x64, 0x56, 0xe9, 0xcd, 0xee, 0x02, 0x0b, 0xbb, 0x30, 0xea, 0xb8, 0x9d, + 0xb8, 0x77, 0x92, 0x74, 0x6f, 0xd9, 0xbd, 0x2b, 0xb8, 0x94, 0x1c, 0xbb, 0xd2, 0x63, 0x8d, 0xdb, + 0x6e, 0xd9, 0xe5, 0x2c, 0x11, 0x42, 0x08, 0x84, 0x10, 0xd2, 0x48, 0x08, 0x6e, 0x48, 0x48, 0x5c, + 0xe0, 0x80, 0x10, 0x77, 0xce, 0xdc, 0x38, 0xf2, 0x27, 0xa0, 0xf9, 0x0f, 0x38, 0x70, 0x00, 0x81, + 0x40, 0x2e, 0xff, 0xec, 0x9f, 0x36, 0x23, 0x4e, 0x99, 0x5b, 0xb7, 0xeb, 0xd5, 0x7b, 0x9f, 0xf7, + 0xaa, 0x6c, 0xd7, 0xf7, 0x19, 0xb6, 0x18, 0xb5, 0xe9, 0xd0, 0xf5, 0x58, 0x23, 0xf0, 0xf5, 0x3e, + 0xa5, 0x67, 0xd4, 0x61, 0x7e, 0xe3, 0x6c, 0x37, 0xff, 0x77, 0x67, 0xe8, 0xb9, 0xcc, 0x45, 0x37, + 0x13, 0xd3, 0x9d, 0xfc, 0xd8, 0xd9, 0x6e, 0x7d, 0x1b, 0x50, 0xaf, 0xbd, 0xa7, 0x3b, 0x0e, 0xf5, + 0x24, 0xdb, 0x32, 0x9e, 0xcb, 0xe1, 0x08, 0x7a, 0x0b, 0x2e, 0xeb, 0x36, 0xf5, 0x58, 0x4d, 0xd8, + 0x10, 0x36, 0xaf, 0xe2, 0xe8, 0x4f, 0x7d, 0x1f, 0x36, 0x7b, 0xed, 0x8e, 0x73, 0xe2, 0xea, 0x9e, + 0x29, 0xb9, 0x83, 0xa1, 0x4d, 0x19, 0x3d, 0x70, 0x35, 0xb7, 0xa5, 0xfb, 0xcf, 0xa2, 0x8b, 0x99, + 0x87, 0x2f, 0xc3, 0x52, 0xe0, 0x53, 0xcf, 0xd1, 0x07, 0x34, 0x76, 0x92, 0xfe, 0xaf, 0x3f, 0x80, + 0x7b, 0xa9, 0x9f, 0xa6, 0x69, 0xee, 0x5b, 0x9e, 0xcf, 0x30, 0xf5, 0xdd, 0xc0, 0x33, 0x68, 0xe6, + 0xa2, 0xbe, 0x9d, 0x0b, 0x37, 0x6e, 0x76, 0xa8, 0xb3, 0x3c, 0x70, 0xfd, 0x09, 0xdc, 0x4d, 0x6d, + 0x55, 0xca, 0x24, 0x8f, 0x9a, 0xd4, 0x61, 0x96, 0x6e, 0xab, 0xc1, 0xc9, 0xc0, 0x62, 0xc5, 0x4c, + 0xdf, 0x87, 0x07, 0xa9, 0x03, 0x4c, 0xfb, 0x96, 0x1f, 0xfa, 0x7f, 0xa6, 0xdb, 0x36, 0x75, 0xfa, + 0xb4, 0xa4, 0x13, 0x74, 0x0b, 0x96, 0x06, 0xa7, 0x3a, 0x61, 0xe7, 0x43, 0x5a, 0xab, 0xf2, 0xb1, + 0x2b, 0x83, 0x53, 0x5d, 0x3b, 0x1f, 0x52, 0xb4, 0x06, 0x60, 0xbb, 0x7d, 0xcb, 0x21, 0xa7, 0xb6, + 0xfb, 0x45, 0x6d, 0x81, 0x0f, 0x5e, 0xe5, 0x57, 0xf6, 0x6d, 0xf7, 0x8b, 0x88, 0x1f, 0x53, 0xc3, + 0x3d, 0xa3, 0xde, 0xb9, 0xe4, 0x9a, 0xd4, 0x97, 0x5c, 0x87, 0x59, 0x4e, 0x40, 0x4b, 0xd6, 0xf4, + 0x23, 0x58, 0x9b, 0x70, 0x30, 0x3c, 0x2f, 0x39, 0xf9, 0x63, 0x58, 0x1f, 0x9b, 0xdc, 0xf5, 0x2c, + 0x87, 0x95, 0x9c, 0x5d, 0x07, 0xb1, 0x65, 0xf9, 0x7c, 0xf2, 0x11, 0x65, 0xba, 0xa9, 0x33, 0x1d, + 0x2d, 0x43, 0xd5, 0x32, 0x63, 0xcb, 0xaa, 0x65, 0xd6, 0x75, 0xa8, 0x25, 0x36, 0xc9, 0x12, 0xa6, + 0xb6, 0x32, 0x2c, 0x79, 0xf1, 0x35, 0x3e, 0x63, 0xf9, 0xbd, 0xad, 0x9d, 0x19, 0xdb, 0x75, 0x67, + 0xdc, 0x09, 0x4e, 0xa7, 0xd6, 0x9f, 0x03, 0x4a, 0x46, 0x55, 0x46, 0x87, 0x2a, 0xd3, 0x59, 0xe0, + 0xa3, 0x27, 0xb0, 0xe8, 0xf3, 0x5f, 0xb1, 0xeb, 0x47, 0x85, 0xae, 0xa3, 0x89, 0x38, 0x9e, 0x16, + 0xde, 0x0a, 0xd4, 0xf3, 0x5c, 0x2f, 0x5e, 0xd0, 0xe8, 0x4f, 0xfd, 0xb7, 0x02, 0xdc, 0xe8, 0xb5, + 0x73, 0x53, 0x3c, 0x46, 0xcd, 0xa8, 0x54, 0x32, 0x2c, 0x0d, 0xe2, 0xd4, 0x78, 0xcc, 0x6b, 0x25, + 0xd2, 0x49, 0x6a, 0x81, 0xd3, 0xa9, 0x48, 0x4a, 0xc1, 0xab, 0xdc, 0xc9, 0xe3, 0x12, 0xe0, 0x49, + 0xd6, 0x09, 0x7c, 0xfd, 0xdf, 0x02, 0x6c, 0x64, 0x98, 0x49, 0xd1, 0x54, 0x6a, 0x53, 0x83, 0x59, + 0xae, 0xf3, 0x7f, 0x05, 0x3e, 0xca, 0x2d, 0x63, 0x84, 0xbc, 0x5b, 0x7a, 0x19, 0x33, 0x77, 0x89, + 0x8b, 0x5c, 0xfe, 0x0b, 0xaf, 0x9e, 0xff, 0x3f, 0x04, 0x58, 0xcd, 0xf2, 0x6f, 0xd1, 0xa1, 0xed, + 0x9e, 0xab, 0xd4, 0x3b, 0xb3, 0x0c, 0x7a, 0xe1, 0x73, 0xff, 0x97, 0x00, 0x77, 0x72, 0xb9, 0xeb, + 0x4c, 0x3f, 0xd1, 0x7d, 0x9a, 0x3c, 0xdb, 0x2e, 0x7c, 0xfa, 0x3f, 0xac, 0xc2, 0xfd, 0xc9, 0xf4, + 0x25, 0xd7, 0x39, 0xb5, 0xfa, 0x81, 0x47, 0x8f, 0xb4, 0x43, 0xf5, 0xc2, 0xd7, 0xe0, 0x67, 0x55, + 0xd8, 0xcd, 0x6f, 0x7f, 0xff, 0x39, 0x73, 0x87, 0x4d, 0x83, 0x59, 0x67, 0xb4, 0x65, 0x79, 0xd4, + 0x60, 0xae, 0x77, 0xae, 0xb9, 0xae, 0xed, 0xb7, 0x1d, 0x9f, 0xe9, 0xb6, 0x7d, 0xe1, 0x0b, 0xf2, + 0xa2, 0x0a, 0x3b, 0x45, 0x05, 0x49, 0xb7, 0xc8, 0x85, 0xaf, 0xc6, 0x1f, 0xaa, 0xf0, 0x30, 0xab, + 0x46, 0x33, 0x60, 0x6e, 0xf2, 0x9b, 0x9a, 0x49, 0x6c, 0xff, 0xa2, 0x57, 0x01, 0x3d, 0x82, 0x95, + 0xc4, 0xa1, 0x4f, 0x0c, 0x37, 0x70, 0x58, 0xed, 0xd2, 0x86, 0xb0, 0xb9, 0x80, 0x97, 0xd3, 0xcb, + 0x52, 0x78, 0xb5, 0xfe, 0x93, 0x2a, 0x6c, 0xcd, 0x79, 0xa2, 0xb4, 0x9b, 0x47, 0x5d, 0xd7, 0xb6, + 0x8c, 0xf3, 0x0b, 0xbf, 0x6f, 0xfe, 0x23, 0x40, 0x3d, 0x2b, 0x44, 0x78, 0x54, 0x34, 0xac, 0xa1, + 0x6e, 0xfb, 0xaf, 0xcf, 0x9d, 0xf3, 0x4f, 0x21, 0x3c, 0x6e, 0x27, 0x06, 0x1a, 0xf5, 0x99, 0xe4, + 0x3a, 0xce, 0x6b, 0x72, 0xa8, 0xfa, 0xbb, 0x00, 0xb5, 0x2c, 0xf9, 0x44, 0x08, 0x9a, 0x17, 0x3e, + 0xef, 0xbf, 0xdd, 0x84, 0x95, 0x5e, 0x68, 0xcd, 0x33, 0xed, 0x38, 0xb4, 0x73, 0x8a, 0x7a, 0xb0, + 0x12, 0x58, 0xe4, 0x84, 0xeb, 0x67, 0x62, 0x84, 0x7a, 0x29, 0xce, 0x7a, 0x76, 0x84, 0x49, 0xb9, + 0xad, 0x54, 0xf0, 0xf5, 0xc0, 0xca, 0x5d, 0x45, 0xbf, 0x12, 0x60, 0x2b, 0xb0, 0x88, 0x1b, 0xe9, + 0x51, 0x62, 0xc4, 0x35, 0x26, 0x7d, 0x97, 0x30, 0x97, 0x98, 0x89, 0xde, 0x8e, 0x23, 0x46, 0x39, + 0x35, 0xe7, 0x44, 0x2c, 0x27, 0xda, 0x95, 0x0a, 0xbe, 0x17, 0x58, 0x85, 0xb6, 0xe8, 0x85, 0x00, + 0xf7, 0x72, 0x74, 0xba, 0x69, 0x92, 0xd3, 0x50, 0x9c, 0x93, 0xa4, 0xde, 0x31, 0xd7, 0x25, 0xce, + 0xf5, 0x71, 0x31, 0xd7, 0xec, 0x26, 0x80, 0x52, 0xc1, 0xeb, 0x29, 0xd2, 0x54, 0xb3, 0xf1, 0x5a, + 0x4d, 0xa1, 0xb1, 0x75, 0x96, 0xae, 0xce, 0xe5, 0xb2, 0xb5, 0x2a, 0xe8, 0x38, 0x8c, 0xd4, 0x6a, + 0xb6, 0x2d, 0xfa, 0xb1, 0x00, 0x1b, 0x39, 0x3a, 0x9f, 0x32, 0x62, 0xa4, 0xcd, 0x09, 0xe2, 0xf3, + 0xc6, 0x42, 0x6d, 0x91, 0x43, 0x7d, 0xa3, 0x18, 0x6a, 0x56, 0x6b, 0x43, 0xa9, 0xe0, 0xd5, 0x94, + 0x66, 0x8a, 0x11, 0xfa, 0xb9, 0x00, 0xf7, 0x73, 0x18, 0x5e, 0xac, 0x02, 0x88, 0x91, 0xb4, 0x38, + 0x12, 0x94, 0x2b, 0x1c, 0xe5, 0x5b, 0xc5, 0x28, 0xf3, 0x9a, 0x24, 0x4a, 0x05, 0x6f, 0xa4, 0x38, + 0x33, 0x0c, 0x93, 0xca, 0x78, 0x71, 0xdb, 0x81, 0x18, 0xae, 0xc9, 0x5f, 0xc0, 0x51, 0xdb, 0x23, + 0x5e, 0xae, 0xa5, 0xc2, 0xca, 0x14, 0x34, 0x4d, 0xa2, 0xca, 0xcc, 0x36, 0x42, 0xdf, 0x85, 0xd5, + 0x69, 0x14, 0xc3, 0xf3, 0x98, 0xe0, 0x2a, 0x27, 0xf8, 0x6a, 0x79, 0x82, 0x7c, 0xd7, 0x45, 0xa9, + 0xe0, 0xda, 0x44, 0xf4, 0xd8, 0x00, 0x7d, 0x0f, 0xd6, 0x26, 0x23, 0x0f, 0x3d, 0xcb, 0x61, 0x71, + 0x68, 0xe0, 0xa1, 0xbf, 0x56, 0x36, 0xf4, 0x58, 0xcf, 0x46, 0xa9, 0xe0, 0x5b, 0x63, 0xb1, 0x33, + 0x0b, 0x64, 0xc3, 0xad, 0xc0, 0x22, 0x66, 0xfc, 0xb4, 0x23, 0x7e, 0xd4, 0xc1, 0x20, 0xdc, 0x79, + 0xed, 0x1a, 0x0f, 0xdc, 0x98, 0x13, 0x78, 0x5a, 0xe7, 0x43, 0xa9, 0xe0, 0x1b, 0x81, 0x35, 0xb5, + 0x27, 0xf2, 0x22, 0xda, 0x7e, 0x69, 0xb8, 0xf4, 0xd6, 0xf4, 0x93, 0x56, 0x44, 0x1c, 0xf9, 0x0d, + 0x1e, 0xf9, 0xeb, 0x25, 0x22, 0x4f, 0x6f, 0x66, 0x44, 0x3b, 0xaf, 0xa0, 0xe1, 0xf1, 0x03, 0xbe, + 0xf1, 0x52, 0x18, 0x93, 0xb7, 0x05, 0x88, 0x1f, 0xf5, 0x05, 0x62, 0x90, 0xeb, 0x1c, 0xe4, 0x2b, + 0x25, 0x40, 0x26, 0xbb, 0x0a, 0xd1, 0x9e, 0x9b, 0xd3, 0x75, 0xf8, 0x69, 0xf4, 0x00, 0xcd, 0x08, + 0xe2, 0xb3, 0x64, 0x76, 0x5f, 0x46, 0x10, 0xcb, 0x1c, 0xe2, 0xc3, 0x32, 0x10, 0xd3, 0xe4, 0xbd, + 0x52, 0xc1, 0x77, 0x72, 0x1c, 0x53, 0x3b, 0x00, 0xbf, 0x8c, 0x9e, 0x9e, 0x93, 0x28, 0x46, 0x72, + 0x98, 0x23, 0x03, 0x66, 0xfb, 0x31, 0xd0, 0x0a, 0x07, 0xfa, 0xe6, 0xff, 0x00, 0x34, 0x29, 0xb8, + 0x95, 0x0a, 0xbe, 0x3f, 0x49, 0x95, 0xd9, 0x31, 0x3b, 0xd6, 0x1c, 0x7f, 0x12, 0xe0, 0xc3, 0xd1, + 0x75, 0xe2, 0x72, 0x8d, 0xe8, 0x5c, 0xaf, 0x11, 0x33, 0x11, 0x6c, 0x84, 0x85, 0x12, 0x96, 0x58, + 0x91, 0x86, 0x8d, 0x49, 0x45, 0x4e, 0xfa, 0x49, 0xa9, 0xf5, 0x2b, 0x25, 0x8b, 0x95, 0x0a, 0xde, + 0xcd, 0x2f, 0x6a, 0x39, 0x2d, 0xfd, 0x47, 0x01, 0x3e, 0x28, 0x95, 0x43, 0x56, 0xee, 0x88, 0xff, + 0x4d, 0xce, 0x7f, 0xf0, 0xca, 0xfc, 0xa3, 0x67, 0x71, 0xa5, 0x82, 0x77, 0x8a, 0xe0, 0xc7, 0x4e, + 0xef, 0xbf, 0x16, 0xe0, 0x71, 0x9e, 0x5c, 0x0f, 0xc2, 0x93, 0x47, 0xaa, 0x0f, 0x49, 0xa6, 0x99, + 0x22, 0x60, 0xc4, 0x81, 0x9f, 0x94, 0x00, 0x9e, 0x27, 0x34, 0x95, 0x0a, 0x7e, 0x98, 0x81, 0xce, + 0x95, 0xa4, 0xbf, 0x13, 0xa0, 0x51, 0xb0, 0x73, 0x2d, 0x7d, 0x40, 0x86, 0x5c, 0x93, 0xc5, 0x90, + 0x5f, 0xe2, 0x90, 0x7b, 0xaf, 0xb2, 0x7f, 0x47, 0xe5, 0x9d, 0x52, 0xc1, 0x5b, 0x73, 0x36, 0x71, + 0x5b, 0x1f, 0xe4, 0xb5, 0xe0, 0x2f, 0x04, 0x78, 0x98, 0x47, 0x1d, 0xa6, 0x92, 0x69, 0x62, 0xdd, + 0xdf, 0xe2, 0x84, 0x1f, 0x95, 0x20, 0x9c, 0xa5, 0xbb, 0x94, 0x0a, 0xae, 0x67, 0x68, 0x33, 0xd5, + 0xd9, 0x8f, 0x04, 0xb8, 0x9b, 0x67, 0x62, 0xd4, 0x67, 0x21, 0x8d, 0x33, 0xf2, 0x3c, 0x7e, 0xbb, + 0xf0, 0xed, 0x37, 0x47, 0x04, 0x29, 0x15, 0xbc, 0x96, 0x91, 0x4c, 0x53, 0x49, 0x1e, 0xdc, 0xce, + 0x33, 0x24, 0xe7, 0xdc, 0xe4, 0x3d, 0x74, 0xa3, 0xe0, 0xe4, 0x3f, 0x4b, 0x85, 0x44, 0xaf, 0xdd, + 0xe9, 0x63, 0x7b, 0x57, 0xe0, 0x32, 0xf7, 0xf0, 0xc9, 0xa5, 0xa5, 0xaa, 0xb8, 0x10, 0x3e, 0xa9, + 0xd3, 0x63, 0x51, 0x9f, 0xb2, 0xf4, 0x4d, 0xc8, 0x5f, 0xc1, 0xdb, 0xbf, 0x5f, 0xcc, 0x3e, 0x6e, + 0x24, 0xfb, 0x0f, 0xdd, 0x85, 0xb5, 0x56, 0x5b, 0x95, 0x3a, 0x9f, 0xc9, 0x98, 0x60, 0x59, 0xed, + 0xf4, 0xb0, 0x24, 0x93, 0xde, 0xb1, 0xda, 0x95, 0xa5, 0xf6, 0x7e, 0x5b, 0x6e, 0x89, 0x15, 0xb4, + 0x0a, 0xb5, 0x49, 0x13, 0x55, 0xc6, 0x9f, 0xc9, 0x58, 0x14, 0xd0, 0x06, 0xac, 0x4e, 0x8e, 0x3e, + 0xed, 0xed, 0xc9, 0xf8, 0x58, 0xd6, 0x64, 0x55, 0xac, 0xa2, 0xf7, 0xa1, 0x31, 0x69, 0xd1, 0x6a, + 0x6a, 0xcd, 0xbd, 0xa6, 0x2a, 0x93, 0x6e, 0x47, 0xd5, 0x0e, 0xb0, 0xac, 0x12, 0x55, 0x3e, 0xdc, + 0x27, 0x4a, 0x47, 0xd5, 0xe4, 0x96, 0xb8, 0x80, 0xde, 0x85, 0x77, 0xe6, 0x4c, 0x3a, 0xfa, 0xb6, + 0xfa, 0xe9, 0xe1, 0xc8, 0x8c, 0x4b, 0xe8, 0x3d, 0xd8, 0x99, 0x37, 0xa3, 0x73, 0x7c, 0xd0, 0x69, + 0xed, 0x8d, 0xcc, 0xb9, 0x8c, 0x1e, 0xc3, 0xa3, 0x32, 0x68, 0xb8, 0xa5, 0x8a, 0x8b, 0x68, 0x13, + 0xee, 0x17, 0x22, 0x85, 0x96, 0x57, 0xd0, 0x43, 0xa8, 0x4f, 0x5a, 0x36, 0xbb, 0xdd, 0xc3, 0xb6, + 0xd4, 0xd4, 0xda, 0x9d, 0x63, 0xa2, 0x68, 0x5a, 0x57, 0x5c, 0x42, 0x0f, 0xe0, 0xee, 0x7c, 0x3b, + 0x4d, 0xea, 0x8a, 0x57, 0xa7, 0x9b, 0x7d, 0xde, 0x3e, 0x6e, 0x75, 0x3e, 0x57, 0x49, 0x4b, 0x56, + 0x9f, 0x6a, 0x9d, 0xae, 0x08, 0xe8, 0x1d, 0xd8, 0x9c, 0xc3, 0xa7, 0x7e, 0x7a, 0x18, 0xad, 0x19, + 0x67, 0xbc, 0x56, 0x50, 0xe0, 0x2c, 0x75, 0xb9, 0xa5, 0x2a, 0xed, 0x7d, 0x4d, 0x7c, 0x03, 0x7d, + 0x00, 0xef, 0x96, 0xf2, 0x9f, 0x2f, 0xf1, 0xf5, 0x82, 0x38, 0x58, 0x6e, 0xb5, 0x47, 0x97, 0x7e, + 0xb9, 0xec, 0xa2, 0x1c, 0x48, 0x5d, 0x71, 0xa5, 0xd4, 0xa2, 0x84, 0x96, 0x62, 0xe9, 0xf2, 0x84, + 0xd6, 0x6f, 0x6e, 0xff, 0x46, 0x80, 0xe5, 0xd1, 0xaf, 0x68, 0xe8, 0x0e, 0xdc, 0x4e, 0x1d, 0xa8, + 0x5a, 0x53, 0xeb, 0xa9, 0x63, 0x37, 0xca, 0x6d, 0xb8, 0x39, 0x6e, 0xa0, 0xf6, 0x24, 0x49, 0x56, + 0x55, 0x51, 0x98, 0x3a, 0xf8, 0xb4, 0xdd, 0xed, 0xca, 0x2d, 0xb1, 0x8a, 0x6e, 0xc1, 0xdb, 0xe3, + 0x83, 0x32, 0xc6, 0x1d, 0x2c, 0x2e, 0x4c, 0x9b, 0xd7, 0xdc, 0xeb, 0x60, 0xbe, 0xe7, 0xf7, 0x3a, + 0x7f, 0x7e, 0xb9, 0x2e, 0xfc, 0xe5, 0xe5, 0xba, 0xf0, 0xd7, 0x97, 0xeb, 0xc2, 0x77, 0x9a, 0x7d, + 0x8b, 0x3d, 0x0b, 0x4e, 0x76, 0x0c, 0x77, 0xd0, 0xe8, 0x7b, 0xfa, 0x99, 0xc5, 0xf4, 0xf0, 0xf1, + 0xa4, 0xdb, 0x8d, 0xf4, 0xe3, 0xba, 0x3e, 0xb4, 0x1a, 0x7d, 0xea, 0x34, 0xf8, 0x97, 0xf4, 0x46, + 0xdf, 0x1d, 0xfb, 0xda, 0x7e, 0xb2, 0xc8, 0x07, 0xde, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x2e, 0xf2, 0x3e, 0x8f, 0x1f, 0x00, 0x00, } func (m *UIBannerClickEvent) Marshal() (dAtA []byte, err error) { diff --git a/api/proto/teleport/usageevents/v1/usageevents.proto b/api/proto/teleport/usageevents/v1/usageevents.proto index c4e46d913b7..4e716d2f7de 100644 --- a/api/proto/teleport/usageevents/v1/usageevents.proto +++ b/api/proto/teleport/usageevents/v1/usageevents.proto @@ -99,6 +99,13 @@ enum DiscoverResource { DISCOVER_RESOURCE_APPLICATION_HTTP = 8; DISCOVER_RESOURCE_APPLICATION_TCP = 9; DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11; + DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13; + DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14; + DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15; + DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17; } // DiscoverResourceMetadata contains common metadata identifying resource type being added. diff --git a/gen/proto/go/prehog/v1alpha/teleport.pb.go b/gen/proto/go/prehog/v1alpha/teleport.pb.go index 37386ae6486..508027f5684 100644 --- a/gen/proto/go/prehog/v1alpha/teleport.pb.go +++ b/gen/proto/go/prehog/v1alpha/teleport.pb.go @@ -40,17 +40,24 @@ const ( type DiscoverResource int32 const ( - DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0 - DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1 - DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6 - DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7 - DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8 - DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9 - DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10 + DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0 + DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1 + DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7 + DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8 + DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9 + DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS DiscoverResource = 11 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT DiscoverResource = 12 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED DiscoverResource = 13 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED DiscoverResource = 14 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP DiscoverResource = 15 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_GCP DiscoverResource = 16 + DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP DiscoverResource = 17 ) // Enum value maps for DiscoverResource. @@ -67,19 +74,33 @@ var ( 8: "DISCOVER_RESOURCE_APPLICATION_HTTP", 9: "DISCOVER_RESOURCE_APPLICATION_TCP", 10: "DISCOVER_RESOURCE_WINDOWS_DESKTOP", + 11: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS", + 12: "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT", + 13: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED", + 14: "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED", + 15: "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP", + 16: "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP", + 17: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP", } DiscoverResource_value = map[string]int32{ - "DISCOVER_RESOURCE_UNSPECIFIED": 0, - "DISCOVER_RESOURCE_SERVER": 1, - "DISCOVER_RESOURCE_KUBERNETES": 2, - "DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3, - "DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4, - "DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5, - "DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6, - "DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7, - "DISCOVER_RESOURCE_APPLICATION_HTTP": 8, - "DISCOVER_RESOURCE_APPLICATION_TCP": 9, - "DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10, + "DISCOVER_RESOURCE_UNSPECIFIED": 0, + "DISCOVER_RESOURCE_SERVER": 1, + "DISCOVER_RESOURCE_KUBERNETES": 2, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3, + "DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4, + "DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6, + "DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7, + "DISCOVER_RESOURCE_APPLICATION_HTTP": 8, + "DISCOVER_RESOURCE_APPLICATION_TCP": 9, + "DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS": 11, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT": 12, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED": 13, + "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED": 14, + "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP": 15, + "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP": 16, + "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP": 17, } ) @@ -2953,7 +2974,7 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2a, 0xdd, 0x03, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x6e, 0x73, 0x65, 0x2a, 0xaa, 0x06, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x44, @@ -2983,35 +3004,56 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x09, 0x12, 0x25, 0x0a, 0x21, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f, - 0x50, 0x10, 0x0a, 0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, - 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, - 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, - 0x53, 0x53, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, - 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, - 0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x32, 0xd4, 0x01, 0x0a, 0x18, 0x54, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x5e, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, - 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, - 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x50, 0x10, 0x0a, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, + 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x44, 0x53, 0x10, + 0x0b, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, + 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46, + 0x54, 0x10, 0x0c, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, + 0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x4c, 0x46, + 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, + 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, + 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x53, 0x45, + 0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x2b, 0x0a, 0x27, 0x44, + 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, + 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, + 0x45, 0x53, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x0f, 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43, + 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, + 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x47, 0x43, 0x50, + 0x10, 0x10, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, + 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, + 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x11, + 0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10, + 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x02, 0x12, 0x19, + 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, + 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x42, 0x4f, + 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x32, 0xd4, 0x01, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, + 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x24, + 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3f, 0x5a, + 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, + 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts b/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts index 32bdc4c1ecf..0c0a7fdac4d 100644 --- a/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts +++ b/gen/proto/js/prehog/v1alpha/teleport_pb.d.ts @@ -1215,6 +1215,13 @@ export enum DiscoverResource { DISCOVER_RESOURCE_APPLICATION_HTTP = 8, DISCOVER_RESOURCE_APPLICATION_TCP = 9, DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11, + DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13, + DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14, + DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15, + DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17, } export enum DiscoverStatus { diff --git a/gen/proto/js/prehog/v1alpha/teleport_pb.js b/gen/proto/js/prehog/v1alpha/teleport_pb.js index ad5cd7a6eb9..8d026cf7cda 100644 --- a/gen/proto/js/prehog/v1alpha/teleport_pb.js +++ b/gen/proto/js/prehog/v1alpha/teleport_pb.js @@ -8310,7 +8310,14 @@ proto.prehog.v1alpha.DiscoverResource = { DISCOVER_RESOURCE_DATABASE_MYSQL_RDS: 7, DISCOVER_RESOURCE_APPLICATION_HTTP: 8, DISCOVER_RESOURCE_APPLICATION_TCP: 9, - DISCOVER_RESOURCE_WINDOWS_DESKTOP: 10 + DISCOVER_RESOURCE_WINDOWS_DESKTOP: 10, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS: 11, + DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT: 12, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED: 13, + DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED: 14, + DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP: 15, + DISCOVER_RESOURCE_DATABASE_MYSQL_GCP: 16, + DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP: 17 }; /** diff --git a/lib/web/userevent.go b/lib/web/userevent.go index b5fddff8ed2..57c436625fa 100644 --- a/lib/web/userevent.go +++ b/lib/web/userevent.go @@ -228,7 +228,17 @@ func convertUserEventRequestToUsageEvent(req createUserEventRequest) (*v1.UsageE nil case uiDiscoverStartedEvent, - uiDiscoverResourceSelectionEvent: + uiDiscoverResourceSelectionEvent, + uiDiscoverDeployServiceEvent, + uiDiscoverDatabaseRegisterEvent, + uiDiscoverDatabaseConfigureMTLSEvent, + uiDiscoverDatabaseConfigureIAMPolicyEvent, + uiDiscoverDesktopActiveDirectoryToolsInstallEvent, + uiDiscoverDesktopActiveDirectoryConfigureEvent, + uiDiscoverAutoDiscoveredResourcesEvent, + uiDiscoverPrincipalsConfigureEvent, + uiDiscoverTestConnectionEvent, + uiDiscoverCompletedEvent: var discoverEvent DiscoverEventData if err := json.Unmarshal([]byte(*req.EventData), &discoverEvent); err != nil { diff --git a/proto/prehog/v1alpha/teleport.proto b/proto/prehog/v1alpha/teleport.proto index 9a58c265f29..636b681a014 100644 --- a/proto/prehog/v1alpha/teleport.proto +++ b/proto/prehog/v1alpha/teleport.proto @@ -138,6 +138,13 @@ enum DiscoverResource { DISCOVER_RESOURCE_APPLICATION_HTTP = 8; DISCOVER_RESOURCE_APPLICATION_TCP = 9; DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11; + DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13; + DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14; + DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15; + DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16; + DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17; } // DiscoverResourceMetadata contains common metadata identifying resource type being added. diff --git a/web/packages/teleport/src/Discover/Database/CreateDatabase/useCreateDatabase.ts b/web/packages/teleport/src/Discover/Database/CreateDatabase/useCreateDatabase.ts index 83751539cf3..78434a4d742 100644 --- a/web/packages/teleport/src/Discover/Database/CreateDatabase/useCreateDatabase.ts +++ b/web/packages/teleport/src/Discover/Database/CreateDatabase/useCreateDatabase.ts @@ -17,6 +17,7 @@ import useAttempt from 'shared/hooks/useAttemptNext'; import useTeleport from 'teleport/useTeleport'; +import { useDiscover } from 'teleport/Discover/useDiscover'; // import { usePoll } from 'teleport/Discover/Shared/usePoll'; import { Database } from '../resources'; @@ -36,6 +37,7 @@ export function useCreateDatabase(props: AgentStepProps) { const ctx = useTeleport(); const clusterId = ctx.storeUser.getClusterId(); const { attempt, setAttempt } = useAttempt(''); + const { emitErrorEvent } = useDiscover(); // const [pollTimeout, setPollTimeout] = useState(0); // const [pollActive, setPollActive] = useState(false); @@ -116,7 +118,12 @@ export function useCreateDatabase(props: AgentStepProps) { // request operation is only a CREATE operation). // if (!newDb || db.name != newDb.name) { try { - const createdDb = await ctx.databaseService.createDatabase(clusterId, db); + const createdDb = await ctx.databaseService + .createDatabase(clusterId, db) + .catch((error: Error) => { + emitErrorEvent(error.message); + throw error; + }); // setNewDb(db); props.updateAgentMeta({ ...(props.agentMeta as DbMeta), diff --git a/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.story.tsx b/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.story.tsx index dfb8393854e..1519521c8a6 100644 --- a/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.story.tsx +++ b/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.story.tsx @@ -26,6 +26,8 @@ import { } from 'teleport/Discover/Shared/JoinTokenContext'; import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext'; import { userContext } from 'teleport/mocks/contexts'; +import { DiscoverProvider } from 'teleport/Discover/useDiscover'; +import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import DownloadScript from './DownloadScript'; @@ -139,17 +141,25 @@ const Provider = props => { const ctx = createTeleportContext(); return ( - + - - - {props.children} - - + + + + + {props.children} + + + + ); diff --git a/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.tsx b/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.tsx index d476ddaa063..d438b556c61 100644 --- a/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.tsx +++ b/web/packages/teleport/src/Discover/Database/DownloadScript/DownloadScript.tsx @@ -101,7 +101,7 @@ export default function Container( null} disableProceed={true} - onSkip={props.nextStep} + onSkip={() => props.nextStep(0)} /> )} @@ -118,7 +118,7 @@ export default function Container( null} disableProceed={true} - onSkip={props.nextStep} + onSkip={() => props.nextStep(0)} /> } @@ -137,7 +137,7 @@ export default function Container( null} disableProceed={true} - onSkip={props.nextStep} + onSkip={() => props.nextStep(0)} /> )} @@ -242,7 +242,7 @@ export function DownloadScript( props.nextStep(0)} /> ); diff --git a/web/packages/teleport/src/Discover/Database/IamPolicy/useIamPolicy.ts b/web/packages/teleport/src/Discover/Database/IamPolicy/useIamPolicy.ts index 4391d9ed27e..bfa6fc268f9 100644 --- a/web/packages/teleport/src/Discover/Database/IamPolicy/useIamPolicy.ts +++ b/web/packages/teleport/src/Discover/Database/IamPolicy/useIamPolicy.ts @@ -18,12 +18,14 @@ import { useEffect, useState } from 'react'; import useAttempt from 'shared/hooks/useAttemptNext'; import TeleportContext from 'teleport/teleportContext'; +import { useDiscover } from 'teleport/Discover/useDiscover'; import type { AgentStepProps } from '../../types'; import type { DatabaseIamPolicyResponse } from 'teleport/services/databases'; export function useIamPolicy({ ctx, props }: Props) { const { attempt, run } = useAttempt(''); + const { emitErrorEvent } = useDiscover(); const [iamPolicy, setIamPolicy] = useState(); @@ -41,6 +43,10 @@ export function useIamPolicy({ ctx, props }: Props) { ctx.databaseService .fetchDatabaseIamPolicy(clusterId, props.agentMeta.resourceName) .then(setIamPolicy) + .catch((error: Error) => { + emitErrorEvent(error.message); + throw error; + }) ); } diff --git a/web/packages/teleport/src/Discover/Database/MutualTls/useMutualTls.ts b/web/packages/teleport/src/Discover/Database/MutualTls/useMutualTls.ts index 12d21cf359a..46b2d0b3c92 100644 --- a/web/packages/teleport/src/Discover/Database/MutualTls/useMutualTls.ts +++ b/web/packages/teleport/src/Discover/Database/MutualTls/useMutualTls.ts @@ -23,7 +23,7 @@ import { useJoinTokenValue } from 'teleport/Discover/Shared/JoinTokenContext'; import { ResourceKind } from 'teleport/Discover/Shared'; import { resourceKindToJoinRole } from 'teleport/Discover/Shared/ResourceKind'; -import { DbMeta } from '../../useDiscover'; +import { DbMeta, useDiscover } from '../../useDiscover'; import type { AgentStepProps } from '../../types'; import type { Database } from '../resources'; @@ -32,6 +32,7 @@ export function useMutualTls({ ctx, props }: Props) { const { attempt, run } = useAttempt(''); const prevFetchedJoinToken = useJoinTokenValue(); + const { emitErrorEvent } = useDiscover(); const [joinToken, setJoinToken] = useState(prevFetchedJoinToken); const meta = props.agentMeta as DbMeta; const clusterId = ctx.storeUser.getClusterId(); @@ -52,6 +53,10 @@ export function useMutualTls({ ctx, props }: Props) { method: 'token', }) .then(setJoinToken) + .catch((error: Error) => { + emitErrorEvent(`error with fetching join token: ${error.message}`); + throw error; + }) ); } // Ensure runs only once. @@ -71,6 +76,12 @@ export function useMutualTls({ ctx, props }: Props) { caCert, }) .then(() => props.nextStep()) + .catch((error: Error) => { + emitErrorEvent( + `error with update database with caCert: ${error.message}` + ); + throw error; + }) ); } diff --git a/web/packages/teleport/src/Discover/Database/index.tsx b/web/packages/teleport/src/Discover/Database/index.tsx index c4dce732658..1d8e8944339 100644 --- a/web/packages/teleport/src/Discover/Database/index.tsx +++ b/web/packages/teleport/src/Discover/Database/index.tsx @@ -32,6 +32,7 @@ import { DownloadScript } from 'teleport/Discover/Database/DownloadScript'; import { MutualTls } from 'teleport/Discover/Database/MutualTls'; import { TestConnection } from 'teleport/Discover/Database/TestConnection'; import { IamPolicy } from 'teleport/Discover/Database/IamPolicy'; +import { DiscoverEvent } from 'teleport/services/userEvent'; export const DatabaseResource: Resource = { kind: ResourceKind.Database, @@ -52,14 +53,17 @@ export const DatabaseResource: Resource = { { title: 'Register a Database', component: CreateDatabase, + eventName: DiscoverEvent.DatabaseRegister, }, { title: 'Deploy Database Service', component: DownloadScript, + eventName: DiscoverEvent.DeployService, }, { title: 'Configure IAM Policy', component: IamPolicy, + eventName: DiscoverEvent.DatabaseConfigureIAMPolicy, }, ]; @@ -70,14 +74,17 @@ export const DatabaseResource: Resource = { { title: 'Register a Database', component: CreateDatabase, + eventName: DiscoverEvent.DatabaseRegister, }, { title: 'Deploy Database Service', component: DownloadScript, + eventName: DiscoverEvent.DeployService, }, { title: 'Configure mTLS', component: MutualTls, + eventName: DiscoverEvent.DatabaseConfigureMTLS, }, ]; @@ -88,6 +95,7 @@ export const DatabaseResource: Resource = { return [ { title: 'Select Resource Type', + eventName: DiscoverEvent.ResourceSelection, }, { title: 'Configure Resource', @@ -96,14 +104,18 @@ export const DatabaseResource: Resource = { { title: 'Set Up Access', component: SetupAccess, + eventName: DiscoverEvent.PrincipalsConfigure, }, { title: 'Test Connection', component: TestConnection, + eventName: DiscoverEvent.TestConnection, + manuallyEmitSuccessEvent: true, }, { title: 'Finished', component: Finished, + eventName: DiscoverEvent.Completed, hide: true, }, ]; diff --git a/web/packages/teleport/src/Discover/Desktop/ConnectTeleport/ConnectTeleport.tsx b/web/packages/teleport/src/Discover/Desktop/ConnectTeleport/ConnectTeleport.tsx index ff829033d36..f722c1a860c 100644 --- a/web/packages/teleport/src/Discover/Desktop/ConnectTeleport/ConnectTeleport.tsx +++ b/web/packages/teleport/src/Discover/Desktop/ConnectTeleport/ConnectTeleport.tsx @@ -96,6 +96,10 @@ const verticalTransitionStyles = { }; import { State } from 'teleport/Discover/useDiscover'; +import { + DiscoverEvent, + DiscoverEventStatus, +} from 'teleport/services/userEvent'; export function ConnectTeleport(props: State) { const [currentStep, setCurrentStep] = useState(StepKind.RunConfigureScript); @@ -156,7 +160,16 @@ export function ConnectTeleport(props: State) { {currentStep === StepKind.RunConfigureScript && ( }> setCurrentStep(StepKind.CopyOutput)} + onNext={() => { + props.emitEvent( + { stepStatus: DiscoverEventStatus.Success }, + { + eventName: + DiscoverEvent.DesktopActiveDirectoryConfigure, + } + ); + setCurrentStep(StepKind.CopyOutput); + }} /> )} diff --git a/web/packages/teleport/src/Discover/Desktop/DiscoverDesktops/DiscoverDesktops.tsx b/web/packages/teleport/src/Discover/Desktop/DiscoverDesktops/DiscoverDesktops.tsx index 90e621203cb..af3d6ccb7e4 100644 --- a/web/packages/teleport/src/Discover/Desktop/DiscoverDesktops/DiscoverDesktops.tsx +++ b/web/packages/teleport/src/Discover/Desktop/DiscoverDesktops/DiscoverDesktops.tsx @@ -5,7 +5,7 @@ import { Box, ButtonPrimary, Text } from 'design'; import { DesktopItem } from 'teleport/Discover/Desktop/DiscoverDesktops/DesktopItem'; import { Header } from 'teleport/Discover/Shared'; -import { State } from 'teleport/Discover/useDiscover'; +import { useDiscover } from 'teleport/Discover/useDiscover'; import { ProxyDesktopServiceDiagram } from 'teleport/Discover/Desktop/DiscoverDesktops/ProxyDesktopServiceDiagram'; import { usePoll } from 'teleport/Discover/Shared/usePoll'; import { useTeleport } from 'teleport'; @@ -13,6 +13,7 @@ import useStickyClusterId from 'teleport/useStickyClusterId'; import { usePingTeleport } from 'teleport/Discover/Shared/PingTeleportContext'; import cfg from 'teleport/config'; import { NavLink } from 'teleport/components/Router'; +import { DiscoverEventStatus } from 'teleport/services/userEvent'; import type { WindowsDesktopService } from 'teleport/services/desktops'; @@ -82,8 +83,9 @@ const TimedOutTitle = styled.div` font-size: 16px; `; -export function DiscoverDesktops(props: State) { +export function DiscoverDesktops() { const ctx = useTeleport(); + const { emitEvent, nextStep } = useDiscover(); const { result: desktopService } = usePingTeleport(); @@ -107,6 +109,14 @@ export function DiscoverDesktops(props: State) { const ref = useRef(); + function handleNextStep() { + emitEvent( + { stepStatus: DiscoverEventStatus.Success }, + { autoDiscoverResourcesCount: result.agents.length } + ); + nextStep(); + } + const desktops = []; if (result && result.agents) { @@ -215,7 +225,7 @@ export function DiscoverDesktops(props: State) { - props.nextStep()}> + Finish diff --git a/web/packages/teleport/src/Discover/Desktop/index.tsx b/web/packages/teleport/src/Discover/Desktop/index.tsx index f70a2e8ed8a..823860efc26 100644 --- a/web/packages/teleport/src/Discover/Desktop/index.tsx +++ b/web/packages/teleport/src/Discover/Desktop/index.tsx @@ -27,6 +27,7 @@ import { InstallActiveDirectory } from 'teleport/Discover/Desktop/InstallActiveD import { Resource } from 'teleport/Discover/flow'; import { DesktopWrapper } from 'teleport/Discover/Desktop/DesktopWrapper'; +import { DiscoverEvent } from 'teleport/services/userEvent'; export const DesktopResource: Resource = { kind: ResourceKind.Desktop, @@ -46,22 +47,30 @@ export const DesktopResource: Resource = { views: [ { title: 'Select Resource Type', + eventName: DiscoverEvent.ResourceSelection, }, { title: 'Install Active Directory', component: InstallActiveDirectory, + eventName: DiscoverEvent.DesktopActiveDirectoryToolsInstall, }, { title: 'Connect Teleport', component: ConnectTeleport, + // Sub-step events are handled inside its component. + // This eventName defines the event to emit for the `last` sub-step. + eventName: DiscoverEvent.DeployService, }, { title: 'Discover Desktops', component: DiscoverDesktops, + eventName: DiscoverEvent.AutoDiscoveredResources, + manuallyEmitSuccessEvent: true, }, { title: 'Finished', component: Finished, + eventName: DiscoverEvent.Completed, hide: true, }, ], diff --git a/web/packages/teleport/src/Discover/Discover.test.tsx b/web/packages/teleport/src/Discover/Discover.test.tsx index 894defc3413..431a33da8e2 100644 --- a/web/packages/teleport/src/Discover/Discover.test.tsx +++ b/web/packages/teleport/src/Discover/Discover.test.tsx @@ -27,6 +27,16 @@ import { Discover } from 'teleport/Discover/Discover'; import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import { fullAcl } from 'teleport/mocks/contexts'; import { getOSSFeatures } from 'teleport/features'; +import cfg from 'teleport/config'; + +const crypto = require('crypto'); + +// eslint-disable-next-line jest/require-hook +Object.defineProperty(globalThis, 'crypto', { + value: { + randomUUID: () => crypto.randomUUID(), + }, +}); const userContextJson = { authType: 'sso', @@ -56,7 +66,11 @@ describe('discover', () => { }); return render( - + diff --git a/web/packages/teleport/src/Discover/Discover.tsx b/web/packages/teleport/src/Discover/Discover.tsx index 86961e0729e..cf71f1a9694 100644 --- a/web/packages/teleport/src/Discover/Discover.tsx +++ b/web/packages/teleport/src/Discover/Discover.tsx @@ -75,7 +75,7 @@ function DiscoverContent() { { if (nextLocation.pathname === cfg.routes.discover) return true; - return 'Are you sure you want to exit the “Add New Resource” workflow? You’ll have to start from the beginning next time.'; + return 'Are you sure you want to exit the "Enroll New Resource” workflow? You’ll have to start from the beginning next time.'; }} when={selectedResource.shouldPrompt(currentStep)} /> diff --git a/web/packages/teleport/src/Discover/Kubernetes/HelmChart/HelmChart.story.tsx b/web/packages/teleport/src/Discover/Kubernetes/HelmChart/HelmChart.story.tsx index 50aad3c76c9..7e6adca0046 100644 --- a/web/packages/teleport/src/Discover/Kubernetes/HelmChart/HelmChart.story.tsx +++ b/web/packages/teleport/src/Discover/Kubernetes/HelmChart/HelmChart.story.tsx @@ -26,6 +26,8 @@ import { } from 'teleport/Discover/Shared/JoinTokenContext'; import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext'; import { userContext } from 'teleport/mocks/contexts'; +import { DiscoverProvider } from 'teleport/Discover/useDiscover'; +import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import HelmChart from './HelmChart'; @@ -126,17 +128,25 @@ const Provider = props => { const ctx = createTeleportContext(); return ( - + - - - {props.children} - - + + + + + {props.children} + + + + ); diff --git a/web/packages/teleport/src/Discover/Kubernetes/index.tsx b/web/packages/teleport/src/Discover/Kubernetes/index.tsx index b4073dfd073..706576ba1d2 100644 --- a/web/packages/teleport/src/Discover/Kubernetes/index.tsx +++ b/web/packages/teleport/src/Discover/Kubernetes/index.tsx @@ -20,6 +20,7 @@ import { Kubernetes } from 'design/Icon'; import { Finished, ResourceKind } from 'teleport/Discover/Shared'; import { Resource } from 'teleport/Discover/flow'; +import { DiscoverEvent } from 'teleport/services/userEvent'; import { KubeWrapper } from './KubeWrapper'; import { SetupAccess } from './SetupAccess'; @@ -39,23 +40,29 @@ export const KubernetesResource: Resource = { views: [ { title: 'Select Resource Type', + eventName: DiscoverEvent.ResourceSelection, }, { title: 'Configure Resource', component: HelmChart, + eventName: DiscoverEvent.DeployService, }, { title: 'Set Up Access', component: SetupAccess, + eventName: DiscoverEvent.PrincipalsConfigure, }, { title: 'Test Connection', component: TestConnection, + eventName: DiscoverEvent.TestConnection, + manuallyEmitSuccessEvent: true, }, { title: 'Finished', component: Finished, hide: true, + eventName: DiscoverEvent.Completed, }, ], }; diff --git a/web/packages/teleport/src/Discover/SelectResource/SelectResource.test.tsx b/web/packages/teleport/src/Discover/SelectResource/SelectResource.test.tsx index da7ca543701..503ff4f3d3c 100644 --- a/web/packages/teleport/src/Discover/SelectResource/SelectResource.test.tsx +++ b/web/packages/teleport/src/Discover/SelectResource/SelectResource.test.tsx @@ -29,6 +29,16 @@ import { DiscoverProvider } from 'teleport/Discover/useDiscover'; import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import { fullAccess, fullAcl } from 'teleport/mocks/contexts'; import { getOSSFeatures } from 'teleport/features'; +import cfg from 'teleport/config'; + +const crypto = require('crypto'); + +// eslint-disable-next-line jest/require-hook +Object.defineProperty(globalThis, 'crypto', { + value: { + randomUUID: () => crypto.randomUUID(), + }, +}); const userContextJson = { authType: 'sso', @@ -58,7 +68,7 @@ describe('select resource', () => { }); return render( - + diff --git a/web/packages/teleport/src/Discover/SelectResource/SelectResource.tsx b/web/packages/teleport/src/Discover/SelectResource/SelectResource.tsx index 5d76eb0fb15..ae1414789a5 100644 --- a/web/packages/teleport/src/Discover/SelectResource/SelectResource.tsx +++ b/web/packages/teleport/src/Discover/SelectResource/SelectResource.tsx @@ -25,6 +25,10 @@ import useTeleport from 'teleport/useTeleport'; import { Acl } from 'teleport/services/user'; import { ResourceKind, Header, HeaderSubtitle } from 'teleport/Discover/Shared'; +import { + DiscoverEvent, + DiscoverEventStatus, +} from 'teleport/services/userEvent'; import { ApplicationResource } from '../Application/ApplicationResource'; import { DatabaseResource } from '../Database/DatabaseResource'; @@ -32,6 +36,7 @@ import { DesktopResource } from '../Desktop/DesktopResource'; import { KubernetesResource } from '../Kubernetes/KubernetesResource'; import { ServerResource } from '../Server/ServerResource'; import { DatabaseEngine, DatabaseLocation } from '../Database/resources'; +import { useDiscover } from '../useDiscover'; import k8sIcon from './assets/kubernetes.png'; import serverIcon from './assets/server.png'; @@ -67,6 +72,7 @@ interface SelectResourceProps { export function SelectResource(props: SelectResourceProps) { const ctx = useTeleport(); + const { emitEvent } = useDiscover(); const userContext = ctx.storeUser.state; const { acl } = userContext; @@ -141,6 +147,7 @@ export function SelectResource(props: SelectResourceProps) { state.engine === DatabaseEngine.MySQL ) { props.onNext(); + return; } } @@ -150,10 +157,12 @@ export function SelectResource(props: SelectResourceProps) { state.engine === DatabaseEngine.MySQL ) { props.onNext(); + return; } } // Unsupported databases will default to the modal popup. + emitEvent({ stepStatus: DiscoverEventStatus.Success }); return setShowAddDB(true); }} /> @@ -161,7 +170,13 @@ export function SelectResource(props: SelectResourceProps) { {props.selectedResourceKind === ResourceKind.Application && ( setShowAddApp(true)} + onProceed={() => { + setShowAddApp(true); + emitEvent( + { stepStatus: DiscoverEventStatus.Success }, + { eventName: DiscoverEvent.ResourceSelection } + ); + }} /> )} {props.selectedResourceKind === ResourceKind.Desktop && ( diff --git a/web/packages/teleport/src/Discover/Server/DownloadScript/DownloadScript.story.tsx b/web/packages/teleport/src/Discover/Server/DownloadScript/DownloadScript.story.tsx index 292ffe5a7be..115bf870c30 100644 --- a/web/packages/teleport/src/Discover/Server/DownloadScript/DownloadScript.story.tsx +++ b/web/packages/teleport/src/Discover/Server/DownloadScript/DownloadScript.story.tsx @@ -26,6 +26,8 @@ import { import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext'; import { userContext } from 'teleport/Main/fixtures'; import { ResourceKind } from 'teleport/Discover/Shared'; +import { DiscoverProvider } from 'teleport/Discover/useDiscover'; +import { FeaturesContextProvider } from 'teleport/FeaturesContext'; import DownloadScript from './DownloadScript'; @@ -118,17 +120,25 @@ const Provider = props => { const ctx = createTeleportContext(); return ( - + - - - {props.children} - - + + + + + {props.children} + + + + ); diff --git a/web/packages/teleport/src/Discover/Server/index.tsx b/web/packages/teleport/src/Discover/Server/index.tsx index f8cbb1e8851..0b61034790d 100644 --- a/web/packages/teleport/src/Discover/Server/index.tsx +++ b/web/packages/teleport/src/Discover/Server/index.tsx @@ -23,6 +23,7 @@ import { DownloadScript } from 'teleport/Discover/Server/DownloadScript'; import { SetupAccess } from 'teleport/Discover/Server/SetupAccess'; import { TestConnection } from 'teleport/Discover/Server/TestConnection'; import { ResourceKind, Finished } from 'teleport/Discover/Shared'; +import { DiscoverEvent } from 'teleport/services/userEvent'; import { ServerWrapper } from './ServerWrapper'; @@ -39,23 +40,29 @@ export const ServerResource: Resource = { views: [ { title: 'Select Resource Type', + eventName: DiscoverEvent.ResourceSelection, }, { title: 'Configure Resource', component: DownloadScript, + eventName: DiscoverEvent.DeployService, }, { title: 'Set Up Access', component: SetupAccess, + eventName: DiscoverEvent.PrincipalsConfigure, }, { title: 'Test Connection', component: TestConnection, + eventName: DiscoverEvent.TestConnection, + manuallyEmitSuccessEvent: true, }, { title: 'Finished', component: Finished, hide: true, + eventName: DiscoverEvent.Completed, }, ], }; diff --git a/web/packages/teleport/src/Discover/Shared/ConnectionDiagnostic/useConnectionDiagnostic.ts b/web/packages/teleport/src/Discover/Shared/ConnectionDiagnostic/useConnectionDiagnostic.ts index 83703d7668e..6c4d367735a 100644 --- a/web/packages/teleport/src/Discover/Shared/ConnectionDiagnostic/useConnectionDiagnostic.ts +++ b/web/packages/teleport/src/Discover/Shared/ConnectionDiagnostic/useConnectionDiagnostic.ts @@ -18,12 +18,13 @@ import { useState } from 'react'; import useAttempt from 'shared/hooks/useAttemptNext'; import useTeleport from 'teleport/useTeleport'; +import { useDiscover } from 'teleport/Discover/useDiscover'; +import { DiscoverEventStatus } from 'teleport/services/userEvent'; import type { ConnectionDiagnostic, ConnectionDiagnosticRequest, } from 'teleport/services/agents'; - import type { AgentStepProps } from '../../types'; export function useConnectionDiagnostic(props: AgentStepProps) { @@ -31,14 +32,42 @@ export function useConnectionDiagnostic(props: AgentStepProps) { const { attempt, run } = useAttempt(''); const [diagnosis, setDiagnosis] = useState(); + const [ranDiagnosis, setRanDiagnosis] = useState(false); + const { emitErrorEvent, emitEvent } = useDiscover(); const access = ctx.storeUser.getConnectionDiagnosticAccess(); const canTestConnection = access.create && access.edit && access.read; function runConnectionDiagnostic(req: ConnectionDiagnosticRequest) { setDiagnosis(null); // reset since user's can re-test connection. + setRanDiagnosis(true); run(() => - ctx.agentService.createConnectionDiagnostic(req).then(setDiagnosis) + ctx.agentService + .createConnectionDiagnostic(req) + .then(diag => { + setDiagnosis(diag); + + // The request may succeed, but the connection + // test itself can fail: + if (!diag.success) { + // Append all possible errors: + const errors: string[] = []; + diag.traces.forEach(trace => { + if (trace.status === 'failed') { + errors.push( + `[${trace.traceType}] ${trace.error} (${trace.details})` + ); + } + }); + emitErrorEvent(`testing failed: ${errors.join('\n')}`); + } else { + emitEvent({ stepStatus: DiscoverEventStatus.Success }); + } + }) + .catch((error: Error) => { + emitErrorEvent(error.message); + throw error; + }) ); } @@ -48,7 +77,15 @@ export function useConnectionDiagnostic(props: AgentStepProps) { attempt, runConnectionDiagnostic, diagnosis, - nextStep: () => props.nextStep(), + nextStep: () => { + if (!ranDiagnosis) { + emitEvent({ stepStatus: DiscoverEventStatus.Skipped }); + } + // else either a failed or success event would've been + // already sent for each test connection, so we don't need + // to send anything here. + props.nextStep(); + }, prevStep: props.prevStep, canTestConnection, username, diff --git a/web/packages/teleport/src/Discover/Shared/JoinTokenContext.tsx b/web/packages/teleport/src/Discover/Shared/JoinTokenContext.tsx index e9342b224f4..cb7b9afe6a8 100644 --- a/web/packages/teleport/src/Discover/Shared/JoinTokenContext.tsx +++ b/web/packages/teleport/src/Discover/Shared/JoinTokenContext.tsx @@ -1,3 +1,19 @@ +/** + * Copyright 2022 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import React, { useCallback, useContext, useEffect, useState } from 'react'; import { useTeleport } from 'teleport'; @@ -7,6 +23,8 @@ import { resourceKindToJoinRole, } from 'teleport/Discover/Shared/ResourceKind'; +import { useDiscover } from '../useDiscover'; + import type { AgentLabel } from 'teleport/services/agents'; import type { JoinToken, JoinMethod } from 'teleport/services/joinToken'; @@ -90,6 +108,7 @@ export function useJoinToken( } { const ctx = useTeleport(); const tokenContext = useContext(joinTokenContext); + const { emitErrorEvent } = useDiscover(); function run() { abortController = new AbortController(); @@ -116,8 +135,9 @@ export function useJoinToken( tokenContext.setJoinToken(token); tokenContext.startTimer(); }) - .catch(error => { + .catch((error: Error) => { cachedJoinTokenResult.error = error; + emitErrorEvent(error.message); }), }; diff --git a/web/packages/teleport/src/Discover/Shared/PingTeleportContext.tsx b/web/packages/teleport/src/Discover/Shared/PingTeleportContext.tsx index b981ef45b03..ccc540ff5c8 100644 --- a/web/packages/teleport/src/Discover/Shared/PingTeleportContext.tsx +++ b/web/packages/teleport/src/Discover/Shared/PingTeleportContext.tsx @@ -6,6 +6,8 @@ import { INTERNAL_RESOURCE_ID_LABEL_KEY } from 'teleport/services/joinToken'; import { useJoinTokenValue } from 'teleport/Discover/Shared/JoinTokenContext'; import { ResourceKind } from 'teleport/Discover/Shared/ResourceKind'; +import { useDiscover } from '../useDiscover'; + interface PingTeleportContextState { active: boolean; start: () => void; @@ -28,6 +30,7 @@ export function PingTeleportProvider(props: { const [active, setActive] = useState(false); const [timeout, setPollTimeout] = useState(null); + const { emitErrorEvent } = useDiscover(); // alternateSearchTerm when set will be used as the search term // instead of the default search term which is the internal resource ID. @@ -82,6 +85,8 @@ export function PingTeleportProvider(props: { useEffect(() => { if (active && Date.now() > timeout) { + // This means the polling timed out. + emitErrorEvent('polling for resource discovery has timed out'); setActive(false); } }, [active, timeout, timedOut]); diff --git a/web/packages/teleport/src/Discover/Shared/ResourceKind.ts b/web/packages/teleport/src/Discover/Shared/ResourceKind.ts index 0852bb899a7..47b3a152820 100644 --- a/web/packages/teleport/src/Discover/Shared/ResourceKind.ts +++ b/web/packages/teleport/src/Discover/Shared/ResourceKind.ts @@ -14,7 +14,12 @@ * limitations under the License. */ +import { DiscoverEventResource } from 'teleport/services/userEvent'; + +import { DatabaseEngine, DatabaseLocation } from '../Database/resources'; + import type { JoinRole } from 'teleport/services/joinToken'; +import type { Database } from '../Database/resources'; export enum ResourceKind { Application, @@ -38,3 +43,69 @@ export function resourceKindToJoinRole(kind: ResourceKind): JoinRole { return 'Node'; } } + +export function resourceKindToEventResource( + kind: ResourceKind, + resourceState: any +): DiscoverEventResource { + switch (kind) { + case ResourceKind.Database: + const { engine, location } = resourceState as Database; + if (location === DatabaseLocation.AWS) { + if (engine === DatabaseEngine.PostgreSQL) { + return DiscoverEventResource.DatabasePostgresRds; + } + if (engine === DatabaseEngine.MySQL) { + return DiscoverEventResource.DatabaseMysqlRds; + } + if (engine === DatabaseEngine.SQLServer) { + return DiscoverEventResource.DatabaseSqlServerRds; + } + if (engine === DatabaseEngine.RedShift) { + return DiscoverEventResource.DatabasePostgresRedshift; + } + } + + if (location === DatabaseLocation.SelfHosted) { + if (engine === DatabaseEngine.PostgreSQL) { + return DiscoverEventResource.DatabasePostgresSelfHosted; + } + if (engine === DatabaseEngine.MySQL) { + return DiscoverEventResource.DatabaseMysqlSelfHosted; + } + if (engine === DatabaseEngine.Mongo) { + return DiscoverEventResource.DatabaseMongodbSelfHosted; + } + if (engine === DatabaseEngine.SQLServer) { + return DiscoverEventResource.DatabaseSqlServerSelfHosted; + } + if (engine === DatabaseEngine.Redis) { + return DiscoverEventResource.DatabaseRedisSelfHosted; + } + } + + if (location === DatabaseLocation.GCP) { + if (engine === DatabaseEngine.PostgreSQL) { + return DiscoverEventResource.DatabasePostgresGcp; + } + if (engine === DatabaseEngine.MySQL) { + return DiscoverEventResource.DatabaseMysqlGcp; + } + if (engine === DatabaseEngine.SQLServer) { + return DiscoverEventResource.DatabaseMysqlGcp; + } + } + console.error(`resource database event not defined for ${resourceState}`); + return null; + case ResourceKind.Desktop: + return DiscoverEventResource.WindowsDesktop; + case ResourceKind.Kubernetes: + return DiscoverEventResource.Kubernetes; + case ResourceKind.Server: + return DiscoverEventResource.Server; + case ResourceKind.Application: + return DiscoverEventResource.ApplicationHttp; + default: + console.error(`resource event not defined for ${resourceState}`); + } +} diff --git a/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.test.tsx b/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.test.tsx index af0ab65ba61..1cb53b750a1 100644 --- a/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.test.tsx +++ b/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.test.tsx @@ -15,11 +15,16 @@ limitations under the License. */ import React from 'react'; +import { MemoryRouter } from 'react-router'; import { renderHook, act } from '@testing-library/react-hooks'; import { baseContext } from 'teleport/mocks/contexts'; import makeUserContext from 'teleport/services/user/makeUserContext'; import { ContextProvider, Context as TeleportContext } from 'teleport'; +import { FeaturesContextProvider } from 'teleport/FeaturesContext'; +import { DiscoverProvider } from 'teleport/Discover/useDiscover'; +import cfg from 'teleport/config'; +import { userEventService } from 'teleport/services/userEvent'; import { ResourceKind } from '../ResourceKind'; @@ -32,17 +37,35 @@ import type { NodeMeta, } from 'teleport/Discover/useDiscover'; +const crypto = require('crypto'); + +// eslint-disable-next-line jest/require-hook +Object.defineProperty(globalThis, 'crypto', { + value: { + randomUUID: () => crypto.randomUUID(), + }, +}); + describe('onProceed correctly deduplicates, removes static traits, updates meta, and calls updateUser', () => { const ctx = createTeleportContext(); jest.spyOn(ctx.userService, 'fetchUser').mockResolvedValue(getMockUser()); jest.spyOn(ctx.userService, 'updateUser').mockResolvedValue(null); jest.spyOn(ctx.userService, 'applyUserTraits').mockResolvedValue(null); + jest + .spyOn(userEventService, 'captureDiscoverEvent') + .mockResolvedValue(null as never); // return value does not matter but required by ts let wrapper; beforeEach(() => { wrapper = ({ children }) => ( - {children} + + + + {children} + + + ); }); @@ -296,7 +319,13 @@ describe('static and dynamic traits are correctly separated and correctly create }; const wrapper = ({ children }) => ( - {children} + + + + {children} + + + ); const { result, waitForNextUpdate } = renderHook( diff --git a/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.ts b/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.ts index b99c10c0e13..5002984b592 100644 --- a/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.ts +++ b/web/packages/teleport/src/Discover/Shared/SetupAccess/useUserTraits.ts @@ -20,11 +20,12 @@ import useAttempt from 'shared/hooks/useAttemptNext'; import { arrayStrDiff } from 'teleport/lib/util'; import useTeleport from 'teleport/useTeleport'; import { Option } from 'teleport/Discover/Shared/SelectCreatable'; +import { useDiscover } from 'teleport/Discover/useDiscover'; import { ResourceKind } from '../ResourceKind'; -import type { User, UserTraits } from 'teleport/services/user'; import type { DbMeta, KubeMeta, NodeMeta } from 'teleport/Discover/useDiscover'; +import type { User, UserTraits } from 'teleport/services/user'; import type { AgentStepProps } from '../../types'; // useUserTraits handles: @@ -35,6 +36,7 @@ import type { AgentStepProps } from '../../types'; // - provides utility function that makes data objects (type Option) for react-select component export function useUserTraits(props: AgentStepProps) { const ctx = useTeleport(); + const { emitErrorEvent } = useDiscover(); const [user, setUser] = useState(); const { attempt, run, setAttempt, handleError } = useAttempt('processing'); @@ -85,18 +87,19 @@ export function useUserTraits(props: AgentStepProps) { ); } - useEffect( - function initFetchUserTraits() { - run(() => - ctx.userService.fetchUser(ctx.storeUser.getUsername()).then(setUser) - ); - }, - [ctx.storeUser, ctx.userService, run] - ); + useEffect(() => { + fetchUserTraits(); + }, [ctx.storeUser, ctx.userService, run]); function fetchUserTraits() { run(() => - ctx.userService.fetchUser(ctx.storeUser.getUsername()).then(setUser) + ctx.userService + .fetchUser(ctx.storeUser.getUsername()) + .then(setUser) + .catch((error: Error) => { + emitErrorEvent(`error fetching user traits: ${error.message}`); + throw error; + }) ); } @@ -232,15 +235,24 @@ export function useUserTraits(props: AgentStepProps) { updateResourceMetaDynamicTraits(newDynamicTraits); setAttempt({ status: 'processing' }); try { - await ctx.userService.updateUser({ - ...user, - traits: { - ...user.traits, - ...newDynamicTraits, - }, + await ctx.userService + .updateUser({ + ...user, + traits: { + ...user.traits, + ...newDynamicTraits, + }, + }) + .catch((error: Error) => { + emitErrorEvent(`error updating user traits: ${error.message}`); + throw error; + }); + + await ctx.userService.applyUserTraits().catch((error: Error) => { + emitErrorEvent(`error applying new user traits: ${error.message}`); + throw error; }); - await ctx.userService.applyUserTraits(); props.nextStep(); } catch (err) { handleError(err); diff --git a/web/packages/teleport/src/Discover/flow.tsx b/web/packages/teleport/src/Discover/flow.tsx index 99ad0f4188c..30c955b8c9a 100644 --- a/web/packages/teleport/src/Discover/flow.tsx +++ b/web/packages/teleport/src/Discover/flow.tsx @@ -18,6 +18,7 @@ import React from 'react'; import { ResourceKind } from 'teleport/Discover/Shared'; import { AgentStepComponent } from 'teleport/Discover/types'; +import { DiscoverEvent } from 'teleport/services/userEvent'; type ViewFunction = (t: T) => View[]; @@ -35,6 +36,12 @@ export interface View { hide?: boolean; index?: number; views?: View[]; + eventName?: DiscoverEvent; + // manuallyEmitSuccessEvent is a flag that when true + // means success events will be sent by the children + // (current view component) instead of the default + // which is sent by the parent context. + manuallyEmitSuccessEvent?: boolean; } // computeViewChildrenSize calculates how many children a view has, without counting the first diff --git a/web/packages/teleport/src/Discover/useDiscover.test.tsx b/web/packages/teleport/src/Discover/useDiscover.test.tsx new file mode 100644 index 00000000000..b875460b96a --- /dev/null +++ b/web/packages/teleport/src/Discover/useDiscover.test.tsx @@ -0,0 +1,271 @@ +/** + * Copyright 2023 Gravitational, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { MemoryRouter } from 'react-router'; +import { renderHook, act } from '@testing-library/react-hooks'; + +import { createTeleportContext } from 'teleport/mocks/contexts'; +import { ContextProvider } from 'teleport'; +import { + DiscoverEvent, + DiscoverEventResource, + DiscoverEventStatus, + userEventService, +} from 'teleport/services/userEvent'; +import { FeaturesContextProvider } from 'teleport/FeaturesContext'; +import api from 'teleport/services/api'; +import cfg from 'teleport/config'; + +import { useDiscover, DiscoverProvider } from './useDiscover'; +import { ResourceKind } from './Shared'; + +const crypto = require('crypto'); + +// eslint-disable-next-line jest/require-hook +Object.defineProperty(globalThis, 'crypto', { + value: { + randomUUID: () => crypto.randomUUID(), + }, +}); + +describe('emitting events', () => { + const ctx = createTeleportContext(); + let wrapper; + + beforeEach(() => { + jest.spyOn(api, 'get').mockResolvedValue([]); // required for fetchClusterAlerts + jest + .spyOn(userEventService, 'captureDiscoverEvent') + .mockResolvedValue(null as never); // return value does not matter but required by ts + + wrapper = ({ children }) => ( + + + + {children} + + + + ); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + test('init the eventState state', async () => { + const { result } = renderHook(() => useDiscover(), { + wrapper, + }); + + // Test init hook. + expect(result.current.currentStep).toBe(0); + expect(result.current.selectedResourceKind).toEqual(ResourceKind.Server); + expect(result.current.selectedResource.kind).toEqual(ResourceKind.Server); + + expect(result.current.currentStep).toBe(0); + expect(result.current.eventState).toEqual( + expect.objectContaining({ + id: expect.any(String), + currEventName: DiscoverEvent.ResourceSelection, + resource: DiscoverEventResource.Server, + }) + ); + + const eventId = result.current.eventState.id; + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith( + expect.objectContaining({ + event: DiscoverEvent.Started, + eventData: { + id: eventId, + resource: '', + stepStatus: DiscoverEventStatus.Success, + }, + }) + ); + jest.resetAllMocks(); + + // Calling to update eventState again should not emit an event + // but update the state only. + await act(async () => { + result.current.onSelectResource(ResourceKind.Kubernetes); + }); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(0); + expect(result.current.eventState).toEqual({ + id: eventId, + currEventName: DiscoverEvent.ResourceSelection, + resource: DiscoverEventResource.Kubernetes, + }); + }); + + test('incrementing view by one, emits success event', async () => { + const { result } = renderHook(() => useDiscover(), { + wrapper, + }); + jest.resetAllMocks(); // to discount the initial start event. + + const id = result.current.eventState.id; + + // Test next step gets incremented by 1, passing in a non-number. + await act(async () => { + result.current.nextStep('non-number' as any); + }); + expect(result.current.currentStep).toBe(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith( + expect.objectContaining({ + event: DiscoverEvent.ResourceSelection, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Success, + }, + }) + ); + // Test the `eventState` got updated to the next view. + expect(result.current.eventState).toEqual({ + id, + currEventName: DiscoverEvent.DeployService, + resource: DiscoverEventResource.Server, + }); + jest.resetAllMocks(); + + // Test passing in nothing, increments by 1. + await act(async () => { + result.current.nextStep(); + }); + expect(result.current.currentStep).toBe(2); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith( + expect.objectContaining({ + event: DiscoverEvent.DeployService, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Success, + }, + }) + ); + }); + + test('programatically skipping, emits skipped and one success event', async () => { + const { result } = renderHook(() => useDiscover(), { + wrapper, + }); + jest.resetAllMocks(); // to discount the initial start event. + + const id = result.current.eventState.id; + + // Test all skipped steps have been emitted. + await act(async () => { + result.current.nextStep(3); + }); + expect(result.current.currentStep).toBe(3); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(3); + + // Emit the current event. + expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + event: DiscoverEvent.ResourceSelection, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Success, + }, + }) + ); + + // Should have two skipped events. + expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + event: DiscoverEvent.DeployService, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Skipped, + }, + }) + ); + expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith( + 3, + expect.objectContaining({ + event: DiscoverEvent.PrincipalsConfigure, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Skipped, + }, + }) + ); + }); + + test('user intentionally skipping, emits only skipped event', async () => { + const { result } = renderHook(() => useDiscover(), { + wrapper, + }); + jest.resetAllMocks(); // to discount the initial start event. + + const id = result.current.eventState.id; + + await act(async () => { + result.current.nextStep(0); + }); + expect(result.current.currentStep).toBe(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith( + expect.objectContaining({ + event: DiscoverEvent.ResourceSelection, + eventData: { + id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Skipped, + }, + }) + ); + }); + + test('error event', async () => { + const { result } = renderHook(() => useDiscover(), { + wrapper, + }); + jest.resetAllMocks(); // to discount the initial start event. + + await act(async () => { + result.current.emitErrorEvent('some error message'); + }); + expect(result.current.currentStep).toBe(0); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1); + expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith( + expect.objectContaining({ + event: DiscoverEvent.ResourceSelection, + eventData: { + id: result.current.eventState.id, + resource: DiscoverEventResource.Server, + stepStatus: DiscoverEventStatus.Error, + stepStatusError: 'some error message', + }, + }) + ); + }); +}); diff --git a/web/packages/teleport/src/Discover/useDiscover.tsx b/web/packages/teleport/src/Discover/useDiscover.tsx index 4f6694ab820..4c7644c1b48 100644 --- a/web/packages/teleport/src/Discover/useDiscover.tsx +++ b/web/packages/teleport/src/Discover/useDiscover.tsx @@ -14,15 +14,30 @@ * limitations under the License. */ -import React, { useContext, useMemo, useState } from 'react'; +import React, { + useContext, + useMemo, + useState, + useEffect, + useCallback, +} from 'react'; -import { useLocation } from 'react-router'; +import { useLocation, useHistory } from 'react-router'; import { ResourceKind } from 'teleport/Discover/Shared'; +import { + DiscoverEventStatus, + DiscoverEventStepStatus, + DiscoverEvent, + DiscoverEventResource, + userEventService, +} from 'teleport/services/userEvent'; +import cfg from 'teleport/config'; import { addIndexToViews, findViewAtIndex, Resource, View } from './flow'; - +import { resourceKindToEventResource } from './Shared/ResourceKind'; import { resources } from './resources'; +import { DATABASES } from './Database/resources'; import type { Node } from 'teleport/services/nodes'; import type { Kube } from 'teleport/services/kube'; @@ -57,21 +72,44 @@ interface DiscoverContextState { setResourceState: (value: T) => void; updateAgentMeta: (meta: AgentMeta) => void; views: View[]; + emitErrorEvent(errorStr: string): void; + emitEvent(status: DiscoverEventStepStatus, custom?: CustomEventInput): void; + eventState: EventState; } +type EventState = { + id: string; + currEventName: DiscoverEvent; + manuallyEmitSuccessEvent: boolean; + resource: DiscoverEventResource; +}; + +type CustomEventInput = { + eventName?: DiscoverEvent; + autoDiscoverResourcesCount?: number; +}; + const discoverContext = React.createContext(null); export function DiscoverProvider( props: React.PropsWithChildren ) { const location = useLocation<{ entity: string }>(); + const history = useHistory(); const [currentStep, setCurrentStep] = useState(0); const [selectedResourceKind, setSelectedResourceKind] = useState(getKindFromString(location?.state?.entity)); const [agentMeta, setAgentMeta] = useState(); - const [resourceState, setResourceState] = useState(); + const [resourceState, setResourceState] = useState(() => { + // Pre-select the most popular one, to send of a start emit event + // on direct rendering the database view (user comes from clicking "add database") + if (selectedResourceKind === ResourceKind.Database) { + return DATABASES[0] as unknown as T; + } + }); + const [eventState, setEventState] = useState(); const selectedResource = resources.find(r => r.kind === selectedResourceKind); const views = useMemo(() => { @@ -82,16 +120,88 @@ export function DiscoverProvider( return addIndexToViews(selectedResource.views); }, [selectedResource.views, resourceState]); + const emitEvent = useCallback( + (status: DiscoverEventStepStatus, custom?: CustomEventInput) => { + const { id, currEventName, resource } = eventState; + + userEventService.captureDiscoverEvent({ + event: custom?.eventName || currEventName, + eventData: { + id, + resource, + autoDiscoverResourcesCount: custom?.autoDiscoverResourcesCount, + ...status, + }, + }); + }, + [eventState] + ); + + useEffect(() => { + const emitAbortOrSuccessEvent = () => { + if (eventState.currEventName === DiscoverEvent.Completed) { + emitEvent({ stepStatus: DiscoverEventStatus.Success }); + } else { + // TODO(lisa): this is temporary fill in as Application + // flow is not implemented yet and user can only abort + // on resource selection step. + if (selectedResourceKind === ResourceKind.Application) { + emitEvent( + { stepStatus: DiscoverEventStatus.Aborted }, + { eventName: DiscoverEvent.ResourceSelection } + ); + return; + } + emitEvent({ stepStatus: DiscoverEventStatus.Aborted }); + } + }; + + // Emit abort event upon refreshing, going to different route + // (eg: copy and paste url) from same page, or closing tab/browser. + // Does not capture unmounting edge cases which is handled + // with the unmount logic below. + window.addEventListener('beforeunload', emitAbortOrSuccessEvent); + + return () => { + // Emit abort event upon unmounting from going back or + // forward to a non-discover route or upon exiting from + // the exit prompt. + if (history.location.pathname !== cfg.routes.discover) { + emitAbortOrSuccessEvent(); + } + + window.removeEventListener('beforeunload', emitAbortOrSuccessEvent); + }; + }, [eventState, history.location.pathname, emitEvent]); + + useEffect(() => { + if (selectedResourceKind === ResourceKind.Database && !resourceState) { + // resourceState hasn't been loaded yet, this state is required to + // determine what type of database (engine/location) user + // selected to send the correct event. This state gets set when + // user selects a database (deployment type). + return; + } + updateEventState(); + + // Only run it once on init or when resource selection + // or resource state has changed. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedResourceKind, resourceState]); + function onSelectResource(kind: ResourceKind) { setSelectedResourceKind(kind); } - // nextStep takes the user to the next screen. - // The prop `numToIncrement` is used (>1) when we want to - // skip some number of steps. - // eg: particularly for Database flow, if there exists a - // database service, then we don't want to show the user - // the screen that lets them add a database server. + // nextStep takes the user to next screen and sends reporting events. + // The prop `numToIncrement` is used in the following ways: + // - numToIncrement === 0, will be interpreted as user intentionally + // skipping the current view, to go to the next view. + // - numToIncrement === 1 (default), will be interpreted as user finishing + // the current view and is ready to go next view. + // - numToIncrement > 1, will be interprested as skipping some steps FOR the user + // eg: for Database flow, if there exists a database service, then we don't want + // to show the user the screen that lets them add a database service. function nextStep(numToIncrement = 1) { // This function can be used in a way that HTML event // get passed in which isn't a valid number. @@ -99,10 +209,40 @@ export function DiscoverProvider( numToIncrement = 1; } - const nextView = findViewAtIndex(views, currentStep + numToIncrement); - + const numNextSteps = numToIncrement || 1; + const nextView = findViewAtIndex(views, currentStep + numNextSteps); if (nextView) { - setCurrentStep(currentStep + numToIncrement); + setCurrentStep(currentStep + numNextSteps); + setEventState({ + ...eventState, + currEventName: nextView.eventName, + manuallyEmitSuccessEvent: nextView.manuallyEmitSuccessEvent, + }); + } + + // Send reporting events: + + // Emit event for the current view. + // If user intentionally skipped the current step, then + // skipped event will be emitted, else success. + if (!numToIncrement) { + emitEvent({ stepStatus: DiscoverEventStatus.Skipped }); + } else if (!eventState.manuallyEmitSuccessEvent) { + emitEvent({ stepStatus: DiscoverEventStatus.Success }); + } + + // Whenever a numToIncrement is > 1, it means some steps (after the current view) + // are being skipped, which we should send events for. + if (numToIncrement > 1) { + for (let i = 1; i < numToIncrement; i++) { + const currView = findViewAtIndex(views, currentStep + i); + if (currView) { + emitEvent( + { stepStatus: DiscoverEventStatus.Skipped }, + { eventName: currView.eventName } + ); + } + } } } @@ -118,6 +258,63 @@ export function DiscoverProvider( setAgentMeta(meta); } + function emitErrorEvent(errorStr = '') { + emitEvent({ + stepStatus: DiscoverEventStatus.Error, + stepStatusError: errorStr, + }); + } + + // updateEventState is used when the Discover component updates in the following ways: + // - on initial render: sends the `start` event and will initialize the event state with + // the currently selected resource and create a unique ID that will tie the rest of + // the events that follow this `start` event. + // - on user updating `selectedResourceKind` (eg: server to kube) + // or `resourceState` (eg. postgres to mongo) which just updates the `eventState` + function updateEventState() { + const { eventName, manuallyEmitSuccessEvent } = findViewAtIndex( + views, + currentStep + ); + const resource = resourceKindToEventResource( + selectedResourceKind, + resourceState + ); + + // Init the `eventState` and send the `started` event only once. + if (!eventState) { + // Generates a v4 UUID using a cryptographically secure + // random number. + const id = crypto.randomUUID(); + + setEventState({ + id, + currEventName: eventName, + resource, + manuallyEmitSuccessEvent, + }); + userEventService.captureDiscoverEvent({ + event: DiscoverEvent.Started, + eventData: { + id, + stepStatus: DiscoverEventStatus.Success, + // Started event will be the ONLY event + // that won't expect a resource field. + resource: '' as any, + }, + }); + + return; + } + + setEventState({ + ...eventState, + currEventName: eventName, + resource, + manuallyEmitSuccessEvent, + }); + } + const value: DiscoverContextState = { agentMeta, currentStep, @@ -130,6 +327,9 @@ export function DiscoverProvider( setResourceState, updateAgentMeta, views, + emitErrorEvent, + emitEvent, + eventState, }; return ( diff --git a/web/packages/teleport/src/mocks/handlers.ts b/web/packages/teleport/src/mocks/handlers.ts index 769f9dd20b3..2ac3b29a136 100644 --- a/web/packages/teleport/src/mocks/handlers.ts +++ b/web/packages/teleport/src/mocks/handlers.ts @@ -31,4 +31,7 @@ export const handlersTeleport = [ }) ); }), + rest.post(cfg.api.captureUserEventPath, (req, res, ctx) => { + return res(ctx.status(200)); + }), ]; diff --git a/web/packages/teleport/src/services/agents/make.ts b/web/packages/teleport/src/services/agents/make.ts index f20cdf8208f..d2f457e4204 100644 --- a/web/packages/teleport/src/services/agents/make.ts +++ b/web/packages/teleport/src/services/agents/make.ts @@ -38,7 +38,7 @@ function makeTraces(traces: any): ConnectionDiagnosticTrace[] { } return traces.map(t => ({ - traceType: t.trace_type, + traceType: t.traceType, status: t.status?.toLowerCase(), details: t.details, error: t.error, diff --git a/web/packages/teleport/src/services/userEvent/types.ts b/web/packages/teleport/src/services/userEvent/types.ts index 427959909f7..06763cb05b0 100644 --- a/web/packages/teleport/src/services/userEvent/types.ts +++ b/web/packages/teleport/src/services/userEvent/types.ts @@ -16,3 +16,80 @@ export enum CaptureEvent { PreUserRecoveryCodesCopyClickEvent = 'tp.ui.recoveryCodesCopy.click', PreUserRecoveryCodesPrintClickEvent = 'tp.ui.recoveryCodesPrint.click', } + +export enum DiscoverEvent { + Started = 'tp.ui.discover.started', + ResourceSelection = 'tp.ui.discover.resourceSelection', + DeployService = 'tp.ui.discover.deployService', + DatabaseRegister = 'tp.ui.discover.database.register', + DatabaseConfigureMTLS = 'tp.ui.discover.database.configure.mtls', + DatabaseConfigureIAMPolicy = 'tp.ui.discover.database.configure.iampolicy', + DesktopActiveDirectoryToolsInstall = 'tp.ui.discover.desktop.activeDirectory.tools.install', + DesktopActiveDirectoryConfigure = 'tp.ui.discover.desktop.activeDirectory.configure', + AutoDiscoveredResources = 'tp.ui.discover.autoDiscoveredResources', + PrincipalsConfigure = 'tp.ui.discover.principals.configure', + TestConnection = 'tp.ui.discover.testConnection', + Completed = 'tp.ui.discover.completed', +} + +// DiscoverResource represents a resource type. +export enum DiscoverEventResource { + Server = 'DISCOVER_RESOURCE_SERVER', + Kubernetes = 'DISCOVER_RESOURCE_KUBERNETES', + DatabasePostgresSelfHosted = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED', + DatabaseMysqlSelfHosted = 'DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED', + DatabaseMongodbSelfHosted = 'DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED', + DatabasePostgresRds = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS', + DatabaseMysqlRds = 'DISCOVER_RESOURCE_DATABASE_MYSQL_RDS', + + DatabaseSqlServerRds = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS', + DatabasePostgresRedshift = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT', + + DatabaseSqlServerSelfHosted = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED', + DatabaseRedisSelfHosted = 'DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED', + + DatabasePostgresGcp = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP', + DatabaseMysqlGcp = 'DISCOVER_RESOURCE_DATABASE_MYSQL_GCP', + DatabaseSqlServerGcp = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP', + + ApplicationHttp = 'DISCOVER_RESOURCE_APPLICATION_HTTP', + ApplicationTcp = 'DISCOVER_RESOURCE_APPLICATION_TCP', + WindowsDesktop = 'DISCOVER_RESOURCE_WINDOWS_DESKTOP', +} + +export enum DiscoverEventStatus { + Success = 'DISCOVER_STATUS_SUCCESS', + Skipped = 'DISCOVER_STATUS_SKIPPED', + Error = 'DISCOVER_STATUS_ERROR', + Aborted = 'DISCOVER_STATUS_ABORTED', // user exits the wizard +} + +export type UserEvent = { + event: CaptureEvent; + alert?: string; +}; + +export type PreUserEvent = UserEvent & { + username: string; + mfaType?: string; + loginFlow?: string; +}; + +export type DiscoverEventRequest = Omit & { + event: DiscoverEvent; + eventData: DiscoverEventData; +}; + +export type DiscoverEventData = DiscoverEventStepStatus & { + id: string; + resource: DiscoverEventResource; + // AutoDiscoverResourcesCount is the number of + // auto-discovered resources in the Auto Discovering resources screen. + // This value is only considered for the 'tp.ui.discover.autoDiscoveredResources'. + autoDiscoverResourcesCount?: number; +}; + +export type DiscoverEventStepStatus = { + stepStatus: DiscoverEventStatus; + stepStatusError?: string; +}; diff --git a/web/packages/teleport/src/services/userEvent/userEvent.ts b/web/packages/teleport/src/services/userEvent/userEvent.ts index 363bc1da151..2090feb3c11 100644 --- a/web/packages/teleport/src/services/userEvent/userEvent.ts +++ b/web/packages/teleport/src/services/userEvent/userEvent.ts @@ -1,18 +1,7 @@ import api from 'teleport/services/api'; import cfg from 'teleport/config'; -import { CaptureEvent } from './types'; - -export type UserEvent = { - event: CaptureEvent; - alert?: string; -}; - -export type PreUserEvent = UserEvent & { - username: string; - mfaType?: string; - loginFlow?: string; -}; +import { UserEvent, PreUserEvent, DiscoverEventRequest } from './types'; export const userEventService = { captureUserEvent(userEvent: UserEvent) { @@ -32,4 +21,13 @@ export const userEventService = { body: JSON.stringify({ ...preUserEvent }), }); }, + + captureDiscoverEvent(event: DiscoverEventRequest) { + // using api.fetch instead of api.fetchJSON + // because we are not expecting a JSON response + void api.fetch(cfg.api.captureUserEventPath, { + method: 'POST', + body: JSON.stringify(event), + }); + }, };