Skip to content

Commit ed076d7

Browse files
committed
[code] fix #4529: serve each webview from own origin
decoupled from workpace origin (also extension host origin)
1 parent a061798 commit ed076d7

File tree

14 files changed

+271
-83
lines changed

14 files changed

+271
-83
lines changed

chart/templates/ws-manager-configmap.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ data:
6161
},
6262
"heartbeatInterval": "30s",
6363
"hostURL": "https://{{ $.Values.hostname }}",
64+
"workspaceClusterHost": "ws{{- if $gp.installation.shortname -}}-{{ $.Values.installation.shortname }}{{- end -}}.{{ $.Values.hostname }}",
6465
"initProbe": {
6566
"timeout": "1s"
6667
},

components/ide/code/leeway.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ RUN curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh |
4242
&& npm install -g yarn node-gyp
4343
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
4444

45-
ENV GP_CODE_COMMIT a17670ba5af14e0faf3a6927983468d28fda235b
45+
ENV GP_CODE_COMMIT 6cf68cedd9ab62af8e426a364d97ed206bbe0a02
4646
RUN mkdir gp-code \
4747
&& cd gp-code \
4848
&& git init \

components/proxy/conf/Caddyfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ https://*.*.{$GITPOD_DOMAIN} {
236236
}
237237
}
238238

239+
# remove (webview-|browser-|extensions-) after Theia removed and new VS Code is used by all workspaces
239240
@workspace_port header_regexp host Host ^(webview-|browser-|extensions-)?(?P<workspacePort>[0-9]{2,5})-(?P<workspaceID>[a-z0-9][0-9a-z\-]+).ws(?P<location>-[a-z0-9]+)?.{$GITPOD_DOMAIN}
240241
handle @workspace_port {
241242
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
@@ -248,6 +249,7 @@ https://*.*.{$GITPOD_DOMAIN} {
248249
}
249250
}
250251

252+
# remove (webview-|browser-|extensions-) after Theia removed and new VS Code is used by all workspaces
251253
@workspace header_regexp host Host ^(webview-|browser-|extensions-)?(?P<workspaceID>[a-z0-9][0-9a-z\-]+).ws(?P<location>-[a-z0-9]+)?.{$GITPOD_DOMAIN}
252254
handle @workspace {
253255
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
@@ -259,6 +261,17 @@ https://*.*.{$GITPOD_DOMAIN} {
259261
}
260262
}
261263

264+
# foreign content origin should be decoupled from the workspace (port) origin but the workspace (port) prefix should be the path root for routing
265+
@foreign_content header_regexp host Host ^(.*)(foreign).ws(-[a-z0-9]+)?.{$GITPOD_DOMAIN}
266+
handle @foreign_content {
267+
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
268+
import workspace_transport
269+
import upstream_headers
270+
271+
header_up X-WSProxy-Host {http.request.host}
272+
}
273+
}
274+
262275
respond "Not found" 404
263276
}
264277

components/supervisor-api/go/info.pb.go

Lines changed: 35 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/supervisor-api/info.proto

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,7 @@ message WorkspaceInfoResponse {
6565
}
6666
// repository is a repository from which this workspace was created
6767
Repository repository = 10;
68+
69+
// workspace_cluster_host provides the cluster host under which this workspace is served, e.g. ws-eu11.gitpod.io
70+
string workspace_cluster_host = 11;
6871
}

components/supervisor/pkg/supervisor/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ type WorkspaceConfig struct {
205205

206206
// WorkspaceContext is a context for this workspace
207207
WorkspaceContext string `env:"GITPOD_WORKSPACE_CONTEXT"`
208+
209+
// WorkspaceClusterHost is a host under which this workspace is served, e.g. ws-eu11.gitpod.io
210+
WorkspaceClusterHost string `env:"GITPOD_WORKSPACE_CLUSTER_HOST"`
208211
}
209212

210213
// WorkspaceGitpodToken is a list of tokens that should be added to supervisor's token service

