From e0242b147c1d6b6241221f396a14a9dc551c9fac Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 26 Sep 2024 17:01:48 +0400 Subject: [PATCH] bearer,session: Invert method checking token lifetime validity Previously, bearer and session token types provided `InvalidAt` method checking whether the token is invalid at the given epoch. This was not a very good choice, since users are more naturally inclined to work with affirmative methods. In this case, the validity check, not the invalidity one. This extends interface of NeoFS tokens with `ValidAt` method. `InvalidAt` ones are marked deprecated. Signed-off-by: Leonard Lyubich --- bearer/bearer.go | 17 +++++++++++------ bearer/bearer_test.go | 8 ++++++++ session/common.go | 15 ++++++++++----- session/common_test.go | 13 ++++++++++--- session/container_test.go | 2 +- session/object_test.go | 2 +- 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/bearer/bearer.go b/bearer/bearer.go index 05ecbdbc..d9d9ebf3 100644 --- a/bearer/bearer.go +++ b/bearer/bearer.go @@ -167,7 +167,7 @@ func (b Token) WriteToV2(m *acl.BearerToken) { // // Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4. // -// See also InvalidAt. +// See also [Token.ValidAt]. func (b *Token) SetExp(exp uint64) { b.exp = exp } @@ -184,7 +184,7 @@ func (b Token) Exp() uint64 { // // Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5. // -// See also InvalidAt. +// See also [Token.ValidAt]. func (b *Token) SetNbf(nbf uint64) { b.nbf = nbf } @@ -200,7 +200,7 @@ func (b Token) Nbf() uint64 { // // Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6. // -// See also InvalidAt. +// See also [Token.ValidAt]. func (b *Token) SetIat(iat uint64) { b.iat = iat } @@ -210,14 +210,19 @@ func (b Token) Iat() uint64 { return b.iat } +// ValidAt checks whether the Token is still valid at the given epoch according +// to its lifetime claims. +func (b Token) ValidAt(epoch uint64) bool { + return b.Nbf() <= epoch && b.Iat() <= epoch && b.Exp() >= epoch +} + // InvalidAt asserts "exp", "nbf" and "iat" claims for the given epoch. // // Zero Container is invalid in any epoch. // // See also SetExp, SetNbf, SetIat. -func (b Token) InvalidAt(epoch uint64) bool { - return b.Nbf() > epoch || b.Iat() > epoch || b.Exp() < epoch -} +// Deprecated: use inverse [Token.ValidAt] instead. +func (b Token) InvalidAt(epoch uint64) bool { return !b.ValidAt(epoch) } // SetEACLTable sets eacl.Table that replaces the one from the issuer's // container. If table has specified container, bearer token can be used only diff --git a/bearer/bearer_test.go b/bearer/bearer_test.go index 1dd7c2eb..8d3e5838 100644 --- a/bearer/bearer_test.go +++ b/bearer/bearer_test.go @@ -270,18 +270,26 @@ func TestToken_SetExp(t *testing.T) { func TestToken_InvalidAt(t *testing.T) { var val bearer.Token + require.True(t, val.ValidAt(0)) require.False(t, val.InvalidAt(0)) + require.False(t, val.ValidAt(1)) require.True(t, val.InvalidAt(1)) val.SetIat(1) val.SetNbf(2) val.SetExp(4) + require.False(t, val.ValidAt(0)) require.True(t, val.InvalidAt(0)) + require.False(t, val.ValidAt(1)) require.True(t, val.InvalidAt(1)) + require.True(t, val.ValidAt(2)) require.False(t, val.InvalidAt(2)) + require.True(t, val.ValidAt(3)) require.False(t, val.InvalidAt(3)) + require.True(t, val.ValidAt(4)) require.False(t, val.InvalidAt(4)) + require.False(t, val.ValidAt(5)) require.True(t, val.InvalidAt(5)) } diff --git a/session/common.go b/session/common.go index 6d74841d..f40a4610 100644 --- a/session/common.go +++ b/session/common.go @@ -244,7 +244,7 @@ func (x commonData) Exp() uint64 { // // Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5. // -// See also InvalidAt. +// See also ValidAt. func (x *commonData) SetNbf(nbf uint64) { x.nbf = nbf } @@ -260,7 +260,7 @@ func (x commonData) Nbf() uint64 { // // Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6. // -// See also InvalidAt. +// See also ValidAt. func (x *commonData) SetIat(iat uint64) { x.iat = iat } @@ -274,14 +274,19 @@ func (x commonData) expiredAt(epoch uint64) bool { return x.Exp() < epoch } +// ValidAt checks whether the token is still valid at the given epoch according +// to its lifetime claims. +func (x commonData) ValidAt(epoch uint64) bool { + return x.Nbf() <= epoch && x.Iat() <= epoch && x.Exp() >= epoch +} + // InvalidAt asserts "exp", "nbf" and "iat" claims. // // Zero session is invalid in any epoch. // // See also SetExp, SetNbf, SetIat. -func (x commonData) InvalidAt(epoch uint64) bool { - return x.expiredAt(epoch) || x.Nbf() > epoch || x.Iat() > epoch -} +// Deprecated: use inverse [Token.ValidAt] instead. +func (x commonData) InvalidAt(epoch uint64) bool { return !x.ValidAt(epoch) } // SetID sets a unique identifier for the session. The identifier value MUST be // assigned in a manner that ensures that there is a negligible probability diff --git a/session/common_test.go b/session/common_test.go index 417409b0..561ec2e5 100644 --- a/session/common_test.go +++ b/session/common_test.go @@ -226,13 +226,15 @@ func testLifetimeClaim[T session.Container | session.Object](t testing.TB, get f require.EqualValues(t, 5469830342, get(x)) } -func testInvalidAt[T interface { +func testValidAt[T interface { *session.Container | *session.Object SetExp(uint64) SetIat(uint64) SetNbf(uint64) + ValidAt(uint64) bool InvalidAt(uint64) bool }](t testing.TB, x T) { + require.True(t, x.ValidAt(0)) require.False(t, x.InvalidAt(0)) const iat = 13 @@ -243,16 +245,21 @@ func testInvalidAt[T interface { x.SetNbf(nbf) x.SetExp(exp) + require.False(t, x.ValidAt(iat-1)) require.True(t, x.InvalidAt(iat-1)) + require.False(t, x.ValidAt(iat)) require.True(t, x.InvalidAt(iat)) + require.True(t, x.ValidAt(nbf)) require.False(t, x.InvalidAt(nbf)) + require.True(t, x.ValidAt(exp)) require.False(t, x.InvalidAt(exp)) + require.False(t, x.ValidAt(exp+1)) require.True(t, x.InvalidAt(exp+1)) } func TestInvalidAt(t *testing.T) { - testInvalidAt(t, new(session.Container)) - testInvalidAt(t, new(session.Object)) + testValidAt(t, new(session.Container)) + testValidAt(t, new(session.Object)) } func testSetAuthKey[T session.Container | session.Object](t testing.TB, set func(*T, neofscrypto.PublicKey), assert func(T, neofscrypto.PublicKey) bool) { diff --git a/session/container_test.go b/session/container_test.go index e8b7b523..8a6040df 100644 --- a/session/container_test.go +++ b/session/container_test.go @@ -472,7 +472,7 @@ func TestContainer_ApplyOnlyTo(t *testing.T) { } func TestContainer_InvalidAt(t *testing.T) { - testInvalidAt(t, new(session.Container)) + testValidAt(t, new(session.Container)) } func TestContainer_ID(t *testing.T) { diff --git a/session/object_test.go b/session/object_test.go index 578d794c..6c5b427e 100644 --- a/session/object_test.go +++ b/session/object_test.go @@ -529,7 +529,7 @@ func TestObject_LimitByObjects(t *testing.T) { } func TestObject_InvalidAt(t *testing.T) { - testInvalidAt(t, new(session.Object)) + testValidAt(t, new(session.Object)) } func TestObject_ID(t *testing.T) {