feat: add port-sharing backend (#11939)

This commit is contained in:
Garrett Delfosse
2024-02-13 09:31:20 -05:00
committed by GitHub
parent c939416702
commit 3ab3a62bef
48 changed files with 1947 additions and 59 deletions
+73
View File
@@ -909,6 +909,79 @@ func Run(t *testing.T, appHostIsPrimary bool, factory DeploymentFactory) {
require.Equal(t, http.StatusOK, resp.StatusCode)
})
t.Run("PortSharingNoShare", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
userClient, _ := coderdtest.CreateAnotherUser(t, appDetails.SDKClient, appDetails.FirstUser.OrganizationID, rbac.RoleMember())
userAppClient := appDetails.AppClient(t)
userAppClient.SetSessionToken(userClient.SessionToken())
resp, err := requestWithRetries(ctx, t, userAppClient, http.MethodGet, appDetails.SubdomainAppURL(appDetails.Apps.Port).String(), nil)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusNotFound, resp.StatusCode)
})
t.Run("PortSharingAuthenticatedOK", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
// we are shadowing the parent since we are changing the state
appDetails := setupProxyTest(t, nil)
port, err := strconv.ParseInt(appDetails.Apps.Port.AppSlugOrPort, 10, 32)
require.NoError(t, err)
// set the port we have to be shared with authenticated users
_, err = appDetails.SDKClient.UpsertWorkspaceAgentPortShare(ctx, appDetails.Workspace.ID, codersdk.UpsertWorkspaceAgentPortShareRequest{
AgentName: proxyTestAgentName,
Port: int32(port),
ShareLevel: codersdk.WorkspaceAgentPortShareLevelAuthenticated,
})
require.NoError(t, err)
userClient, _ := coderdtest.CreateAnotherUser(t, appDetails.SDKClient, appDetails.FirstUser.OrganizationID, rbac.RoleMember())
userAppClient := appDetails.AppClient(t)
userAppClient.SetSessionToken(userClient.SessionToken())
resp, err := requestWithRetries(ctx, t, userAppClient, http.MethodGet, appDetails.SubdomainAppURL(appDetails.Apps.Port).String(), nil)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
})
t.Run("PortSharingPublicOK", func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
// we are shadowing the parent since we are changing the state
appDetails := setupProxyTest(t, nil)
port, err := strconv.ParseInt(appDetails.Apps.Port.AppSlugOrPort, 10, 32)
require.NoError(t, err)
// set the port we have to be shared with public
_, err = appDetails.SDKClient.UpsertWorkspaceAgentPortShare(ctx, appDetails.Workspace.ID, codersdk.UpsertWorkspaceAgentPortShareRequest{
AgentName: proxyTestAgentName,
Port: int32(port),
ShareLevel: codersdk.WorkspaceAgentPortShareLevelPublic,
})
require.NoError(t, err)
publicAppClient := appDetails.AppClient(t)
publicAppClient.SetSessionToken("")
resp, err := requestWithRetries(ctx, t, publicAppClient, http.MethodGet, appDetails.SubdomainAppURL(appDetails.Apps.Port).String(), nil)
require.NoError(t, err)
defer resp.Body.Close()
require.Equal(t, http.StatusOK, resp.StatusCode)
})
t.Run("ProxyError", func(t *testing.T) {
t.Parallel()
+31
View File
@@ -3,6 +3,7 @@ package workspaceapps
import (
"context"
"database/sql"
"errors"
"fmt"
"net/url"
"strconv"
@@ -313,6 +314,36 @@ func (r Request) getDatabase(ctx context.Context, db database.Store) (*databaseR
// This is only supported for subdomain-based applications.
appURL = fmt.Sprintf("http://127.0.0.1:%d", portUint)
appSharingLevel = database.AppSharingLevelOwner
// Port sharing authorization
agentName := agentNameOrID
id, err := uuid.Parse(agentNameOrID)
for _, a := range agents {
// if err is nil then it's an UUID
if err == nil && a.ID == id {
agentName = a.Name
break
}
// otherwise it's a name
if a.Name == agentNameOrID {
break
}
}
// First check if there is a port share for the port
ps, err := db.GetWorkspaceAgentPortShare(ctx, database.GetWorkspaceAgentPortShareParams{
WorkspaceID: workspace.ID,
AgentName: agentName,
Port: int32(portUint),
})
if err != nil {
if !errors.Is(err, sql.ErrNoRows) {
return nil, xerrors.Errorf("get workspace agent port share: %w", err)
}
// No port share found, so we keep default to owner.
} else {
appSharingLevel = ps.ShareLevel
}
} else {
for _, app := range apps {
if app.Slug == r.AppSlugOrPort {