cloudflared/management/token_test.go
Devin Carr 38cd455e4d TUN-7373: Streaming logs override for same actor
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).
2023-04-21 11:54:37 -07:00

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
}