Skip to content

Conversation

@End-rey
Copy link
Contributor

@End-rey End-rey commented Nov 7, 2025

@End-rey End-rey self-assigned this Nov 7, 2025
@End-rey End-rey force-pushed the new-session-token-v2 branch from 5bba446 to f730e2f Compare November 7, 2025 20:53
@codecov
Copy link

codecov bot commented Nov 7, 2025

Codecov Report

❌ Patch coverage is 24.29501% with 349 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.55%. Comparing base (8677303) to head (9a6fcc8).

Files with missing lines Patch % Lines
pkg/services/object/acl/v2/service.go 16.12% 101 Missing and 3 partials ⚠️
pkg/services/container/server.go 51.61% 43 Missing and 17 partials ⚠️
pkg/innerring/processors/container/common.go 0.00% 33 Missing ⚠️
cmd/neofs-cli/modules/object/util.go 0.00% 29 Missing ⚠️
pkg/services/object/util/prm.go 0.00% 19 Missing ⚠️
pkg/services/object/get/util.go 0.00% 15 Missing ⚠️
pkg/core/object/fmt.go 33.33% 11 Missing and 1 partial ⚠️
internal/crypto/object.go 23.07% 9 Missing and 1 partial ⚠️
internal/chaintime/chaintime.go 0.00% 8 Missing ⚠️
cmd/neofs-node/container.go 0.00% 7 Missing ⚠️
... and 16 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3671      +/-   ##
==========================================
- Coverage   25.60%   25.55%   -0.06%     
==========================================
  Files         657      658       +1     
  Lines       42097    42468     +371     
