Skip to content

Commit 411c0f2

Browse files
committed
ui: show tenant dropdown in insecure mode when multiple tenants exist
Previously, the tenant dropdown would not appear in insecure mode because it required a tenant cookie to be set, which only happens after authentication. This change modifies the dropdown logic to show when running in insecure mode and the virtual_clusters endpoint returns more than one tenant. In insecure mode, the dropdown now displays "default" when no tenant cookie is set, allowing users to select from available virtual clusters without requiring authentication. Release note (ui change): The tenant dropdown now appears in insecure mode when multiple virtual clusters are available. Epic: none.
1 parent 802ecdc commit 411c0f2

File tree

4 files changed

+55
-7
lines changed

4 files changed

+55
-7
lines changed

pkg/server/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,7 @@ func NewServer(cfg Config, stopper *stop.Stopper) (serverctl.ServerStartupInterf
13031303
tenantCapabilitiesWatcher,
13041304
cfg.DisableSQLServer,
13051305
cfg.BaseConfig.DisableTLSForHTTP,
1306+
cfg.Insecure,
13061307
)
13071308
drain.serverCtl = sc
13081309

pkg/server/server_controller.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ type serverController struct {
100100

101101
disableTLSForHTTP bool
102102

103+
insecure bool
104+
103105
mu struct {
104106
syncutil.RWMutex
105107

@@ -136,6 +138,7 @@ func newServerController(
136138
watcher *tenantcapabilitieswatcher.Watcher,
137139
disableSQLServer bool,
138140
disableTLSForHTTP bool,
141+
insecure bool,
139142
) *serverController {
140143
c := &serverController{
141144
AmbientContext: ambientCtx,
@@ -150,6 +153,7 @@ func newServerController(
150153
drainCh: make(chan struct{}),
151154
disableSQLServer: disableSQLServer,
152155
disableTLSForHTTP: disableTLSForHTTP,
156+
insecure: insecure,
153157
}
154158
c.orchestrator = newChannelOrchestrator(parentStopper, c)
155159
c.mu.servers = map[roachpb.TenantName]*serverState{

pkg/server/server_controller_http.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package server
77

88
import (
99
"bytes"
10+
"encoding/json"
1011
"io"
1112
"net/http"
1213
"strconv"
@@ -53,6 +54,26 @@ var ServerHTTPBasePath = settings.RegisterStringSetting(
5354
settings.WithPublic,
5455
)
5556

57+
func (c *serverController) insecureVirtualClusterList(w http.ResponseWriter, r *http.Request) {
58+
tenantNames := c.getCurrentTenantNames()
59+
tenants := make([]string, len(tenantNames))
60+
for i, name := range tenantNames {
61+
tenants[i] = string(name)
62+
}
63+
64+
resp := &virtualClustersResp{
65+
VirtualClusters: tenants,
66+
}
67+
respBytes, err := json.Marshal(resp)
68+
if err != nil {
69+
http.Error(w, "unable to marshal virtual clusters JSON", http.StatusInternalServerError)
70+
return
71+
}
72+
if _, err := w.Write(respBytes); err != nil {
73+
log.Errorf(r.Context(), "unable to write virtual clusters response: %s", err.Error())
74+
}
75+
}
76+
5677
// httpMux redirects incoming HTTP requests to the server selected by
5778
// the special HTTP request header.
5879
// If no tenant is specified, the default tenant is used.
@@ -78,6 +99,13 @@ func (c *serverController) httpMux(w http.ResponseWriter, r *http.Request) {
7899
c.attemptLogoutFromAllTenants().ServeHTTP(w, r)
79100
return
80101
}
102+
if c.insecure && r.URL.Path == virtualClustersPath {
103+
// If the insecure flag is set, the virtual clusters endpoint should just
104+
// return all tennants instead of delegating to a tenant server to read the
105+
// auth cookie which doesn't exist.
106+
c.insecureVirtualClusterList(w, r)
107+
return
108+
}
81109
tenantName := getTenantNameFromHTTPRequest(c.st, r)
82110
noFallback := false
83111
if noFallbackValue := r.URL.Query().Get(NoFallbackParam); noFallbackValue != "" {

pkg/ui/workspaces/db-console/src/views/app/components/tenantDropdown/tenantDropdown.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import React from "react";
77

88
import { getCookieValue, setCookie } from "src/redux/cookies";
99
import { isSystemTenant } from "src/redux/tenants";
10+
import { getDataFromServer } from "src/util/dataFromServer";
1011

1112
import ErrorBoundary from "../errorMessage/errorBoundary";
1213

@@ -76,22 +77,36 @@ export default class TenantDropdown extends React.Component<
7677
}
7778

7879
render() {
79-
if (
80-
!this.state.currentTenant ||
81-
(this.state.virtualClusters?.length < 2 &&
82-
isSystemTenant(this.state.currentTenant))
83-
) {
84-
return null;
80+
const dataFromServer = getDataFromServer();
81+
const isInsecure = dataFromServer.Insecure;
82+
// In insecure mode, show dropdown if there are >1 virtual clusters
83+
if (isInsecure) {
84+
if (this.state.virtualClusters?.length <= 1) {
85+
return null;
86+
}
87+
} else {
88+
// In secure mode, use the original logic
89+
if (
90+
!this.state.currentTenant ||
91+
(this.state.virtualClusters?.length < 2 &&
92+
isSystemTenant(this.state.currentTenant))
93+
) {
94+
return null;
95+
}
8596
}
8697

98+
// In insecure mode, show "default" if no tenant is set
99+
const displayTenant =
100+
this.state.currentTenant || (isInsecure ? "default" : "");
101+
87102
return (
88103
<ErrorBoundary>
89104
<Dropdown
90105
items={this.createDropdownItems()}
91106
onChange={(tenantID: string) => this.onTenantChange(tenantID)}
92107
>
93108
<div className="virtual-cluster-selected">
94-
{"Virtual cluster: " + this.state.currentTenant}
109+
{"Virtual cluster: " + displayTenant}
95110
</div>
96111
</Dropdown>
97112
</ErrorBoundary>

0 commit comments

Comments
 (0)