package session_test import ( "fmt" "testing" "github.com/nspcc-dev/neofs-api-go/v2/acl" "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" grpc "github.com/nspcc-dev/neofs-api-go/v2/session/grpc" "github.com/stretchr/testify/require" goproto "google.golang.org/protobuf/proto" ) func TestCreateRequestBody_StableMarshal(t *testing.T) { requestFrom := generateCreateSessionRequestBody("Owner ID") transport := new(grpc.CreateRequest_Body) t.Run("non empty", func(t *testing.T) { wire, err := requestFrom.StableMarshal(nil) require.NoError(t, err) err = goproto.Unmarshal(wire, transport) require.NoError(t, err) requestTo := session.CreateRequestBodyFromGRPCMessage(transport) require.Equal(t, requestFrom, requestTo) }) } func TestCreateResponseBody_StableMarshal(t *testing.T) { responseFrom := generateCreateSessionResponseBody("ID", "Session Public Key") transport := new(grpc.CreateResponse_Body) t.Run("non empty", func(t *testing.T) { wire, err := responseFrom.StableMarshal(nil) require.NoError(t, err) err = goproto.Unmarshal(wire, transport) require.NoError(t, err) responseTo := session.CreateResponseBodyFromGRPCMessage(transport) require.Equal(t, responseFrom, responseTo) }) } func TestXHeader_StableMarshal(t *testing.T) { xheaderFrom := generateXHeader("X-Header-Key", "X-Header-Value") t.Run("non empty", func(t *testing.T) { wire, err := xheaderFrom.StableMarshal(nil) require.NoError(t, err) xheaderTo := new(session.XHeader) require.NoError(t, xheaderTo.Unmarshal(wire)) require.Equal(t, xheaderFrom, xheaderTo) }) } func TestTokenLifetime_StableMarshal(t *testing.T) { lifetimeFrom := generateLifetime(10, 20, 30) t.Run("non empty", func(t *testing.T) { wire, err := lifetimeFrom.StableMarshal(nil) require.NoError(t, err) lifetimeTo := new(session.TokenLifetime) require.NoError(t, lifetimeTo.Unmarshal(wire)) require.Equal(t, lifetimeFrom, lifetimeTo) }) } func TestObjectSessionContext_StableMarshal(t *testing.T) { objectCtxFrom := generateObjectCtx("Object ID") t.Run("non empty", func(t *testing.T) { wire, err := objectCtxFrom.StableMarshal(nil) require.NoError(t, err) objectCtxTo := new(session.ObjectSessionContext) require.NoError(t, objectCtxTo.Unmarshal(wire)) require.Equal(t, objectCtxFrom, objectCtxTo) }) } func TestSessionTokenBody_StableMarshal(t *testing.T) { sessionTokenBodyFrom := generateSessionTokenBody("Session Token Body") t.Run("non empty", func(t *testing.T) { wire, err := sessionTokenBodyFrom.StableMarshal(nil) require.NoError(t, err) sessionTokenBodyTo := new(session.SessionTokenBody) require.NoError(t, sessionTokenBodyTo.Unmarshal(wire)) require.Equal(t, sessionTokenBodyFrom, sessionTokenBodyTo) }) } func TestSessionToken_StableMarshal(t *testing.T) { sessionTokenFrom := generateSessionToken("Session Token") t.Run("non empty", func(t *testing.T) { wire, err := sessionTokenFrom.StableMarshal(nil) require.NoError(t, err) sessionTokenTo := new(session.SessionToken) require.NoError(t, sessionTokenTo.Unmarshal(wire)) require.Equal(t, sessionTokenFrom, sessionTokenTo) }) } func TestRequestMetaHeader_StableMarshal(t *testing.T) { metaHeaderOrigin := generateRequestMetaHeader(10, "Bearer One", "Session One") metaHeaderFrom := generateRequestMetaHeader(20, "Bearer Two", "Session Two") metaHeaderFrom.SetOrigin(metaHeaderOrigin) t.Run("non empty", func(t *testing.T) { wire, err := metaHeaderFrom.StableMarshal(nil) require.NoError(t, err) metaHeaderTo := new(session.RequestMetaHeader) require.NoError(t, metaHeaderTo.Unmarshal(wire)) require.Equal(t, metaHeaderFrom, metaHeaderTo) }) } func TestRequestVerificationHeader_StableMarshal(t *testing.T) { verifHeaderOrigin := generateRequestVerificationHeader("Key", "Inside") verifHeaderFrom := generateRequestVerificationHeader("Value", "Outside") verifHeaderFrom.SetOrigin(verifHeaderOrigin) t.Run("non empty", func(t *testing.T) { wire, err := verifHeaderFrom.StableMarshal(nil) require.NoError(t, err) verifHeaderTo := new(session.RequestVerificationHeader) require.NoError(t, verifHeaderTo.Unmarshal(wire)) require.Equal(t, verifHeaderFrom, verifHeaderTo) }) } func TestResponseMetaHeader_StableMarshal(t *testing.T) { metaHeaderOrigin := generateResponseMetaHeader(10) metaHeaderFrom := generateResponseMetaHeader(20) metaHeaderFrom.SetOrigin(metaHeaderOrigin) t.Run("non empty", func(t *testing.T) { wire, err := metaHeaderFrom.StableMarshal(nil) require.NoError(t, err) metaHeaderTo := new(session.ResponseMetaHeader) require.NoError(t, metaHeaderTo.Unmarshal(wire)) require.Equal(t, metaHeaderFrom, metaHeaderTo) }) } func TestResponseVerificationHeader_StableMarshal(t *testing.T) { verifHeaderOrigin := generateResponseVerificationHeader("Key", "Inside") verifHeaderFrom := generateResponseVerificationHeader("Value", "Outside") verifHeaderFrom.SetOrigin(verifHeaderOrigin) t.Run("non empty", func(t *testing.T) { wire, err := verifHeaderFrom.StableMarshal(nil) require.NoError(t, err) verifHeaderTo := new(session.ResponseVerificationHeader) require.NoError(t, verifHeaderTo.Unmarshal(wire)) require.Equal(t, verifHeaderFrom, verifHeaderTo) }) } func generateCreateSessionRequestBody(id string) *session.CreateRequestBody { lifetime := new(session.TokenLifetime) lifetime.SetIat(1) lifetime.SetNbf(2) lifetime.SetExp(3) owner := new(refs.OwnerID) owner.SetValue([]byte(id)) s := new(session.CreateRequestBody) s.SetOwnerID(owner) s.SetExpiration(10) return s } func generateCreateSessionResponseBody(id, key string) *session.CreateResponseBody { s := new(session.CreateResponseBody) s.SetID([]byte(id)) s.SetSessionKey([]byte(key)) return s } func generateSignature(k, v string) *refs.Signature { sig := new(refs.Signature) sig.SetKey([]byte(k)) sig.SetSign([]byte(v)) return sig } func generateVersion(maj, min uint32) *refs.Version { version := new(refs.Version) version.SetMajor(maj) version.SetMinor(min) return version } func generateXHeader(k, v string) *session.XHeader { xheader := new(session.XHeader) xheader.SetKey(k) xheader.SetValue(v) return xheader } func generateLifetime(exp, nbf, iat uint64) *session.TokenLifetime { lifetime := new(session.TokenLifetime) lifetime.SetExp(exp) lifetime.SetNbf(nbf) lifetime.SetIat(iat) return lifetime } func generateBearerLifetime(exp, nbf, iat uint64) *acl.TokenLifetime { lifetime := new(acl.TokenLifetime) lifetime.SetExp(exp) lifetime.SetNbf(nbf) lifetime.SetIat(iat) return lifetime } func generateObjectCtx(id string) *session.ObjectSessionContext { objectCtx := new(session.ObjectSessionContext) objectCtx.SetVerb(session.ObjectVerbPut) cid := new(refs.ContainerID) cid.SetValue([]byte("ContainerID")) oid := new(refs.ObjectID) oid.SetValue([]byte(id)) addr := new(refs.Address) addr.SetContainerID(cid) addr.SetObjectID(oid) objectCtx.SetAddress(addr) return objectCtx } func generateEACL(n int, k, v string) *acl.Table { target := new(acl.Target) target.SetRole(acl.RoleUser) keys := make([][]byte, n) for i := 0; i < n; i++ { s := fmt.Sprintf("Public Key %d", i+1) keys[i] = []byte(s) } filter := new(acl.HeaderFilter) filter.SetHeaderType(acl.HeaderTypeObject) filter.SetMatchType(acl.MatchTypeStringEqual) filter.SetKey(k) filter.SetValue(v) record := new(acl.Record) record.SetOperation(acl.OperationHead) record.SetAction(acl.ActionDeny) record.SetTargets([]*acl.Target{target}) record.SetFilters([]*acl.HeaderFilter{filter}) table := new(acl.Table) cid := new(refs.ContainerID) cid.SetValue([]byte("Container ID")) table.SetContainerID(cid) table.SetRecords([]*acl.Record{record}) return table } func generateSessionTokenBody(id string) *session.SessionTokenBody { owner := new(refs.OwnerID) owner.SetValue([]byte("Owner ID")) tokenBody := new(session.SessionTokenBody) tokenBody.SetID([]byte(id)) tokenBody.SetOwnerID(owner) tokenBody.SetSessionKey([]byte(id)) tokenBody.SetLifetime(generateLifetime(1, 2, 3)) tokenBody.SetContext(generateObjectCtx(id)) return tokenBody } func generateSessionToken(id string) *session.SessionToken { sessionToken := new(session.SessionToken) sessionToken.SetBody(generateSessionTokenBody(id)) sessionToken.SetSignature(generateSignature("id", id)) return sessionToken } func generateBearerTokenBody(id string) *acl.BearerTokenBody { owner := new(refs.OwnerID) owner.SetValue([]byte(id)) tokenBody := new(acl.BearerTokenBody) tokenBody.SetOwnerID(owner) tokenBody.SetLifetime(generateBearerLifetime(1, 2, 3)) tokenBody.SetEACL(generateEACL(10, "id", id)) return tokenBody } func generateBearerToken(id string) *acl.BearerToken { bearerToken := new(acl.BearerToken) bearerToken.SetBody(generateBearerTokenBody(id)) bearerToken.SetSignature(generateSignature("id", id)) return bearerToken } func generateRequestMetaHeader(n int, b, s string) *session.RequestMetaHeader { reqMetaHeader := new(session.RequestMetaHeader) reqMetaHeader.SetVersion(generateVersion(2, 0)) reqMetaHeader.SetEpoch(uint64(n)) reqMetaHeader.SetTTL(uint32(n)) reqMetaHeader.SetXHeaders([]*session.XHeader{ generateXHeader("key-one", "val-one"), generateXHeader("key-two", "val-two"), }) reqMetaHeader.SetBearerToken(generateBearerToken(b)) reqMetaHeader.SetSessionToken(generateSessionToken(s)) return reqMetaHeader } func generateRequestVerificationHeader(k, v string) *session.RequestVerificationHeader { reqVerifHeader := new(session.RequestVerificationHeader) reqVerifHeader.SetBodySignature(generateSignature(k+"body", v+"body")) reqVerifHeader.SetMetaSignature(generateSignature(k+"meta", v+"meta")) reqVerifHeader.SetOriginSignature(generateSignature(k+"orig", v+"orig")) return reqVerifHeader } func generateResponseMetaHeader(n int) *session.ResponseMetaHeader { respMetaHeader := new(session.ResponseMetaHeader) respMetaHeader.SetVersion(generateVersion(2, 0)) respMetaHeader.SetEpoch(uint64(n)) respMetaHeader.SetTTL(uint32(n)) respMetaHeader.SetXHeaders([]*session.XHeader{ generateXHeader("key-one", "val-one"), generateXHeader("key-two", "val-two"), }) return respMetaHeader } func generateResponseVerificationHeader(k, v string) *session.ResponseVerificationHeader { respVerifHeader := new(session.ResponseVerificationHeader) respVerifHeader.SetBodySignature(generateSignature(k+"body", v+"body")) respVerifHeader.SetMetaSignature(generateSignature(k+"meta", v+"meta")) respVerifHeader.SetOriginSignature(generateSignature(k+"orig", v+"orig")) return respVerifHeader }