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 }