github.com/hpcng/singularity@v3.1.1+incompatible/pkg/util/capabilities/config_test.go (about) 1 // Copyright (c) 2018-2019, Sylabs Inc. All rights reserved. 2 // This software is licensed under a 3-clause BSD license. Please consult the 3 // LICENSE.md file distributed with the sources of this project regarding your 4 // rights to use or distribute this software. 5 6 package capabilities 7 8 import ( 9 "bytes" 10 "reflect" 11 "testing" 12 ) 13 14 type readFromTest struct { 15 c Config 16 shouldFail bool 17 } 18 19 type readWriteTest struct { 20 name string 21 c Config 22 } 23 24 func TestReadFromWriteTo(t *testing.T) { 25 testsPass := []readWriteTest{ 26 readWriteTest{ 27 name: "empty config", 28 c: Config{ 29 Users: map[string][]string{}, 30 Groups: map[string][]string{}, 31 }, 32 }, 33 readWriteTest{ 34 name: "config with stuff", 35 c: Config{ 36 Users: map[string][]string{ 37 "user1": []string{"CAP_SYS_ADMIN"}, 38 "user2": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 39 }, 40 Groups: map[string][]string{ 41 "user1": []string{"CAP_SYS_ADMIN"}, 42 "user2": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 43 }, 44 }, 45 }, 46 } 47 48 for _, test := range testsPass { 49 t.Run(test.name, func(t *testing.T) { 50 var r bytes.Buffer 51 52 test.c.WriteTo(&r) 53 54 new, err := ReadFrom(&r) 55 if err != nil { 56 t.Errorf("unexpected failure running %s test: %s", test.name, err) 57 } 58 59 if !reflect.DeepEqual(test.c, *new) { 60 t.Errorf("failed to read/write config:\n\thave: %v\n\twant: %v", test.c, *new) 61 } 62 }) 63 } 64 65 t.Run("empty config no data", func(t *testing.T) { 66 var r bytes.Buffer 67 68 _, err := ReadFrom(&r) 69 70 if err != nil { 71 t.Errorf("unexpected failure running %s test: %s", t.Name(), err) 72 } 73 74 }) 75 76 } 77 78 func checkReadFrom(t *testing.T, confExpected Config, shouldFail bool) { 79 var r *bytes.Buffer 80 81 confExpected.WriteTo(r) 82 83 confActual, err := ReadFrom(r) 84 if err == nil && shouldFail { 85 t.Errorf("unexpected success running test") 86 return 87 } else if err != nil && !shouldFail { 88 t.Errorf("unexpected failure running test") 89 return 90 } 91 92 if !reflect.DeepEqual(confExpected, *confActual) { 93 t.Errorf("ReadFrom returned incorrect capability config") 94 } 95 } 96 97 type capTest struct { 98 name string 99 old Config 100 new Config 101 id string 102 caps []string 103 } 104 105 func TestAddUserCaps(t *testing.T) { 106 testsPass := []capTest{ 107 capTest{ 108 name: "add existing user single cap", 109 old: Config{ 110 Users: map[string][]string{ 111 "root": []string{"CAP_SYS_ADMIN"}, 112 }, 113 }, 114 new: Config{ 115 Users: map[string][]string{ 116 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 117 }, 118 }, 119 id: "root", 120 caps: []string{"CAP_DAC_OVERRIDE"}, 121 }, 122 capTest{ 123 name: "add existing user multiple caps", 124 old: Config{ 125 Users: map[string][]string{ 126 "user1": []string{"CAP_SYS_ADMIN"}, 127 }, 128 }, 129 new: Config{ 130 Users: map[string][]string{ 131 "user1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 132 }, 133 }, 134 id: "user1", 135 caps: []string{"CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 136 }, 137 capTest{ 138 name: "add new user", 139 old: Config{ 140 Users: map[string][]string{ 141 "root": []string{"CAP_SYS_ADMIN"}, 142 }, 143 }, 144 new: Config{ 145 Users: map[string][]string{ 146 "root": []string{"CAP_SYS_ADMIN"}, 147 "user1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 148 }, 149 }, 150 id: "user1", 151 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 152 }, 153 capTest{ 154 name: "add duplicate cap", 155 old: Config{ 156 Users: map[string][]string{ 157 "root": []string{"CAP_SYS_ADMIN"}, 158 }, 159 }, 160 new: Config{ 161 Users: map[string][]string{ 162 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 163 }, 164 }, 165 id: "root", 166 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 167 }, 168 } 169 170 for _, test := range testsPass { 171 t.Run(test.name, func(t *testing.T) { 172 if err := test.old.AddUserCaps(test.id, test.caps); err != nil { 173 t.Error("failed to add capability to config") 174 } 175 176 if !reflect.DeepEqual(test.old, test.new) { 177 t.Errorf("AddUserCaps failed to set config:\n\thave: %v\n\twant: %v", test.old, test.new) 178 } 179 }) 180 } 181 182 testFail := capTest{ 183 name: "add bad cap fail", 184 old: Config{ 185 Users: map[string][]string{ 186 "root": []string{"CAP_SYS_ADMIN"}, 187 }, 188 }, 189 new: Config{ 190 Users: map[string][]string{ 191 "root": []string{"CAP_SYS_ADMIN"}, 192 }, 193 }, 194 id: "root", 195 caps: []string{"CAP_BAD_WRONG_INCORRECT_BAD"}, 196 } 197 198 t.Run(testFail.name, func(t *testing.T) { 199 if err := testFail.old.AddUserCaps(testFail.id, testFail.caps); err == nil { 200 t.Error("unexpected success adding non-existent capability") 201 } 202 }) 203 } 204 205 func TestAddGroupCaps(t *testing.T) { 206 testsPass := []capTest{ 207 capTest{ 208 name: "add existing group single cap", 209 old: Config{ 210 Groups: map[string][]string{ 211 "root": []string{"CAP_SYS_ADMIN"}, 212 }, 213 }, 214 new: Config{ 215 Groups: map[string][]string{ 216 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 217 }, 218 }, 219 id: "root", 220 caps: []string{"CAP_DAC_OVERRIDE"}, 221 }, 222 capTest{ 223 name: "add existing group multiple caps", 224 old: Config{ 225 Groups: map[string][]string{ 226 "group1": []string{"CAP_SYS_ADMIN"}, 227 }, 228 }, 229 new: Config{ 230 Groups: map[string][]string{ 231 "group1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 232 }, 233 }, 234 id: "group1", 235 caps: []string{"CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 236 }, 237 capTest{ 238 name: "add new group", 239 old: Config{ 240 Groups: map[string][]string{ 241 "root": []string{"CAP_SYS_ADMIN"}, 242 }, 243 }, 244 new: Config{ 245 Groups: map[string][]string{ 246 "root": []string{"CAP_SYS_ADMIN"}, 247 "group1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 248 }, 249 }, 250 id: "group1", 251 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 252 }, 253 capTest{ 254 name: "add duplicate cap", 255 old: Config{ 256 Groups: map[string][]string{ 257 "root": []string{"CAP_SYS_ADMIN"}, 258 }, 259 }, 260 new: Config{ 261 Groups: map[string][]string{ 262 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 263 }, 264 }, 265 id: "root", 266 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 267 }, 268 } 269 270 for _, test := range testsPass { 271 t.Run(test.name, func(t *testing.T) { 272 if err := test.old.AddGroupCaps(test.id, test.caps); err != nil { 273 t.Error("failed to add capability to config") 274 } 275 276 if !reflect.DeepEqual(test.old, test.new) { 277 t.Errorf("AddGroupCaps failed to set config:\n\thave: %v\n\twant: %v", test.old, test.new) 278 } 279 }) 280 } 281 282 testFail := capTest{ 283 name: "add bad cap fail", 284 old: Config{ 285 Groups: map[string][]string{ 286 "root": []string{"CAP_SYS_ADMIN"}, 287 }, 288 }, 289 new: Config{ 290 Groups: map[string][]string{ 291 "root": []string{"CAP_SYS_ADMIN"}, 292 }, 293 }, 294 id: "root", 295 caps: []string{"CAP_BAD_WRONG_INCORRECT_BAD"}, 296 } 297 298 t.Run(testFail.name, func(t *testing.T) { 299 if err := testFail.old.AddGroupCaps(testFail.id, testFail.caps); err == nil { 300 t.Error("unexpected success adding non-existent capability") 301 } 302 }) 303 } 304 305 func TestDropUserCaps(t *testing.T) { 306 testsPass := []capTest{ 307 capTest{ 308 name: "drop existing user single cap", 309 old: Config{ 310 Users: map[string][]string{ 311 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 312 }, 313 }, 314 new: Config{ 315 Users: map[string][]string{ 316 "root": []string{"CAP_SYS_ADMIN"}, 317 }, 318 }, 319 id: "root", 320 caps: []string{"CAP_DAC_OVERRIDE"}, 321 }, 322 capTest{ 323 name: "drop existing user multiple caps", 324 old: Config{ 325 Users: map[string][]string{ 326 "user1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 327 }, 328 }, 329 new: Config{ 330 Users: map[string][]string{ 331 "user1": []string{"CAP_SYS_ADMIN"}, 332 }, 333 }, 334 id: "user1", 335 caps: []string{"CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 336 }, 337 capTest{ 338 name: "drop duplicate cap", 339 old: Config{ 340 Users: map[string][]string{ 341 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 342 }, 343 }, 344 new: Config{ 345 Users: map[string][]string{ 346 "root": []string{}, 347 }, 348 }, 349 id: "root", 350 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 351 }, 352 } 353 354 for _, test := range testsPass { 355 t.Run(test.name, func(t *testing.T) { 356 if err := test.old.DropUserCaps(test.id, test.caps); err != nil { 357 t.Error("failed to drop capability to config") 358 } 359 360 if !reflect.DeepEqual(test.old, test.new) { 361 t.Errorf("DropUserCaps failed to set config:\n\thave: %v\n\twant: %v", test.old, test.new) 362 } 363 }) 364 } 365 366 testsFail := []capTest{ 367 capTest{ 368 name: "drop bad cap fail", 369 old: Config{ 370 Users: map[string][]string{ 371 "root": []string{"CAP_SYS_ADMIN"}, 372 }, 373 }, 374 new: Config{ 375 Users: map[string][]string{ 376 "root": []string{"CAP_SYS_ADMIN"}, 377 }, 378 }, 379 id: "root", 380 caps: []string{"CAP_BAD_WRONG_INCORRECT_BAD"}, 381 }, 382 capTest{ 383 name: "drop bad user fail", 384 old: Config{ 385 Users: map[string][]string{ 386 "root": []string{"CAP_SYS_ADMIN"}, 387 }, 388 }, 389 new: Config{ 390 Users: map[string][]string{ 391 "root": []string{"CAP_SYS_ADMIN"}, 392 }, 393 }, 394 id: "non_existent_user", 395 caps: []string{"CAP_SYS_ADMIN"}, 396 }, 397 } 398 399 for _, test := range testsFail { 400 t.Run(test.name, func(t *testing.T) { 401 if err := test.old.DropUserCaps(test.id, test.caps); err == nil { 402 t.Error("unexpected success dropping non-existent capability") 403 } 404 }) 405 } 406 } 407 408 func TestDropGroupCaps(t *testing.T) { 409 testsPass := []capTest{ 410 capTest{ 411 name: "drop existing group single cap", 412 old: Config{ 413 Groups: map[string][]string{ 414 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 415 }, 416 }, 417 new: Config{ 418 Groups: map[string][]string{ 419 "root": []string{"CAP_SYS_ADMIN"}, 420 }, 421 }, 422 id: "root", 423 caps: []string{"CAP_DAC_OVERRIDE"}, 424 }, 425 capTest{ 426 name: "drop existing group multiple caps", 427 old: Config{ 428 Groups: map[string][]string{ 429 "group1": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 430 }, 431 }, 432 new: Config{ 433 Groups: map[string][]string{ 434 "group1": []string{"CAP_SYS_ADMIN"}, 435 }, 436 }, 437 id: "group1", 438 caps: []string{"CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 439 }, 440 capTest{ 441 name: "drop duplicate cap", 442 old: Config{ 443 Groups: map[string][]string{ 444 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 445 }, 446 }, 447 new: Config{ 448 Groups: map[string][]string{ 449 "root": []string{}, 450 }, 451 }, 452 id: "root", 453 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE", "CAP_CHOWN"}, 454 }, 455 } 456 457 for _, test := range testsPass { 458 t.Run(test.name, func(t *testing.T) { 459 if err := test.old.DropGroupCaps(test.id, test.caps); err != nil { 460 t.Error("failed to drop capability to config") 461 } 462 463 if !reflect.DeepEqual(test.old, test.new) { 464 t.Errorf("DropGroupCaps failed to set config:\n\thave: %v\n\twant: %v", test.old, test.new) 465 } 466 }) 467 } 468 469 testsFail := []capTest{ 470 capTest{ 471 name: "drop bad cap fail", 472 old: Config{ 473 Groups: map[string][]string{ 474 "root": []string{"CAP_SYS_ADMIN"}, 475 }, 476 }, 477 new: Config{ 478 Groups: map[string][]string{ 479 "root": []string{"CAP_SYS_ADMIN"}, 480 }, 481 }, 482 id: "root", 483 caps: []string{"CAP_BAD_WRONG_INCORRECT_BAD"}, 484 }, 485 capTest{ 486 name: "drop bad group fail", 487 old: Config{ 488 Groups: map[string][]string{ 489 "root": []string{"CAP_SYS_ADMIN"}, 490 }, 491 }, 492 new: Config{ 493 Groups: map[string][]string{ 494 "root": []string{"CAP_SYS_ADMIN"}, 495 }, 496 }, 497 id: "non_existent_group", 498 caps: []string{"CAP_SYS_ADMIN"}, 499 }, 500 } 501 502 for _, test := range testsFail { 503 t.Run(test.name, func(t *testing.T) { 504 if err := test.old.DropGroupCaps(test.id, test.caps); err == nil { 505 t.Error("unexpected success dropping non-existent capability") 506 } 507 }) 508 } 509 } 510 511 func TestListCaps(t *testing.T) { 512 conf := Config{ 513 Users: map[string][]string{ 514 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 515 "user1": []string{"CAP_CHOWN"}, 516 }, 517 Groups: map[string][]string{ 518 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 519 "user2": []string{"CAP_CHOWN"}, 520 }, 521 } 522 523 if !reflect.DeepEqual(conf.ListUserCaps("root"), conf.Users["root"]) { 524 t.Error("user cap lookup failed") 525 } 526 527 if !reflect.DeepEqual(conf.ListGroupCaps("user2"), conf.Groups["user2"]) { 528 t.Error("group cap lookup failed") 529 } 530 531 u, g := conf.ListAllCaps() 532 533 if !reflect.DeepEqual(conf.Users, u) || !reflect.DeepEqual(conf.Groups, g) { 534 t.Error("all caps lookup failed") 535 } 536 } 537 538 type capCheckTest struct { 539 name string 540 id string 541 caps []string 542 authorized []string 543 unauthorized []string 544 } 545 546 func TestCheckCaps(t *testing.T) { 547 conf := Config{ 548 Users: map[string][]string{ 549 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 550 "user1": []string{"CAP_CHOWN", "CAP_SYS_ADMIN"}, 551 "user2": []string{}, 552 }, 553 Groups: map[string][]string{ 554 "root": []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 555 "user1": []string{"CAP_CHOWN", "CAP_SYS_ADMIN"}, 556 "user2": []string{}, 557 }, 558 } 559 560 testsPass := []capCheckTest{ 561 capCheckTest{ 562 name: "check multiple authorized", 563 id: "root", 564 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 565 authorized: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 566 }, 567 capCheckTest{ 568 name: "check multiple unauthorized", 569 id: "user2", 570 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 571 unauthorized: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 572 }, 573 capCheckTest{ 574 name: "check multiple authorized & unauthorized", 575 id: "user1", 576 caps: []string{"CAP_SYS_ADMIN", "CAP_DAC_OVERRIDE"}, 577 authorized: []string{"CAP_SYS_ADMIN"}, 578 unauthorized: []string{"CAP_DAC_OVERRIDE"}, 579 }, 580 } 581 582 for _, test := range testsPass { 583 t.Run(test.name, func(t *testing.T) { 584 aUser, uUser := conf.CheckUserCaps(test.id, test.caps) 585 if !reflect.DeepEqual(aUser, test.authorized) { 586 t.Errorf("returned incorrect authorized user caps:\n\thave: %v\n\twant: %v", test.authorized, aUser) 587 } 588 589 if !reflect.DeepEqual(uUser, test.unauthorized) { 590 t.Errorf("returned incorrect unauthorized user caps:\n\thave: %v\n\twant: %v", test.unauthorized, uUser) 591 } 592 593 aGroup, uGroup := conf.CheckGroupCaps(test.id, test.caps) 594 if !reflect.DeepEqual(aGroup, test.authorized) { 595 t.Errorf("returned incorrect authorized group caps:\n\thave: %v\n\twant: %v", test.authorized, aGroup) 596 } 597 598 if !reflect.DeepEqual(uGroup, test.unauthorized) { 599 t.Errorf("returned incorrect unauthorized group caps:\n\thave: %v\n\twant: %v", test.unauthorized, uGroup) 600 } 601 602 }) 603 } 604 605 }