fix(gateway): strip provider authority from client egress
Verify Data Plane / gateway (push) Failing after 4m32s
Verify Data Plane / gateway (push) Failing after 4m32s
This commit is contained in:
+65
-8
@@ -12,6 +12,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
@@ -969,10 +970,61 @@ func newNativeGatewayLifecycleHarness(t *testing.T, sessionID string) nativeGate
|
|||||||
return nativeGatewayLifecycleHarness{native: native, key: key, client: client, admission: admission, reporter: reporter}
|
return nativeGatewayLifecycleHarness{native: native, key: key, client: client, admission: admission, reporter: reporter}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGatewayEgressReturnsProviderFreeClientAuthority(t *testing.T) {
|
||||||
|
h := newNativeGatewayLifecycleHarness(t, "session-client-authority")
|
||||||
|
var got map[string]any
|
||||||
|
if err := json.Unmarshal(h.client.authorityRaw, &got); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
want := map[string]any{
|
||||||
|
"version": "1",
|
||||||
|
"session_id": "session-client-authority",
|
||||||
|
"gateway_id": "gateway-1",
|
||||||
|
"audience": "versevdi-gateway",
|
||||||
|
"reconnect_sequence": float64(0),
|
||||||
|
"expires_at": h.admission.authority.ExpiresAt,
|
||||||
|
"capabilities": map[string]any{
|
||||||
|
"transport": "quic-tls13",
|
||||||
|
"framing": "datagram-v2",
|
||||||
|
"media": "encoded",
|
||||||
|
"audio": "encoded",
|
||||||
|
"source_rate_control": "server",
|
||||||
|
"client_decode": []any{"h264-opus"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("raw client authority = %s", h.client.authorityRaw)
|
||||||
|
}
|
||||||
|
if err := h.client.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
h.waitReleased(t)
|
||||||
|
if !reflect.DeepEqual(h.admission.releaseAuthority, h.admission.authority) {
|
||||||
|
t.Fatalf("release authority = %#v, want provider-bearing %#v", h.admission.releaseAuthority, h.admission.authority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestClientSessionAuthorityRejectsProviderBearingRC3(t *testing.T) {
|
||||||
|
var _ protocol.ClientSessionAuthority = Client{}.Authority
|
||||||
|
raw, err := protocol.EncodeSessionAuthority(protocol.SessionAuthority{
|
||||||
|
Version: "1", SessionID: "session-rc3", GatewayID: "gateway-1", Audience: "versevdi-gateway",
|
||||||
|
ExpiresAt: time.Now().Add(time.Minute).UTC().Format(time.RFC3339Nano), Capabilities: DefaultCapabilities(),
|
||||||
|
ProviderProfile: ProviderProfileApollo, ProviderIdentity: "apollo-fixture-1#sha256:fixture-apollo-1",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := protocol.DecodeClientSessionAuthority(raw); err == nil {
|
||||||
|
t.Fatalf("accepted provider-bearing RC3 authority: %s", raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type independentGatewayClient struct {
|
type independentGatewayClient struct {
|
||||||
connection *quic.Conn
|
connection *quic.Conn
|
||||||
control *quic.Stream
|
control *quic.Stream
|
||||||
media independentMediaReassembler
|
authority protocol.ClientSessionAuthority
|
||||||
|
authorityRaw []byte
|
||||||
|
media independentMediaReassembler
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialIndependentGateway(ctx context.Context, address string, tlsConfig *tls.Config, request protocol.TunnelAdmissionRequest) (*independentGatewayClient, error) {
|
func dialIndependentGateway(ctx context.Context, address string, tlsConfig *tls.Config, request protocol.TunnelAdmissionRequest) (*independentGatewayClient, error) {
|
||||||
@@ -994,17 +1046,20 @@ func dialIndependentGateway(ctx context.Context, address string, tlsConfig *tls.
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
encoded, err = independentReadWire(stream, defaultHelloLimit)
|
encoded, err = independentReadWire(stream, defaultHelloLimit)
|
||||||
}
|
}
|
||||||
|
var authority protocol.ClientSessionAuthority
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, err = protocol.DecodeSessionAuthority(encoded)
|
authority, err = protocol.DecodeClientSessionAuthority(encoded)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = connection.CloseWithError(applicationError, "independent client admission failed")
|
_ = connection.CloseWithError(applicationError, "independent client admission failed")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &independentGatewayClient{
|
return &independentGatewayClient{
|
||||||
connection: connection,
|
connection: connection,
|
||||||
control: stream,
|
control: stream,
|
||||||
media: independentMediaReassembler{incomplete: make(map[independentMediaKey]*independentMediaUnit)},
|
authority: authority,
|
||||||
|
authorityRaw: encoded,
|
||||||
|
media: independentMediaReassembler{incomplete: make(map[independentMediaKey]*independentMediaUnit)},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1529,6 +1584,7 @@ func testTLS(t *testing.T) (*tls.Config, *tls.Config) {
|
|||||||
type oneTimeAdmission struct {
|
type oneTimeAdmission struct {
|
||||||
used atomic.Bool
|
used atomic.Bool
|
||||||
authority protocol.SessionAuthority
|
authority protocol.SessionAuthority
|
||||||
|
releaseAuthority protocol.SessionAuthority
|
||||||
releases atomic.Int64
|
releases atomic.Int64
|
||||||
released chan struct{}
|
released chan struct{}
|
||||||
streamPolicy protocol.ProviderStreamPolicy
|
streamPolicy protocol.ProviderStreamPolicy
|
||||||
@@ -1603,8 +1659,9 @@ func (a *oneTimeAdmission) ProviderWork(_ context.Context, authority protocol.Se
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *oneTimeAdmission) Release(context.Context, protocol.SessionAuthority) error {
|
func (a *oneTimeAdmission) Release(_ context.Context, authority protocol.SessionAuthority) error {
|
||||||
if a.releases.Add(1) == 1 {
|
if a.releases.Add(1) == 1 {
|
||||||
|
a.releaseAuthority = authority
|
||||||
close(a.released)
|
close(a.released)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -291,8 +291,11 @@ func (s *Server) handleConnection(parent context.Context, connection *quic.Conn)
|
|||||||
_ = writeStableError(stream, "provider_state_unavailable", err, true)
|
_ = writeStableError(stream, "provider_state_unavailable", err, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authority.Capabilities = selected
|
clientAuthority := protocol.ClientSessionAuthority{
|
||||||
authorityBytes, err := protocol.EncodeSessionAuthority(authority)
|
Version: authority.Version, SessionID: authority.SessionID, GatewayID: authority.GatewayID, Audience: authority.Audience,
|
||||||
|
ReconnectSequence: authority.ReconnectSequence, ExpiresAt: authority.ExpiresAt, Capabilities: selected,
|
||||||
|
}
|
||||||
|
authorityBytes, err := protocol.EncodeClientSessionAuthority(clientAuthority)
|
||||||
if err != nil || writeWire(stream, authorityBytes, defaultHelloLimit) != nil {
|
if err != nil || writeWire(stream, authorityBytes, defaultHelloLimit) != nil {
|
||||||
_ = providerSession.ReleaseAll(context.Background())
|
_ = providerSession.ReleaseAll(context.Background())
|
||||||
_ = providerSession.Terminate(context.Background())
|
_ = providerSession.Terminate(context.Background())
|
||||||
@@ -1010,7 +1013,7 @@ type Client struct {
|
|||||||
controlReadMu sync.Mutex
|
controlReadMu sync.Mutex
|
||||||
controlWriteMu sync.Mutex
|
controlWriteMu sync.Mutex
|
||||||
pendingControl map[string][][]byte
|
pendingControl map[string][][]byte
|
||||||
Authority protocol.SessionAuthority
|
Authority protocol.ClientSessionAuthority
|
||||||
}
|
}
|
||||||
|
|
||||||
func Dial(ctx context.Context, address string, tlsConfig *tls.Config, request protocol.TunnelAdmissionRequest) (*Client, error) {
|
func Dial(ctx context.Context, address string, tlsConfig *tls.Config, request protocol.TunnelAdmissionRequest) (*Client, error) {
|
||||||
@@ -1045,7 +1048,7 @@ func Dial(ctx context.Context, address string, tlsConfig *tls.Config, request pr
|
|||||||
_ = connection.CloseWithError(applicationError, "no authority")
|
_ = connection.CloseWithError(applicationError, "no authority")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
authority, authorityErr := protocol.DecodeSessionAuthority(response)
|
authority, authorityErr := protocol.DecodeClientSessionAuthority(response)
|
||||||
if authorityErr != nil {
|
if authorityErr != nil {
|
||||||
stable, stableErr := protocol.DecodeStableError(response)
|
stable, stableErr := protocol.DecodeStableError(response)
|
||||||
if stableErr == nil {
|
if stableErr == nil {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module git.sechmachine.io.vn/sechmachine/VerseVDI-Data-Plane
|
|||||||
go 1.26.5
|
go 1.26.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.3
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.5
|
||||||
github.com/quic-go/quic-go v0.61.0
|
github.com/quic-go/quic-go v0.61.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.2 h1
|
|||||||
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.2/go.mod h1:7PhFIDhjtr20btWoEb2GqB+7dBpzJt43olrnHVutWoc=
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.2/go.mod h1:7PhFIDhjtr20btWoEb2GqB+7dBpzJt43olrnHVutWoc=
|
||||||
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.3 h1:43EJHiKcbWdF0K1dvVznpWaUUWcvT5nogcGiSnOVu5s=
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.3 h1:43EJHiKcbWdF0K1dvVznpWaUUWcvT5nogcGiSnOVu5s=
|
||||||
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.3/go.mod h1:7PhFIDhjtr20btWoEb2GqB+7dBpzJt43olrnHVutWoc=
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.3/go.mod h1:7PhFIDhjtr20btWoEb2GqB+7dBpzJt43olrnHVutWoc=
|
||||||
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.5 h1:bJ3JeCm7dsQwWc7kMjcSgBrtATT1hi2xUSNdE73q4X4=
|
||||||
|
git.sechmachine.io.vn/sechmachine/VerseVDI-Protocol v1.0.0-phase3d-macos-rc.5/go.mod h1:7PhFIDhjtr20btWoEb2GqB+7dBpzJt43olrnHVutWoc=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
|||||||
Reference in New Issue
Block a user