git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/eacl/record_test.go (about)

     1  package eacl
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"fmt"
     6  	"testing"
     7  
     8  	v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
     9  	checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test"
    10  	cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
    11  	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
    12  	oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
    13  	usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
    14  	versiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version/test"
    15  	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestRecord(t *testing.T) {
    20  	record := NewRecord()
    21  	record.SetOperation(OperationRange)
    22  	record.SetAction(ActionAllow)
    23  	record.AddFilter(HeaderFromRequest, MatchStringEqual, "A", "B")
    24  	record.AddFilter(HeaderFromRequest, MatchStringNotEqual, "C", "D")
    25  
    26  	target := NewTarget()
    27  	target.SetRole(RoleSystem)
    28  	AddRecordTarget(record, target)
    29  
    30  	v2 := record.ToV2()
    31  	require.NotNil(t, v2)
    32  	require.Equal(t, v2acl.OperationRange, v2.GetOperation())
    33  	require.Equal(t, v2acl.ActionAllow, v2.GetAction())
    34  	require.Len(t, v2.GetFilters(), len(record.Filters()))
    35  	require.Len(t, v2.GetTargets(), len(record.Targets()))
    36  
    37  	newRecord := NewRecordFromV2(v2)
    38  	require.Equal(t, record, newRecord)
    39  
    40  	t.Run("create record", func(t *testing.T) {
    41  		record := CreateRecord(ActionAllow, OperationGet)
    42  		require.Equal(t, ActionAllow, record.Action())
    43  		require.Equal(t, OperationGet, record.Operation())
    44  	})
    45  
    46  	t.Run("new from nil v2 record", func(t *testing.T) {
    47  		require.Equal(t, new(Record), NewRecordFromV2(nil))
    48  	})
    49  }
    50  
    51  func TestAddFormedTarget(t *testing.T) {
    52  	items := []struct {
    53  		role Role
    54  		keys []ecdsa.PublicKey
    55  	}{
    56  		{
    57  			role: RoleUnknown,
    58  			keys: []ecdsa.PublicKey{*randomPublicKey(t)},
    59  		},
    60  		{
    61  			role: RoleSystem,
    62  			keys: []ecdsa.PublicKey{},
    63  		},
    64  	}
    65  
    66  	targets := make([]Target, len(items))
    67  
    68  	r := NewRecord()
    69  
    70  	for i := range items {
    71  		targets[i].SetRole(items[i].role)
    72  		SetTargetECDSAKeys(&targets[i], ecdsaKeysToPtrs(items[i].keys)...)
    73  		AddFormedTarget(r, items[i].role, items[i].keys...)
    74  	}
    75  
    76  	tgts := r.Targets()
    77  	require.Len(t, tgts, len(targets))
    78  
    79  	for _, tgt := range targets {
    80  		require.Contains(t, tgts, tgt)
    81  	}
    82  }
    83  
    84  func TestRecord_AddFilter(t *testing.T) {
    85  	filters := []Filter{
    86  		*newObjectFilter(MatchStringEqual, "some name", "ContainerID"),
    87  		*newObjectFilter(MatchStringNotEqual, "X-Header-Name", "X-Header-Value"),
    88  	}
    89  
    90  	r := NewRecord()
    91  	for _, filter := range filters {
    92  		r.AddFilter(filter.From(), filter.Matcher(), filter.Key(), filter.Value())
    93  	}
    94  
    95  	require.Equal(t, filters, r.Filters())
    96  }
    97  
    98  func TestRecordEncoding(t *testing.T) {
    99  	r := NewRecord()
   100  	r.SetOperation(OperationHead)
   101  	r.SetAction(ActionDeny)
   102  	r.AddObjectAttributeFilter(MatchStringEqual, "key", "value")
   103  	AddFormedTarget(r, RoleSystem, *randomPublicKey(t))
   104  
   105  	t.Run("binary", func(t *testing.T) {
   106  		data, err := r.Marshal()
   107  		require.NoError(t, err)
   108  
   109  		r2 := NewRecord()
   110  		require.NoError(t, r2.Unmarshal(data))
   111  
   112  		require.Equal(t, r, r2)
   113  	})
   114  
   115  	t.Run("json", func(t *testing.T) {
   116  		data, err := r.MarshalJSON()
   117  		require.NoError(t, err)
   118  
   119  		r2 := NewRecord()
   120  		require.NoError(t, r2.UnmarshalJSON(data))
   121  
   122  		require.Equal(t, r, r2)
   123  	})
   124  }
   125  
   126  func TestRecord_ToV2(t *testing.T) {
   127  	t.Run("nil", func(t *testing.T) {
   128  		var x *Record
   129  
   130  		require.Nil(t, x.ToV2())
   131  	})
   132  
   133  	t.Run("default values", func(t *testing.T) {
   134  		record := NewRecord()
   135  
   136  		// check initial values
   137  		require.Equal(t, OperationUnknown, record.Operation())
   138  		require.Equal(t, ActionUnknown, record.Action())
   139  		require.Nil(t, record.Targets())
   140  		require.Nil(t, record.Filters())
   141  
   142  		// convert to v2 message
   143  		recordV2 := record.ToV2()
   144  
   145  		require.Equal(t, v2acl.OperationUnknown, recordV2.GetOperation())
   146  		require.Equal(t, v2acl.ActionUnknown, recordV2.GetAction())
   147  		require.Nil(t, recordV2.GetTargets())
   148  		require.Nil(t, recordV2.GetFilters())
   149  	})
   150  }
   151  
   152  func TestReservedRecords(t *testing.T) {
   153  	var (
   154  		v       = versiontest.Version()
   155  		oid     = oidtest.ID()
   156  		cid     = cidtest.ID()
   157  		ownerid = usertest.ID()
   158  		h       = checksumtest.Checksum()
   159  		typ     = new(object.Type)
   160  	)
   161  
   162  	testSuit := []struct {
   163  		f     func(r *Record)
   164  		key   string
   165  		value string
   166  	}{
   167  		{
   168  			f:     func(r *Record) { r.AddObjectAttributeFilter(MatchStringEqual, "foo", "bar") },
   169  			key:   "foo",
   170  			value: "bar",
   171  		},
   172  		{
   173  			f:     func(r *Record) { r.AddObjectVersionFilter(MatchStringEqual, &v) },
   174  			key:   v2acl.FilterObjectVersion,
   175  			value: v.String(),
   176  		},
   177  		{
   178  			f:     func(r *Record) { r.AddObjectIDFilter(MatchStringEqual, oid) },
   179  			key:   v2acl.FilterObjectID,
   180  			value: oid.EncodeToString(),
   181  		},
   182  		{
   183  			f:     func(r *Record) { r.AddObjectContainerIDFilter(MatchStringEqual, cid) },
   184  			key:   v2acl.FilterObjectContainerID,
   185  			value: cid.EncodeToString(),
   186  		},
   187  		{
   188  			f:     func(r *Record) { r.AddObjectOwnerIDFilter(MatchStringEqual, ownerid) },
   189  			key:   v2acl.FilterObjectOwnerID,
   190  			value: ownerid.EncodeToString(),
   191  		},
   192  		{
   193  			f:     func(r *Record) { r.AddObjectCreationEpoch(MatchStringEqual, 100) },
   194  			key:   v2acl.FilterObjectCreationEpoch,
   195  			value: "100",
   196  		},
   197  		{
   198  			f:     func(r *Record) { r.AddObjectPayloadLengthFilter(MatchStringEqual, 5000) },
   199  			key:   v2acl.FilterObjectPayloadLength,
   200  			value: "5000",
   201  		},
   202  		{
   203  			f:     func(r *Record) { r.AddObjectPayloadHashFilter(MatchStringEqual, h) },
   204  			key:   v2acl.FilterObjectPayloadHash,
   205  			value: h.String(),
   206  		},
   207  		{
   208  			f:     func(r *Record) { r.AddObjectHomomorphicHashFilter(MatchStringEqual, h) },
   209  			key:   v2acl.FilterObjectHomomorphicHash,
   210  			value: h.String(),
   211  		},
   212  		{
   213  			f: func(r *Record) {
   214  				require.True(t, typ.FromString("REGULAR"))
   215  				r.AddObjectTypeFilter(MatchStringEqual, *typ)
   216  			},
   217  			key:   v2acl.FilterObjectType,
   218  			value: "REGULAR",
   219  		},
   220  		{
   221  			f: func(r *Record) {
   222  				require.True(t, typ.FromString("TOMBSTONE"))
   223  				r.AddObjectTypeFilter(MatchStringEqual, *typ)
   224  			},
   225  			key:   v2acl.FilterObjectType,
   226  			value: "TOMBSTONE",
   227  		},
   228  	}
   229  
   230  	for n, testCase := range testSuit {
   231  		desc := fmt.Sprintf("case #%d", n)
   232  		record := NewRecord()
   233  		testCase.f(record)
   234  		require.Len(t, record.Filters(), 1, desc)
   235  		f := record.Filters()[0]
   236  		require.Equal(t, f.Key(), testCase.key, desc)
   237  		require.Equal(t, f.Value(), testCase.value, desc)
   238  	}
   239  }
   240  
   241  func randomPublicKey(t *testing.T) *ecdsa.PublicKey {
   242  	p, err := keys.NewPrivateKey()
   243  	require.NoError(t, err)
   244  	return &p.PrivateKey.PublicKey
   245  }