mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-05-11 21:06:34 +00:00

To help accommodate web browser interactions with websockets, when a streaming logs session is requested for the same actor while already serving a session for that user in a separate request, the original request will be closed and the new request start streaming logs instead. This should help with rogue sessions holding on for too long with no client on the other side (before idle timeout or connection close).
131 lines
3.2 KiB
Go
131 lines
3.2 KiB
Go
package management
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/square/go-jose.v2"
|
|
)
|
|
|
|
const (
|
|
validToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiIsImtpZCI6IjEifQ.eyJ0dW4iOnsiaWQiOiI3YjA5ODE0OS01MWZlLTRlZTUtYTY4Ny0zZTM3NDQ2NmVmYzciLCJhY2NvdW50X3RhZyI6ImNkMzkxZTljMDYyNmE4Zjc2Y2IxZjY3MGY2NTkxYjA1In0sImFjdG9yIjp7ImlkIjoiZGNhcnJAY2xvdWRmbGFyZS5jb20iLCJzdXBwb3J0IjpmYWxzZX0sInJlcyI6WyJsb2dzIl0sImV4cCI6MTY3NzExNzY5NiwiaWF0IjoxNjc3MTE0MDk2LCJpc3MiOiJ0dW5uZWxzdG9yZSJ9.mKenOdOy3Xi4O-grldFnAAemdlE9WajEpTDC_FwezXQTstWiRTLwU65P5jt4vNsIiZA4OJRq7bH-QYID9wf9NA"
|
|
|
|
accountTag = "cd391e9c0626a8f76cb1f670f6591b05"
|
|
tunnelID = "7b098149-51fe-4ee5-a687-3e374466efc7"
|
|
actorID = "45d2751e-6b59-45a9-814d-f630786bd0cd"
|
|
)
|
|
|
|
type invalidManagementTokenClaims struct {
|
|
Invalid string `json:"invalid"`
|
|
}
|
|
|
|
func TestParseToken(t *testing.T) {
|
|
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
require.NoError(t, err)
|
|
|
|
for _, test := range []struct {
|
|
name string
|
|
claims any
|
|
err error
|
|
}{
|
|
{
|
|
name: "Valid",
|
|
claims: managementTokenClaims{
|
|
Tunnel: tunnel{
|
|
ID: tunnelID,
|
|
AccountTag: accountTag,
|
|
},
|
|
Actor: actor{
|
|
ID: actorID,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "Invalid claims",
|
|
claims: invalidManagementTokenClaims{Invalid: "invalid"},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
{
|
|
name: "Missing Tunnel",
|
|
claims: managementTokenClaims{
|
|
Actor: actor{
|
|
ID: actorID,
|
|
},
|
|
},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
{
|
|
name: "Missing Tunnel ID",
|
|
claims: managementTokenClaims{
|
|
Tunnel: tunnel{
|
|
AccountTag: accountTag,
|
|
},
|
|
Actor: actor{
|
|
ID: actorID,
|
|
},
|
|
},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
{
|
|
name: "Missing Account Tag",
|
|
claims: managementTokenClaims{
|
|
Tunnel: tunnel{
|
|
ID: tunnelID,
|
|
},
|
|
Actor: actor{
|
|
ID: actorID,
|
|
},
|
|
},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
{
|
|
name: "Missing Actor",
|
|
claims: managementTokenClaims{
|
|
Tunnel: tunnel{
|
|
ID: tunnelID,
|
|
AccountTag: accountTag,
|
|
},
|
|
},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
{
|
|
name: "Missing Actor ID",
|
|
claims: managementTokenClaims{
|
|
Tunnel: tunnel{
|
|
ID: tunnelID,
|
|
},
|
|
Actor: actor{},
|
|
},
|
|
err: errors.New("invalid management token format provided"),
|
|
},
|
|
} {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
jwt := signToken(t, test.claims, key)
|
|
claims, err := parseToken(jwt)
|
|
if test.err != nil {
|
|
require.EqualError(t, err, test.err.Error())
|
|
return
|
|
}
|
|
require.Nil(t, err)
|
|
require.Equal(t, test.claims, *claims)
|
|
})
|
|
}
|
|
}
|
|
|
|
func signToken(t *testing.T, token any, key *ecdsa.PrivateKey) string {
|
|
opts := (&jose.SignerOptions{}).WithType("JWT").WithHeader("kid", "1")
|
|
signer, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.ES256, Key: key}, opts)
|
|
require.NoError(t, err)
|
|
payload, err := json.Marshal(token)
|
|
require.NoError(t, err)
|
|
jws, err := signer.Sign(payload)
|
|
require.NoError(t, err)
|
|
jwt, err := jws.CompactSerialize()
|
|
require.NoError(t, err)
|
|
return jwt
|
|
}
|