frostfs-node/pkg/services/object/acl/eacl/v2/eacl_test.go

167 lines
4.0 KiB
Go

package v2
import (
"context"
"crypto/ecdsa"
"errors"
"testing"
objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
type testLocalStorage struct {
t *testing.T
expAddr oid.Address
obj *objectSDK.Object
err error
}
func (s *testLocalStorage) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
require.True(s.t, addr.Container().Equals(s.expAddr.Container()))
require.True(s.t, addr.Object().Equals(s.expAddr.Object()))
return s.obj, s.err
}
func testXHeaders(strs ...string) []session.XHeader {
res := make([]session.XHeader, len(strs)/2)
for i := 0; i < len(strs); i += 2 {
res[i/2].SetKey(strs[i])
res[i/2].SetValue(strs[i+1])
}
return res
}
func TestHeadRequest(t *testing.T) {
req := new(objectV2.HeadRequest)
meta := new(session.RequestMetaHeader)
req.SetMetaHeader(meta)
body := new(objectV2.HeadRequestBody)
req.SetBody(body)
addr := oidtest.Address()
var addrV2 refs.Address
addr.WriteToV2(&addrV2)
body.SetAddress(&addrV2)
xKey := "x-key"
xVal := "x-val"
xHdrs := testXHeaders(
xKey, xVal,
)
meta.SetXHeaders(xHdrs)
obj := objectSDK.New()
attrKey := "attr_key"
attrVal := "attr_val"
var attr objectSDK.Attribute
attr.SetKey(attrKey)
attr.SetValue(attrVal)
obj.SetAttributes(attr)
table := new(eaclSDK.Table)
priv, err := keys.NewPrivateKey()
require.NoError(t, err)
senderKey := priv.PublicKey()
r := eaclSDK.NewRecord()
r.SetOperation(eaclSDK.OperationHead)
r.SetAction(eaclSDK.ActionDeny)
r.AddFilter(eaclSDK.HeaderFromObject, eaclSDK.MatchStringEqual, attrKey, attrVal)
r.AddFilter(eaclSDK.HeaderFromRequest, eaclSDK.MatchStringEqual, xKey, xVal)
eaclSDK.AddFormedTarget(r, eaclSDK.RoleUnknown, (ecdsa.PublicKey)(*senderKey))
table.AddRecord(r)
lStorage := &testLocalStorage{
t: t,
expAddr: addr,
obj: obj,
}
id := addr.Object()
newSource := func(t *testing.T) eaclSDK.TypedHeaderSource {
hdrSrc, err := NewMessageHeaderSource(
lStorage,
NewRequestXHeaderSource(req),
addr.Container(),
WithOID(&id))
require.NoError(t, err)
return hdrSrc
}
cnr := addr.Container()
unit := new(eaclSDK.ValidationUnit).
WithContainerID(&cnr).
WithOperation(eaclSDK.OperationHead).
WithSenderKey(senderKey.Bytes()).
WithEACLTable(table)
validator := eaclSDK.NewValidator()
checkAction(t, eaclSDK.ActionDeny, validator, unit.WithHeaderSource(newSource(t)))
meta.SetXHeaders(nil)
checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t)))
meta.SetXHeaders(xHdrs)
obj.SetAttributes()
checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t)))
lStorage.err = errors.New("any error")
checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t)))
r.SetAction(eaclSDK.ActionAllow)
rID := eaclSDK.NewRecord()
rID.SetOperation(eaclSDK.OperationHead)
rID.SetAction(eaclSDK.ActionDeny)
rID.AddObjectIDFilter(eaclSDK.MatchStringEqual, addr.Object())
eaclSDK.AddFormedTarget(rID, eaclSDK.RoleUnknown, (ecdsa.PublicKey)(*senderKey))
table = eaclSDK.NewTable()
table.AddRecord(r)
table.AddRecord(rID)
unit.WithEACLTable(table)
checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t)))
}
func checkAction(t *testing.T, expected eaclSDK.Action, v *eaclSDK.Validator, u *eaclSDK.ValidationUnit) {
actual, fromRule := v.CalculateAction(u)
require.True(t, fromRule)
require.Equal(t, expected, actual)
}
func checkDefaultAction(t *testing.T, v *eaclSDK.Validator, u *eaclSDK.ValidationUnit) {
actual, fromRule := v.CalculateAction(u)
require.False(t, fromRule)
require.Equal(t, eaclSDK.ActionAllow, actual)
}