github.com/cs3org/reva/v2@v2.27.7/pkg/storage/utils/eosfs/eosfs_test.go (about) 1 // Copyright 2018-2021 CERN 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // In applying this license, CERN does not waive the privileges and immunities 16 // granted to it by virtue of its status as an Intergovernmental Organization 17 // or submit itself to any jurisdiction. 18 19 //go:build eos 20 // +build eos 21 22 package eosfs 23 24 import ( 25 "context" 26 "os/exec" 27 "path" 28 "reflect" 29 "testing" 30 31 userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 32 provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" 33 ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" 34 "github.com/cs3org/reva/v2/pkg/eosclient" 35 "github.com/gdexlab/go-render/render" 36 "github.com/thanhpk/randstr" 37 ) 38 39 const ( 40 uid string = "0" 41 gid string = "0" 42 rootDir string = "/eos/homecanary/opstest/testacl/grants" 43 ) 44 45 func createTempDirectory(ctx context.Context, t *testing.T, eos *eosfs, rootDir string) (string, func()) { 46 path := path.Join(rootDir, randstr.String(8)) 47 err := eos.c.CreateDir(ctx, uid, gid, path) 48 if err != nil { 49 t.Fatalf("error creating temp folder %s: %v", path, err) 50 } 51 cleanup := func() { 52 err := eos.c.Remove(ctx, uid, gid, path) 53 if err != nil { 54 t.Fatalf("error deleting folder %s: %v", path, err) 55 } 56 } 57 return path, cleanup 58 } 59 60 func createTempFile(ctx context.Context, t *testing.T, eos *eosfs, dir string) (string, func()) { 61 path := path.Join(dir, randstr.String(8)) 62 err := eos.c.Touch(ctx, uid, gid, path) 63 if err != nil { 64 t.Fatalf("error creating new file %s: %v", path, err) 65 } 66 cleanup := func() { 67 err := eos.c.Remove(ctx, uid, gid, path) 68 if err != nil { 69 t.Fatalf("error deleting folder %s: %v", path, err) 70 } 71 } 72 return path, cleanup 73 } 74 75 // return true if the command exist 76 func commandExists(path string) bool { 77 _, err := exec.LookPath(path) 78 return err == nil 79 } 80 81 func TestAddGrant(t *testing.T) { 82 83 if !commandExists("/usr/bin/eos") { 84 t.Skip("/usr/bin/eos does not exist") 85 } 86 87 fs, err := NewEOSFS(&Config{ 88 MasterURL: "root://eoshomecanary.cern.ch", 89 UseGRPC: false, 90 ForceSingleUserMode: true, 91 }) 92 93 if err != nil { 94 t.Fatal("error creating a new EOS client:", err) 95 } 96 97 eos, ok := fs.(*eosfs) 98 if !ok { 99 t.Fatal("error creating a new EOS client:", err) 100 } 101 102 testCases := []struct { 103 description string 104 initial string 105 grant *provider.Grant 106 expected []*provider.Grant 107 }{ 108 { 109 description: "all-positive", 110 initial: "u:1:r,u:2:w,u:3:rw", 111 grant: &provider.Grant{ 112 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 113 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 114 }, 115 expected: []*provider.Grant{ 116 { 117 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 118 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 119 }, 120 { 121 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 122 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 123 }, 124 { 125 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 126 Permissions: &provider.ResourcePermissions{CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 127 }, 128 { 129 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 130 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true, CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 131 }, 132 }, 133 }, 134 { 135 description: "all-negative", 136 initial: "u:1:!r!w!x!m!u!d,u:2:!r!w!x!m!u!d,u:3:!r!w!x!m!u!d", 137 grant: &provider.Grant{ 138 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 139 Permissions: &provider.ResourcePermissions{}, 140 }, 141 expected: []*provider.Grant{ 142 { 143 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 144 Permissions: &provider.ResourcePermissions{}, 145 }, 146 { 147 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 148 Permissions: &provider.ResourcePermissions{}, 149 }, 150 { 151 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 152 Permissions: &provider.ResourcePermissions{}, 153 }, 154 { 155 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 156 Permissions: &provider.ResourcePermissions{}, 157 }, 158 }, 159 }, 160 { 161 description: "user-not-in-grant-list-add-positive", 162 initial: "u:1:rw,u:2:r,u:3:!r!w!x!m!u!d", 163 grant: &provider.Grant{ 164 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 165 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 166 }, 167 expected: []*provider.Grant{ 168 { 169 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 170 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 171 }, 172 { 173 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 174 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true, CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 175 }, 176 { 177 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 178 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 179 }, 180 { 181 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 182 Permissions: &provider.ResourcePermissions{}, 183 }, 184 }, 185 }, 186 { 187 description: "user-not-in-grant-list-add-negative", 188 initial: "u:1:rw,u:2:r,u:3:!r!w!x!m!u!d", 189 grant: &provider.Grant{ 190 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 191 Permissions: &provider.ResourcePermissions{}, 192 }, 193 expected: []*provider.Grant{ 194 { 195 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 196 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true, CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 197 }, 198 { 199 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 200 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 201 }, 202 { 203 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 204 Permissions: &provider.ResourcePermissions{}, 205 }, 206 { 207 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "9"}}}, 208 Permissions: &provider.ResourcePermissions{}, 209 }, 210 }, 211 }, 212 { 213 description: "user-in-grant-list-add-positive", 214 initial: "u:1:r,u:2:r,u:3:!r!w!x!m!u!d", 215 grant: &provider.Grant{ 216 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 217 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true, CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 218 }, 219 expected: []*provider.Grant{ 220 { 221 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 222 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 223 }, 224 { 225 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 226 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true, CreateContainer: true, InitiateFileUpload: true, Delete: true, Move: true}, 227 }, 228 { 229 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 230 Permissions: &provider.ResourcePermissions{}, 231 }, 232 }, 233 }, 234 { 235 description: "user-in-grant-list-add-negative", 236 initial: "u:1:r,u:2:r,u:3:!r!w!x!m!u!d", 237 grant: &provider.Grant{ 238 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 239 Permissions: &provider.ResourcePermissions{}, 240 }, 241 expected: []*provider.Grant{ 242 { 243 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "2"}}}, 244 Permissions: &provider.ResourcePermissions{Stat: true, InitiateFileDownload: true}, 245 }, 246 { 247 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "3"}}}, 248 Permissions: &provider.ResourcePermissions{}, 249 }, 250 { 251 Grantee: &provider.Grantee{Id: &provider.Grantee_UserId{UserId: &userv1beta1.UserId{OpaqueId: "1"}}}, 252 Permissions: &provider.ResourcePermissions{}, 253 }, 254 }, 255 }, 256 } 257 258 for _, test := range testCases { 259 260 t.Run(test.description, func(t *testing.T) { 261 ctx := ctxpkg.ContextSetUser(context.TODO(), &userv1beta1.User{ 262 UidNumber: 138406, 263 GidNumber: 2763, 264 }) 265 266 // test grants for a folder 267 dir, cleanupDir := createTempDirectory(ctx, t, eos, rootDir) 268 defer cleanupDir() 269 270 // set initial acls 271 err := eos.c.SetAttr(ctx, uid, gid, &eosclient.Attribute{Type: SystemAttr, Key: "acl", Val: test.initial}, true, dir) 272 if err != nil { 273 t.Fatal("error setting initial attributes:", err) 274 } 275 276 dirRef := &provider.Reference{Path: dir} 277 278 // set new grant 279 err = eos.AddGrant(ctx, dirRef, test.grant) 280 if err != nil { 281 t.Fatal("error adding grant:", err) 282 } 283 284 // check that the new grants list corresponds to expected result 285 grants, err := eos.ListGrants(ctx, dirRef) 286 if err != nil { 287 t.Fatal("error getting grants:", err) 288 } 289 290 if !reflect.DeepEqual(grants, test.expected) { 291 t.Fatalf("grants do not correspond in folder %s: got=%v expected=%v", dir, render.AsCode(grants), render.AsCode(test.expected)) 292 } 293 294 // test grants for a file 295 file, cleanupFile := createTempFile(ctx, t, eos, rootDir) 296 defer cleanupFile() 297 298 // set initial acls 299 err = eos.c.SetAttr(ctx, uid, gid, &eosclient.Attribute{Type: UserAttr, Key: "acl", Val: test.initial}, true, dir) 300 if err != nil { 301 t.Fatal("error setting initial attributes:", err) 302 } 303 304 fileRef := &provider.Reference{Path: file} 305 306 // set new grant 307 err = eos.AddGrant(ctx, fileRef, test.grant) 308 if err != nil { 309 t.Fatal("error adding grant:", err) 310 } 311 312 // check that the new grants list corresponds to expected result 313 grants, err = eos.ListGrants(ctx, fileRef) 314 if err != nil { 315 t.Fatal("error getting grants:", err) 316 } 317 318 if !reflect.DeepEqual(grants, test.expected) { 319 t.Fatalf("grants do not correspond in file %s: got=%v expected=%v", file, render.AsCode(grants), render.AsCode(test.expected)) 320 } 321 }) 322 323 } 324 325 }