Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions lib/web/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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{
Expand All @@ -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:
Expand All @@ -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 {
Expand All @@ -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)
}
Expand All @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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{
Expand Down
4 changes: 2 additions & 2 deletions lib/web/databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion lib/web/integrations_awsoidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
8 changes: 4 additions & 4 deletions lib/web/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
46 changes: 26 additions & 20 deletions lib/web/ui/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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() {
Expand All @@ -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
Expand Down
63 changes: 37 additions & 26 deletions lib/web/ui/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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.
Expand All @@ -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{
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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, ":")
Expand All @@ -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,
}
}

Expand Down
8 changes: 4 additions & 4 deletions lib/web/ui/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
})
Expand All @@ -430,7 +430,7 @@ func TestMakeDatabaseHiddenLabels(t *testing.T) {
},
}

outputDb := MakeDatabase(inputDb, nil, nil)
outputDb := MakeDatabase(inputDb, nil, nil, false)

require.Equal(t, []Label{
{
Expand All @@ -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",
Expand Down Expand Up @@ -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)
}
})
Expand Down
3 changes: 2 additions & 1 deletion web/packages/teleport/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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[];
}
Expand Down
Loading