components/supervisor/pkg/supervisor/services.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -585,11 +585,12 @@ func (is *InfoService) RegisterREST(mux *runtime.ServeMux, grpcEndpoint string)
585585
// WorkspaceInfo provides information about the workspace
586586
func (is *InfoService) WorkspaceInfo(context.Context, *api.WorkspaceInfoRequest) (*api.WorkspaceInfoResponse, error) {
587587
resp := &api.WorkspaceInfoResponse{
588-
CheckoutLocation: is.cfg.RepoRoot,
589-
InstanceId: is.cfg.WorkspaceInstanceID,
590-
WorkspaceId: is.cfg.WorkspaceID,
591-
GitpodHost: is.cfg.GitpodHost,
592-
WorkspaceContextUrl: is.cfg.WorkspaceContextURL,
588+
CheckoutLocation: is.cfg.RepoRoot,
589+
InstanceId: is.cfg.WorkspaceInstanceID,
590+
WorkspaceId: is.cfg.WorkspaceID,
591+
GitpodHost: is.cfg.GitpodHost,
592+
WorkspaceContextUrl: is.cfg.WorkspaceContextURL,
593+
WorkspaceClusterHost: is.cfg.WorkspaceClusterHost,
593594
}
594595

595596
commit, err := is.cfg.getCommit()

components/ws-manager/pkg/manager/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ type Configuration struct {
7979
WorkspaceDaemon WorkspaceDaemonConfiguration `json:"wsdaemon"`
8080
// RegistryFacadeHost is the host (possibly including port) on which the registry facade resolves
8181
RegistryFacadeHost string `json:"registryFacadeHost"`
82+
// Cluster host under which workspaces are served, e.g. ws-eu11.gitpod.io
83+
WorkspaceClusterHost string `json:"workspaceClusterHost"`
8284
}
8385

8486
// AllContainerConfiguration contains the configuration for all container in a workspace pod

components/ws-manager/pkg/manager/create.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,9 @@ func (m *Manager) createWorkspaceEnvironment(startContext *startWorkspaceContext
512512
result = append(result, corev1.EnvVar{Name: "THEIA_WORKSPACE_ROOT", Value: getWorkspaceRelativePath(spec.WorkspaceLocation)})
513513
result = append(result, corev1.EnvVar{Name: "GITPOD_HOST", Value: m.Config.GitpodHostURL})
514514
result = append(result, corev1.EnvVar{Name: "GITPOD_WORKSPACE_URL", Value: startContext.WorkspaceURL})
515+
result = append(result, corev1.EnvVar{Name: "GITPOD_WORKSPACE_CLUSTER_HOST", Value: m.Config.WorkspaceClusterHost})
515516
result = append(result, corev1.EnvVar{Name: "THEIA_SUPERVISOR_ENDPOINT", Value: fmt.Sprintf(":%d", startContext.SupervisorPort)})
517+
// TODO(ak) remove THEIA_WEBVIEW_EXTERNAL_ENDPOINT and THEIA_MINI_BROWSER_HOST_PATTERN when Theia is removed
516518
result = append(result, corev1.EnvVar{Name: "THEIA_WEBVIEW_EXTERNAL_ENDPOINT", Value: "webview-{{hostname}}"})
517519
result = append(result, corev1.EnvVar{Name: "THEIA_MINI_BROWSER_HOST_PATTERN", Value: "browser-{{hostname}}"})
518520

components/ws-proxy/pkg/proxy/pass.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"syscall"
1414
"time"
1515

16+
"github.com/gorilla/mux"
1617
"github.com/sirupsen/logrus"
1718
"golang.org/x/xerrors"
1819

@@ -187,3 +188,22 @@ func withXFrameOptionsFilter() proxyPassOpt {
187188
})
188189
}
189190
}
191+
192+
type workspaceTransport struct {
193+
transport http.RoundTripper
194+
}
195+
196+
func (t *workspaceTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
197+
vars := mux.Vars(req)
198+
if vars[foreignPathIdentifier] != "" {
199+
req = req.Clone(req.Context())
200+
req.URL.Path = vars[foreignPathIdentifier]
201+
}
202+
return t.transport.RoundTrip(req)
203+
}
204+
205+
func withWorkspaceTransport() proxyPassOpt {
206+
return func(h *proxyPassConfig) {
207+
h.Transport = &workspaceTransport{h.Transport}
208+
}
209+
}

components/ws-proxy/pkg/proxy/routes.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ func installWorkspaceRoutes(r *mux.Router, config *RouteHandlerConfig, ip Worksp
104104
routes.HandleDirectSupervisorRoute(r.PathPrefix("/_supervisor"), true)
105105

106106
routes.HandleDirectIDERoute(r.MatcherFunc(func(req *http.Request, m *mux.RouteMatch) bool {
107-
return m.Vars != nil && m.Vars[foreignOriginPrefix] != ""
107+
// this handles all foreign (none-IDE) content
108+
return m.Vars != nil && m.Vars[foreignOriginIdentifier] != ""
108109
}))
109110

110111
routes.HandleRoot(r.NewRoute())
@@ -132,7 +133,7 @@ func (ir *ideRoutes) HandleDirectIDERoute(route *mux.Route) {
132133
r.Use(ir.Config.WorkspaceAuthHandler)
133134
r.Use(ir.workspaceMustExistHandler)
134135

135-
r.NewRoute().HandlerFunc(proxyPass(ir.Config, workspacePodResolver))
136+
r.NewRoute().HandlerFunc(proxyPass(ir.Config, workspacePodResolver, withWorkspaceTransport()))
136137
}
137138

138139
func (ir *ideRoutes) HandleDirectSupervisorRoute(route *mux.Route, authenticated bool) {
@@ -323,6 +324,7 @@ func installWorkspacePortRoutes(r *mux.Router, config *RouteHandlerConfig) error
323324
workspacePodPortResolver,
324325
withHTTPErrorHandler(showPortNotFoundPage),
325326
withXFrameOptionsFilter(),
327+
withWorkspaceTransport(),
326328
)(rw, r)
327329
},
328330
)

components/ws-proxy/pkg/proxy/routes_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,26 @@ func TestRoutes(t *testing.T) {
580580
Body: "blobserve hit: /blobserve/gitpod-io/supervisor:latest/main.js\nreadOnly: true\n",
581581
},
582582
},
583+
{
584+
Desc: "extensions route GET",
585+
Request: modifyRequest(httptest.NewRequest("GET", "https://extensions-foreign.test-domain.com/"+workspaces[0].WorkspaceID+"/extensions.js", nil),
586+
addHostHeader,
587+
addHeader("Origin", config.GitpodInstallation.HostName),
588+
addOwnerToken(workspaces[0].InstanceID, workspaces[0].Auth.OwnerToken),
589+
),
590+
Expectation: Expectation{
591+
Status: http.StatusOK,
592+
Header: http.Header{
593+
"Access-Control-Allow-Credentials": {"true"},
594+
"Access-Control-Allow-Origin": {"test-domain.com"},
595+
"Access-Control-Expose-Headers": {"Authorization"},
596+
"Content-Length": {"30"},
597+
"Content-Type": {"text/plain; charset=utf-8"},
598+
"Vary": {"Accept-Encoding"},
599+
},
600+
Body: "workspace hit: /extensions.js\n",
601+
},
602+
},
583603
}
584604

585605
log.Init("ws-proxy-test", "", false, true)

0 commit comments

Comments
 (0)