1package sops 2 3import ( 4 "bytes" 5 "fmt" 6 "reflect" 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10) 11 12type reverseCipher struct{} 13 14// reverse returns its argument string reversed rune-wise left to right. 15func reverse(s string) string { 16 r := []rune(s) 17 for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { 18 r[i], r[j] = r[j], r[i] 19 } 20 return string(r) 21} 22 23func (c reverseCipher) Encrypt(value interface{}, key []byte, path string) (string, error) { 24 b, err := ToBytes(value) 25 if err != nil { 26 return "", err 27 } 28 return reverse(string(b)), nil 29} 30func (c reverseCipher) Decrypt(value string, key []byte, path string) (plaintext interface{}, err error) { 31 if value == "error" { 32 return nil, fmt.Errorf("Error") 33 } 34 return reverse(value), nil 35} 36 37func TestUnencryptedSuffix(t *testing.T) { 38 branches := TreeBranches{ 39 TreeBranch{ 40 TreeItem{ 41 Key: "foo_unencrypted", 42 Value: "bar", 43 }, 44 TreeItem{ 45 Key: "bar_unencrypted", 46 Value: TreeBranch{ 47 TreeItem{ 48 Key: "foo", 49 Value: "bar", 50 }, 51 }, 52 }, 53 }, 54 } 55 tree := Tree{Branches: branches, Metadata: Metadata{UnencryptedSuffix: "_unencrypted"}} 56 expected := TreeBranch{ 57 TreeItem{ 58 Key: "foo_unencrypted", 59 Value: "bar", 60 }, 61 TreeItem{ 62 Key: "bar_unencrypted", 63 Value: TreeBranch{ 64 TreeItem{ 65 Key: "foo", 66 Value: "bar", 67 }, 68 }, 69 }, 70 } 71 cipher := reverseCipher{} 72 _, err := tree.Encrypt(bytes.Repeat([]byte("f"), 32), cipher) 73 if err != nil { 74 t.Errorf("Encrypting the tree failed: %s", err) 75 } 76 if !reflect.DeepEqual(tree.Branches[0], expected) { 77 t.Errorf("Trees don't match: \ngot \t\t%+v,\n expected \t\t%+v", tree.Branches[0], expected) 78 } 79 _, err = tree.Decrypt(bytes.Repeat([]byte("f"), 32), cipher) 80 if err != nil { 81 t.Errorf("Decrypting the tree failed: %s", err) 82 } 83 if !reflect.DeepEqual(tree.Branches[0], expected) { 84 t.Errorf("Trees don't match: \ngot\t\t\t%+v,\nexpected\t\t%+v", tree.Branches[0], expected) 85 } 86} 87 88func TestEncryptedSuffix(t *testing.T) { 89 branches := TreeBranches{ 90 TreeBranch{ 91 TreeItem{ 92 Key: "foo_encrypted", 93 Value: "bar", 94 }, 95 TreeItem{ 96 Key: "bar", 97 Value: TreeBranch{ 98 TreeItem{ 99 Key: "foo", 100 Value: "bar", 101 }, 102 }, 103 }, 104 }, 105 } 106 tree := Tree{Branches: branches, Metadata: Metadata{EncryptedSuffix: "_encrypted"}} 107 expected := TreeBranch{ 108 TreeItem{ 109 Key: "foo_encrypted", 110 Value: "rab", 111 }, 112 TreeItem{ 113 Key: "bar", 114 Value: TreeBranch{ 115 TreeItem{ 116 Key: "foo", 117 Value: "bar", 118 }, 119 }, 120 }, 121 } 122 cipher := reverseCipher{} 123 _, err := tree.Encrypt(bytes.Repeat([]byte("f"), 32), cipher) 124 if err != nil { 125 t.Errorf("Encrypting the tree failed: %s", err) 126 } 127 if !reflect.DeepEqual(tree.Branches[0], expected) { 128 t.Errorf("Trees don't match: \ngot \t\t%+v,\n expected \t\t%+v", tree.Branches[0], expected) 129 } 130 _, err = tree.Decrypt(bytes.Repeat([]byte("f"), 32), cipher) 131 if err != nil { 132 t.Errorf("Decrypting the tree failed: %s", err) 133 } 134 expected[0].Value = "bar" 135 if !reflect.DeepEqual(tree.Branches[0], expected) { 136 t.Errorf("Trees don't match: \ngot\t\t\t%+v,\nexpected\t\t%+v", tree.Branches[0], expected) 137 } 138} 139 140func TestEncryptedRegex(t *testing.T) { 141 branches := TreeBranches{ 142 TreeBranch{ 143 TreeItem{ 144 Key: "enc:foo", 145 Value: "bar", 146 }, 147 TreeItem{ 148 Key: "bar", 149 Value: TreeBranch{ 150 TreeItem{ 151 Key: "foo", 152 Value: "bar", 153 }, 154 }, 155 }, 156 }, 157 } 158 tree := Tree{Branches: branches, Metadata: Metadata{EncryptedRegex: "^enc:"}} 159 expected := TreeBranch{ 160 TreeItem{ 161 Key: "enc:foo", 162 Value: "rab", 163 }, 164 TreeItem{ 165 Key: "bar", 166 Value: TreeBranch{ 167 TreeItem{ 168 Key: "foo", 169 Value: "bar", 170 }, 171 }, 172 }, 173 } 174 cipher := reverseCipher{} 175 _, err := tree.Encrypt(bytes.Repeat([]byte("f"), 32), cipher) 176 if err != nil { 177 t.Errorf("Encrypting the tree failed: %s", err) 178 } 179 if !reflect.DeepEqual(tree.Branches[0], expected) { 180 t.Errorf("Trees don't match: \ngot \t\t%+v,\n expected \t\t%+v", tree.Branches[0], expected) 181 } 182 _, err = tree.Decrypt(bytes.Repeat([]byte("f"), 32), cipher) 183 if err != nil { 184 t.Errorf("Decrypting the tree failed: %s", err) 185 } 186 expected[0].Value = "bar" 187 if !reflect.DeepEqual(tree.Branches[0], expected) { 188 t.Errorf("Trees don't match: \ngot\t\t\t%+v,\nexpected\t\t%+v", tree.Branches[0], expected) 189 } 190} 191 192func TestUnencryptedRegex(t *testing.T) { 193 branches := TreeBranches{ 194 TreeBranch{ 195 TreeItem{ 196 Key: "dec:foo", 197 Value: "bar", 198 }, 199 TreeItem{ 200 Key: "dec:bar", 201 Value: TreeBranch{ 202 TreeItem{ 203 Key: "foo", 204 Value: "bar", 205 }, 206 }, 207 }, 208 }, 209 } 210 tree := Tree{Branches: branches, Metadata: Metadata{UnencryptedRegex: "^dec:"}} 211 expected := TreeBranch{ 212 TreeItem{ 213 Key: "dec:foo", 214 Value: "bar", 215 }, 216 TreeItem{ 217 Key: "dec:bar", 218 Value: TreeBranch{ 219 TreeItem{ 220 Key: "foo", 221 Value: "bar", 222 }, 223 }, 224 }, 225 } 226 cipher := reverseCipher{} 227 228 _, err := tree.Encrypt(bytes.Repeat([]byte("f"), 32), cipher) 229 if err != nil { 230 t.Errorf("Encrypting the tree failed: %s", err) 231 } 232 // expected[1].Value[] = "bar" 233 if !reflect.DeepEqual(tree.Branches[0], expected) { 234 t.Errorf("Trees don't match: \ngot \t\t%+v,\n expected \t\t%+v", tree.Branches[0], expected) 235 } 236 _, err = tree.Decrypt(bytes.Repeat([]byte("f"), 32), cipher) 237 if err != nil { 238 t.Errorf("Decrypting the tree failed: %s", err) 239 } 240 if !reflect.DeepEqual(tree.Branches[0], expected) { 241 t.Errorf("Trees don't match: \ngot\t\t\t%+v,\nexpected\t\t%+v", tree.Branches[0], expected) 242 } 243} 244 245type MockCipher struct{} 246 247func (m MockCipher) Encrypt(value interface{}, key []byte, path string) (string, error) { 248 return "a", nil 249} 250 251func (m MockCipher) Decrypt(value string, key []byte, path string) (interface{}, error) { 252 return "a", nil 253} 254 255func TestEncrypt(t *testing.T) { 256 branches := TreeBranches{ 257 TreeBranch{ 258 TreeItem{ 259 Key: "foo", 260 Value: "bar", 261 }, 262 TreeItem{ 263 Key: "baz", 264 Value: TreeBranch{ 265 TreeItem{ 266 Key: "bar", 267 Value: 5, 268 }, 269 }, 270 }, 271 TreeItem{ 272 Key: "bar", 273 Value: false, 274 }, 275 TreeItem{ 276 Key: "foobar", 277 Value: 2.12, 278 }, 279 TreeItem{ 280 Key: "barfoo", 281 Value: nil, 282 }, 283 }, 284 TreeBranch{ 285 TreeItem{ 286 Key: "foo2", 287 Value: "bar", 288 }, 289 }, 290 TreeBranch{ 291 TreeItem{ 292 Key: "foo3", 293 Value: "bar", 294 }, 295 }, 296 } 297 expected := TreeBranches{ 298 TreeBranch{ 299 TreeItem{ 300 Key: "foo", 301 Value: "a", 302 }, 303 TreeItem{ 304 Key: "baz", 305 Value: TreeBranch{ 306 TreeItem{ 307 Key: "bar", 308 Value: "a", 309 }, 310 }, 311 }, 312 TreeItem{ 313 Key: "bar", 314 Value: "a", 315 }, 316 TreeItem{ 317 Key: "foobar", 318 Value: "a", 319 }, 320 TreeItem{ 321 Key: "barfoo", 322 Value: nil, 323 }, 324 }, 325 TreeBranch{ 326 TreeItem{ 327 Key: "foo2", 328 Value: "a", 329 }, 330 }, 331 TreeBranch{ 332 TreeItem{ 333 Key: "foo3", 334 Value: "a", 335 }, 336 }, 337 } 338 tree := Tree{Branches: branches, Metadata: Metadata{UnencryptedSuffix: DefaultUnencryptedSuffix}} 339 tree.Encrypt(bytes.Repeat([]byte{'f'}, 32), MockCipher{}) 340 if !reflect.DeepEqual(tree.Branches, expected) { 341 t.Errorf("%s does not equal expected tree: %s", tree.Branches, expected) 342 } 343} 344 345func TestDecrypt(t *testing.T) { 346 branches := TreeBranches{ 347 TreeBranch{ 348 TreeItem{ 349 Key: "foo", 350 Value: "bar", 351 }, 352 TreeItem{ 353 Key: "baz", 354 Value: TreeBranch{ 355 TreeItem{ 356 Key: "bar", 357 Value: "5", 358 }, 359 }, 360 }, 361 TreeItem{ 362 Key: "bar", 363 Value: "false", 364 }, 365 TreeItem{ 366 Key: "foobar", 367 Value: "2.12", 368 }, 369 TreeItem{ 370 Key: "barfoo", 371 Value: nil, 372 }, 373 }, 374 TreeBranch{ 375 TreeItem{ 376 Key: "foo", 377 Value: "bar", 378 }, 379 TreeItem{ 380 Key: "baz", 381 Value: TreeBranch{ 382 TreeItem{ 383 Key: "bar", 384 Value: "6", 385 }, 386 }, 387 }, 388 }, 389 TreeBranch{ 390 TreeItem{ 391 Key: "foo3", 392 Value: "bar", 393 }, 394 }, 395 } 396 expected := TreeBranches{ 397 TreeBranch{ 398 TreeItem{ 399 Key: "foo", 400 Value: "a", 401 }, 402 TreeItem{ 403 Key: "baz", 404 Value: TreeBranch{ 405 TreeItem{ 406 Key: "bar", 407 Value: "a", 408 }, 409 }, 410 }, 411 TreeItem{ 412 Key: "bar", 413 Value: "a", 414 }, 415 TreeItem{ 416 Key: "foobar", 417 Value: "a", 418 }, 419 TreeItem{ 420 Key: "barfoo", 421 Value: nil, 422 }, 423 }, 424 TreeBranch{ 425 TreeItem{ 426 Key: "foo", 427 Value: "a", 428 }, 429 TreeItem{ 430 Key: "baz", 431 Value: TreeBranch{ 432 TreeItem{ 433 Key: "bar", 434 Value: "a", 435 }, 436 }, 437 }, 438 }, 439 TreeBranch{ 440 TreeItem{ 441 Key: "foo3", 442 Value: "a", 443 }, 444 }, 445 } 446 tree := Tree{Branches: branches, Metadata: Metadata{UnencryptedSuffix: DefaultUnencryptedSuffix}} 447 tree.Decrypt(bytes.Repeat([]byte{'f'}, 32), MockCipher{}) 448 if !reflect.DeepEqual(tree.Branches, expected) { 449 t.Errorf("%s does not equal expected tree: %s", tree.Branches[0], expected) 450 } 451} 452 453func TestTruncateTree(t *testing.T) { 454 tree := TreeBranch{ 455 TreeItem{ 456 Key: "foo", 457 Value: 2, 458 }, 459 TreeItem{ 460 Key: "bar", 461 Value: TreeBranch{ 462 TreeItem{ 463 Key: "foobar", 464 Value: []int{ 465 1, 466 2, 467 3, 468 4, 469 }, 470 }, 471 }, 472 }, 473 } 474 expected := 3 475 result, err := tree.Truncate([]interface{}{ 476 "bar", 477 "foobar", 478 2, 479 }) 480 assert.Equal(t, nil, err) 481 assert.Equal(t, expected, result) 482} 483 484func TestEncryptComments(t *testing.T) { 485 tree := Tree{ 486 Branches: TreeBranches{ 487 TreeBranch{ 488 TreeItem{ 489 Key: Comment{"foo"}, 490 Value: nil, 491 }, 492 TreeItem{ 493 Key: "list", 494 Value: []interface{}{ 495 "1", 496 Comment{"bar"}, 497 "2", 498 }, 499 }, 500 }, 501 }, 502 Metadata: Metadata{ 503 UnencryptedSuffix: DefaultUnencryptedSuffix, 504 }, 505 } 506 tree.Encrypt(bytes.Repeat([]byte{'f'}, 32), reverseCipher{}) 507 assert.Equal(t, "oof", tree.Branches[0][0].Key.(Comment).Value) 508 assert.Equal(t, "rab", tree.Branches[0][1].Value.([]interface{})[1]) 509} 510 511func TestDecryptComments(t *testing.T) { 512 tree := Tree{ 513 Branches: TreeBranches{ 514 TreeBranch{ 515 TreeItem{ 516 Key: Comment{"oof"}, 517 Value: nil, 518 }, 519 TreeItem{ 520 Key: "list", 521 Value: []interface{}{ 522 "1", 523 Comment{"rab"}, 524 "2", 525 }, 526 }, 527 TreeItem{ 528 Key: "list", 529 Value: nil, 530 }, 531 }, 532 }, 533 Metadata: Metadata{ 534 UnencryptedSuffix: DefaultUnencryptedSuffix, 535 }, 536 } 537 tree.Decrypt(bytes.Repeat([]byte{'f'}, 32), reverseCipher{}) 538 assert.Equal(t, "foo", tree.Branches[0][0].Key.(Comment).Value) 539 assert.Equal(t, "bar", tree.Branches[0][1].Value.([]interface{})[1]) 540} 541 542func TestDecryptUnencryptedComments(t *testing.T) { 543 tree := Tree{ 544 Branches: TreeBranches{ 545 TreeBranch{ 546 TreeItem{ 547 // We use `error` to simulate an error decrypting, the fake cipher will error in this case 548 Key: Comment{"error"}, 549 Value: nil, 550 }, 551 }, 552 }, 553 Metadata: Metadata{}, 554 } 555 tree.Decrypt(bytes.Repeat([]byte{'f'}, 32), reverseCipher{}) 556 assert.Equal(t, "error", tree.Branches[0][0].Key.(Comment).Value) 557} 558 559func TestSetNewKey(t *testing.T) { 560 branch := TreeBranch{ 561 TreeItem{ 562 Key: "foo", 563 Value: TreeBranch{ 564 TreeItem{ 565 Key: "bar", 566 Value: TreeBranch{ 567 TreeItem{ 568 Key: "baz", 569 Value: "foobar", 570 }, 571 }, 572 }, 573 }, 574 }, 575 } 576 set := branch.Set([]interface{}{"foo", "bar", "foo"}, "hello") 577 assert.Equal(t, "hello", set[0].Value.(TreeBranch)[0].Value.(TreeBranch)[1].Value) 578} 579 580func TestSetArrayDeepNew(t *testing.T) { 581 branch := TreeBranch{ 582 TreeItem{ 583 Key: "foo", 584 Value: []interface{}{ 585 "one", 586 "two", 587 }, 588 }, 589 } 590 set := branch.Set([]interface{}{"foo", 2, "bar"}, "hello") 591 assert.Equal(t, "hello", set[0].Value.([]interface{})[2].(TreeBranch)[0].Value) 592} 593 594func TestSetNewKeyDeep(t *testing.T) { 595 branch := TreeBranch{ 596 TreeItem{ 597 Key: "foo", 598 Value: "bar", 599 }, 600 } 601 set := branch.Set([]interface{}{"foo", "bar", "baz"}, "hello") 602 assert.Equal(t, "hello", set[0].Value.(TreeBranch)[0].Value.(TreeBranch)[0].Value) 603} 604 605func TestSetNewKeyOnEmptyBranch(t *testing.T) { 606 branch := TreeBranch{} 607 set := branch.Set([]interface{}{"foo", "bar", "baz"}, "hello") 608 assert.Equal(t, "hello", set[0].Value.(TreeBranch)[0].Value.(TreeBranch)[0].Value) 609} 610 611func TestSetArray(t *testing.T) { 612 branch := TreeBranch{ 613 TreeItem{ 614 Key: "foo", 615 Value: []interface{}{ 616 "one", 617 "two", 618 "three", 619 }, 620 }, 621 } 622 set := branch.Set([]interface{}{"foo", 0}, "uno") 623 assert.Equal(t, "uno", set[0].Value.([]interface{})[0]) 624} 625 626func TestSetArrayNew(t *testing.T) { 627 branch := TreeBranch{} 628 set := branch.Set([]interface{}{"foo", 0, 0}, "uno") 629 assert.Equal(t, "uno", set[0].Value.([]interface{})[0].([]interface{})[0]) 630} 631 632func TestSetExisting(t *testing.T) { 633 branch := TreeBranch{ 634 TreeItem{ 635 Key: "foo", 636 Value: "foobar", 637 }, 638 } 639 set := branch.Set([]interface{}{"foo"}, "bar") 640 assert.Equal(t, "bar", set[0].Value) 641} 642 643func TestSetArrayLeafNewItem(t *testing.T) { 644 branch := TreeBranch{ 645 TreeItem{ 646 Key: "array", 647 Value: []interface{}{}, 648 }, 649 } 650 set := branch.Set([]interface{}{"array", 2}, "hello") 651 assert.Equal(t, TreeBranch{ 652 TreeItem{ 653 Key: "array", 654 Value: []interface{}{ 655 "hello", 656 }, 657 }, 658 }, set) 659} 660 661func TestSetArrayNonLeaf(t *testing.T) { 662 branch := TreeBranch{ 663 TreeItem{ 664 Key: "array", 665 Value: []interface{}{ 666 1, 667 }, 668 }, 669 } 670 set := branch.Set([]interface{}{"array", 0, "hello"}, "hello") 671 assert.Equal(t, TreeBranch{ 672 TreeItem{ 673 Key: "array", 674 Value: []interface{}{ 675 TreeBranch{ 676 TreeItem{ 677 Key: "hello", 678 Value: "hello", 679 }, 680 }, 681 }, 682 }, 683 }, set) 684} 685 686func TestEmitAsMap(t *testing.T) { 687 expected := map[string]interface{}{ 688 "foobar": "barfoo", 689 "number": 42, 690 "foo": map[string]interface{}{ 691 "bar": map[string]interface{}{ 692 "baz": "foobar", 693 }, 694 }, 695 } 696 branches := TreeBranches{ 697 TreeBranch{ 698 TreeItem{ 699 Key: "foobar", 700 Value: "barfoo", 701 }, 702 TreeItem{ 703 Key: "number", 704 Value: 42, 705 }, 706 }, 707 TreeBranch{ 708 TreeItem{ 709 Key: "foo", 710 Value: TreeBranch{ 711 TreeItem{ 712 Key: "bar", 713 Value: TreeBranch{ 714 TreeItem{ 715 Key: "baz", 716 Value: "foobar", 717 }, 718 }, 719 }, 720 }, 721 }, 722 }, 723 } 724 725 data, err := EmitAsMap(branches) 726 727 if assert.NoError(t, err) { 728 assert.Equal(t, expected, data) 729 } 730} 731