github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/policy/policy_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package policy_test 21 22 import ( 23 "strings" 24 "testing" 25 26 . "gopkg.in/check.v1" 27 28 "github.com/snapcore/snapd/asserts" 29 "github.com/snapcore/snapd/interfaces" 30 "github.com/snapcore/snapd/interfaces/policy" 31 "github.com/snapcore/snapd/release" 32 "github.com/snapcore/snapd/snap" 33 "github.com/snapcore/snapd/snap/snaptest" 34 ) 35 36 func TestPolicy(t *testing.T) { TestingT(t) } 37 38 type policySuite struct { 39 baseDecl *asserts.BaseDeclaration 40 41 plugSnap *snap.Info 42 slotSnap *snap.Info 43 44 plugDecl *asserts.SnapDeclaration 45 slotDecl *asserts.SnapDeclaration 46 47 randomSnap *snap.Info 48 randomDecl *asserts.SnapDeclaration 49 50 restoreSanitize func() 51 } 52 53 var _ = Suite(&policySuite{}) 54 55 func (s *policySuite) SetUpSuite(c *C) { 56 s.restoreSanitize = snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {}) 57 a, err := asserts.Decode([]byte(`type: base-declaration 58 authority-id: canonical 59 series: 16 60 plugs: 61 base-plug-allow: true 62 base-plug-not-allow: 63 allow-connection: false 64 base-plug-not-allow-slots: 65 allow-connection: 66 slot-attributes: 67 s: S 68 base-plug-not-allow-plugs: 69 allow-connection: 70 plug-attributes: 71 p: P 72 base-plug-deny: 73 deny-connection: true 74 same-plug-publisher-id: 75 allow-connection: 76 slot-publisher-id: 77 - $PLUG_PUBLISHER_ID 78 plug-plug-attr: 79 allow-connection: 80 slot-attributes: 81 c: $PLUG(c) 82 plug-slot-attr: 83 allow-connection: 84 plug-attributes: 85 c: $SLOT(c) 86 plug-or: 87 allow-connection: 88 - 89 slot-attributes: 90 s: S1 91 plug-attributes: 92 p: P1 93 - 94 slot-attributes: 95 s: S2 96 plug-attributes: 97 p: P2 98 plug-on-classic-true: 99 allow-connection: 100 on-classic: true 101 plug-on-classic-distros: 102 allow-connection: 103 on-classic: 104 - ubuntu 105 - debian 106 plug-on-classic-false: 107 allow-connection: 108 on-classic: false 109 auto-base-plug-allow: true 110 auto-base-plug-not-allow: 111 allow-auto-connection: false 112 auto-base-plug-not-allow-slots: 113 allow-auto-connection: 114 slot-attributes: 115 s: S 116 auto-base-plug-not-allow-plugs: 117 allow-auto-connection: 118 plug-attributes: 119 p: P 120 auto-base-plug-deny: 121 deny-auto-connection: true 122 auto-plug-or: 123 allow-auto-connection: 124 - 125 slot-attributes: 126 s: S1 127 plug-attributes: 128 p: P1 129 - 130 slot-attributes: 131 s: S2 132 plug-attributes: 133 p: P2 134 auto-plug-on-store1: 135 allow-auto-connection: false 136 auto-plug-on-my-brand: 137 allow-auto-connection: false 138 auto-plug-on-my-model2: 139 allow-auto-connection: false 140 auto-plug-on-multi: 141 allow-auto-connection: false 142 install-plug-attr-ok: 143 allow-installation: 144 plug-attributes: 145 attr: ok 146 install-plug-gadget-only: 147 allow-installation: 148 plug-snap-type: 149 - gadget 150 install-plug-base-deny-snap-allow: 151 deny-installation: 152 plug-attributes: 153 attr: attrvalue 154 install-plug-or: 155 deny-installation: 156 - 157 plug-attributes: 158 p: P1 159 - 160 plug-snap-type: 161 - gadget 162 plug-attributes: 163 p: P2 164 install-plug-on-classic-distros: 165 allow-installation: 166 on-classic: 167 - ubuntu 168 - debian 169 install-plug-device-scope: 170 allow-installation: false 171 slots: 172 base-slot-allow: true 173 base-slot-not-allow: 174 allow-connection: false 175 base-slot-not-allow-slots: 176 allow-connection: 177 slot-attributes: 178 s: S 179 base-slot-not-allow-plugs: 180 allow-connection: 181 plug-attributes: 182 p: P 183 base-slot-deny: 184 deny-connection: true 185 base-deny-snap-slot-allow: false 186 base-deny-snap-plug-allow: false 187 base-allow-snap-slot-not-allow: true 188 gadgethelp: 189 allow-connection: 190 plug-snap-type: 191 - gadget 192 same-slot-publisher-id: 193 allow-connection: 194 plug-publisher-id: 195 - $SLOT_PUBLISHER_ID 196 slot-slot-attr: 197 allow-connection: 198 plug-attributes: 199 a: 200 b: $SLOT(a.b) 201 slot-plug-attr: 202 allow-connection: 203 slot-attributes: 204 c: $PLUG(c) 205 slot-plug-missing: 206 allow-connection: 207 plug-attributes: 208 x: $MISSING 209 slot-or: 210 allow-connection: 211 - 212 slot-attributes: 213 s: S1 214 plug-attributes: 215 p: P1 216 - 217 slot-attributes: 218 s: S2 219 plug-attributes: 220 p: P2 221 slot-on-classic-true: 222 allow-connection: 223 on-classic: true 224 slot-on-classic-distros: 225 allow-connection: 226 on-classic: 227 - ubuntu 228 - debian 229 slot-on-classic-false: 230 allow-connection: 231 on-classic: false 232 auto-base-slot-allow: true 233 auto-base-slot-not-allow: 234 allow-auto-connection: false 235 auto-base-slot-not-allow-slots: 236 allow-auto-connection: 237 slot-attributes: 238 s: S 239 auto-base-slot-not-allow-plugs: 240 allow-auto-connection: 241 plug-attributes: 242 p: P 243 auto-base-slot-deny: 244 deny-auto-connection: true 245 auto-base-deny-snap-slot-allow: false 246 auto-base-deny-snap-plug-allow: false 247 auto-base-allow-snap-slot-not-allow: true 248 auto-slot-or: 249 allow-auto-connection: 250 - 251 slot-attributes: 252 s: S1 253 plug-attributes: 254 p: P1 255 - 256 slot-attributes: 257 s: S2 258 plug-attributes: 259 p: P2 260 auto-slot-on-store1: 261 allow-auto-connection: false 262 auto-slot-on-my-brand: 263 allow-auto-connection: false 264 auto-slot-on-my-model2: 265 allow-auto-connection: false 266 auto-slot-on-multi: 267 allow-auto-connection: false 268 install-slot-coreonly: 269 allow-installation: 270 slot-snap-type: 271 - core 272 install-slot-attr-ok: 273 allow-installation: 274 slot-attributes: 275 attr: ok 276 install-slot-attr-deny: 277 deny-installation: 278 slot-attributes: 279 trust: trusted 280 install-slot-base-deny-snap-allow: 281 deny-installation: 282 slot-attributes: 283 have: true 284 install-slot-or: 285 deny-installation: 286 - 287 slot-attributes: 288 p: P1 289 - 290 slot-snap-type: 291 - gadget 292 slot-attributes: 293 p: P2 294 install-slot-on-classic-distros: 295 allow-installation: 296 on-classic: 297 - ubuntu 298 - debian 299 install-slot-device-scope: 300 allow-installation: false 301 timestamp: 2016-09-30T12:00:00Z 302 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 303 304 AXNpZw==`)) 305 c.Assert(err, IsNil) 306 s.baseDecl = a.(*asserts.BaseDeclaration) 307 308 s.plugSnap = snaptest.MockInfo(c, ` 309 name: plug-snap 310 version: 0 311 plugs: 312 random: 313 mismatchy: 314 interface: bar 315 316 base-plug-allow: 317 base-plug-not-allow: 318 base-plug-not-allow-slots: 319 base-plug-not-allow-plugs: 320 base-plug-deny: 321 322 base-slot-allow: 323 base-slot-not-allow: 324 base-slot-not-allow-slots: 325 base-slot-not-allow-plugs: 326 base-slot-deny: 327 328 auto-base-plug-allow: 329 auto-base-plug-not-allow: 330 auto-base-plug-not-allow-slots: 331 auto-base-plug-not-allow-plugs: 332 auto-base-plug-deny: 333 334 auto-base-slot-allow: 335 auto-base-slot-not-allow: 336 auto-base-slot-not-allow-slots: 337 auto-base-slot-not-allow-plugs: 338 auto-base-slot-deny: 339 340 snap-plug-allow: 341 snap-plug-not-allow: 342 snap-plug-deny: 343 344 snap-slot-allow: 345 snap-slot-not-allow: 346 snap-slot-deny: 347 348 base-deny-snap-slot-allow: 349 base-deny-snap-plug-allow: 350 base-allow-snap-slot-not-allow: 351 352 snap-slot-deny-snap-plug-allow: 353 354 auto-snap-plug-allow: 355 auto-snap-plug-not-allow: 356 auto-snap-plug-deny: 357 358 auto-snap-slot-allow: 359 auto-snap-slot-not-allow: 360 auto-snap-slot-deny: 361 362 auto-base-deny-snap-slot-allow: 363 auto-base-deny-snap-plug-allow: 364 auto-base-allow-snap-slot-not-allow: 365 366 auto-snap-slot-deny-snap-plug-allow: 367 368 gadgethelp: 369 trustedhelp: 370 371 precise-plug-snap-id: 372 precise-slot-snap-id: 373 374 checked-plug-publisher-id: 375 checked-slot-publisher-id: 376 377 same-plug-publisher-id: 378 379 slot-slot-attr-mismatch: 380 interface: slot-slot-attr 381 a: 382 b: [] 383 384 slot-slot-attr-match: 385 interface: slot-slot-attr 386 a: 387 b: ["x", "y"] 388 389 slot-plug-attr-mismatch: 390 interface: slot-plug-attr 391 c: "Z" 392 393 slot-plug-attr-dynamic: 394 interface: slot-plug-attr 395 396 slot-plug-attr-match: 397 interface: slot-plug-attr 398 c: "C" 399 400 slot-plug-missing-mismatch: 401 interface: slot-plug-missing 402 x: 1 403 z: 2 404 405 slot-plug-missing-match: 406 interface: slot-plug-missing 407 z: 2 408 409 plug-plug-attr: 410 c: "C" 411 412 plug-slot-attr: 413 c: "C" 414 415 plug-or-p1-s1: 416 interface: plug-or 417 p: P1 418 419 plug-or-p2-s2: 420 interface: plug-or 421 p: P2 422 423 plug-or-p1-s2: 424 interface: plug-or 425 p: P1 426 427 auto-plug-or-p1-s1: 428 interface: auto-plug-or 429 p: P1 430 431 auto-plug-or-p2-s2: 432 interface: auto-plug-or 433 p: P2 434 435 auto-plug-or-p2-s1: 436 interface: auto-plug-or 437 p: P2 438 439 auto-plug-on-store1: 440 auto-plug-on-my-brand: 441 auto-plug-on-my-model2: 442 auto-plug-on-multi: 443 444 slot-or-p1-s1: 445 interface: slot-or 446 p: P1 447 448 slot-or-p2-s2: 449 interface: slot-or 450 p: P2 451 452 slot-or-p1-s2: 453 interface: slot-or 454 p: P1 455 456 auto-slot-or-p1-s1: 457 interface: auto-slot-or 458 p: P1 459 460 auto-slot-or-p2-s2: 461 interface: auto-slot-or 462 p: P2 463 464 auto-slot-or-p2-s1: 465 interface: auto-slot-or 466 p: P2 467 468 auto-slot-on-store1: 469 auto-slot-on-my-brand: 470 auto-slot-on-my-model2: 471 auto-slot-on-multi: 472 473 slot-on-classic-true: 474 slot-on-classic-distros: 475 slot-on-classic-false: 476 477 plug-on-classic-true: 478 plug-on-classic-distros: 479 plug-on-classic-false: 480 `, nil) 481 482 s.slotSnap = snaptest.MockInfo(c, ` 483 name: slot-snap 484 version: 0 485 slots: 486 random: 487 mismatchy: 488 interface: baz 489 490 base-plug-allow: 491 base-plug-not-allow: 492 base-plug-not-allow-slots: 493 base-plug-not-allow-plugs: 494 base-plug-deny: 495 496 base-slot-allow: 497 base-slot-not-allow: 498 base-slot-not-allow-slots: 499 base-slot-not-allow-plugs: 500 base-slot-deny: 501 502 auto-base-plug-allow: 503 auto-base-plug-not-allow: 504 auto-base-plug-not-allow-slots: 505 auto-base-plug-not-allow-plugs: 506 auto-base-plug-deny: 507 508 auto-base-slot-allow: 509 auto-base-slot-not-allow: 510 auto-base-slot-not-allow-slots: 511 auto-base-slot-not-allow-plugs: 512 auto-base-slot-deny: 513 514 snap-plug-allow: 515 snap-plug-not-allow: 516 snap-plug-deny: 517 518 snap-slot-allow: 519 snap-slot-not-allow: 520 snap-slot-deny: 521 522 base-deny-snap-slot-allow: 523 base-deny-snap-plug-allow: 524 base-allow-snap-slot-not-allow: 525 526 snap-slot-deny-snap-plug-allow: 527 528 auto-snap-plug-allow: 529 auto-snap-plug-not-allow: 530 auto-snap-plug-deny: 531 532 auto-snap-slot-allow: 533 auto-snap-slot-not-allow: 534 auto-snap-slot-deny: 535 536 auto-base-deny-snap-slot-allow: 537 auto-base-deny-snap-plug-allow: 538 auto-base-allow-snap-slot-not-allow: 539 540 auto-snap-slot-deny-snap-plug-allow: 541 542 trustedhelp: 543 544 precise-plug-snap-id: 545 precise-slot-snap-id: 546 547 checked-plug-publisher-id: 548 checked-slot-publisher-id: 549 550 same-slot-publisher-id: 551 552 slot-slot-attr: 553 a: 554 b: ["x", "y"] 555 556 slot-plug-attr: 557 c: "C" 558 559 slot-plug-missing: 560 561 plug-plug-attr-mismatch: 562 interface: plug-plug-attr 563 c: "Z" 564 565 plug-plug-attr-match: 566 interface: plug-plug-attr 567 c: "C" 568 569 plug-plug-attr-dynamic: 570 interface: plug-plug-attr 571 572 plug-slot-attr-mismatch: 573 interface: plug-slot-attr 574 c: "Z" 575 576 plug-slot-attr-match: 577 interface: plug-slot-attr 578 c: "C" 579 580 plug-or-p1-s1: 581 interface: plug-or 582 s: S1 583 584 plug-or-p2-s2: 585 interface: plug-or 586 s: S2 587 588 plug-or-p1-s2: 589 interface: plug-or 590 s: S2 591 592 auto-plug-or-p1-s1: 593 interface: auto-plug-or 594 s: S1 595 596 auto-plug-or-p2-s2: 597 interface: auto-plug-or 598 s: S2 599 600 auto-plug-or-p2-s1: 601 interface: auto-plug-or 602 s: S1 603 604 auto-plug-on-store1: 605 auto-plug-on-my-brand: 606 auto-plug-on-my-model2: 607 auto-plug-on-multi: 608 609 slot-or-p1-s1: 610 interface: slot-or 611 s: S1 612 613 slot-or-p2-s2: 614 interface: slot-or 615 s: S2 616 617 slot-or-p1-s2: 618 interface: slot-or 619 s: S2 620 621 auto-slot-or-p1-s1: 622 interface: auto-slot-or 623 s: S1 624 625 auto-slot-or-p2-s2: 626 interface: auto-slot-or 627 s: S2 628 629 auto-slot-or-p2-s1: 630 interface: auto-slot-or 631 s: S1 632 633 auto-slot-on-store1: 634 auto-slot-on-my-brand: 635 auto-slot-on-my-model2: 636 auto-slot-on-multi: 637 638 slot-on-classic-true: 639 slot-on-classic-distros: 640 slot-on-classic-false: 641 642 plug-on-classic-true: 643 plug-on-classic-distros: 644 plug-on-classic-false: 645 `, nil) 646 647 a, err = asserts.Decode([]byte(`type: snap-declaration 648 authority-id: canonical 649 series: 16 650 snap-name: plug-snap 651 snap-id: plugsnapidididididididididididid 652 publisher-id: plug-publisher 653 plugs: 654 snap-plug-allow: true 655 snap-plug-deny: false 656 snap-plug-not-allow: 657 allow-connection: false 658 base-deny-snap-plug-allow: true 659 snap-slot-deny-snap-plug-allow: 660 deny-connection: false 661 trustedhelp: 662 allow-connection: 663 slot-snap-type: 664 - core 665 - gadget 666 precise-slot-snap-id: 667 allow-connection: 668 slot-snap-id: 669 - slotsnapidididididididididididid 670 checked-slot-publisher-id: 671 allow-connection: 672 slot-publisher-id: 673 - slot-publisher 674 - $PLUG_PUBLISHER_ID 675 auto-snap-plug-allow: true 676 auto-snap-plug-deny: false 677 auto-snap-plug-not-allow: 678 allow-auto-connection: false 679 auto-snap-slot-deny-snap-plug-allow: 680 deny-auto-connection: false 681 auto-base-deny-snap-plug-allow: true 682 auto-plug-on-store1: 683 allow-auto-connection: 684 on-store: 685 - store1 686 auto-plug-on-my-brand: 687 allow-auto-connection: 688 on-brand: 689 - my-brand 690 - my-brand-subbrand 691 auto-plug-on-my-model2: 692 allow-auto-connection: 693 on-model: 694 - my-brand-subbrand/my-model2 695 auto-plug-on-multi: 696 allow-auto-connection: 697 on-brand: 698 - my-brand 699 - my-brand-subbrand 700 on-store: 701 - store1 702 - other-store 703 on-model: 704 - my-brand/my-model1 705 - my-brand-subbrand/my-model2 706 timestamp: 2016-09-30T12:00:00Z 707 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 708 709 AXNpZw==`)) 710 c.Assert(err, IsNil) 711 s.plugDecl = a.(*asserts.SnapDeclaration) 712 713 a, err = asserts.Decode([]byte(`type: snap-declaration 714 authority-id: canonical 715 series: 16 716 snap-name: slot-snap 717 snap-id: slotsnapidididididididididididid 718 publisher-id: slot-publisher 719 slots: 720 snap-slot-allow: true 721 snap-slot-deny: false 722 snap-slot-not-allow: 723 allow-connection: false 724 base-deny-snap-slot-allow: true 725 snap-slot-deny-snap-plug-allow: 726 deny-connection: true 727 base-allow-snap-slot-not-allow: 728 allow-connection: false 729 precise-plug-snap-id: 730 allow-connection: 731 plug-snap-id: 732 - plugsnapidididididididididididid 733 checked-plug-publisher-id: 734 allow-connection: 735 plug-publisher-id: 736 - plug-publisher 737 auto-snap-slot-allow: true 738 auto-snap-slot-deny: false 739 auto-snap-slot-not-allow: 740 allow-auto-connection: false 741 auto-base-deny-snap-slot-allow: true 742 auto-snap-slot-deny-snap-plug-allow: 743 deny-auto-connection: true 744 auto-base-allow-snap-slot-not-allow: 745 allow-auto-connection: false 746 auto-slot-on-store1: 747 allow-auto-connection: 748 on-store: 749 - store1 750 auto-slot-on-my-brand: 751 allow-auto-connection: 752 on-brand: 753 - my-brand 754 - my-brand-subbrand 755 auto-slot-on-my-model2: 756 allow-auto-connection: 757 on-model: 758 - my-brand-subbrand/my-model2 759 auto-slot-on-multi: 760 allow-auto-connection: 761 on-brand: 762 - my-brand 763 - my-brand-subbrand 764 on-store: 765 - store1 766 - other-store 767 on-model: 768 - my-brand/my-model1 769 - my-brand-subbrand/my-model2 770 timestamp: 2016-09-30T12:00:00Z 771 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 772 773 AXNpZw==`)) 774 c.Assert(err, IsNil) 775 s.slotDecl = a.(*asserts.SnapDeclaration) 776 777 s.randomSnap = snaptest.MockInfo(c, ` 778 name: random-snap 779 version: 0 780 plugs: 781 precise-plug-snap-id: 782 checked-plug-publisher-id: 783 same-slot-publisher-id: 784 slot-slot-attr: 785 slots: 786 precise-slot-snap-id: 787 checked-slot-publisher-id: 788 same-plug-publisher-id: 789 `, nil) 790 791 a, err = asserts.Decode([]byte(`type: snap-declaration 792 authority-id: canonical 793 series: 16 794 snap-name: random-snap 795 snap-id: randomsnapididididididididid 796 publisher-id: random-publisher 797 timestamp: 2016-09-30T12:00:00Z 798 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 799 800 AXNpZw==`)) 801 c.Assert(err, IsNil) 802 s.randomDecl = a.(*asserts.SnapDeclaration) 803 } 804 805 func (s *policySuite) TearDownSuite(c *C) { 806 s.restoreSanitize() 807 } 808 809 func (s *policySuite) TestBaselineDefaultIsAllow(c *C) { 810 cand := policy.ConnectCandidate{ 811 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["random"], nil, nil), 812 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["random"], nil, nil), 813 BaseDeclaration: s.baseDecl, 814 } 815 816 c.Check(cand.Check(), IsNil) 817 c.Check(cand.CheckAutoConnect(), IsNil) 818 } 819 820 func (s *policySuite) TestInterfaceMismatch(c *C) { 821 cand := policy.ConnectCandidate{ 822 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["mismatchy"], nil, nil), 823 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["mismatchy"], nil, nil), 824 BaseDeclaration: s.baseDecl, 825 } 826 827 c.Check(cand.Check(), ErrorMatches, `cannot connect mismatched plug interface "bar" to slot interface "baz"`) 828 } 829 830 func (s *policySuite) TestBaseDeclAllowDenyConnection(c *C) { 831 tests := []struct { 832 iface string 833 expected string // "" => no error 834 }{ 835 {"base-plug-allow", ""}, 836 {"base-plug-deny", `connection denied by plug rule of interface "base-plug-deny"`}, 837 {"base-plug-not-allow", `connection not allowed by plug rule of interface "base-plug-not-allow"`}, 838 {"base-slot-allow", ""}, 839 {"base-slot-deny", `connection denied by slot rule of interface "base-slot-deny"`}, 840 {"base-slot-not-allow", `connection not allowed by slot rule of interface "base-slot-not-allow"`}, 841 {"base-plug-not-allow-slots", `connection not allowed.*`}, 842 {"base-slot-not-allow-slots", `connection not allowed.*`}, 843 {"base-plug-not-allow-plugs", `connection not allowed.*`}, 844 {"base-slot-not-allow-plugs", `connection not allowed.*`}, 845 {"plug-or-p1-s1", ""}, 846 {"plug-or-p2-s2", ""}, 847 {"plug-or-p1-s2", "connection not allowed by plug rule.*"}, 848 {"slot-or-p1-s1", ""}, 849 {"slot-or-p2-s2", ""}, 850 {"slot-or-p1-s2", "connection not allowed by slot rule.*"}, 851 } 852 853 for _, t := range tests { 854 cand := policy.ConnectCandidate{ 855 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 856 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 857 BaseDeclaration: s.baseDecl, 858 } 859 860 err := cand.Check() 861 if t.expected == "" { 862 c.Check(err, IsNil) 863 } else { 864 c.Check(err, ErrorMatches, t.expected) 865 } 866 } 867 } 868 869 func (s *policySuite) TestBaseDeclAllowDenyAutoConnection(c *C) { 870 tests := []struct { 871 iface string 872 expected string // "" => no error 873 }{ 874 {"auto-base-plug-allow", ""}, 875 {"auto-base-plug-deny", `auto-connection denied by plug rule of interface "auto-base-plug-deny"`}, 876 {"auto-base-plug-not-allow", `auto-connection not allowed by plug rule of interface "auto-base-plug-not-allow"`}, 877 {"auto-base-slot-allow", ""}, 878 {"auto-base-slot-deny", `auto-connection denied by slot rule of interface "auto-base-slot-deny"`}, 879 {"auto-base-slot-not-allow", `auto-connection not allowed by slot rule of interface "auto-base-slot-not-allow"`}, 880 {"auto-base-plug-not-allow-slots", `auto-connection not allowed.*`}, 881 {"auto-base-slot-not-allow-slots", `auto-connection not allowed.*`}, 882 {"auto-base-plug-not-allow-plugs", `auto-connection not allowed.*`}, 883 {"auto-base-slot-not-allow-plugs", `auto-connection not allowed.*`}, 884 {"auto-plug-or-p1-s1", ""}, 885 {"auto-plug-or-p2-s2", ""}, 886 {"auto-plug-or-p2-s1", "auto-connection not allowed by plug rule.*"}, 887 {"auto-slot-or-p1-s1", ""}, 888 {"auto-slot-or-p2-s2", ""}, 889 {"auto-slot-or-p2-s1", "auto-connection not allowed by slot rule.*"}, 890 } 891 892 for _, t := range tests { 893 cand := policy.ConnectCandidate{ 894 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 895 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 896 BaseDeclaration: s.baseDecl, 897 } 898 899 err := cand.CheckAutoConnect() 900 if t.expected == "" { 901 c.Check(err, IsNil) 902 } else { 903 c.Check(err, ErrorMatches, t.expected) 904 } 905 } 906 } 907 908 func (s *policySuite) TestSnapDeclAllowDenyConnection(c *C) { 909 tests := []struct { 910 iface string 911 expected string // "" => no error 912 }{ 913 {"random", ""}, 914 {"snap-plug-allow", ""}, 915 {"snap-plug-deny", `connection denied by plug rule of interface "snap-plug-deny" for "plug-snap" snap`}, 916 {"snap-plug-not-allow", `connection not allowed by plug rule of interface "snap-plug-not-allow" for "plug-snap" snap`}, 917 {"snap-slot-allow", ""}, 918 {"snap-slot-deny", `connection denied by slot rule of interface "snap-slot-deny" for "slot-snap" snap`}, 919 {"snap-slot-not-allow", `connection not allowed by slot rule of interface "snap-slot-not-allow" for "slot-snap" snap`}, 920 {"base-deny-snap-slot-allow", ""}, 921 {"base-deny-snap-plug-allow", ""}, 922 {"snap-slot-deny-snap-plug-allow", ""}, 923 {"base-allow-snap-slot-not-allow", `connection not allowed.*`}, 924 } 925 926 for _, t := range tests { 927 cand := policy.ConnectCandidate{ 928 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 929 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 930 PlugSnapDeclaration: s.plugDecl, 931 SlotSnapDeclaration: s.slotDecl, 932 BaseDeclaration: s.baseDecl, 933 } 934 935 err := cand.Check() 936 if t.expected == "" { 937 c.Check(err, IsNil) 938 } else { 939 c.Check(err, ErrorMatches, t.expected) 940 } 941 } 942 } 943 944 func (s *policySuite) TestSnapDeclAllowDenyAutoConnection(c *C) { 945 tests := []struct { 946 iface string 947 expected string // "" => no error 948 }{ 949 {"random", ""}, 950 {"auto-snap-plug-allow", ""}, 951 {"auto-snap-plug-deny", `auto-connection denied by plug rule of interface "auto-snap-plug-deny" for "plug-snap" snap`}, 952 {"auto-snap-plug-not-allow", `auto-connection not allowed by plug rule of interface "auto-snap-plug-not-allow" for "plug-snap" snap`}, 953 {"auto-snap-slot-allow", ""}, 954 {"auto-snap-slot-deny", `auto-connection denied by slot rule of interface "auto-snap-slot-deny" for "slot-snap" snap`}, 955 {"auto-snap-slot-not-allow", `auto-connection not allowed by slot rule of interface "auto-snap-slot-not-allow" for "slot-snap" snap`}, 956 {"auto-base-deny-snap-slot-allow", ""}, 957 {"auto-base-deny-snap-plug-allow", ""}, 958 {"auto-snap-slot-deny-snap-plug-allow", ""}, 959 {"auto-base-allow-snap-slot-not-allow", `auto-connection not allowed.*`}, 960 } 961 962 for _, t := range tests { 963 cand := policy.ConnectCandidate{ 964 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 965 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 966 PlugSnapDeclaration: s.plugDecl, 967 SlotSnapDeclaration: s.slotDecl, 968 BaseDeclaration: s.baseDecl, 969 } 970 971 err := cand.CheckAutoConnect() 972 if t.expected == "" { 973 c.Check(err, IsNil) 974 } else { 975 c.Check(err, ErrorMatches, t.expected) 976 } 977 } 978 } 979 980 func (s *policySuite) TestSnapTypeCheckConnection(c *C) { 981 gadgetSnap := snaptest.MockInfo(c, ` 982 name: gadget 983 version: 0 984 type: gadget 985 plugs: 986 gadgethelp: 987 slots: 988 trustedhelp: 989 `, nil) 990 991 coreSnap := snaptest.MockInfo(c, ` 992 name: core 993 version: 0 994 type: os 995 slots: 996 gadgethelp: 997 trustedhelp: 998 `, nil) 999 1000 cand := policy.ConnectCandidate{ 1001 Plug: interfaces.NewConnectedPlug(gadgetSnap.Plugs["gadgethelp"], nil, nil), 1002 Slot: interfaces.NewConnectedSlot(coreSnap.Slots["gadgethelp"], nil, nil), 1003 BaseDeclaration: s.baseDecl, 1004 } 1005 c.Check(cand.Check(), IsNil) 1006 1007 cand = policy.ConnectCandidate{ 1008 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["gadgethelp"], nil, nil), 1009 Slot: interfaces.NewConnectedSlot(coreSnap.Slots["gadgethelp"], nil, nil), 1010 BaseDeclaration: s.baseDecl, 1011 } 1012 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1013 1014 for _, trustedSide := range []*snap.Info{coreSnap, gadgetSnap} { 1015 cand = policy.ConnectCandidate{ 1016 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["trustedhelp"], nil, nil), 1017 PlugSnapDeclaration: s.plugDecl, 1018 Slot: interfaces.NewConnectedSlot(trustedSide.Slots["trustedhelp"], nil, nil), 1019 BaseDeclaration: s.baseDecl, 1020 } 1021 c.Check(cand.Check(), IsNil) 1022 } 1023 1024 cand = policy.ConnectCandidate{ 1025 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["trustedhelp"], nil, nil), 1026 PlugSnapDeclaration: s.plugDecl, 1027 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["trustedhelp"], nil, nil), 1028 BaseDeclaration: s.baseDecl, 1029 } 1030 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1031 } 1032 1033 func (s *policySuite) TestPlugSnapIDCheckConnection(c *C) { 1034 // no plug-side declaration 1035 cand := policy.ConnectCandidate{ 1036 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["precise-plug-snap-id"], nil, nil), 1037 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil), 1038 SlotSnapDeclaration: s.slotDecl, 1039 BaseDeclaration: s.baseDecl, 1040 } 1041 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1042 1043 // plug-side declaration, wrong snap-id 1044 cand = policy.ConnectCandidate{ 1045 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["precise-plug-snap-id"], nil, nil), 1046 PlugSnapDeclaration: s.randomDecl, 1047 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil), 1048 SlotSnapDeclaration: s.slotDecl, 1049 BaseDeclaration: s.baseDecl, 1050 } 1051 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1052 1053 // right snap-id 1054 cand = policy.ConnectCandidate{ 1055 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-plug-snap-id"], nil, nil), 1056 PlugSnapDeclaration: s.plugDecl, 1057 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil), 1058 SlotSnapDeclaration: s.slotDecl, 1059 BaseDeclaration: s.baseDecl, 1060 } 1061 c.Check(cand.Check(), IsNil) 1062 } 1063 1064 func (s *policySuite) TestSlotSnapIDCheckConnection(c *C) { 1065 // no slot-side declaration 1066 cand := policy.ConnectCandidate{ 1067 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil), 1068 PlugSnapDeclaration: s.plugDecl, 1069 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["precise-slot-snap-id"], nil, nil), 1070 BaseDeclaration: s.baseDecl, 1071 } 1072 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1073 1074 // slot-side declaration, wrong snap-id 1075 cand = policy.ConnectCandidate{ 1076 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil), 1077 PlugSnapDeclaration: s.plugDecl, 1078 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["precise-slot-snap-id"], nil, nil), 1079 SlotSnapDeclaration: s.randomDecl, 1080 BaseDeclaration: s.baseDecl, 1081 } 1082 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1083 1084 // right snap-id 1085 cand = policy.ConnectCandidate{ 1086 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil), 1087 PlugSnapDeclaration: s.plugDecl, 1088 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-slot-snap-id"], nil, nil), 1089 SlotSnapDeclaration: s.slotDecl, 1090 BaseDeclaration: s.baseDecl, 1091 } 1092 c.Check(cand.Check(), IsNil) 1093 } 1094 1095 func (s *policySuite) TestPlugPublisherIDCheckConnection(c *C) { 1096 // no plug-side declaration 1097 cand := policy.ConnectCandidate{ 1098 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["checked-plug-publisher-id"], nil, nil), 1099 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil), 1100 SlotSnapDeclaration: s.slotDecl, 1101 BaseDeclaration: s.baseDecl, 1102 } 1103 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1104 1105 // plug-side declaration, wrong publisher-id 1106 cand = policy.ConnectCandidate{ 1107 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["checked-plug-publisher-id"], nil, nil), 1108 PlugSnapDeclaration: s.randomDecl, 1109 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil), 1110 SlotSnapDeclaration: s.slotDecl, 1111 BaseDeclaration: s.baseDecl, 1112 } 1113 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1114 1115 // right publisher-id 1116 cand = policy.ConnectCandidate{ 1117 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-plug-publisher-id"], nil, nil), 1118 PlugSnapDeclaration: s.plugDecl, 1119 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil), 1120 SlotSnapDeclaration: s.slotDecl, 1121 BaseDeclaration: s.baseDecl, 1122 } 1123 c.Check(cand.Check(), IsNil) 1124 } 1125 1126 func (s *policySuite) TestSlotPublisherIDCheckConnection(c *C) { 1127 // no slot-side declaration 1128 cand := policy.ConnectCandidate{ 1129 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil), 1130 PlugSnapDeclaration: s.plugDecl, 1131 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["checked-slot-publisher-id"], nil, nil), 1132 BaseDeclaration: s.baseDecl, 1133 } 1134 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1135 1136 // slot-side declaration, wrong publisher-id 1137 cand = policy.ConnectCandidate{ 1138 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil), 1139 PlugSnapDeclaration: s.plugDecl, 1140 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["checked-slot-publisher-id"], nil, nil), 1141 SlotSnapDeclaration: s.randomDecl, 1142 BaseDeclaration: s.baseDecl, 1143 } 1144 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1145 1146 // right publisher-id 1147 cand = policy.ConnectCandidate{ 1148 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil), 1149 PlugSnapDeclaration: s.plugDecl, 1150 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-slot-publisher-id"], nil, nil), 1151 SlotSnapDeclaration: s.slotDecl, 1152 BaseDeclaration: s.baseDecl, 1153 } 1154 c.Check(cand.Check(), IsNil) 1155 } 1156 1157 func (s *policySuite) TestDollarPlugPublisherIDCheckConnection(c *C) { 1158 // no known publishers 1159 cand := policy.ConnectCandidate{ 1160 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil), 1161 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil), 1162 BaseDeclaration: s.baseDecl, 1163 } 1164 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1165 1166 // no slot-side declaration 1167 cand = policy.ConnectCandidate{ 1168 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil), 1169 PlugSnapDeclaration: s.plugDecl, 1170 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil), 1171 BaseDeclaration: s.baseDecl, 1172 } 1173 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1174 1175 // slot-side declaration, wrong publisher-id 1176 cand = policy.ConnectCandidate{ 1177 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil), 1178 PlugSnapDeclaration: s.plugDecl, 1179 Slot: interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil), 1180 SlotSnapDeclaration: s.randomDecl, 1181 BaseDeclaration: s.baseDecl, 1182 } 1183 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1184 1185 // slot publisher id == plug publisher id 1186 samePubSlotSnap := snaptest.MockInfo(c, ` 1187 name: same-pub-slot-snap 1188 version: 0 1189 slots: 1190 same-plug-publisher-id: 1191 `, nil) 1192 1193 a, err := asserts.Decode([]byte(`type: snap-declaration 1194 authority-id: canonical 1195 series: 16 1196 snap-name: same-pub-slot-snap 1197 snap-id: samepublslotsnapidididididididid 1198 publisher-id: plug-publisher 1199 timestamp: 2016-09-30T12:00:00Z 1200 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1201 1202 AXNpZw==`)) 1203 c.Assert(err, IsNil) 1204 samePubSlotDecl := a.(*asserts.SnapDeclaration) 1205 1206 cand = policy.ConnectCandidate{ 1207 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil), 1208 PlugSnapDeclaration: s.plugDecl, 1209 Slot: interfaces.NewConnectedSlot(samePubSlotSnap.Slots["same-plug-publisher-id"], nil, nil), 1210 SlotSnapDeclaration: samePubSlotDecl, 1211 BaseDeclaration: s.baseDecl, 1212 } 1213 c.Check(cand.Check(), IsNil) 1214 } 1215 1216 func (s *policySuite) TestDollarSlotPublisherIDCheckConnection(c *C) { 1217 // no known publishers 1218 cand := policy.ConnectCandidate{ 1219 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil), 1220 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil), 1221 BaseDeclaration: s.baseDecl, 1222 } 1223 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1224 1225 // no plug-side declaration 1226 cand = policy.ConnectCandidate{ 1227 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil), 1228 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil), 1229 SlotSnapDeclaration: s.slotDecl, 1230 BaseDeclaration: s.baseDecl, 1231 } 1232 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1233 1234 // plug-side declaration, wrong publisher-id 1235 cand = policy.ConnectCandidate{ 1236 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil), 1237 PlugSnapDeclaration: s.randomDecl, 1238 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil), 1239 SlotSnapDeclaration: s.slotDecl, 1240 BaseDeclaration: s.baseDecl, 1241 } 1242 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 1243 1244 // plug publisher id == slot publisher id 1245 samePubPlugSnap := snaptest.MockInfo(c, ` 1246 name: same-pub-plug-snap 1247 version: 0 1248 plugs: 1249 same-slot-publisher-id: 1250 `, nil) 1251 1252 a, err := asserts.Decode([]byte(`type: snap-declaration 1253 authority-id: canonical 1254 series: 16 1255 snap-name: same-pub-plug-snap 1256 snap-id: samepublplugsnapidididididididid 1257 publisher-id: slot-publisher 1258 timestamp: 2016-09-30T12:00:00Z 1259 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1260 1261 AXNpZw==`)) 1262 c.Assert(err, IsNil) 1263 samePubPlugDecl := a.(*asserts.SnapDeclaration) 1264 1265 cand = policy.ConnectCandidate{ 1266 Plug: interfaces.NewConnectedPlug(samePubPlugSnap.Plugs["same-slot-publisher-id"], nil, nil), 1267 PlugSnapDeclaration: samePubPlugDecl, 1268 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil), 1269 SlotSnapDeclaration: s.slotDecl, 1270 BaseDeclaration: s.baseDecl, 1271 } 1272 c.Check(cand.Check(), IsNil) 1273 } 1274 1275 func (s *policySuite) TestBaselineDefaultIsAllowInstallation(c *C) { 1276 installSnap := snaptest.MockInfo(c, ` 1277 name: install-slot-snap 1278 version: 0 1279 slots: 1280 random1: 1281 plugs: 1282 random2: 1283 `, nil) 1284 1285 cand := policy.InstallCandidate{ 1286 Snap: installSnap, 1287 BaseDeclaration: s.baseDecl, 1288 } 1289 1290 c.Check(cand.Check(), IsNil) 1291 } 1292 1293 func (s *policySuite) TestBaseDeclAllowDenyInstallation(c *C) { 1294 1295 tests := []struct { 1296 installYaml string 1297 expected string // "" => no error 1298 }{ 1299 {`name: install-snap 1300 version: 0 1301 slots: 1302 innocuous: 1303 install-slot-coreonly: 1304 `, `installation not allowed by "install-slot-coreonly" slot rule of interface "install-slot-coreonly"`}, 1305 {`name: install-snap 1306 version: 0 1307 slots: 1308 install-slot-attr-ok: 1309 attr: ok 1310 `, ""}, 1311 {`name: install-snap 1312 version: 0 1313 slots: 1314 install-slot-attr-deny: 1315 trust: trusted 1316 `, `installation denied by "install-slot-attr-deny" slot rule of interface "install-slot-attr-deny"`}, 1317 {`name: install-snap 1318 version: 0 1319 plugs: 1320 install-plug-attr-ok: 1321 attr: ok 1322 `, ""}, 1323 {`name: install-snap 1324 version: 0 1325 plugs: 1326 install-plug-attr-ok: 1327 attr: not-ok 1328 `, `installation not allowed by "install-plug-attr-ok" plug rule of interface "install-plug-attr-ok"`}, 1329 {`name: install-snap 1330 version: 0 1331 plugs: 1332 install-plug-gadget-only: 1333 `, `installation not allowed by "install-plug-gadget-only" plug rule of interface "install-plug-gadget-only"`}, 1334 {`name: install-gadget 1335 version: 0 1336 type: gadget 1337 plugs: 1338 install-plug-gadget-only: 1339 `, ""}, 1340 {`name: install-gadget 1341 version: 0 1342 type: gadget 1343 plugs: 1344 install-plug-or: 1345 p: P2`, `installation denied by "install-plug-or" plug rule.*`}, 1346 {`name: install-snap 1347 version: 0 1348 plugs: 1349 install-plug-or: 1350 p: P1`, `installation denied by "install-plug-or" plug rule.*`}, 1351 {`name: install-snap 1352 version: 0 1353 plugs: 1354 install-plug-or: 1355 p: P3`, ""}, 1356 {`name: install-gadget 1357 version: 0 1358 type: gadget 1359 slots: 1360 install-slot-or: 1361 p: P2`, `installation denied by "install-slot-or" slot rule.*`}, 1362 {`name: install-snap 1363 version: 0 1364 slots: 1365 install-slot-or: 1366 p: P1`, `installation denied by "install-slot-or" slot rule.*`}, 1367 {`name: install-snap 1368 version: 0 1369 slots: 1370 install-slot-or: 1371 p: P3`, ""}, 1372 } 1373 1374 for _, t := range tests { 1375 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 1376 1377 cand := policy.InstallCandidate{ 1378 Snap: installSnap, 1379 BaseDeclaration: s.baseDecl, 1380 } 1381 1382 err := cand.Check() 1383 if t.expected == "" { 1384 c.Check(err, IsNil) 1385 } else { 1386 c.Check(err, ErrorMatches, t.expected) 1387 } 1388 } 1389 } 1390 1391 func (s *policySuite) TestSnapDeclAllowDenyInstallation(c *C) { 1392 1393 tests := []struct { 1394 installYaml string 1395 plugsSlots string 1396 expected string // "" => no error 1397 }{ 1398 {`name: install-snap 1399 version: 0 1400 slots: 1401 install-slot-base-allow-snap-deny: 1402 have: yes # bool 1403 `, `slots: 1404 install-slot-base-allow-snap-deny: 1405 deny-installation: 1406 slot-attributes: 1407 have: true 1408 `, `installation denied by "install-slot-base-allow-snap-deny" slot rule of interface "install-slot-base-allow-snap-deny" for "install-snap" snap`}, 1409 {`name: install-snap 1410 version: 0 1411 slots: 1412 install-slot-base-allow-snap-not-allow: 1413 have: yes # bool 1414 `, `slots: 1415 install-slot-base-allow-snap-not-allow: 1416 allow-installation: 1417 slot-attributes: 1418 have: false 1419 `, `installation not allowed by "install-slot-base-allow-snap-not-allow" slot rule of interface "install-slot-base-allow-snap-not-allow" for "install-snap" snap`}, 1420 {`name: install-snap 1421 version: 0 1422 slots: 1423 install-slot-base-deny-snap-allow: 1424 have: yes 1425 `, `slots: 1426 install-slot-base-deny-snap-allow: 1427 allow-installation: true 1428 `, ""}, 1429 {`name: install-snap 1430 version: 0 1431 plugs: 1432 install-plug-base-allow-snap-deny: 1433 attr: give-me 1434 `, `plugs: 1435 install-plug-base-allow-snap-deny: 1436 deny-installation: 1437 plug-attributes: 1438 attr: .* 1439 `, `installation denied by "install-plug-base-allow-snap-deny" plug rule of interface "install-plug-base-allow-snap-deny" for "install-snap" snap`}, 1440 {`name: install-snap 1441 version: 0 1442 plugs: 1443 install-plug-base-allow-snap-not-allow: 1444 attr: give-me 1445 `, `plugs: 1446 install-plug-base-allow-snap-not-allow: 1447 allow-installation: 1448 plug-attributes: 1449 attr: minimal 1450 `, `installation not allowed by "install-plug-base-allow-snap-not-allow" plug rule of interface "install-plug-base-allow-snap-not-allow" for "install-snap" snap`}, 1451 {`name: install-snap 1452 version: 0 1453 plugs: 1454 install-plug-base-deny-snap-allow: 1455 attr: attrvalue 1456 `, `plugs: 1457 install-plug-base-deny-snap-allow: 1458 allow-installation: 1459 plug-attributes: 1460 attr: attrvalue 1461 `, ""}, 1462 } 1463 1464 for _, t := range tests { 1465 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 1466 1467 a, err := asserts.Decode([]byte(strings.Replace(`type: snap-declaration 1468 authority-id: canonical 1469 series: 16 1470 snap-name: install-snap 1471 snap-id: installsnap6idididididididididid 1472 publisher-id: publisher 1473 @plugsSlots@ 1474 timestamp: 2016-09-30T12:00:00Z 1475 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1476 1477 AXNpZw==`, "@plugsSlots@", strings.TrimSpace(t.plugsSlots), 1))) 1478 c.Assert(err, IsNil) 1479 snapDecl := a.(*asserts.SnapDeclaration) 1480 1481 cand := policy.InstallCandidate{ 1482 Snap: installSnap, 1483 SnapDeclaration: snapDecl, 1484 BaseDeclaration: s.baseDecl, 1485 } 1486 1487 err = cand.Check() 1488 if t.expected == "" { 1489 c.Check(err, IsNil) 1490 } else { 1491 c.Check(err, ErrorMatches, t.expected) 1492 } 1493 } 1494 } 1495 1496 func (s *policySuite) TestBaseDeclAllowDenyInstallationMinimalCheck(c *C) { 1497 tests := []struct { 1498 installYaml string 1499 expected string // "" => no error 1500 }{ 1501 {`name: install-snap 1502 version: 0 1503 slots: 1504 innocuous: 1505 install-slot-coreonly: 1506 `, `installation not allowed by "install-slot-coreonly" slot rule of interface "install-slot-coreonly"`}, 1507 {`name: install-gadget 1508 version: 0 1509 type: gadget 1510 slots: 1511 install-slot-or: 1512 `, `installation denied by "install-slot-or" slot rule.*`}, 1513 {`name: install-snap 1514 version: 0 1515 slots: 1516 install-slot-or: 1517 `, ""}, 1518 {`name: install-snap 1519 version: 0 1520 plugs: 1521 install-plug-gadget-only: 1522 `, ``}, // plug is not validated with minimal installation check 1523 } 1524 1525 for _, t := range tests { 1526 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 1527 1528 cand := policy.InstallCandidateMinimalCheck{ 1529 Snap: installSnap, 1530 BaseDeclaration: s.baseDecl, 1531 } 1532 1533 err := cand.Check() 1534 if t.expected == "" { 1535 c.Check(err, IsNil) 1536 } else { 1537 c.Check(err, ErrorMatches, t.expected) 1538 } 1539 } 1540 } 1541 1542 func (s *policySuite) TestOnClassicMinimalInstallationCheck(c *C) { 1543 r1 := release.MockOnClassic(false) 1544 defer r1() 1545 r2 := release.MockReleaseInfo(&release.ReleaseInfo) 1546 defer r2() 1547 1548 tests := []struct { 1549 distro string // "" => not classic 1550 installYaml string 1551 err string // "" => no error 1552 }{ 1553 {"", `name: install-snap 1554 version: 0 1555 slots: 1556 install-slot-on-classic-distros:`, `installation not allowed by "install-slot-on-classic-distros" slot rule.*`}, 1557 {"debian", `name: install-snap 1558 version: 0 1559 slots: 1560 install-slot-on-classic-distros:`, ""}, 1561 {"", `name: install-snap 1562 version: 0 1563 plugs: 1564 install-plug-on-classic-distros:`, ""}, // plug is not validated with minimal installation check 1565 {"debian", `name: install-snap 1566 version: 0 1567 plugs: 1568 install-plug-on-classic-distros:`, ""}, 1569 } 1570 1571 for _, t := range tests { 1572 if t.distro == "" { 1573 release.OnClassic = false 1574 } else { 1575 release.OnClassic = true 1576 release.ReleaseInfo = release.OS{ 1577 ID: t.distro, 1578 } 1579 } 1580 1581 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 1582 1583 cand := policy.InstallCandidateMinimalCheck{ 1584 Snap: installSnap, 1585 BaseDeclaration: s.baseDecl, 1586 } 1587 err := cand.Check() 1588 if t.err == "" { 1589 c.Check(err, IsNil) 1590 } else { 1591 c.Check(err, ErrorMatches, t.err) 1592 } 1593 } 1594 } 1595 1596 func (s *policySuite) TestPlugOnClassicCheckConnection(c *C) { 1597 r1 := release.MockOnClassic(false) 1598 defer r1() 1599 r2 := release.MockReleaseInfo(&release.ReleaseInfo) 1600 defer r2() 1601 1602 tests := []struct { 1603 distro string // "" => not classic 1604 iface string 1605 err string // "" => no error 1606 }{ 1607 {"ubuntu", "plug-on-classic-true", ""}, 1608 {"", "plug-on-classic-true", `connection not allowed by plug rule of interface "plug-on-classic-true"`}, 1609 {"", "plug-on-classic-false", ""}, 1610 {"ubuntu", "plug-on-classic-false", "connection not allowed.*"}, 1611 {"ubuntu", "plug-on-classic-distros", ""}, 1612 {"debian", "plug-on-classic-distros", ""}, 1613 {"", "plug-on-classic-distros", "connection not allowed.*"}, 1614 {"other", "plug-on-classic-distros", "connection not allowed.*"}, 1615 } 1616 1617 for _, t := range tests { 1618 if t.distro == "" { 1619 release.OnClassic = false 1620 } else { 1621 release.OnClassic = true 1622 release.ReleaseInfo = release.OS{ 1623 ID: t.distro, 1624 } 1625 } 1626 cand := policy.ConnectCandidate{ 1627 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1628 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1629 BaseDeclaration: s.baseDecl, 1630 } 1631 err := cand.Check() 1632 if t.err == "" { 1633 c.Check(err, IsNil) 1634 } else { 1635 c.Check(err, ErrorMatches, t.err) 1636 } 1637 } 1638 } 1639 1640 func (s *policySuite) TestSlotOnClassicCheckConnection(c *C) { 1641 r1 := release.MockOnClassic(false) 1642 defer r1() 1643 r2 := release.MockReleaseInfo(&release.ReleaseInfo) 1644 defer r2() 1645 1646 tests := []struct { 1647 distro string // "" => not classic 1648 iface string 1649 err string // "" => no error 1650 }{ 1651 {"ubuntu", "slot-on-classic-true", ""}, 1652 {"", "slot-on-classic-true", `connection not allowed by slot rule of interface "slot-on-classic-true"`}, 1653 {"", "slot-on-classic-false", ""}, 1654 {"ubuntu", "slot-on-classic-false", "connection not allowed.*"}, 1655 {"ubuntu", "slot-on-classic-distros", ""}, 1656 {"debian", "slot-on-classic-distros", ""}, 1657 {"", "slot-on-classic-distros", "connection not allowed.*"}, 1658 {"other", "slot-on-classic-distros", "connection not allowed.*"}, 1659 } 1660 1661 for _, t := range tests { 1662 if t.distro == "" { 1663 release.OnClassic = false 1664 } else { 1665 release.OnClassic = true 1666 release.ReleaseInfo = release.OS{ 1667 ID: t.distro, 1668 } 1669 } 1670 cand := policy.ConnectCandidate{ 1671 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1672 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1673 BaseDeclaration: s.baseDecl, 1674 } 1675 err := cand.Check() 1676 if t.err == "" { 1677 c.Check(err, IsNil) 1678 } else { 1679 c.Check(err, ErrorMatches, t.err) 1680 } 1681 } 1682 } 1683 1684 func (s *policySuite) TestOnClassicInstallation(c *C) { 1685 r1 := release.MockOnClassic(false) 1686 defer r1() 1687 r2 := release.MockReleaseInfo(&release.ReleaseInfo) 1688 defer r2() 1689 1690 tests := []struct { 1691 distro string // "" => not classic 1692 installYaml string 1693 err string // "" => no error 1694 }{ 1695 {"", `name: install-snap 1696 version: 0 1697 slots: 1698 install-slot-on-classic-distros:`, `installation not allowed by "install-slot-on-classic-distros" slot rule.*`}, 1699 {"debian", `name: install-snap 1700 version: 0 1701 slots: 1702 install-slot-on-classic-distros:`, ""}, 1703 {"", `name: install-snap 1704 version: 0 1705 plugs: 1706 install-plug-on-classic-distros:`, `installation not allowed by "install-plug-on-classic-distros" plug rule.*`}, 1707 {"debian", `name: install-snap 1708 version: 0 1709 plugs: 1710 install-plug-on-classic-distros:`, ""}, 1711 } 1712 1713 for _, t := range tests { 1714 if t.distro == "" { 1715 release.OnClassic = false 1716 } else { 1717 release.OnClassic = true 1718 release.ReleaseInfo = release.OS{ 1719 ID: t.distro, 1720 } 1721 } 1722 1723 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 1724 1725 cand := policy.InstallCandidate{ 1726 Snap: installSnap, 1727 BaseDeclaration: s.baseDecl, 1728 } 1729 err := cand.Check() 1730 if t.err == "" { 1731 c.Check(err, IsNil) 1732 } else { 1733 c.Check(err, ErrorMatches, t.err) 1734 } 1735 } 1736 } 1737 1738 var ( 1739 otherModel *asserts.Model 1740 myModel1 *asserts.Model 1741 myModel2 *asserts.Model 1742 myModel3 *asserts.Model 1743 1744 substore1 *asserts.Store 1745 ) 1746 1747 func init() { 1748 a, err := asserts.Decode([]byte(`type: model 1749 authority-id: other-brand 1750 series: 16 1751 brand-id: other-brand 1752 model: other-model 1753 classic: true 1754 gadget: gadget 1755 timestamp: 2018-09-12T12:00:00Z 1756 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1757 1758 AXNpZw==`)) 1759 if err != nil { 1760 panic(err) 1761 } 1762 otherModel = a.(*asserts.Model) 1763 1764 a, err = asserts.Decode([]byte(`type: model 1765 authority-id: my-brand 1766 series: 16 1767 brand-id: my-brand 1768 model: my-model1 1769 store: store1 1770 architecture: armhf 1771 kernel: krnl 1772 gadget: gadget 1773 timestamp: 2018-09-12T12:00:00Z 1774 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1775 1776 AXNpZw==`)) 1777 if err != nil { 1778 panic(err) 1779 } 1780 myModel1 = a.(*asserts.Model) 1781 1782 a, err = asserts.Decode([]byte(`type: model 1783 authority-id: my-brand-subbrand 1784 series: 16 1785 brand-id: my-brand-subbrand 1786 model: my-model2 1787 store: store2 1788 architecture: armhf 1789 kernel: krnl 1790 gadget: gadget 1791 timestamp: 2018-09-12T12:00:00Z 1792 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1793 1794 AXNpZw==`)) 1795 if err != nil { 1796 panic(err) 1797 } 1798 myModel2 = a.(*asserts.Model) 1799 1800 a, err = asserts.Decode([]byte(`type: model 1801 authority-id: my-brand 1802 series: 16 1803 brand-id: my-brand 1804 model: my-model3 1805 store: substore1 1806 architecture: armhf 1807 kernel: krnl 1808 gadget: gadget 1809 timestamp: 2018-09-12T12:00:00Z 1810 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1811 1812 AXNpZw==`)) 1813 if err != nil { 1814 panic(err) 1815 } 1816 myModel3 = a.(*asserts.Model) 1817 1818 a, err = asserts.Decode([]byte(`type: store 1819 store: substore1 1820 authority-id: canonical 1821 operator-id: canonical 1822 friendly-stores: 1823 - a-store 1824 - store1 1825 - store2 1826 timestamp: 2018-09-12T12:00:00Z 1827 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 1828 1829 AXNpZw==`)) 1830 if err != nil { 1831 panic(err) 1832 } 1833 substore1 = a.(*asserts.Store) 1834 } 1835 1836 func (s *policySuite) TestPlugDeviceScopeCheckAutoConnection(c *C) { 1837 tests := []struct { 1838 model *asserts.Model 1839 iface string 1840 err string // "" => no error 1841 }{ 1842 {nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1843 {otherModel, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1844 {myModel1, "auto-plug-on-store1", ""}, 1845 {myModel2, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1846 {otherModel, "auto-plug-on-my-brand", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-brand" for "plug-snap" snap`}, 1847 {myModel1, "auto-plug-on-my-brand", ""}, 1848 {myModel2, "auto-plug-on-my-brand", ""}, 1849 {otherModel, "auto-plug-on-my-model2", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-model2" for "plug-snap" snap`}, 1850 {myModel1, "auto-plug-on-my-model2", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-model2" for "plug-snap" snap`}, 1851 {myModel2, "auto-plug-on-my-model2", ""}, 1852 // on-store/on-brand/on-model are ANDed for consistency! 1853 {otherModel, "auto-plug-on-multi", `auto-connection not allowed by plug rule of interface "auto-plug-on-multi" for "plug-snap" snap`}, 1854 {myModel1, "auto-plug-on-multi", ""}, 1855 {myModel2, "auto-plug-on-multi", `auto-connection not allowed by plug rule of interface "auto-plug-on-multi" for "plug-snap" snap`}, 1856 } 1857 1858 for _, t := range tests { 1859 cand := policy.ConnectCandidate{ 1860 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1861 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1862 PlugSnapDeclaration: s.plugDecl, 1863 SlotSnapDeclaration: s.slotDecl, 1864 1865 BaseDeclaration: s.baseDecl, 1866 1867 Model: t.model, 1868 } 1869 err := cand.CheckAutoConnect() 1870 if t.err == "" { 1871 c.Check(err, IsNil) 1872 } else { 1873 c.Check(err, ErrorMatches, t.err) 1874 } 1875 } 1876 } 1877 1878 func (s *policySuite) TestPlugDeviceScopeFriendlyStoreCheckAutoConnection(c *C) { 1879 tests := []struct { 1880 model *asserts.Model 1881 store *asserts.Store 1882 iface string 1883 err string // "" => no error 1884 }{ 1885 {nil, nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1886 {myModel3, nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1887 {myModel3, substore1, "auto-plug-on-store1", ""}, 1888 {myModel2, substore1, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`}, 1889 } 1890 1891 for _, t := range tests { 1892 cand := policy.ConnectCandidate{ 1893 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1894 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1895 PlugSnapDeclaration: s.plugDecl, 1896 SlotSnapDeclaration: s.slotDecl, 1897 1898 BaseDeclaration: s.baseDecl, 1899 1900 Model: t.model, 1901 Store: t.store, 1902 } 1903 err := cand.CheckAutoConnect() 1904 if t.err == "" { 1905 c.Check(err, IsNil) 1906 } else { 1907 c.Check(err, ErrorMatches, t.err) 1908 } 1909 } 1910 } 1911 1912 func (s *policySuite) TestSlotDeviceScopeCheckAutoConnection(c *C) { 1913 tests := []struct { 1914 model *asserts.Model 1915 iface string 1916 err string // "" => no error 1917 }{ 1918 {nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1919 {otherModel, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1920 {myModel1, "auto-slot-on-store1", ""}, 1921 {myModel2, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1922 {otherModel, "auto-slot-on-my-brand", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-brand" for "slot-snap" snap`}, 1923 {myModel1, "auto-slot-on-my-brand", ""}, 1924 {myModel2, "auto-slot-on-my-brand", ""}, 1925 {otherModel, "auto-slot-on-my-model2", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-model2" for "slot-snap" snap`}, 1926 {myModel1, "auto-slot-on-my-model2", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-model2" for "slot-snap" snap`}, 1927 {myModel2, "auto-slot-on-my-model2", ""}, 1928 // on-store/on-brand/on-model are ANDed for consistency! 1929 {otherModel, "auto-slot-on-multi", `auto-connection not allowed by slot rule of interface "auto-slot-on-multi" for "slot-snap" snap`}, 1930 {myModel1, "auto-slot-on-multi", ""}, 1931 {myModel2, "auto-slot-on-multi", `auto-connection not allowed by slot rule of interface "auto-slot-on-multi" for "slot-snap" snap`}, 1932 } 1933 1934 for _, t := range tests { 1935 cand := policy.ConnectCandidate{ 1936 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1937 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1938 PlugSnapDeclaration: s.plugDecl, 1939 SlotSnapDeclaration: s.slotDecl, 1940 1941 BaseDeclaration: s.baseDecl, 1942 1943 Model: t.model, 1944 } 1945 err := cand.CheckAutoConnect() 1946 if t.err == "" { 1947 c.Check(err, IsNil) 1948 } else { 1949 c.Check(err, ErrorMatches, t.err) 1950 } 1951 } 1952 } 1953 1954 func (s *policySuite) TestSlotDeviceScopeFriendlyStoreCheckAutoConnection(c *C) { 1955 tests := []struct { 1956 model *asserts.Model 1957 store *asserts.Store 1958 iface string 1959 err string // "" => no error 1960 }{ 1961 {nil, nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1962 {myModel3, nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1963 {myModel3, substore1, "auto-slot-on-store1", ""}, 1964 {myModel2, substore1, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`}, 1965 } 1966 1967 for _, t := range tests { 1968 cand := policy.ConnectCandidate{ 1969 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil), 1970 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil), 1971 PlugSnapDeclaration: s.plugDecl, 1972 SlotSnapDeclaration: s.slotDecl, 1973 1974 BaseDeclaration: s.baseDecl, 1975 1976 Model: t.model, 1977 Store: t.store, 1978 } 1979 err := cand.CheckAutoConnect() 1980 if t.err == "" { 1981 c.Check(err, IsNil) 1982 } else { 1983 c.Check(err, ErrorMatches, t.err) 1984 } 1985 } 1986 } 1987 1988 func (s *policySuite) TestDeviceScopeInstallation(c *C) { 1989 const plugSnap = `name: install-snap 1990 version: 0 1991 plugs: 1992 install-plug-device-scope:` 1993 1994 const slotSnap = `name: install-snap 1995 version: 0 1996 slots: 1997 install-slot-device-scope:` 1998 1999 const plugOnStore1 = `plugs: 2000 install-plug-device-scope: 2001 allow-installation: 2002 on-store: 2003 - store1 2004 ` 2005 const plugOnMulti = `plugs: 2006 install-plug-device-scope: 2007 allow-installation: 2008 on-brand: 2009 - my-brand 2010 - my-brand-subbrand 2011 on-store: 2012 - store1 2013 - other-store 2014 on-model: 2015 - my-brand/my-model1 2016 - my-brand-subbrand/my-model2 2017 ` 2018 const slotOnStore2 = `slots: 2019 install-slot-device-scope: 2020 allow-installation: 2021 on-store: 2022 - store2 2023 ` 2024 2025 tests := []struct { 2026 model *asserts.Model 2027 store *asserts.Store 2028 installYaml string 2029 plugsSlots string 2030 err string // "" => no error 2031 }{ 2032 {nil, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2033 {otherModel, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2034 {myModel1, nil, plugSnap, plugOnStore1, ""}, 2035 {myModel2, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2036 {otherModel, nil, plugSnap, plugOnMulti, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2037 {myModel1, nil, plugSnap, plugOnMulti, ""}, 2038 {myModel2, nil, plugSnap, plugOnMulti, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2039 {otherModel, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for "install-snap" snap`}, 2040 {myModel1, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for "install-snap" snap`}, 2041 {myModel2, nil, slotSnap, slotOnStore2, ""}, 2042 // friendly-stores 2043 {myModel3, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2044 {myModel3, substore1, plugSnap, plugOnStore1, ""}, 2045 {myModel2, substore1, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`}, 2046 {myModel3, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for \"install-snap\" snap`}, 2047 {myModel3, substore1, slotSnap, slotOnStore2, ""}, 2048 {myModel2, substore1, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for \"install-snap\" snap`}, 2049 } 2050 2051 for _, t := range tests { 2052 installSnap := snaptest.MockInfo(c, t.installYaml, nil) 2053 2054 a, err := asserts.Decode([]byte(strings.Replace(`type: snap-declaration 2055 authority-id: canonical 2056 series: 16 2057 snap-name: install-snap 2058 snap-id: installsnap6idididididididididid 2059 publisher-id: publisher 2060 @plugsSlots@ 2061 timestamp: 2016-09-30T12:00:00Z 2062 sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij 2063 2064 AXNpZw==`, "@plugsSlots@", strings.TrimSpace(t.plugsSlots), 1))) 2065 c.Assert(err, IsNil) 2066 snapDecl := a.(*asserts.SnapDeclaration) 2067 2068 cand := policy.InstallCandidate{ 2069 Snap: installSnap, 2070 SnapDeclaration: snapDecl, 2071 BaseDeclaration: s.baseDecl, 2072 Model: t.model, 2073 Store: t.store, 2074 } 2075 err = cand.Check() 2076 if t.err == "" { 2077 c.Check(err, IsNil) 2078 } else { 2079 c.Check(err, ErrorMatches, t.err) 2080 } 2081 } 2082 } 2083 2084 func (s *policySuite) TestSlotDollarSlotAttrConnection(c *C) { 2085 // no corresponding attr 2086 cand := policy.ConnectCandidate{ 2087 Plug: interfaces.NewConnectedPlug(s.randomSnap.Plugs["slot-slot-attr"], nil, nil), 2088 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil), 2089 BaseDeclaration: s.baseDecl, 2090 } 2091 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2092 2093 // different attr values 2094 cand = policy.ConnectCandidate{ 2095 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-slot-attr-mismatch"], nil, nil), 2096 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil), 2097 BaseDeclaration: s.baseDecl, 2098 } 2099 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2100 2101 // plug attr == slot attr 2102 cand = policy.ConnectCandidate{ 2103 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-slot-attr-match"], nil, nil), 2104 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil), 2105 BaseDeclaration: s.baseDecl, 2106 } 2107 c.Check(cand.Check(), IsNil) 2108 } 2109 2110 func (s *policySuite) TestSlotDollarPlugAttrConnection(c *C) { 2111 // different attr values 2112 cand := policy.ConnectCandidate{ 2113 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-mismatch"], nil, nil), 2114 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil), 2115 BaseDeclaration: s.baseDecl, 2116 } 2117 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2118 2119 // plug attr == slot attr 2120 cand = policy.ConnectCandidate{ 2121 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-match"], nil, nil), 2122 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil), 2123 BaseDeclaration: s.baseDecl, 2124 } 2125 c.Check(cand.Check(), IsNil) 2126 } 2127 2128 func (s *policySuite) TestPlugDollarPlugAttrConnection(c *C) { 2129 // different attr values 2130 cand := policy.ConnectCandidate{ 2131 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil), 2132 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-mismatch"], nil, nil), 2133 BaseDeclaration: s.baseDecl, 2134 } 2135 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2136 2137 // plug attr == slot attr 2138 cand = policy.ConnectCandidate{ 2139 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil), 2140 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-match"], nil, nil), 2141 BaseDeclaration: s.baseDecl, 2142 } 2143 c.Check(cand.Check(), IsNil) 2144 } 2145 2146 func (s *policySuite) TestPlugDollarSlotAttrConnection(c *C) { 2147 // different attr values 2148 cand := policy.ConnectCandidate{ 2149 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-slot-attr"], nil, nil), 2150 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-slot-attr-mismatch"], nil, nil), 2151 BaseDeclaration: s.baseDecl, 2152 } 2153 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2154 2155 // plug attr == slot attr 2156 cand = policy.ConnectCandidate{ 2157 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-slot-attr"], nil, nil), 2158 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-slot-attr-match"], nil, nil), 2159 BaseDeclaration: s.baseDecl, 2160 } 2161 c.Check(cand.Check(), IsNil) 2162 } 2163 2164 func (s *policySuite) TestDollarMissingConnection(c *C) { 2165 // not missing 2166 cand := policy.ConnectCandidate{ 2167 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-missing-mismatch"], nil, nil), 2168 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-missing"], nil, nil), 2169 BaseDeclaration: s.baseDecl, 2170 } 2171 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2172 2173 // missing 2174 cand = policy.ConnectCandidate{ 2175 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-missing-match"], nil, nil), 2176 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-missing"], nil, nil), 2177 BaseDeclaration: s.baseDecl, 2178 } 2179 c.Check(cand.Check(), IsNil) 2180 } 2181 2182 func (s *policySuite) TestSlotDollarPlugDynamicAttrConnection(c *C) { 2183 // "c" attribute of the plug missing 2184 cand := policy.ConnectCandidate{ 2185 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-dynamic"], nil, map[string]interface{}{}), 2186 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil), 2187 BaseDeclaration: s.baseDecl, 2188 } 2189 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2190 2191 // plug attr == slot attr, "c" attribute of the plug provided by dynamic attribute 2192 cand = policy.ConnectCandidate{ 2193 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-dynamic"], nil, map[string]interface{}{ 2194 "c": "C", 2195 }), 2196 2197 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil), 2198 BaseDeclaration: s.baseDecl, 2199 } 2200 c.Check(cand.Check(), IsNil) 2201 } 2202 2203 func (s *policySuite) TestPlugDollarSlotDynamicAttrConnection(c *C) { 2204 // "c" attribute of the slot missing 2205 cand := policy.ConnectCandidate{ 2206 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil), 2207 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-dynamic"], nil, map[string]interface{}{}), 2208 BaseDeclaration: s.baseDecl, 2209 } 2210 c.Check(cand.Check(), ErrorMatches, "connection not allowed.*") 2211 2212 // plug attr == slot attr, "c" attribute of the slot provided by dynamic attribute 2213 cand = policy.ConnectCandidate{ 2214 Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil), 2215 Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-dynamic"], nil, map[string]interface{}{ 2216 "c": "C", 2217 }), 2218 2219 BaseDeclaration: s.baseDecl, 2220 } 2221 c.Check(cand.Check(), IsNil) 2222 }