diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index d2346a7997eee..6f915b2de4f3b 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -2806,7 +2806,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt return nil, trace.Wrap(err) } - unifiedResources = append(unifiedResources, ui.MakeServer(site.GetName(), r, logins)) + unifiedResources = append(unifiedResources, ui.MakeServer(site.GetName(), r, logins, enriched.RequiresRequest)) case types.DatabaseServer: if !hasFetchedDBUsersAndNames { dbNames, dbUsers, err = getDatabaseUsersAndNames(accessChecker) @@ -2815,7 +2815,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt } hasFetchedDBUsersAndNames = true } - db := ui.MakeDatabase(r.GetDatabase(), dbUsers, dbNames) + db := ui.MakeDatabase(r.GetDatabase(), dbUsers, dbNames, enriched.RequiresRequest) unifiedResources = append(unifiedResources, db) case types.AppServer: app := ui.MakeApp(r.GetApp(), ui.MakeAppsConfig{ @@ -2825,6 +2825,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt Identity: identity, UserGroupLookup: getUserGroupLookup(), Logger: h.log, + RequiresRequest: enriched.RequiresRequest, }) unifiedResources = append(unifiedResources, app) case types.AppServerOrSAMLIdPServiceProvider: @@ -2837,6 +2838,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt Identity: identity, UserGroupLookup: getUserGroupLookup(), Logger: h.log, + RequiresRequest: enriched.RequiresRequest, }) unifiedResources = append(unifiedResources, app) } else { @@ -2845,6 +2847,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt LocalProxyDNSName: h.proxyDNSName(), AppClusterName: site.GetName(), Identity: identity, + RequiresRequest: enriched.RequiresRequest, }) unifiedResources = append(unifiedResources, app) } @@ -2856,6 +2859,7 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt LocalProxyDNSName: h.proxyDNSName(), AppClusterName: site.GetName(), Identity: identity, + RequiresRequest: enriched.RequiresRequest, }) unifiedResources = append(unifiedResources, app) case types.WindowsDesktop: @@ -2864,12 +2868,12 @@ func (h *Handler) clusterUnifiedResourcesGet(w http.ResponseWriter, request *htt return nil, trace.Wrap(err) } - unifiedResources = append(unifiedResources, ui.MakeDesktop(r, logins)) + unifiedResources = append(unifiedResources, ui.MakeDesktop(r, logins, enriched.RequiresRequest)) case types.KubeCluster: - kube := ui.MakeKubeCluster(r, accessChecker) + kube := ui.MakeKubeCluster(r, accessChecker, enriched.RequiresRequest) unifiedResources = append(unifiedResources, kube) case types.KubeServer: - kube := ui.MakeKubeCluster(r.GetCluster(), accessChecker) + kube := ui.MakeKubeCluster(r.GetCluster(), accessChecker, enriched.RequiresRequest) unifiedResources = append(unifiedResources, kube) default: return nil, trace.Errorf("UI Resource has unknown type: %T", enriched) @@ -2926,7 +2930,7 @@ func (h *Handler) clusterNodesGet(w http.ResponseWriter, r *http.Request, p http return nil, trace.Wrap(err) } - uiServers = append(uiServers, ui.MakeServer(site.GetName(), server, logins)) + uiServers = append(uiServers, ui.MakeServer(site.GetName(), server, logins, false /* requiresRequest */)) } return listResourcesGetResponse{ diff --git a/lib/web/databases.go b/lib/web/databases.go index 7e05abc161626..78e3dbc397d8d 100644 --- a/lib/web/databases.go +++ b/lib/web/databases.go @@ -130,7 +130,7 @@ func (h *Handler) handleDatabaseCreate(w http.ResponseWriter, r *http.Request, p return nil, trace.Wrap(err) } - return ui.MakeDatabase(database, dbUsers, dbNames), nil + return ui.MakeDatabase(database, dbUsers, dbNames, false /* requiresRequest */), nil } // updateDatabaseRequest contains some updatable fields of a database resource. @@ -239,7 +239,7 @@ func (h *Handler) handleDatabaseUpdate(w http.ResponseWriter, r *http.Request, p return nil, trace.Wrap(err) } - return ui.MakeDatabase(database, nil /* dbUsers */, nil /* dbNames */), nil + return ui.MakeDatabase(database, nil /* dbUsers */, nil /* dbNames */, false /* requiresRequest */), nil } // databaseIAMPolicyResponse is the response type for handleDatabaseGetIAMPolicy. diff --git a/lib/web/integrations_awsoidc.go b/lib/web/integrations_awsoidc.go index 40034a9f4a79d..a4c89baec937f 100644 --- a/lib/web/integrations_awsoidc.go +++ b/lib/web/integrations_awsoidc.go @@ -527,7 +527,7 @@ func (h *Handler) awsOIDCListEC2(w http.ResponseWriter, r *http.Request, p httpr return nil, trace.Wrap(err) } - servers = append(servers, ui.MakeServer(h.auth.clusterName, s, logins)) + servers = append(servers, ui.MakeServer(h.auth.clusterName, s, logins, false /* requiresRequest */)) } return ui.AWSOIDCListEC2Response{ diff --git a/lib/web/servers.go b/lib/web/servers.go index 1543c5a96de34..62919e6194637 100644 --- a/lib/web/servers.go +++ b/lib/web/servers.go @@ -148,7 +148,7 @@ func (h *Handler) clusterDatabaseGet(w http.ResponseWriter, r *http.Request, p h return nil, trace.Wrap(err) } - return ui.MakeDatabase(database, dbUsers, dbNames), nil + return ui.MakeDatabase(database, dbUsers, dbNames, false /* requiresRequest */), nil } // clusterDatabaseServicesList returns a list of DatabaseServices (database agents) in a form the UI can present. @@ -209,7 +209,7 @@ func (h *Handler) clusterDesktopsGet(w http.ResponseWriter, r *http.Request, p h return nil, trace.Wrap(err) } - uiDesktops = append(uiDesktops, ui.MakeDesktop(desktop, logins)) + uiDesktops = append(uiDesktops, ui.MakeDesktop(desktop, logins, false /* requiresRequest */)) } return listResourcesGetResponse{ @@ -277,7 +277,7 @@ func (h *Handler) getDesktopHandle(w http.ResponseWriter, r *http.Request, p htt return nil, trace.Wrap(err) } - return ui.MakeDesktop(desktop, logins), nil + return ui.MakeDesktop(desktop, logins, false /* requiresRequest */), nil } // desktopIsActive checks if a desktop has an active session and returns a desktopIsActive. @@ -445,5 +445,5 @@ func (h *Handler) handleNodeCreate(w http.ResponseWriter, r *http.Request, p htt return nil, trace.Wrap(err) } - return ui.MakeServer(site.GetName(), server, logins), nil + return ui.MakeServer(site.GetName(), server, logins, false /* requiresRequest */), nil } diff --git a/lib/web/ui/app.go b/lib/web/ui/app.go index e5a9a87e940a8..376dad9069901 100644 --- a/lib/web/ui/app.go +++ b/lib/web/ui/app.go @@ -57,6 +57,8 @@ type App struct { UserGroups []UserGroupAndDescription `json:"userGroups,omitempty"` // SAMLApp if true, indicates that the app is a SAML Application (SAML IdP Service Provider) SAMLApp bool `json:"samlApp,omitempty"` + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool `json:"requiresRequest,omitempty"` } // UserGroupAndDescription is a user group name and its description. @@ -85,6 +87,8 @@ type MakeAppsConfig struct { UserGroupLookup map[string]types.UserGroup // Logger is a logger used for debugging while making an app Logger logrus.FieldLogger + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool } // MakeApp creates an application object for the WebUI. @@ -118,18 +122,19 @@ func MakeApp(app types.Application, c MakeAppsConfig) App { } resultApp := App{ - Kind: types.KindApp, - Name: app.GetName(), - Description: description, - URI: app.GetURI(), - PublicAddr: app.GetPublicAddr(), - Labels: labels, - ClusterID: c.AppClusterName, - FQDN: fqdn, - AWSConsole: app.IsAWSConsole(), - FriendlyName: types.FriendlyName(app), - UserGroups: userGroupAndDescriptions, - SAMLApp: false, + Kind: types.KindApp, + Name: app.GetName(), + Description: description, + URI: app.GetURI(), + PublicAddr: app.GetPublicAddr(), + Labels: labels, + ClusterID: c.AppClusterName, + FQDN: fqdn, + AWSConsole: app.IsAWSConsole(), + FriendlyName: types.FriendlyName(app), + UserGroups: userGroupAndDescriptions, + SAMLApp: false, + RequiresRequest: c.RequiresRequest, } if app.IsAWSConsole() { @@ -145,14 +150,15 @@ func MakeApp(app types.Application, c MakeAppsConfig) App { func MakeAppTypeFromSAMLApp(app types.SAMLIdPServiceProvider, c MakeAppsConfig) App { labels := makeLabels(app.GetAllLabels()) resultApp := App{ - Kind: types.KindApp, - Name: app.GetName(), - Description: "SAML Application", - PublicAddr: "", - Labels: labels, - ClusterID: c.AppClusterName, - FriendlyName: types.FriendlyName(app), - SAMLApp: true, + Kind: types.KindApp, + Name: app.GetName(), + Description: "SAML Application", + PublicAddr: "", + Labels: labels, + ClusterID: c.AppClusterName, + FriendlyName: types.FriendlyName(app), + SAMLApp: true, + RequiresRequest: c.RequiresRequest, } return resultApp diff --git a/lib/web/ui/server.go b/lib/web/ui/server.go index 6037c1540e6ae..cbd827e0b3528 100644 --- a/lib/web/ui/server.go +++ b/lib/web/ui/server.go @@ -59,6 +59,8 @@ type Server struct { SSHLogins []string `json:"sshLogins"` // AWS contains metadata for instances hosted in AWS. AWS *AWSMetadata `json:"aws,omitempty"` + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool `json:"requiresRequest,omitempty"` } // AWSMetadata describes the AWS metadata for instances hosted in AWS. @@ -102,21 +104,22 @@ func (s sortedLabels) Swap(i, j int) { } // MakeServer creates a server object for the web ui -func MakeServer(clusterName string, server types.Server, logins []string) Server { +func MakeServer(clusterName string, server types.Server, logins []string, requiresRequest bool) Server { serverLabels := server.GetStaticLabels() serverCmdLabels := server.GetCmdLabels() uiLabels := makeLabels(serverLabels, transformCommandLabels(serverCmdLabels)) uiServer := Server{ - Kind: server.GetKind(), - ClusterName: clusterName, - Labels: uiLabels, - Name: server.GetName(), - Hostname: server.GetHostname(), - Addr: server.GetAddr(), - Tunnel: server.GetUseTunnel(), - SubKind: server.GetSubKind(), - SSHLogins: logins, + Kind: server.GetKind(), + ClusterName: clusterName, + Labels: uiLabels, + Name: server.GetName(), + Hostname: server.GetHostname(), + Addr: server.GetAddr(), + Tunnel: server.GetUseTunnel(), + SubKind: server.GetSubKind(), + RequiresRequest: requiresRequest, + SSHLogins: logins, } if server.GetSubKind() == types.SubKindOpenSSHEICENode { @@ -156,20 +159,23 @@ type KubeCluster struct { KubeUsers []string `json:"kubernetes_users"` // KubeGroups is the list of allowed Kubernetes RBAC groups that the user can impersonate. KubeGroups []string `json:"kubernetes_groups"` + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool `json:"requiresRequest,omitempty"` } // MakeKubeCluster creates a kube cluster object for the web ui -func MakeKubeCluster(cluster types.KubeCluster, accessChecker services.AccessChecker) KubeCluster { +func MakeKubeCluster(cluster types.KubeCluster, accessChecker services.AccessChecker, requiresRequest bool) KubeCluster { staticLabels := cluster.GetStaticLabels() dynamicLabels := cluster.GetDynamicLabels() uiLabels := makeLabels(staticLabels, transformCommandLabels(dynamicLabels)) kubeUsers, kubeGroups := getAllowedKubeUsersAndGroupsForCluster(accessChecker, cluster) return KubeCluster{ - Kind: cluster.GetKind(), - Name: cluster.GetName(), - Labels: uiLabels, - KubeUsers: kubeUsers, - KubeGroups: kubeGroups, + Kind: cluster.GetKind(), + Name: cluster.GetName(), + Labels: uiLabels, + KubeUsers: kubeUsers, + RequiresRequest: requiresRequest, + KubeGroups: kubeGroups, } } @@ -330,6 +336,8 @@ type Database struct { DatabaseNames []string `json:"database_names,omitempty"` // AWS contains AWS specific fields. AWS *AWS `json:"aws,omitempty"` + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool `json:"requiresRequest,omitempty"` } // AWS contains AWS specific fields. @@ -347,7 +355,7 @@ const ( ) // MakeDatabase creates database objects. -func MakeDatabase(database types.Database, dbUsers, dbNames []string) Database { +func MakeDatabase(database types.Database, dbUsers, dbNames []string, requiresRequest bool) Database { uiLabels := makeLabels(database.GetAllLabels()) db := Database{ @@ -381,7 +389,7 @@ func MakeDatabase(database types.Database, dbUsers, dbNames []string) Database { func MakeDatabases(databases []*types.DatabaseV3, dbUsers, dbNames []string) []Database { uiServers := make([]Database, 0, len(databases)) for _, database := range databases { - db := MakeDatabase(database, dbUsers, dbNames) + db := MakeDatabase(database, dbUsers, dbNames, false /* requiresRequest */) uiServers = append(uiServers, db) } @@ -431,10 +439,12 @@ type Desktop struct { HostID string `json:"host_id"` // Logins is the list of logins this user can use on this desktop. Logins []string `json:"logins"` + // RequireRequest indicates if a returned resource is only accessible after an access request + RequiresRequest bool `json:"requiresRequest,omitempty"` } // MakeDesktop converts a desktop from its API form to a type the UI can display. -func MakeDesktop(windowsDesktop types.WindowsDesktop, logins []string) Desktop { +func MakeDesktop(windowsDesktop types.WindowsDesktop, logins []string, requiresRequest bool) Desktop { // stripRdpPort strips the default rdp port from an ip address since it is unimportant to display stripRdpPort := func(addr string) string { splitAddr := strings.Split(addr, ":") @@ -447,13 +457,14 @@ func MakeDesktop(windowsDesktop types.WindowsDesktop, logins []string) Desktop { uiLabels := makeLabels(windowsDesktop.GetAllLabels()) return Desktop{ - Kind: windowsDesktop.GetKind(), - OS: constants.WindowsOS, - Name: windowsDesktop.GetName(), - Addr: stripRdpPort(windowsDesktop.GetAddr()), - Labels: uiLabels, - HostID: windowsDesktop.GetHostID(), - Logins: logins, + Kind: windowsDesktop.GetKind(), + OS: constants.WindowsOS, + Name: windowsDesktop.GetName(), + Addr: stripRdpPort(windowsDesktop.GetAddr()), + Labels: uiLabels, + HostID: windowsDesktop.GetHostID(), + Logins: logins, + RequiresRequest: requiresRequest, } } diff --git a/lib/web/ui/server_test.go b/lib/web/ui/server_test.go index 97e47f3e668f7..a8f6c76997a66 100644 --- a/lib/web/ui/server_test.go +++ b/lib/web/ui/server_test.go @@ -406,7 +406,7 @@ func TestMakeServersHiddenLabels(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for i, srv := range tc.servers { - server := MakeServer(tc.clusterName, srv, nil) + server := MakeServer(tc.clusterName, srv, nil, false) assert.Equal(t, tc.expectedLabels[i], server.Labels) } }) @@ -430,7 +430,7 @@ func TestMakeDatabaseHiddenLabels(t *testing.T) { }, } - outputDb := MakeDatabase(inputDb, nil, nil) + outputDb := MakeDatabase(inputDb, nil, nil, false) require.Equal(t, []Label{ { @@ -451,7 +451,7 @@ func TestMakeDesktopHiddenLabel(t *testing.T) { ) require.NoError(t, err) - desktop := MakeDesktop(windowsDesktop, nil) + desktop := MakeDesktop(windowsDesktop, nil, false) labels := []Label{ { Name: "label3", @@ -583,7 +583,7 @@ func TestSortedLabels(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for i, srv := range tc.servers { - server := MakeServer(tc.clusterName, srv, nil) + server := MakeServer(tc.clusterName, srv, nil, false) assert.Equal(t, tc.expectedLabels[i], server.Labels) } }) diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index 67b3e652147d0..e05ac862b0986 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -203,7 +203,7 @@ const cfg = { passwordTokenPath: '/v1/webapi/users/password/token/:tokenId?', changeUserPasswordPath: '/v1/webapi/users/password', unifiedResourcesPath: - '/v1/webapi/sites/:clusterId/resources?searchAsRoles=:searchAsRoles?&limit=:limit?&startKey=:startKey?&kinds=:kinds?&query=:query?&search=:search?&sort=:sort?&pinnedOnly=:pinnedOnly?', + '/v1/webapi/sites/:clusterId/resources?searchAsRoles=:searchAsRoles?&limit=:limit?&startKey=:startKey?&kinds=:kinds?&query=:query?&search=:search?&sort=:sort?&pinnedOnly=:pinnedOnly?&includeRequestable=:includeRequestable?', nodesPath: '/v1/webapi/sites/:clusterId/nodes?searchAsRoles=:searchAsRoles?&limit=:limit?&startKey=:startKey?&query=:query?&search=:search?&sort=:sort?', nodesPathNoParams: '/v1/webapi/sites/:clusterId/nodes', @@ -1185,6 +1185,7 @@ export interface UrlResourcesParams { startKey?: string; searchAsRoles?: 'yes' | ''; pinnedOnly?: boolean; + includeRequestable?: boolean; // TODO(bl-nero): Remove this once filters are expressed as advanced search. kinds?: string[]; } diff --git a/web/packages/teleport/src/generateResourcePath.ts b/web/packages/teleport/src/generateResourcePath.ts index 863b0b488256b..92d1d16beb166 100644 --- a/web/packages/teleport/src/generateResourcePath.ts +++ b/web/packages/teleport/src/generateResourcePath.ts @@ -49,7 +49,8 @@ export default function generateResourcePath( .replace(':searchAsRoles?', processedParams.searchAsRoles || '') .replace(':sort?', processedParams.sort || '') .replace(':kinds?', processedParams.kinds || '') - .replace(':pinnedOnly?', processedParams.pinnedOnly || ''); + .replace(':pinnedOnly?', processedParams.pinnedOnly || '') + .replace(':includeRequestable?', processedParams.includeRequestable || ''); return output; } diff --git a/web/packages/teleport/src/services/apps/makeApps.ts b/web/packages/teleport/src/services/apps/makeApps.ts index d6eb4b9ccb66a..a292c004fdff2 100644 --- a/web/packages/teleport/src/services/apps/makeApps.ts +++ b/web/packages/teleport/src/services/apps/makeApps.ts @@ -32,6 +32,7 @@ export default function makeApp(json: any): App { awsConsole = false, samlApp = false, friendlyName = '', + requiresRequest, } = json; const canCreateUrl = fqdn && clusterId && publicAddr; @@ -81,5 +82,6 @@ export default function makeApp(json: any): App { userGroups, samlApp, samlAppSsoUrl, + requiresRequest, }; } diff --git a/web/packages/teleport/src/services/apps/types.ts b/web/packages/teleport/src/services/apps/types.ts index 3bb928a3065ae..ae61f6c3d7856 100644 --- a/web/packages/teleport/src/services/apps/types.ts +++ b/web/packages/teleport/src/services/apps/types.ts @@ -33,6 +33,7 @@ export interface App { fqdn: string; awsRoles: AwsRole[]; awsConsole: boolean; + requiresRequest?: boolean; isCloudOrTcpEndpoint?: boolean; // addrWithProtocol can either be a public address or // if public address wasn't defined, fallback to uri diff --git a/web/packages/teleport/src/services/databases/makeDatabase.ts b/web/packages/teleport/src/services/databases/makeDatabase.ts index 32f70f65b826b..940bd55ed9621 100644 --- a/web/packages/teleport/src/services/databases/makeDatabase.ts +++ b/web/packages/teleport/src/services/databases/makeDatabase.ts @@ -21,7 +21,7 @@ import { formatDatabaseInfo } from 'shared/services/databases'; import { Aws, Database, DatabaseService } from './types'; export function makeDatabase(json: any): Database { - const { name, desc, protocol, type, aws } = json; + const { name, desc, protocol, type, aws, requiresRequest } = json; const labels = json.labels || []; @@ -52,6 +52,7 @@ export function makeDatabase(json: any): Database { users: json.database_users || [], hostname: json.hostname, aws: madeAws, + requiresRequest, }; } diff --git a/web/packages/teleport/src/services/databases/types.ts b/web/packages/teleport/src/services/databases/types.ts index ad538455d4d0d..2247532da0b7d 100644 --- a/web/packages/teleport/src/services/databases/types.ts +++ b/web/packages/teleport/src/services/databases/types.ts @@ -47,6 +47,7 @@ export interface Database { users?: string[]; hostname: string; aws?: Aws; + requiresRequest?: boolean; } export type DatabasesResponse = { diff --git a/web/packages/teleport/src/services/desktops/makeDesktop.ts b/web/packages/teleport/src/services/desktops/makeDesktop.ts index 33ff74107766a..ca21d97213703 100644 --- a/web/packages/teleport/src/services/desktops/makeDesktop.ts +++ b/web/packages/teleport/src/services/desktops/makeDesktop.ts @@ -19,7 +19,7 @@ import type { Desktop, WindowsDesktopService } from './types'; export function makeDesktop(json): Desktop { - const { os, name, addr, host_id } = json; + const { os, name, addr, host_id, requiresRequest } = json; const labels = json.labels || []; const logins = json.logins || []; @@ -32,6 +32,7 @@ export function makeDesktop(json): Desktop { labels, host_id, logins, + requiresRequest, }; } diff --git a/web/packages/teleport/src/services/desktops/types.ts b/web/packages/teleport/src/services/desktops/types.ts index ab7149f3b66a2..f48b81d397eb2 100644 --- a/web/packages/teleport/src/services/desktops/types.ts +++ b/web/packages/teleport/src/services/desktops/types.ts @@ -34,6 +34,7 @@ export type Desktop = { host_id?: string; host_addr?: string; + requiresRequest?: boolean; }; // DesktopService is a Windows Desktop Service. diff --git a/web/packages/teleport/src/services/kube/makeKube.ts b/web/packages/teleport/src/services/kube/makeKube.ts index 101309b13ba2e..7831cd097fc21 100644 --- a/web/packages/teleport/src/services/kube/makeKube.ts +++ b/web/packages/teleport/src/services/kube/makeKube.ts @@ -19,7 +19,7 @@ import { Kube } from './types'; export default function makeKube(json): Kube { - const { name } = json; + const { name, requiresRequest } = json; const labels = json.labels || []; return { @@ -28,5 +28,6 @@ export default function makeKube(json): Kube { labels, users: json.kubernetes_users || [], groups: json.kubernetes_groups || [], + requiresRequest, }; } diff --git a/web/packages/teleport/src/services/kube/types.ts b/web/packages/teleport/src/services/kube/types.ts index 859bd92b682ee..4925517ef86d7 100644 --- a/web/packages/teleport/src/services/kube/types.ts +++ b/web/packages/teleport/src/services/kube/types.ts @@ -23,4 +23,5 @@ export interface Kube { labels: ResourceLabel[]; users?: string[]; groups?: string[]; + requiresRequest?: boolean; } diff --git a/web/packages/teleport/src/services/nodes/makeNode.ts b/web/packages/teleport/src/services/nodes/makeNode.ts index b77fc20b7cb98..43c631e52240c 100644 --- a/web/packages/teleport/src/services/nodes/makeNode.ts +++ b/web/packages/teleport/src/services/nodes/makeNode.ts @@ -20,8 +20,18 @@ import { Node, AwsMetadata } from './types'; export default function makeNode(json: any): Node { json = json ?? {}; - const { id, siteId, subKind, hostname, addr, tunnel, tags, sshLogins, aws } = - json; + const { + id, + siteId, + subKind, + hostname, + addr, + tunnel, + tags, + sshLogins, + aws, + requiresRequest, + } = json; return { kind: 'node', @@ -32,6 +42,7 @@ export default function makeNode(json: any): Node { labels: tags ?? [], addr, tunnel, + requiresRequest, sshLogins: sshLogins ?? [], awsMetadata: aws ? makeAwsMetadata(aws) : undefined, }; diff --git a/web/packages/teleport/src/services/nodes/nodes.test.ts b/web/packages/teleport/src/services/nodes/nodes.test.ts index 74b6d09fe91d6..948e88228ba5d 100644 --- a/web/packages/teleport/src/services/nodes/nodes.test.ts +++ b/web/packages/teleport/src/services/nodes/nodes.test.ts @@ -36,6 +36,7 @@ test('correct formatting of nodes fetch response', async () => { tunnel: false, sshLogins: ['root'], subKind: 'teleport', + requiresRequest: true, }, ], startKey: mockResponse.startKey, @@ -78,6 +79,7 @@ const mockResponse = { tunnel: false, sshLogins: ['root'], subKind: 'teleport', + requiresRequest: true, }, ], startKey: 'mockKey', diff --git a/web/packages/teleport/src/services/nodes/types.ts b/web/packages/teleport/src/services/nodes/types.ts index 0bc0e32519783..41c385c101a94 100644 --- a/web/packages/teleport/src/services/nodes/types.ts +++ b/web/packages/teleport/src/services/nodes/types.ts @@ -33,6 +33,7 @@ export interface Node { subKind: NodeSubKind; sshLogins: string[]; awsMetadata?: AwsMetadata; + requiresRequest?: boolean; } export interface BashCommand { diff --git a/web/packages/teleport/src/services/userGroups/types.ts b/web/packages/teleport/src/services/userGroups/types.ts index 050b185399ba1..4f7304aaed724 100644 --- a/web/packages/teleport/src/services/userGroups/types.ts +++ b/web/packages/teleport/src/services/userGroups/types.ts @@ -31,6 +31,9 @@ export type UserGroup = { friendlyName?: string; // Applications is a list of associated applications. applications?: ApplicationAndFriendlyName[]; + // userGroups won't ever have this flag, but the key is added here + // so it can appear on the common 'UnifiedResource' type + requiresRequest?: false; }; export type ApplicationAndFriendlyName = {