fix: avoid redirect loop on workspace proxies (#9389)

* fix: avoid redirect loop on workspace proxies

---------

Co-authored-by: Steven Masley <stevenmasley@coder.com>
This commit is contained in:
Dean Sheather
2023-08-28 18:34:52 -07:00
committed by GitHub
parent eb68684327
commit 5993f85ec9
12 changed files with 265 additions and 99 deletions

View File

@ -2,9 +2,13 @@ package workspaceapps_test
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/coder/coder/v2/codersdk"
"github.com/go-jose/go-jose/v3"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
@ -46,6 +50,29 @@ func Test_TokenMatchesRequest(t *testing.T) {
},
want: true,
},
{
name: "NormalizePath",
req: workspaceapps.Request{
AccessMethod: workspaceapps.AccessMethodPath,
BasePath: "/app",
UsernameOrID: "foo",
WorkspaceNameOrID: "bar",
AgentNameOrID: "baz",
AppSlugOrPort: "qux",
},
token: workspaceapps.SignedToken{
Request: workspaceapps.Request{
AccessMethod: workspaceapps.AccessMethodPath,
// With trailing slash
BasePath: "/app/",
UsernameOrID: "foo",
WorkspaceNameOrID: "bar",
AgentNameOrID: "baz",
AppSlugOrPort: "qux",
},
},
want: true,
},
{
name: "DifferentAccessMethod",
req: workspaceapps.Request{
@ -283,6 +310,62 @@ func Test_GenerateToken(t *testing.T) {
}
}
func Test_FromRequest(t *testing.T) {
t.Parallel()
t.Run("MultipleTokens", func(t *testing.T) {
t.Parallel()
r := httptest.NewRequest("GET", "/", nil)
// Add an invalid token
r.AddCookie(&http.Cookie{
Name: codersdk.SignedAppTokenCookie,
Value: "invalid",
})
token := workspaceapps.SignedToken{
Request: workspaceapps.Request{
AccessMethod: workspaceapps.AccessMethodSubdomain,
BasePath: "/",
UsernameOrID: "user",
WorkspaceAndAgent: "workspace/agent",
WorkspaceNameOrID: "workspace",
AgentNameOrID: "agent",
AppSlugOrPort: "app",
},
Expiry: time.Now().Add(time.Hour),
UserID: uuid.New(),
WorkspaceID: uuid.New(),
AgentID: uuid.New(),
AppURL: "/",
}
// Add an expired cookie
expired := token
expired.Expiry = time.Now().Add(time.Hour * -1)
expiredStr, err := coderdtest.AppSecurityKey.SignToken(token)
require.NoError(t, err)
r.AddCookie(&http.Cookie{
Name: codersdk.SignedAppTokenCookie,
Value: expiredStr,
})
// Add a valid token
validStr, err := coderdtest.AppSecurityKey.SignToken(token)
require.NoError(t, err)
r.AddCookie(&http.Cookie{
Name: codersdk.SignedAppTokenCookie,
Value: validStr,
})
signed, ok := workspaceapps.FromRequest(r, coderdtest.AppSecurityKey)
require.True(t, ok, "expected a token to be found")
// Confirm it is the correct token.
require.Equal(t, signed.UserID, token.UserID)
})
}
// The ParseToken fn is tested quite thoroughly in the GenerateToken test as
// well.
func Test_ParseToken(t *testing.T) {