mirror of https://github.com/coder/coder.git
feat: add s suffix to use HTTPS for ports (#12862)
This commit is contained in:
parent
189b8626d0
commit
1d4bf30c0d
|
@ -40,6 +40,7 @@ func Test_ResolveRequest(t *testing.T) {
|
|||
// Users can access unhealthy and initializing apps (as of 2024-02).
|
||||
appNameUnhealthy = "app-unhealthy"
|
||||
appNameInitializing = "app-initializing"
|
||||
appNameEndsInS = "app-ends-in-s"
|
||||
|
||||
// This agent will never connect, so it will never become "connected".
|
||||
// Users cannot access unhealthy agents.
|
||||
|
@ -166,6 +167,12 @@ func Test_ResolveRequest(t *testing.T) {
|
|||
Threshold: 1000,
|
||||
},
|
||||
},
|
||||
{
|
||||
Slug: appNameEndsInS,
|
||||
DisplayName: appNameEndsInS,
|
||||
SharingLevel: proto.AppSharingLevel_OWNER,
|
||||
Url: appURL,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -644,6 +651,67 @@ func Test_ResolveRequest(t *testing.T) {
|
|||
require.Equal(t, "http://127.0.0.1:9090", token.AppURL)
|
||||
})
|
||||
|
||||
t.Run("PortSubdomainHTTPSS", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
req := (workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
BasePath: "/",
|
||||
UsernameOrID: me.Username,
|
||||
WorkspaceNameOrID: workspace.Name,
|
||||
AgentNameOrID: agentName,
|
||||
AppSlugOrPort: "9090ss",
|
||||
}).Normalize()
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r.Header.Set(codersdk.SessionTokenHeader, client.SessionToken())
|
||||
|
||||
_, ok := workspaceapps.ResolveRequest(rw, r, workspaceapps.ResolveRequestOptions{
|
||||
Logger: api.Logger,
|
||||
SignedTokenProvider: api.WorkspaceAppsProvider,
|
||||
DashboardURL: api.AccessURL,
|
||||
PathAppBaseURL: api.AccessURL,
|
||||
AppHostname: api.AppHostname,
|
||||
AppRequest: req,
|
||||
})
|
||||
// should parse as app and fail to find app "9090ss"
|
||||
require.False(t, ok)
|
||||
w := rw.Result()
|
||||
_ = w.Body.Close()
|
||||
b, err := io.ReadAll(w.Body)
|
||||
require.NoError(t, err)
|
||||
require.Contains(t, string(b), "404 - Application Not Found")
|
||||
})
|
||||
|
||||
t.Run("SubdomainEndsInS", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
req := (workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
BasePath: "/",
|
||||
UsernameOrID: me.Username,
|
||||
WorkspaceNameOrID: workspace.Name,
|
||||
AgentNameOrID: agentName,
|
||||
AppSlugOrPort: appNameEndsInS,
|
||||
}).Normalize()
|
||||
|
||||
rw := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
r.Header.Set(codersdk.SessionTokenHeader, client.SessionToken())
|
||||
|
||||
token, ok := workspaceapps.ResolveRequest(rw, r, workspaceapps.ResolveRequestOptions{
|
||||
Logger: api.Logger,
|
||||
SignedTokenProvider: api.WorkspaceAppsProvider,
|
||||
DashboardURL: api.AccessURL,
|
||||
PathAppBaseURL: api.AccessURL,
|
||||
AppHostname: api.AppHostname,
|
||||
AppRequest: req,
|
||||
})
|
||||
require.True(t, ok)
|
||||
require.Equal(t, req.AppSlugOrPort, token.AppSlugOrPort)
|
||||
})
|
||||
|
||||
t.Run("Terminal", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
@ -287,12 +287,20 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
|
|||
// whether the app is a slug or a port and whether there are multiple agents
|
||||
// in the workspace or not.
|
||||
var (
|
||||
agentNameOrID = r.AgentNameOrID
|
||||
appURL string
|
||||
appSharingLevel database.AppSharingLevel
|
||||
portUint, portUintErr = strconv.ParseUint(r.AppSlugOrPort, 10, 16)
|
||||
agentNameOrID = r.AgentNameOrID
|
||||
appURL string
|
||||
appSharingLevel database.AppSharingLevel
|
||||
// First check if it's a port-based URL with an optional "s" suffix for HTTPS.
|
||||
potentialPortStr = strings.TrimSuffix(r.AppSlugOrPort, "s")
|
||||
portUint, portUintErr = strconv.ParseUint(potentialPortStr, 10, 16)
|
||||
)
|
||||
//nolint:nestif
|
||||
if portUintErr == nil {
|
||||
protocol := "http"
|
||||
if strings.HasSuffix(r.AppSlugOrPort, "s") {
|
||||
protocol = "https"
|
||||
}
|
||||
|
||||
if r.AccessMethod != AccessMethodSubdomain {
|
||||
// TODO(@deansheather): this should return a 400 instead of a 500.
|
||||
return nil, xerrors.New("port-based URLs are only supported for subdomain-based applications")
|
||||
|
@ -309,10 +317,10 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
|
|||
}
|
||||
|
||||
// If the app slug is a port number, then route to the port as an
|
||||
// "anonymous app". We only support HTTP for port-based URLs.
|
||||
// "anonymous app".
|
||||
//
|
||||
// This is only supported for subdomain-based applications.
|
||||
appURL = fmt.Sprintf("http://127.0.0.1:%d", portUint)
|
||||
appURL = fmt.Sprintf("%s://127.0.0.1:%d", protocol, portUint)
|
||||
appSharingLevel = database.AppSharingLevelOwner
|
||||
|
||||
// Port sharing authorization
|
||||
|
|
|
@ -57,6 +57,26 @@ func Test_RequestValidate(t *testing.T) {
|
|||
AppSlugOrPort: "baz",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK5",
|
||||
req: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AppSlugOrPort: "8080",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "OK6",
|
||||
req: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AppSlugOrPort: "8080s",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "NoAccessMethod",
|
||||
req: workspaceapps.Request{
|
||||
|
|
|
@ -222,6 +222,54 @@ func Test_TokenMatchesRequest(t *testing.T) {
|
|||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "PortPortocolHTTP",
|
||||
req: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
Prefix: "yolo--",
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "8080",
|
||||
},
|
||||
token: workspaceapps.SignedToken{
|
||||
Request: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
Prefix: "yolo--",
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "8080",
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "PortPortocolHTTPS",
|
||||
req: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
Prefix: "yolo--",
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "8080s",
|
||||
},
|
||||
token: workspaceapps.SignedToken{
|
||||
Request: workspaceapps.Request{
|
||||
AccessMethod: workspaceapps.AccessMethodSubdomain,
|
||||
Prefix: "yolo--",
|
||||
BasePath: "/",
|
||||
UsernameOrID: "foo",
|
||||
WorkspaceNameOrID: "bar",
|
||||
AgentNameOrID: "baz",
|
||||
AppSlugOrPort: "8080s",
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
|
|
Loading…
Reference in New Issue