frostfs-sdk-go/bearer/bearer_test.go
Denis Kirillov 15b4287092 [#49] bearer: Allow empty eacl if token is impersonated
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-05-05 12:45:39 +03:00

394 lines
8.2 KiB
Go

package bearer_test
import (
"bytes"
"math/rand"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test"
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
eacltest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl/test"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
// compares binary representations of two eacl.Table instances.
func isEqualEACLTables(t1, t2 eacl.Table) bool {
d1, err := t1.Marshal()
if err != nil {
panic(err)
}
d2, err := t2.Marshal()
if err != nil {
panic(err)
}
return bytes.Equal(d1, d2)
}
func TestToken_SetEACLTable(t *testing.T) {
var val bearer.Token
var m acl.BearerToken
filled := bearertest.Token()
val.WriteToV2(&m)
require.Zero(t, m.GetBody())
val2 := filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
require.Zero(t, val2.EACLTable())
val2 = filled
jd, err := val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
require.Zero(t, val2.EACLTable())
// set value
eaclTable := *eacltest.Table()
val.SetEACLTable(eaclTable)
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
val.WriteToV2(&m)
eaclTableV2 := eaclTable.ToV2()
require.Equal(t, eaclTableV2, m.GetBody().GetEACL())
val2 = filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
val2 = filled
jd, err = val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
require.True(t, isEqualEACLTables(eaclTable, val.EACLTable()))
}
func TestToken_ForUser(t *testing.T) {
var val bearer.Token
var m acl.BearerToken
filled := bearertest.Token()
val.WriteToV2(&m)
require.Zero(t, m.GetBody())
val2 := filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
val2.WriteToV2(&m)
require.Zero(t, m.GetBody())
val2 = filled
jd, err := val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
val2.WriteToV2(&m)
require.Zero(t, m.GetBody())
// set value
usr := *usertest.ID()
var usrV2 refs.OwnerID
usr.WriteToV2(&usrV2)
val.ForUser(usr)
val.WriteToV2(&m)
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
val2 = filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
val2.WriteToV2(&m)
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
val2 = filled
jd, err = val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
val2.WriteToV2(&m)
require.Equal(t, usrV2, *m.GetBody().GetOwnerID())
}
func testLifetimeClaim(t *testing.T, setter func(*bearer.Token, uint64), getter func(*acl.BearerToken) uint64) {
var val bearer.Token
var m acl.BearerToken
filled := bearertest.Token()
val.WriteToV2(&m)
require.Zero(t, m.GetBody())
val2 := filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
val2.WriteToV2(&m)
require.Zero(t, m.GetBody())
val2 = filled
jd, err := val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
val2.WriteToV2(&m)
require.Zero(t, m.GetBody())
// set value
exp := rand.Uint64()
setter(&val, exp)
val.WriteToV2(&m)
require.Equal(t, exp, getter(&m))
val2 = filled
require.NoError(t, val2.Unmarshal(val.Marshal()))
val2.WriteToV2(&m)
require.Equal(t, exp, getter(&m))
val2 = filled
jd, err = val.MarshalJSON()
require.NoError(t, err)
require.NoError(t, val2.UnmarshalJSON(jd))
val2.WriteToV2(&m)
require.Equal(t, exp, getter(&m))
}
func TestToken_SetLifetime(t *testing.T) {
t.Run("iat", func(t *testing.T) {
testLifetimeClaim(t, (*bearer.Token).SetIat, func(token *acl.BearerToken) uint64 {
return token.GetBody().GetLifetime().GetIat()
})
})
t.Run("nbf", func(t *testing.T) {
testLifetimeClaim(t, (*bearer.Token).SetNbf, func(token *acl.BearerToken) uint64 {
return token.GetBody().GetLifetime().GetNbf()
})
})
t.Run("exp", func(t *testing.T) {
testLifetimeClaim(t, (*bearer.Token).SetExp, func(token *acl.BearerToken) uint64 {
return token.GetBody().GetLifetime().GetExp()
})
})
}
func TestToken_InvalidAt(t *testing.T) {
var val bearer.Token
require.True(t, val.InvalidAt(0))
require.True(t, val.InvalidAt(1))
val.SetIat(1)
val.SetNbf(2)
val.SetExp(4)
require.True(t, val.InvalidAt(0))
require.True(t, val.InvalidAt(1))
require.False(t, val.InvalidAt(2))
require.False(t, val.InvalidAt(3))
require.False(t, val.InvalidAt(4))
require.True(t, val.InvalidAt(5))
}
func TestToken_AssertContainer(t *testing.T) {
var val bearer.Token
cnr := cidtest.ID()
require.True(t, val.AssertContainer(cnr))
eaclTable := *eacltest.Table()
eaclTable.SetCID(cidtest.ID())
val.SetEACLTable(eaclTable)
require.False(t, val.AssertContainer(cnr))
eaclTable.SetCID(cnr)
val.SetEACLTable(eaclTable)
require.True(t, val.AssertContainer(cnr))
}
func TestToken_AssertUser(t *testing.T) {
var val bearer.Token
usr := *usertest.ID()
require.True(t, val.AssertUser(usr))
val.ForUser(*usertest.ID())
require.False(t, val.AssertUser(usr))
val.ForUser(usr)
require.True(t, val.AssertUser(usr))
}
func TestToken_Sign(t *testing.T) {
var val bearer.Token
require.False(t, val.VerifySignature())
k, err := keys.NewPrivateKey()
require.NoError(t, err)
key := k.PrivateKey
val = bearertest.Token()
require.NoError(t, val.Sign(key))
require.True(t, val.VerifySignature())
var m acl.BearerToken
val.WriteToV2(&m)
require.NotZero(t, m.GetSignature().GetKey())
require.NotZero(t, m.GetSignature().GetSign())
val2 := bearertest.Token()
require.NoError(t, val2.Unmarshal(val.Marshal()))
require.True(t, val2.VerifySignature())
jd, err := val.MarshalJSON()
require.NoError(t, err)
val2 = bearertest.Token()
require.NoError(t, val2.UnmarshalJSON(jd))
require.True(t, val2.VerifySignature())
}
func TestToken_ReadFromV2(t *testing.T) {
var val bearer.Token
var m acl.BearerToken
require.Error(t, val.ReadFromV2(m))
var body acl.BearerTokenBody
m.SetBody(&body)
require.Error(t, val.ReadFromV2(m))
eaclTable := eacltest.Table().ToV2()
body.SetEACL(eaclTable)
require.Error(t, val.ReadFromV2(m))
var lifetime acl.TokenLifetime
body.SetLifetime(&lifetime)
require.Error(t, val.ReadFromV2(m))
const iat, nbf, exp = 1, 2, 3
lifetime.SetIat(iat)
lifetime.SetNbf(nbf)
lifetime.SetExp(exp)
body.SetLifetime(&lifetime)
require.Error(t, val.ReadFromV2(m))
var sig refs.Signature
m.SetSignature(&sig)
require.NoError(t, val.ReadFromV2(m))
body.SetEACL(nil)
body.SetImpersonate(true)
require.NoError(t, val.ReadFromV2(m))
var m2 acl.BearerToken
val.WriteToV2(&m2)
require.Equal(t, m, m2)
usr, usr2 := *usertest.ID(), *usertest.ID()
require.True(t, val.AssertUser(usr))
require.True(t, val.AssertUser(usr2))
var usrV2 refs.OwnerID
usr.WriteToV2(&usrV2)
body.SetOwnerID(&usrV2)
require.NoError(t, val.ReadFromV2(m))
val.WriteToV2(&m2)
require.Equal(t, m, m2)
require.True(t, val.AssertUser(usr))
require.False(t, val.AssertUser(usr2))
k, err := keys.NewPrivateKey()
require.NoError(t, err)
signer := frostfsecdsa.Signer(k.PrivateKey)
var s frostfscrypto.Signature
require.NoError(t, s.Calculate(signer, body.StableMarshal(nil)))
s.WriteToV2(&sig)
require.NoError(t, val.ReadFromV2(m))
require.True(t, val.VerifySignature())
require.Equal(t, sig.GetKey(), val.SigningKeyBytes())
}
func TestResolveIssuer(t *testing.T) {
k, err := keys.NewPrivateKey()
require.NoError(t, err)
var val bearer.Token
require.Zero(t, bearer.ResolveIssuer(val))
var m acl.BearerToken
var sig refs.Signature
sig.SetKey([]byte("invalid key"))
m.SetSignature(&sig)
require.NoError(t, val.Unmarshal(m.StableMarshal(nil)))
require.Zero(t, bearer.ResolveIssuer(val))
require.NoError(t, val.Sign(k.PrivateKey))
var usr user.ID
user.IDFromKey(&usr, k.PrivateKey.PublicKey)
require.Equal(t, usr, bearer.ResolveIssuer(val))
}