package accessbox import ( "encoding/hex" "testing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) func assertBearerToken(t *testing.T, exp, act bearer.Token) { // compare binary representations since deep equal is not guaranteed require.Equal(t, exp.Marshal(), act.Marshal()) } func TestTokensEncryptDecrypt(t *testing.T) { var ( tkn bearer.Token tkn2 bearer.Token ) sec, err := keys.NewPrivateKey() require.NoError(t, err) cred, err := keys.NewPrivateKey() require.NoError(t, err) tkn.SetEACLTable(*eacl.NewTable()) require.NoError(t, tkn.Sign(sec.PrivateKey)) data, err := encrypt(cred, cred.PublicKey(), tkn.Marshal()) require.NoError(t, err) rawTkn2, err := decrypt(cred, cred.PublicKey(), data) require.NoError(t, err) err = tkn2.Unmarshal(rawTkn2) require.NoError(t, err) assertBearerToken(t, tkn, tkn2) } func TestBearerTokenInAccessBox(t *testing.T) { var ( box *AccessBox box2 AccessBox tkn bearer.Token ) sec, err := keys.NewPrivateKey() require.NoError(t, err) cred, err := keys.NewPrivateKey() require.NoError(t, err) tkn.SetEACLTable(*eacl.NewTable()) require.NoError(t, tkn.Sign(sec.PrivateKey)) gate := NewGateData(cred.PublicKey(), &tkn) box, _, err = PackTokens([]*GateData{gate}, nil, false) require.NoError(t, err) data, err := box.Marshal() require.NoError(t, err) err = box2.Unmarshal(data) require.NoError(t, err) tkns, err := box2.GetTokens(cred) require.NoError(t, err) assertBearerToken(t, tkn, *tkns.BearerToken) } func TestSessionTokenInAccessBox(t *testing.T) { var ( box *AccessBox box2 AccessBox tkn = new(session.Container) ) sec, err := keys.NewPrivateKey() require.NoError(t, err) cred, err := keys.NewPrivateKey() require.NoError(t, err) tkn.SetID(uuid.New()) tkn.SetAuthKey((*frostfsecdsa.PublicKey)(sec.PublicKey())) require.NoError(t, tkn.Sign(sec.PrivateKey)) var newTkn bearer.Token gate := NewGateData(cred.PublicKey(), &newTkn) gate.SessionTokens = []*session.Container{tkn} box, _, err = PackTokens([]*GateData{gate}, nil, false) require.NoError(t, err) data, err := box.Marshal() require.NoError(t, err) err = box2.Unmarshal(data) require.NoError(t, err) tkns, err := box2.GetTokens(cred) require.NoError(t, err) require.Equal(t, []*session.Container{tkn}, tkns.SessionTokens) } func TestAccessboxMultipleKeys(t *testing.T) { var ( box *AccessBox tkn bearer.Token ) sec, err := keys.NewPrivateKey() require.NoError(t, err) tkn.SetEACLTable(*eacl.NewTable()) require.NoError(t, tkn.Sign(sec.PrivateKey)) count := 10 gates := make([]*GateData, 0, count) privateKeys := make([]*keys.PrivateKey, 0, count) { // generate keys for i := 0; i < count; i++ { cred, err := keys.NewPrivateKey() require.NoError(t, err) gates = append(gates, NewGateData(cred.PublicKey(), &tkn)) privateKeys = append(privateKeys, cred) } } box, _, err = PackTokens(gates, nil, false) require.NoError(t, err) for i, k := range privateKeys { tkns, err := box.GetTokens(k) require.NoError(t, err, "key #%d: %s failed", i, k) assertBearerToken(t, tkn, *tkns.BearerToken) } } func TestUnknownKey(t *testing.T) { var ( box *AccessBox tkn bearer.Token ) sec, err := keys.NewPrivateKey() require.NoError(t, err) cred, err := keys.NewPrivateKey() require.NoError(t, err) wrongCred, err := keys.NewPrivateKey() require.NoError(t, err) tkn.SetEACLTable(*eacl.NewTable()) require.NoError(t, tkn.Sign(sec.PrivateKey)) gate := NewGateData(cred.PublicKey(), &tkn) box, _, err = PackTokens([]*GateData{gate}, nil, false) require.NoError(t, err) _, err = box.GetTokens(wrongCred) require.Error(t, err) } func TestGateDataSessionToken(t *testing.T) { cred, err := keys.NewPrivateKey() require.NoError(t, err) var tkn bearer.Token gate := NewGateData(cred.PublicKey(), &tkn) require.Equal(t, cred.PublicKey(), gate.GateKey) assertBearerToken(t, tkn, *gate.BearerToken) t.Run("session token for put", func(t *testing.T) { gate.SessionTokens = []*session.Container{} sessionTkn := gate.SessionTokenForPut() require.Nil(t, sessionTkn) sessionTknPut := new(session.Container) sessionTknPut.ForVerb(session.VerbContainerPut) gate.SessionTokens = []*session.Container{sessionTknPut} sessionTkn = gate.SessionTokenForPut() require.Equal(t, sessionTknPut, sessionTkn) }) t.Run("session token for delete", func(t *testing.T) { gate.SessionTokens = []*session.Container{} sessionTkn := gate.SessionTokenForDelete() require.Nil(t, sessionTkn) sessionTknDelete := new(session.Container) sessionTknDelete.ForVerb(session.VerbContainerDelete) gate.SessionTokens = []*session.Container{sessionTknDelete} sessionTkn = gate.SessionTokenForDelete() require.Equal(t, sessionTknDelete, sessionTkn) }) t.Run("session token", func(t *testing.T) { gate.SessionTokens = []*session.Container{} sessionTkn := gate.SessionToken() require.Nil(t, sessionTkn) sessionTknPut := new(session.Container) sessionTknPut.ForVerb(session.VerbContainerPut) gate.SessionTokens = []*session.Container{sessionTknPut} sessionTkn = gate.SessionToken() require.Equal(t, sessionTkn, sessionTknPut) }) } func TestGetBox(t *testing.T) { cred, err := keys.NewPrivateKey() require.NoError(t, err) var tkn bearer.Token gate := NewGateData(cred.PublicKey(), &tkn) secret := []byte("secret") t.Run("regular secret", func(t *testing.T) { accessBox, secrets, err := PackTokens([]*GateData{gate}, secret, false) require.NoError(t, err) require.Equal(t, hex.EncodeToString(secret), secrets.SecretKey) box, err := accessBox.GetBox(cred) require.NoError(t, err) require.Equal(t, hex.EncodeToString(secret), box.Gate.SecretKey) }) t.Run("custom secret", func(t *testing.T) { accessBox, secrets, err := PackTokens([]*GateData{gate}, secret, true) require.NoError(t, err) require.Equal(t, string(secret), secrets.SecretKey) box, err := accessBox.GetBox(cred) require.NoError(t, err) require.Equal(t, string(secret), box.Gate.SecretKey) }) } func TestAccessBox(t *testing.T) { cred, err := keys.NewPrivateKey() require.NoError(t, err) var tkn bearer.Token gate := NewGateData(cred.PublicKey(), &tkn) accessBox, _, err := PackTokens([]*GateData{gate}, nil, false) require.NoError(t, err) t.Run("invalid owner", func(t *testing.T) { randomKey, err := keys.NewPrivateKey() require.NoError(t, err) _, err = accessBox.GetTokens(randomKey) require.Error(t, err) _, err = accessBox.GetBox(randomKey) require.Error(t, err) }) t.Run("empty placement policy", func(t *testing.T) { policy, err := accessBox.GetPlacementPolicy() require.NoError(t, err) require.Nil(t, policy) }) t.Run("get correct placement policy", func(t *testing.T) { policy := &AccessBox_ContainerPolicy{LocationConstraint: "locationConstraint"} accessBox.ContainerPolicy = []*AccessBox_ContainerPolicy{policy} policies, err := accessBox.GetPlacementPolicy() require.NoError(t, err) require.Len(t, policies, 1) require.Equal(t, policy.LocationConstraint, policies[0].LocationConstraint) }) t.Run("get incorrect placement policy", func(t *testing.T) { policy := &AccessBox_ContainerPolicy{ LocationConstraint: "locationConstraint", Policy: []byte("policy"), } accessBox.ContainerPolicy = []*AccessBox_ContainerPolicy{policy} _, err = accessBox.GetPlacementPolicy() require.Error(t, err) _, err = accessBox.GetBox(cred) require.Error(t, err) }) t.Run("empty seed key", func(t *testing.T) { accessBox.SeedKey = nil _, err = accessBox.GetTokens(cred) require.Error(t, err) _, err = accessBox.GetBox(cred) require.Error(t, err) }) t.Run("invalid gate key", func(t *testing.T) { gate = &GateData{ BearerToken: &tkn, GateKey: &keys.PublicKey{}, } _, _, err = PackTokens([]*GateData{gate}, nil, false) require.Error(t, err) }) }