==========================================
+ Hits        10780    10852      +72     
- Misses      30338    30613     +275     
- Partials      979     1003      +24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@End-rey End-rey force-pushed the new-session-token-v2 branch 4 times, most recently from 41ab8d0 to e66bf4b Compare November 18, 2025 12:30
@End-rey End-rey force-pushed the new-session-token-v2 branch 2 times, most recently from eed01c8 to f9d051d Compare December 12, 2025 15:42
@End-rey End-rey force-pushed the new-session-token-v2 branch 2 times, most recently from 5b82365 to cea1b4d Compare December 20, 2025 23:05
This was referenced Dec 22, 2025
@End-rey End-rey force-pushed the new-session-token-v2 branch from cea1b4d to 2122d4d Compare December 22, 2025 18:37
roman-khimov added a commit that referenced this pull request Dec 25, 2025
@End-rey End-rey force-pushed the new-session-token-v2 branch 5 times, most recently from eb453b4 to 1a9aab2 Compare December 26, 2025 16:11
@End-rey End-rey marked this pull request as ready for review December 26, 2025 16:26
type nnsResolver struct {
fsChain FSChain

nnsCache *lru.Cache[string, bool]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nns checks never expire (if size is big enough)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reset cache with the (s *Server) ResetSessionTokenCheckCache().

@End-rey End-rey requested a review from carpawell January 12, 2026 16:00
verb = sessionv2.VerbObjectDelete
// For DELETE, create context with two verbs:
// 1. DELETE for the deleted object
// 2. PUT for the tombstone
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be required, tombstone PUT is DELETE ACL-wise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, using Put without objects is more logical for verification than Delete with an object tombstone whose ID we don't know yet.

op, verb, verbv2 := acl.OpObjectPut, sessionSDK.VerbObjectPut, sessionSDKv2.VerbObjectPut
tombstone := header.GetObjectType() == protoobject.ObjectType_TOMBSTONE
if tombstone {
// such objects are specific - saving them is essentially the removal of other
// objects
op, verb = acl.OpObjectDelete, sessionSDK.VerbObjectDelete
}
reqInfo, err := b.findRequestInfo(request, cnr, op, verb, verbv2, obj)

If I check Delete without objects here, it will be a bad check for the initial request with the object that needs to be deleted. There is no need to check Put with an object, because the ID is usually generated after the token is signed.

// When we PUT a tombstone, the requested object is not zero,
// but the session is not bound to it because the user cannot predict its ID.
if !reqObj.IsZero() && reqVerb != sessionSDKv2.VerbObjectPut {
if !token.AssertObject(reqVerb, reqCnr, reqObj) {
return errors.New("v2 session token does not authorize access to the object")
}
} else {
if !token.AssertVerb(reqVerb, reqCnr) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The meaning of OID for DELETE is to represent deleted OID.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems strange and incorrect to me when the request changes from PUT for the tombstone to DELETE with the OID of the tombstone itself. In that case, I suggest specifying zero OID for Put with a tombstone here:

op, verb, verbv2 := acl.OpObjectPut, sessionSDK.VerbObjectPut, sessionSDKv2.VerbObjectPut
tombstone := header.GetObjectType() == protoobject.ObjectType_TOMBSTONE
if tombstone {
// such objects are specific - saving them is essentially the removal of other
// objects
op, verb = acl.OpObjectDelete, sessionSDK.VerbObjectDelete
}
reqInfo, err := b.findRequestInfo(request, cnr, op, verb, verbv2, obj)

And replace PUT with DELETE, as for token v1.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why zero? Rather it can be an associated ID, we know it from the header.

}

func (r nnsResolver) HasUser(name string, userID user.ID) (bool, error) {
cacheKey := fmt.Sprintf("%s|%s", name, userID.String())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not very efficient.

@End-rey End-rey force-pushed the new-session-token-v2 branch 2 times, most recently from ee17ebb to 3f6a367 Compare January 14, 2026 12:39
@End-rey End-rey requested a review from roman-khimov January 14, 2026 12:49
@End-rey End-rey force-pushed the new-session-token-v2 branch from 3f6a367 to 245a33a Compare January 14, 2026 14:08
verb = sessionv2.VerbObjectDelete
// For DELETE, create context with two verbs:
// 1. DELETE for the deleted object
// 2. PUT for the tombstone
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The meaning of OID for DELETE is to represent deleted OID.

if err != nil {
return fmt.Errorf("get current block count: %w", err)
}
bh, err := cp.cnrClient.Morph().GetBlockHeader(idx - 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IR is subscribed to headers, it should have this data somewhere.

if err != nil {
return token, fmt.Errorf("get FS chain block count: %w", err)
}
header, err := s.GetBlockHeader(idx - 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SN also has this data from the latest header. Doing header lookups per-request is too costly.

}
case neofscrypto.N3:
if sessionToken != nil {
if sessionToken != nil || sessionTokenV2 != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine a v2 token signed for some NNS names and one account signing something with it. It can be contract-based. This couldn't happen with v1 token, but for v2 it's totally possible.

origin = origin.Origin()
}

neoPub, err := keys.NewPublicKeyFromBytes(key, elliptic.P256())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be an N3 signature at any step of v2 chain.


func (b Service) verifySessionTokenV2AgainstRequest(token sessionSDKv2.Token, reqVerb sessionSDKv2.Verb, reqCnr cid.ID, reqObj oid.ID) error {
// When we PUT a tombstone, the requested object is not zero,
// but the session is not bound to it because the user cannot predict its ID.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something has to substitute it for associated ID above. IIRC this was the case once upon a time for v1 tokens.

@End-rey End-rey force-pushed the new-session-token-v2 branch from 245a33a to a5ef555 Compare January 16, 2026 18:18
Set subjects to default session token from `session-subjects` and
`session-subjects-nns` flags for put, delete and lock operations.

Signed-off-by: Andrey Butusov <andrey@nspcc.io>
Signed-off-by: Andrey Butusov <andrey@nspcc.io>
@End-rey End-rey force-pushed the new-session-token-v2 branch 3 times, most recently from 1936daf to 9a6fcc8 Compare January 16, 2026 19:28
Check new session tokens in inner ring container processors.

Signed-off-by: Andrey Butusov <andrey@nspcc.io>
Check container requests with new v2 session tokens, verify them using the nns
resolver.

Signed-off-by: Andrey Butusov <andrey@nspcc.io>
Check object requests with new v2 session tokens, verify them using the nns
resolver. Pass the v2 session token through the slicer, set them to the object
session token, and authorize objects using the token.

Signed-off-by: Andrey Butusov <andrey@nspcc.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants