191 lines
6.5 KiB
Go
191 lines
6.5 KiB
Go
package integration_test
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"galaxy/integration/testenv"
|
|
usermodel "galaxy/model/user"
|
|
"galaxy/transcoder"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// TestGatewayEdge_PublicBodyTooLarge tightens the public body size
|
|
// limit and asserts that the gateway rejects an oversize public auth
|
|
// payload before reaching backend.
|
|
func TestGatewayEdge_PublicBodyTooLarge(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{
|
|
GatewayExtra: map[string]string{
|
|
"GATEWAY_PUBLIC_HTTP_ANTI_ABUSE_PUBLIC_AUTH_MAX_BODY_BYTES": "256",
|
|
},
|
|
})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
huge := strings.Repeat("x", 4096)
|
|
public := testenv.NewPublicRESTClient(plat.Gateway.HTTPURL)
|
|
_, _, err := public.SendEmailCode(ctx, huge+"@example.com", "")
|
|
if err == nil {
|
|
t.Fatalf("expected error for oversize public payload, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), "413") && !strings.Contains(err.Error(), "request_too_large") {
|
|
t.Fatalf("expected 413 or request_too_large, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestGatewayEdge_BadSignature corrupts the request signature and
|
|
// asserts the gateway rejects it as Unauthenticated.
|
|
func TestGatewayEdge_BadSignature(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
|
defer cancel()
|
|
sess := testenv.RegisterSession(t, plat, "pilot+badsig@example.com")
|
|
gw, err := sess.DialAuthenticated(ctx, plat)
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer gw.Close()
|
|
|
|
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
|
|
if err != nil {
|
|
t.Fatalf("encode payload: %v", err)
|
|
}
|
|
bogus := make([]byte, 64)
|
|
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
|
|
OverrideSignature: bogus,
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected Unauthenticated for bad signature")
|
|
}
|
|
if !testenv.IsUnauthenticated(err) {
|
|
t.Fatalf("expected Unauthenticated, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestGatewayEdge_PayloadHashMismatch sends a request whose
|
|
// payload_hash is not the SHA-256 of payload_bytes and asserts the
|
|
// gateway rejects it.
|
|
func TestGatewayEdge_PayloadHashMismatch(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
|
defer cancel()
|
|
sess := testenv.RegisterSession(t, plat, "pilot+hash@example.com")
|
|
gw, err := sess.DialAuthenticated(ctx, plat)
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer gw.Close()
|
|
|
|
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
|
|
if err != nil {
|
|
t.Fatalf("encode payload: %v", err)
|
|
}
|
|
// The signed canonical bytes still use this wrong hash; gateway
|
|
// recomputes and should detect the mismatch independently of the
|
|
// signature check.
|
|
wrong := sha256.Sum256([]byte("not-the-payload"))
|
|
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
|
|
OverridePayloadHash: wrong[:],
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected rejection for payload_hash mismatch")
|
|
}
|
|
if !testenv.IsUnauthenticated(err) && !testenv.IsInvalidArgument(err) {
|
|
t.Fatalf("expected Unauthenticated or InvalidArgument, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestGatewayEdge_StaleTimestamp tightens freshness window to 1
|
|
// second, then submits a request whose timestamp is 30 seconds in
|
|
// the past, and asserts the gateway rejects it as stale.
|
|
func TestGatewayEdge_StaleTimestamp(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{
|
|
GatewayExtra: map[string]string{
|
|
"GATEWAY_AUTHENTICATED_GRPC_FRESHNESS_WINDOW": "1s",
|
|
},
|
|
})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
|
defer cancel()
|
|
sess := testenv.RegisterSession(t, plat, "pilot+stale@example.com")
|
|
gw, err := sess.DialAuthenticated(ctx, plat)
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer gw.Close()
|
|
|
|
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
|
|
if err != nil {
|
|
t.Fatalf("encode payload: %v", err)
|
|
}
|
|
stale := time.Now().Add(-30 * time.Second).UnixMilli()
|
|
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
|
|
TimestampMS: stale,
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected rejection for stale timestamp")
|
|
}
|
|
if !testenv.IsUnauthenticated(err) && !testenv.IsInvalidArgument(err) && !testenv.IsFailedPrecondition(err) {
|
|
t.Fatalf("expected Unauthenticated, InvalidArgument or FailedPrecondition, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestGatewayEdge_UnknownSession addresses a session id that backend
|
|
// has never seen; gateway must reject before forwarding.
|
|
func TestGatewayEdge_UnknownSession(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
|
defer cancel()
|
|
sess := testenv.RegisterSession(t, plat, "pilot+unknown@example.com")
|
|
gw, err := sess.DialAuthenticated(ctx, plat)
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer gw.Close()
|
|
|
|
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
|
|
if err != nil {
|
|
t.Fatalf("encode payload: %v", err)
|
|
}
|
|
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
|
|
OverrideSessionID: uuid.NewString(),
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected rejection for unknown session")
|
|
}
|
|
if !testenv.IsUnauthenticated(err) {
|
|
t.Fatalf("expected Unauthenticated, got: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestGatewayEdge_UnsupportedProtocolVersion sets protocol_version
|
|
// to an unknown literal and asserts gateway rejection.
|
|
func TestGatewayEdge_UnsupportedProtocolVersion(t *testing.T) {
|
|
plat := testenv.Bootstrap(t, testenv.BootstrapOptions{})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
|
defer cancel()
|
|
sess := testenv.RegisterSession(t, plat, "pilot+protover@example.com")
|
|
gw, err := sess.DialAuthenticated(ctx, plat)
|
|
if err != nil {
|
|
t.Fatalf("dial: %v", err)
|
|
}
|
|
defer gw.Close()
|
|
|
|
payload, err := transcoder.GetMyAccountRequestToPayload(&usermodel.GetMyAccountRequest{})
|
|
if err != nil {
|
|
t.Fatalf("encode payload: %v", err)
|
|
}
|
|
_, err = gw.Execute(ctx, usermodel.MessageTypeGetMyAccount, payload, testenv.ExecuteOptions{
|
|
OverrideProtocolVersion: "v999",
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected rejection for unsupported protocol_version")
|
|
}
|
|
if !testenv.IsInvalidArgument(err) && !testenv.IsUnauthenticated(err) && !testenv.IsFailedPrecondition(err) {
|
|
t.Fatalf("expected InvalidArgument, Unauthenticated or FailedPrecondition, got: %v", err)
|
|
}
|
|
}
|