github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/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    install-plug-name-bound:
   172      allow-installation:
   173        plug-names:
   174          - $INTERFACE
   175  slots:
   176    base-slot-allow: true
   177    base-slot-not-allow:
   178      allow-connection: false
   179    base-slot-not-allow-slots:
   180      allow-connection:
   181        slot-attributes:
   182          s: S
   183    base-slot-not-allow-plugs:
   184      allow-connection:
   185        plug-attributes:
   186          p: P
   187    base-slot-deny:
   188      deny-connection: true
   189    base-deny-snap-slot-allow: false
   190    base-deny-snap-plug-allow: false
   191    base-allow-snap-slot-not-allow: true
   192    gadgethelp:
   193      allow-connection:
   194        plug-snap-type:
   195          - gadget
   196    same-slot-publisher-id:
   197      allow-connection:
   198        plug-publisher-id:
   199          - $SLOT_PUBLISHER_ID
   200    slot-slot-attr:
   201      allow-connection:
   202        plug-attributes:
   203          a:
   204            b: $SLOT(a.b)
   205    slot-plug-attr:
   206      allow-connection:
   207        slot-attributes:
   208          c: $PLUG(c)
   209    slot-plug-missing:
   210      allow-connection:
   211        plug-attributes:
   212          x: $MISSING
   213    slot-or:
   214      allow-connection:
   215        -
   216          slot-attributes:
   217            s: S1
   218          plug-attributes:
   219            p: P1
   220        -
   221          slot-attributes:
   222            s: S2
   223          plug-attributes:
   224            p: P2
   225    slot-on-classic-true:
   226      allow-connection:
   227        on-classic: true
   228    slot-on-classic-distros:
   229      allow-connection:
   230        on-classic:
   231          - ubuntu
   232          - debian
   233    slot-on-classic-false:
   234      allow-connection:
   235        on-classic: false
   236    auto-base-slot-allow: true
   237    auto-base-slot-not-allow:
   238      allow-auto-connection: false
   239    auto-base-slot-not-allow-slots:
   240      allow-auto-connection:
   241        slot-attributes:
   242          s: S
   243    auto-base-slot-not-allow-plugs:
   244      allow-auto-connection:
   245        plug-attributes:
   246          p: P
   247    auto-base-slot-deny:
   248      deny-auto-connection: true
   249    auto-base-deny-snap-slot-allow: false
   250    auto-base-deny-snap-plug-allow: false
   251    auto-base-allow-snap-slot-not-allow: true
   252    auto-slot-or:
   253      allow-auto-connection:
   254        -
   255          slot-attributes:
   256            s: S1
   257          plug-attributes:
   258            p: P1
   259        -
   260          slot-attributes:
   261            s: S2
   262          plug-attributes:
   263            p: P2
   264    auto-slot-on-store1:
   265      allow-auto-connection: false
   266    auto-slot-on-my-brand:
   267      allow-auto-connection: false
   268    auto-slot-on-my-model2:
   269      allow-auto-connection: false
   270    auto-slot-on-multi:
   271      allow-auto-connection: false
   272    install-slot-coreonly:
   273      allow-installation:
   274        slot-snap-type:
   275          - core
   276    install-slot-attr-ok:
   277      allow-installation:
   278        slot-attributes:
   279          attr: ok
   280    install-slot-attr-deny:
   281      deny-installation:
   282        slot-attributes:
   283          trust: trusted
   284    install-slot-base-deny-snap-allow:
   285      deny-installation:
   286        slot-attributes:
   287          have: true
   288    install-slot-or:
   289      deny-installation:
   290        -
   291          slot-attributes:
   292            p: P1
   293        -
   294          slot-snap-type:
   295            - gadget
   296          slot-attributes:
   297            p: P2
   298    install-slot-on-classic-distros:
   299      allow-installation:
   300        on-classic:
   301          - ubuntu
   302          - debian
   303    install-slot-device-scope:
   304      allow-installation: false
   305    install-slot-name-bound:
   306      allow-installation:
   307        slot-names:
   308          - $INTERFACE
   309    slots-arity-default:
   310      allow-auto-connection: true
   311    slots-arity-slot-any:
   312      deny-auto-connection: true
   313    slots-arity-plug-any:
   314      deny-auto-connection: true
   315    slots-arity-slot-any-plug-one:
   316      deny-auto-connection: true
   317    slots-arity-slot-any-plug-two:
   318      deny-auto-connection: true
   319    slots-arity-slot-any-plug-default:
   320      deny-auto-connection: true
   321    slots-arity-slot-one-plug-any:
   322      deny-auto-connection: true
   323    slots-name-bound:
   324      deny-auto-connection: true
   325    plugs-name-bound:
   326      deny-auto-connection: true
   327  timestamp: 2016-09-30T12:00:00Z
   328  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
   329  
   330  AXNpZw==`))
   331  	c.Assert(err, IsNil)
   332  	s.baseDecl = a.(*asserts.BaseDeclaration)
   333  
   334  	s.plugSnap = snaptest.MockInfo(c, `
   335  name: plug-snap
   336  version: 0
   337  plugs:
   338     random:
   339     mismatchy:
   340       interface: bar
   341  
   342     base-plug-allow:
   343     base-plug-not-allow:
   344     base-plug-not-allow-slots:
   345     base-plug-not-allow-plugs:
   346     base-plug-deny:
   347  
   348     base-slot-allow:
   349     base-slot-not-allow:
   350     base-slot-not-allow-slots:
   351     base-slot-not-allow-plugs:
   352     base-slot-deny:
   353  
   354     auto-base-plug-allow:
   355     auto-base-plug-not-allow:
   356     auto-base-plug-not-allow-slots:
   357     auto-base-plug-not-allow-plugs:
   358     auto-base-plug-deny:
   359  
   360     auto-base-slot-allow:
   361     auto-base-slot-not-allow:
   362     auto-base-slot-not-allow-slots:
   363     auto-base-slot-not-allow-plugs:
   364     auto-base-slot-deny:
   365  
   366     snap-plug-allow:
   367     snap-plug-not-allow:
   368     snap-plug-deny:
   369  
   370     snap-slot-allow:
   371     snap-slot-not-allow:
   372     snap-slot-deny:
   373  
   374     base-deny-snap-slot-allow:
   375     base-deny-snap-plug-allow:
   376     base-allow-snap-slot-not-allow:
   377  
   378     snap-slot-deny-snap-plug-allow:
   379  
   380     auto-snap-plug-allow:
   381     auto-snap-plug-not-allow:
   382     auto-snap-plug-deny:
   383  
   384     auto-snap-slot-allow:
   385     auto-snap-slot-not-allow:
   386     auto-snap-slot-deny:
   387  
   388     auto-base-deny-snap-slot-allow:
   389     auto-base-deny-snap-plug-allow:
   390     auto-base-allow-snap-slot-not-allow:
   391  
   392     auto-snap-slot-deny-snap-plug-allow:
   393  
   394     gadgethelp:
   395     trustedhelp:
   396  
   397     precise-plug-snap-id:
   398     precise-slot-snap-id:
   399  
   400     checked-plug-publisher-id:
   401     checked-slot-publisher-id:
   402  
   403     same-plug-publisher-id:
   404  
   405     slot-slot-attr-mismatch:
   406       interface: slot-slot-attr
   407       a:
   408         b: []
   409  
   410     slot-slot-attr-match:
   411       interface: slot-slot-attr
   412       a:
   413         b: ["x", "y"]
   414  
   415     slot-plug-attr-mismatch:
   416       interface: slot-plug-attr
   417       c: "Z"
   418  
   419     slot-plug-attr-dynamic:
   420       interface: slot-plug-attr
   421  
   422     slot-plug-attr-match:
   423       interface: slot-plug-attr
   424       c: "C"
   425  
   426     slot-plug-missing-mismatch:
   427       interface: slot-plug-missing
   428       x: 1
   429       z: 2
   430  
   431     slot-plug-missing-match:
   432       interface: slot-plug-missing
   433       z: 2
   434  
   435     plug-plug-attr:
   436       c: "C"
   437  
   438     plug-slot-attr:
   439       c: "C"
   440  
   441     plug-or-p1-s1:
   442       interface: plug-or
   443       p: P1
   444  
   445     plug-or-p2-s2:
   446       interface: plug-or
   447       p: P2
   448  
   449     plug-or-p1-s2:
   450       interface: plug-or
   451       p: P1
   452  
   453     auto-plug-or-p1-s1:
   454       interface: auto-plug-or
   455       p: P1
   456  
   457     auto-plug-or-p2-s2:
   458       interface: auto-plug-or
   459       p: P2
   460  
   461     auto-plug-or-p2-s1:
   462       interface: auto-plug-or
   463       p: P2
   464  
   465     auto-plug-on-store1:
   466     auto-plug-on-my-brand:
   467     auto-plug-on-my-model2:
   468     auto-plug-on-multi:
   469  
   470     slot-or-p1-s1:
   471       interface: slot-or
   472       p: P1
   473  
   474     slot-or-p2-s2:
   475       interface: slot-or
   476       p: P2
   477  
   478     slot-or-p1-s2:
   479       interface: slot-or
   480       p: P1
   481  
   482     auto-slot-or-p1-s1:
   483       interface: auto-slot-or
   484       p: P1
   485  
   486     auto-slot-or-p2-s2:
   487       interface: auto-slot-or
   488       p: P2
   489  
   490     auto-slot-or-p2-s1:
   491       interface: auto-slot-or
   492       p: P2
   493  
   494     auto-slot-on-store1:
   495     auto-slot-on-my-brand:
   496     auto-slot-on-my-model2:
   497     auto-slot-on-multi:
   498  
   499     slot-on-classic-true:
   500     slot-on-classic-distros:
   501     slot-on-classic-false:
   502  
   503     plug-on-classic-true:
   504     plug-on-classic-distros:
   505     plug-on-classic-false:
   506  
   507     slots-arity-default:
   508     slots-arity-slot-any:
   509     slots-arity-plug-any:
   510     slots-arity-slot-any-plug-one:
   511     slots-arity-slot-any-plug-two:
   512     slots-arity-slot-any-plug-default:
   513     slots-arity-slot-one-plug-any:
   514  
   515     slots-name-bound-p1:
   516       interface: slots-name-bound
   517     slots-name-bound-p2:
   518       interface: slots-name-bound
   519     plugs-name-bound-p1:
   520       interface: plugs-name-bound
   521     plugs-name-bound-p2:
   522       interface: plugs-name-bound
   523  `, nil)
   524  
   525  	s.slotSnap = snaptest.MockInfo(c, `
   526  name: slot-snap
   527  version: 0
   528  slots:
   529     random:
   530     mismatchy:
   531       interface: baz
   532  
   533     base-plug-allow:
   534     base-plug-not-allow:
   535     base-plug-not-allow-slots:
   536     base-plug-not-allow-plugs:
   537     base-plug-deny:
   538  
   539     base-slot-allow:
   540     base-slot-not-allow:
   541     base-slot-not-allow-slots:
   542     base-slot-not-allow-plugs:
   543     base-slot-deny:
   544  
   545     auto-base-plug-allow:
   546     auto-base-plug-not-allow:
   547     auto-base-plug-not-allow-slots:
   548     auto-base-plug-not-allow-plugs:
   549     auto-base-plug-deny:
   550  
   551     auto-base-slot-allow:
   552     auto-base-slot-not-allow:
   553     auto-base-slot-not-allow-slots:
   554     auto-base-slot-not-allow-plugs:
   555     auto-base-slot-deny:
   556  
   557     snap-plug-allow:
   558     snap-plug-not-allow:
   559     snap-plug-deny:
   560  
   561     snap-slot-allow:
   562     snap-slot-not-allow:
   563     snap-slot-deny:
   564  
   565     base-deny-snap-slot-allow:
   566     base-deny-snap-plug-allow:
   567     base-allow-snap-slot-not-allow:
   568  
   569     snap-slot-deny-snap-plug-allow:
   570  
   571     auto-snap-plug-allow:
   572     auto-snap-plug-not-allow:
   573     auto-snap-plug-deny:
   574  
   575     auto-snap-slot-allow:
   576     auto-snap-slot-not-allow:
   577     auto-snap-slot-deny:
   578  
   579     auto-base-deny-snap-slot-allow:
   580     auto-base-deny-snap-plug-allow:
   581     auto-base-allow-snap-slot-not-allow:
   582  
   583     auto-snap-slot-deny-snap-plug-allow:
   584  
   585     trustedhelp:
   586  
   587     precise-plug-snap-id:
   588     precise-slot-snap-id:
   589  
   590     checked-plug-publisher-id:
   591     checked-slot-publisher-id:
   592  
   593     same-slot-publisher-id:
   594  
   595     slot-slot-attr:
   596       a:
   597         b: ["x", "y"]
   598  
   599     slot-plug-attr:
   600       c: "C"
   601  
   602     slot-plug-missing:
   603  
   604     plug-plug-attr-mismatch:
   605       interface: plug-plug-attr
   606       c: "Z"
   607  
   608     plug-plug-attr-match:
   609       interface: plug-plug-attr
   610       c: "C"
   611  
   612     plug-plug-attr-dynamic:
   613       interface: plug-plug-attr
   614  
   615     plug-slot-attr-mismatch:
   616       interface: plug-slot-attr
   617       c: "Z"
   618  
   619     plug-slot-attr-match:
   620       interface: plug-slot-attr
   621       c: "C"
   622  
   623     plug-or-p1-s1:
   624       interface: plug-or
   625       s: S1
   626  
   627     plug-or-p2-s2:
   628       interface: plug-or
   629       s: S2
   630  
   631     plug-or-p1-s2:
   632       interface: plug-or
   633       s: S2
   634  
   635     auto-plug-or-p1-s1:
   636       interface: auto-plug-or
   637       s: S1
   638  
   639     auto-plug-or-p2-s2:
   640       interface: auto-plug-or
   641       s: S2
   642  
   643     auto-plug-or-p2-s1:
   644       interface: auto-plug-or
   645       s: S1
   646  
   647     auto-plug-on-store1:
   648     auto-plug-on-my-brand:
   649     auto-plug-on-my-model2:
   650     auto-plug-on-multi:
   651  
   652     slot-or-p1-s1:
   653       interface: slot-or
   654       s: S1
   655  
   656     slot-or-p2-s2:
   657       interface: slot-or
   658       s: S2
   659  
   660     slot-or-p1-s2:
   661       interface: slot-or
   662       s: S2
   663  
   664     auto-slot-or-p1-s1:
   665       interface: auto-slot-or
   666       s: S1
   667  
   668     auto-slot-or-p2-s2:
   669       interface: auto-slot-or
   670       s: S2
   671  
   672     auto-slot-or-p2-s1:
   673       interface: auto-slot-or
   674       s: S1
   675  
   676     auto-slot-on-store1:
   677     auto-slot-on-my-brand:
   678     auto-slot-on-my-model2:
   679     auto-slot-on-multi:
   680  
   681     slot-on-classic-true:
   682     slot-on-classic-distros:
   683     slot-on-classic-false:
   684  
   685     plug-on-classic-true:
   686     plug-on-classic-distros:
   687     plug-on-classic-false:
   688  
   689     slots-arity-default:
   690     slots-arity-slot-any:
   691     slots-arity-plug-any:
   692     slots-arity-slot-any-plug-one:
   693     slots-arity-slot-any-plug-two:
   694     slots-arity-slot-any-plug-default:
   695     slots-arity-slot-one-plug-any:
   696  
   697     slots-name-bound-s1:
   698       interface: slots-name-bound
   699     slots-name-bound-s2:
   700       interface: slots-name-bound
   701     plugs-name-bound-s1:
   702       interface: plugs-name-bound
   703     plugs-name-bound-s2:
   704       interface: plugs-name-bound
   705  
   706  `, nil)
   707  
   708  	a, err = asserts.Decode([]byte(`type: snap-declaration
   709  authority-id: canonical
   710  series: 16
   711  snap-name: plug-snap
   712  snap-id: plugsnapidididididididididididid
   713  publisher-id: plug-publisher
   714  plugs:
   715    snap-plug-allow: true
   716    snap-plug-deny: false
   717    snap-plug-not-allow:
   718      allow-connection: false
   719    base-deny-snap-plug-allow: true
   720    snap-slot-deny-snap-plug-allow:
   721      deny-connection: false
   722    trustedhelp:
   723      allow-connection:
   724        slot-snap-type:
   725          - core
   726          - gadget
   727    precise-slot-snap-id:
   728      allow-connection:
   729        slot-snap-id:
   730          - slotsnapidididididididididididid
   731    checked-slot-publisher-id:
   732      allow-connection:
   733        slot-publisher-id:
   734          - slot-publisher
   735          - $PLUG_PUBLISHER_ID
   736    auto-snap-plug-allow: true
   737    auto-snap-plug-deny: false
   738    auto-snap-plug-not-allow:
   739      allow-auto-connection: false
   740    auto-snap-slot-deny-snap-plug-allow:
   741      deny-auto-connection: false
   742    auto-base-deny-snap-plug-allow: true
   743    auto-plug-on-store1:
   744      allow-auto-connection:
   745        on-store:
   746          - store1
   747    auto-plug-on-my-brand:
   748      allow-auto-connection:
   749        on-brand:
   750          - my-brand
   751          - my-brand-subbrand
   752    auto-plug-on-my-model2:
   753      allow-auto-connection:
   754        on-model:
   755          - my-brand-subbrand/my-model2
   756    auto-plug-on-multi:
   757      allow-auto-connection:
   758        on-brand:
   759          - my-brand
   760          - my-brand-subbrand
   761        on-store:
   762          - store1
   763          - other-store
   764        on-model:
   765          - my-brand/my-model1
   766          - my-brand-subbrand/my-model2
   767    slots-arity-plug-any:
   768      allow-auto-connection:
   769        slots-per-plug: *
   770    slots-arity-slot-any-plug-one:
   771      allow-auto-connection:
   772        slots-per-plug: 1
   773    slots-arity-slot-any-plug-two:
   774      allow-auto-connection:
   775        slots-per-plug: 2
   776    slots-arity-slot-any-plug-default:
   777      allow-auto-connection: true
   778    slots-arity-slot-one-plug-any:
   779      allow-auto-connection:
   780        slots-per-plug: *
   781    plugs-name-bound:
   782      allow-auto-connection:
   783        -
   784          plug-names:
   785            - plugs-name-bound-p1
   786          slot-names:
   787            - plugs-name-bound-s2
   788  timestamp: 2016-09-30T12:00:00Z
   789  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
   790  
   791  AXNpZw==`))
   792  	c.Assert(err, IsNil)
   793  	s.plugDecl = a.(*asserts.SnapDeclaration)
   794  
   795  	a, err = asserts.Decode([]byte(`type: snap-declaration
   796  authority-id: canonical
   797  series: 16
   798  snap-name: slot-snap
   799  snap-id: slotsnapidididididididididididid
   800  publisher-id: slot-publisher
   801  slots:
   802    snap-slot-allow: true
   803    snap-slot-deny: false
   804    snap-slot-not-allow:
   805      allow-connection: false
   806    base-deny-snap-slot-allow: true
   807    snap-slot-deny-snap-plug-allow:
   808      deny-connection: true
   809    base-allow-snap-slot-not-allow:
   810      allow-connection: false
   811    precise-plug-snap-id:
   812      allow-connection:
   813        plug-snap-id:
   814          - plugsnapidididididididididididid
   815    checked-plug-publisher-id:
   816      allow-connection:
   817        plug-publisher-id:
   818          - plug-publisher
   819    auto-snap-slot-allow: true
   820    auto-snap-slot-deny: false
   821    auto-snap-slot-not-allow:
   822      allow-auto-connection: false
   823    auto-base-deny-snap-slot-allow: true
   824    auto-snap-slot-deny-snap-plug-allow:
   825      deny-auto-connection: true
   826    auto-base-allow-snap-slot-not-allow:
   827      allow-auto-connection: false
   828    auto-slot-on-store1:
   829      allow-auto-connection:
   830        on-store:
   831          - store1
   832    auto-slot-on-my-brand:
   833      allow-auto-connection:
   834        on-brand:
   835          - my-brand
   836          - my-brand-subbrand
   837    auto-slot-on-my-model2:
   838      allow-auto-connection:
   839        on-model:
   840          - my-brand-subbrand/my-model2
   841    auto-slot-on-multi:
   842      allow-auto-connection:
   843        on-brand:
   844          - my-brand
   845          - my-brand-subbrand
   846        on-store:
   847          - store1
   848          - other-store
   849        on-model:
   850          - my-brand/my-model1
   851          - my-brand-subbrand/my-model2
   852    slots-arity-slot-any:
   853      allow-auto-connection:
   854        slots-per-plug: *
   855    slots-arity-slot-any-plug-one:
   856      allow-auto-connection:
   857        slots-per-plug: *
   858    slots-arity-slot-any-plug-two:
   859      allow-auto-connection:
   860        slots-per-plug: *
   861    slots-arity-slot-any-plug-default:
   862      allow-auto-connection:
   863        slots-per-plug: *
   864    slots-arity-slot-one-plug-any:
   865      allow-auto-connection:
   866        slots-per-plug: 1
   867    slots-name-bound:
   868      allow-auto-connection:
   869        -
   870          plug-names:
   871            - slots-name-bound-p2
   872          slot-names:
   873            - slots-name-bound-s2
   874  timestamp: 2016-09-30T12:00:00Z
   875  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
   876  
   877  AXNpZw==`))
   878  	c.Assert(err, IsNil)
   879  	s.slotDecl = a.(*asserts.SnapDeclaration)
   880  
   881  	s.randomSnap = snaptest.MockInfo(c, `
   882  name: random-snap
   883  version: 0
   884  plugs:
   885    precise-plug-snap-id:
   886    checked-plug-publisher-id:
   887    same-slot-publisher-id:
   888    slot-slot-attr:
   889  slots:
   890    precise-slot-snap-id:
   891    checked-slot-publisher-id:
   892    same-plug-publisher-id:
   893  `, nil)
   894  
   895  	a, err = asserts.Decode([]byte(`type: snap-declaration
   896  authority-id: canonical
   897  series: 16
   898  snap-name: random-snap
   899  snap-id: randomsnapididididididididid
   900  publisher-id: random-publisher
   901  timestamp: 2016-09-30T12:00:00Z
   902  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
   903  
   904  AXNpZw==`))
   905  	c.Assert(err, IsNil)
   906  	s.randomDecl = a.(*asserts.SnapDeclaration)
   907  }
   908  
   909  func (s *policySuite) TearDownSuite(c *C) {
   910  	s.restoreSanitize()
   911  }
   912  
   913  func (s *policySuite) TestBaselineDefaultIsAllow(c *C) {
   914  	cand := policy.ConnectCandidate{
   915  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["random"], nil, nil),
   916  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["random"], nil, nil),
   917  		BaseDeclaration: s.baseDecl,
   918  	}
   919  
   920  	c.Check(cand.Check(), IsNil)
   921  	arity, err := cand.CheckAutoConnect()
   922  	c.Check(err, IsNil)
   923  	c.Check(arity.SlotsPerPlugAny(), Equals, false)
   924  }
   925  
   926  func (s *policySuite) TestInterfaceMismatch(c *C) {
   927  	cand := policy.ConnectCandidate{
   928  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["mismatchy"], nil, nil),
   929  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["mismatchy"], nil, nil),
   930  		BaseDeclaration: s.baseDecl,
   931  	}
   932  
   933  	c.Check(cand.Check(), ErrorMatches, `cannot connect mismatched plug interface "bar" to slot interface "baz"`)
   934  }
   935  
   936  func (s *policySuite) TestBaseDeclAllowDenyConnection(c *C) {
   937  	tests := []struct {
   938  		iface    string
   939  		expected string // "" => no error
   940  	}{
   941  		{"base-plug-allow", ""},
   942  		{"base-plug-deny", `connection denied by plug rule of interface "base-plug-deny"`},
   943  		{"base-plug-not-allow", `connection not allowed by plug rule of interface "base-plug-not-allow"`},
   944  		{"base-slot-allow", ""},
   945  		{"base-slot-deny", `connection denied by slot rule of interface "base-slot-deny"`},
   946  		{"base-slot-not-allow", `connection not allowed by slot rule of interface "base-slot-not-allow"`},
   947  		{"base-plug-not-allow-slots", `connection not allowed.*`},
   948  		{"base-slot-not-allow-slots", `connection not allowed.*`},
   949  		{"base-plug-not-allow-plugs", `connection not allowed.*`},
   950  		{"base-slot-not-allow-plugs", `connection not allowed.*`},
   951  		{"plug-or-p1-s1", ""},
   952  		{"plug-or-p2-s2", ""},
   953  		{"plug-or-p1-s2", "connection not allowed by plug rule.*"},
   954  		{"slot-or-p1-s1", ""},
   955  		{"slot-or-p2-s2", ""},
   956  		{"slot-or-p1-s2", "connection not allowed by slot rule.*"},
   957  	}
   958  
   959  	for _, t := range tests {
   960  		cand := policy.ConnectCandidate{
   961  			Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
   962  			Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
   963  			BaseDeclaration: s.baseDecl,
   964  		}
   965  
   966  		err := cand.Check()
   967  		if t.expected == "" {
   968  			c.Check(err, IsNil)
   969  		} else {
   970  			c.Check(err, ErrorMatches, t.expected)
   971  		}
   972  	}
   973  }
   974  
   975  func (s *policySuite) TestBaseDeclAllowDenyAutoConnection(c *C) {
   976  	tests := []struct {
   977  		iface    string
   978  		expected string // "" => no error
   979  	}{
   980  		{"auto-base-plug-allow", ""},
   981  		{"auto-base-plug-deny", `auto-connection denied by plug rule of interface "auto-base-plug-deny"`},
   982  		{"auto-base-plug-not-allow", `auto-connection not allowed by plug rule of interface "auto-base-plug-not-allow"`},
   983  		{"auto-base-slot-allow", ""},
   984  		{"auto-base-slot-deny", `auto-connection denied by slot rule of interface "auto-base-slot-deny"`},
   985  		{"auto-base-slot-not-allow", `auto-connection not allowed by slot rule of interface "auto-base-slot-not-allow"`},
   986  		{"auto-base-plug-not-allow-slots", `auto-connection not allowed.*`},
   987  		{"auto-base-slot-not-allow-slots", `auto-connection not allowed.*`},
   988  		{"auto-base-plug-not-allow-plugs", `auto-connection not allowed.*`},
   989  		{"auto-base-slot-not-allow-plugs", `auto-connection not allowed.*`},
   990  		{"auto-plug-or-p1-s1", ""},
   991  		{"auto-plug-or-p2-s2", ""},
   992  		{"auto-plug-or-p2-s1", "auto-connection not allowed by plug rule.*"},
   993  		{"auto-slot-or-p1-s1", ""},
   994  		{"auto-slot-or-p2-s2", ""},
   995  		{"auto-slot-or-p2-s1", "auto-connection not allowed by slot rule.*"},
   996  	}
   997  
   998  	for _, t := range tests {
   999  		cand := policy.ConnectCandidate{
  1000  			Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1001  			Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1002  			BaseDeclaration: s.baseDecl,
  1003  		}
  1004  
  1005  		arity, err := cand.CheckAutoConnect()
  1006  		if t.expected == "" {
  1007  			c.Check(err, IsNil)
  1008  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  1009  		} else {
  1010  			c.Check(err, ErrorMatches, t.expected)
  1011  		}
  1012  	}
  1013  }
  1014  
  1015  func (s *policySuite) TestSnapDeclAllowDenyConnection(c *C) {
  1016  	tests := []struct {
  1017  		iface    string
  1018  		expected string // "" => no error
  1019  	}{
  1020  		{"random", ""},
  1021  		{"snap-plug-allow", ""},
  1022  		{"snap-plug-deny", `connection denied by plug rule of interface "snap-plug-deny" for "plug-snap" snap`},
  1023  		{"snap-plug-not-allow", `connection not allowed by plug rule of interface "snap-plug-not-allow" for "plug-snap" snap`},
  1024  		{"snap-slot-allow", ""},
  1025  		{"snap-slot-deny", `connection denied by slot rule of interface "snap-slot-deny" for "slot-snap" snap`},
  1026  		{"snap-slot-not-allow", `connection not allowed by slot rule of interface "snap-slot-not-allow" for "slot-snap" snap`},
  1027  		{"base-deny-snap-slot-allow", ""},
  1028  		{"base-deny-snap-plug-allow", ""},
  1029  		{"snap-slot-deny-snap-plug-allow", ""},
  1030  		{"base-allow-snap-slot-not-allow", `connection not allowed.*`},
  1031  	}
  1032  
  1033  	for _, t := range tests {
  1034  		cand := policy.ConnectCandidate{
  1035  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1036  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1037  			PlugSnapDeclaration: s.plugDecl,
  1038  			SlotSnapDeclaration: s.slotDecl,
  1039  			BaseDeclaration:     s.baseDecl,
  1040  		}
  1041  
  1042  		err := cand.Check()
  1043  		if t.expected == "" {
  1044  			c.Check(err, IsNil)
  1045  		} else {
  1046  			c.Check(err, ErrorMatches, t.expected)
  1047  		}
  1048  	}
  1049  }
  1050  
  1051  func (s *policySuite) TestSnapDeclAllowDenyAutoConnection(c *C) {
  1052  	tests := []struct {
  1053  		iface    string
  1054  		expected string // "" => no error
  1055  	}{
  1056  		{"random", ""},
  1057  		{"auto-snap-plug-allow", ""},
  1058  		{"auto-snap-plug-deny", `auto-connection denied by plug rule of interface "auto-snap-plug-deny" for "plug-snap" snap`},
  1059  		{"auto-snap-plug-not-allow", `auto-connection not allowed by plug rule of interface "auto-snap-plug-not-allow" for "plug-snap" snap`},
  1060  		{"auto-snap-slot-allow", ""},
  1061  		{"auto-snap-slot-deny", `auto-connection denied by slot rule of interface "auto-snap-slot-deny" for "slot-snap" snap`},
  1062  		{"auto-snap-slot-not-allow", `auto-connection not allowed by slot rule of interface "auto-snap-slot-not-allow" for "slot-snap" snap`},
  1063  		{"auto-base-deny-snap-slot-allow", ""},
  1064  		{"auto-base-deny-snap-plug-allow", ""},
  1065  		{"auto-snap-slot-deny-snap-plug-allow", ""},
  1066  		{"auto-base-allow-snap-slot-not-allow", `auto-connection not allowed.*`},
  1067  	}
  1068  
  1069  	for _, t := range tests {
  1070  		cand := policy.ConnectCandidate{
  1071  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1072  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1073  			PlugSnapDeclaration: s.plugDecl,
  1074  			SlotSnapDeclaration: s.slotDecl,
  1075  			BaseDeclaration:     s.baseDecl,
  1076  		}
  1077  
  1078  		arity, err := cand.CheckAutoConnect()
  1079  		if t.expected == "" {
  1080  			c.Check(err, IsNil)
  1081  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  1082  		} else {
  1083  			c.Check(err, ErrorMatches, t.expected)
  1084  		}
  1085  	}
  1086  }
  1087  
  1088  func (s *policySuite) TestSnapTypeCheckConnection(c *C) {
  1089  	gadgetSnap := snaptest.MockInfo(c, `
  1090  name: gadget
  1091  version: 0
  1092  type: gadget
  1093  plugs:
  1094     gadgethelp:
  1095  slots:
  1096     trustedhelp:
  1097  `, nil)
  1098  
  1099  	coreSnap := snaptest.MockInfo(c, `
  1100  name: core
  1101  version: 0
  1102  type: os
  1103  slots:
  1104     gadgethelp:
  1105     trustedhelp:
  1106  `, nil)
  1107  
  1108  	cand := policy.ConnectCandidate{
  1109  		Plug:            interfaces.NewConnectedPlug(gadgetSnap.Plugs["gadgethelp"], nil, nil),
  1110  		Slot:            interfaces.NewConnectedSlot(coreSnap.Slots["gadgethelp"], nil, nil),
  1111  		BaseDeclaration: s.baseDecl,
  1112  	}
  1113  	c.Check(cand.Check(), IsNil)
  1114  
  1115  	cand = policy.ConnectCandidate{
  1116  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["gadgethelp"], nil, nil),
  1117  		Slot:            interfaces.NewConnectedSlot(coreSnap.Slots["gadgethelp"], nil, nil),
  1118  		BaseDeclaration: s.baseDecl,
  1119  	}
  1120  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1121  
  1122  	for _, trustedSide := range []*snap.Info{coreSnap, gadgetSnap} {
  1123  		cand = policy.ConnectCandidate{
  1124  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["trustedhelp"], nil, nil),
  1125  			PlugSnapDeclaration: s.plugDecl,
  1126  			Slot:                interfaces.NewConnectedSlot(trustedSide.Slots["trustedhelp"], nil, nil),
  1127  			BaseDeclaration:     s.baseDecl,
  1128  		}
  1129  		c.Check(cand.Check(), IsNil)
  1130  	}
  1131  
  1132  	cand = policy.ConnectCandidate{
  1133  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["trustedhelp"], nil, nil),
  1134  		PlugSnapDeclaration: s.plugDecl,
  1135  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["trustedhelp"], nil, nil),
  1136  		BaseDeclaration:     s.baseDecl,
  1137  	}
  1138  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1139  }
  1140  
  1141  func (s *policySuite) TestPlugSnapIDCheckConnection(c *C) {
  1142  	// no plug-side declaration
  1143  	cand := policy.ConnectCandidate{
  1144  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["precise-plug-snap-id"], nil, nil),
  1145  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil),
  1146  		SlotSnapDeclaration: s.slotDecl,
  1147  		BaseDeclaration:     s.baseDecl,
  1148  	}
  1149  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1150  
  1151  	// plug-side declaration, wrong snap-id
  1152  	cand = policy.ConnectCandidate{
  1153  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["precise-plug-snap-id"], nil, nil),
  1154  		PlugSnapDeclaration: s.randomDecl,
  1155  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil),
  1156  		SlotSnapDeclaration: s.slotDecl,
  1157  		BaseDeclaration:     s.baseDecl,
  1158  	}
  1159  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1160  
  1161  	// right snap-id
  1162  	cand = policy.ConnectCandidate{
  1163  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-plug-snap-id"], nil, nil),
  1164  		PlugSnapDeclaration: s.plugDecl,
  1165  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-plug-snap-id"], nil, nil),
  1166  		SlotSnapDeclaration: s.slotDecl,
  1167  		BaseDeclaration:     s.baseDecl,
  1168  	}
  1169  	c.Check(cand.Check(), IsNil)
  1170  }
  1171  
  1172  func (s *policySuite) TestSlotSnapIDCheckConnection(c *C) {
  1173  	// no slot-side declaration
  1174  	cand := policy.ConnectCandidate{
  1175  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil),
  1176  		PlugSnapDeclaration: s.plugDecl,
  1177  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["precise-slot-snap-id"], nil, nil),
  1178  		BaseDeclaration:     s.baseDecl,
  1179  	}
  1180  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1181  
  1182  	// slot-side declaration, wrong snap-id
  1183  	cand = policy.ConnectCandidate{
  1184  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil),
  1185  		PlugSnapDeclaration: s.plugDecl,
  1186  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["precise-slot-snap-id"], nil, nil),
  1187  		SlotSnapDeclaration: s.randomDecl,
  1188  		BaseDeclaration:     s.baseDecl,
  1189  	}
  1190  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1191  
  1192  	// right snap-id
  1193  	cand = policy.ConnectCandidate{
  1194  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["precise-slot-snap-id"], nil, nil),
  1195  		PlugSnapDeclaration: s.plugDecl,
  1196  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["precise-slot-snap-id"], nil, nil),
  1197  		SlotSnapDeclaration: s.slotDecl,
  1198  		BaseDeclaration:     s.baseDecl,
  1199  	}
  1200  	c.Check(cand.Check(), IsNil)
  1201  }
  1202  
  1203  func (s *policySuite) TestPlugPublisherIDCheckConnection(c *C) {
  1204  	// no plug-side declaration
  1205  	cand := policy.ConnectCandidate{
  1206  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["checked-plug-publisher-id"], nil, nil),
  1207  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil),
  1208  		SlotSnapDeclaration: s.slotDecl,
  1209  		BaseDeclaration:     s.baseDecl,
  1210  	}
  1211  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1212  
  1213  	// plug-side declaration, wrong publisher-id
  1214  	cand = policy.ConnectCandidate{
  1215  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["checked-plug-publisher-id"], nil, nil),
  1216  		PlugSnapDeclaration: s.randomDecl,
  1217  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil),
  1218  		SlotSnapDeclaration: s.slotDecl,
  1219  		BaseDeclaration:     s.baseDecl,
  1220  	}
  1221  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1222  
  1223  	// right publisher-id
  1224  	cand = policy.ConnectCandidate{
  1225  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-plug-publisher-id"], nil, nil),
  1226  		PlugSnapDeclaration: s.plugDecl,
  1227  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-plug-publisher-id"], nil, nil),
  1228  		SlotSnapDeclaration: s.slotDecl,
  1229  		BaseDeclaration:     s.baseDecl,
  1230  	}
  1231  	c.Check(cand.Check(), IsNil)
  1232  }
  1233  
  1234  func (s *policySuite) TestSlotPublisherIDCheckConnection(c *C) {
  1235  	// no slot-side declaration
  1236  	cand := policy.ConnectCandidate{
  1237  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil),
  1238  		PlugSnapDeclaration: s.plugDecl,
  1239  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["checked-slot-publisher-id"], nil, nil),
  1240  		BaseDeclaration:     s.baseDecl,
  1241  	}
  1242  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1243  
  1244  	// slot-side declaration, wrong publisher-id
  1245  	cand = policy.ConnectCandidate{
  1246  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil),
  1247  		PlugSnapDeclaration: s.plugDecl,
  1248  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["checked-slot-publisher-id"], nil, nil),
  1249  		SlotSnapDeclaration: s.randomDecl,
  1250  		BaseDeclaration:     s.baseDecl,
  1251  	}
  1252  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1253  
  1254  	// right publisher-id
  1255  	cand = policy.ConnectCandidate{
  1256  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["checked-slot-publisher-id"], nil, nil),
  1257  		PlugSnapDeclaration: s.plugDecl,
  1258  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["checked-slot-publisher-id"], nil, nil),
  1259  		SlotSnapDeclaration: s.slotDecl,
  1260  		BaseDeclaration:     s.baseDecl,
  1261  	}
  1262  	c.Check(cand.Check(), IsNil)
  1263  }
  1264  
  1265  func (s *policySuite) TestDollarPlugPublisherIDCheckConnection(c *C) {
  1266  	// no known publishers
  1267  	cand := policy.ConnectCandidate{
  1268  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil),
  1269  		Slot:            interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil),
  1270  		BaseDeclaration: s.baseDecl,
  1271  	}
  1272  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1273  
  1274  	// no slot-side declaration
  1275  	cand = policy.ConnectCandidate{
  1276  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil),
  1277  		PlugSnapDeclaration: s.plugDecl,
  1278  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil),
  1279  		BaseDeclaration:     s.baseDecl,
  1280  	}
  1281  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1282  
  1283  	// slot-side declaration, wrong publisher-id
  1284  	cand = policy.ConnectCandidate{
  1285  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil),
  1286  		PlugSnapDeclaration: s.plugDecl,
  1287  		Slot:                interfaces.NewConnectedSlot(s.randomSnap.Slots["same-plug-publisher-id"], nil, nil),
  1288  		SlotSnapDeclaration: s.randomDecl,
  1289  		BaseDeclaration:     s.baseDecl,
  1290  	}
  1291  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1292  
  1293  	// slot publisher id == plug publisher id
  1294  	samePubSlotSnap := snaptest.MockInfo(c, `
  1295  name: same-pub-slot-snap
  1296  version: 0
  1297  slots:
  1298    same-plug-publisher-id:
  1299  `, nil)
  1300  
  1301  	a, err := asserts.Decode([]byte(`type: snap-declaration
  1302  authority-id: canonical
  1303  series: 16
  1304  snap-name: same-pub-slot-snap
  1305  snap-id: samepublslotsnapidididididididid
  1306  publisher-id: plug-publisher
  1307  timestamp: 2016-09-30T12:00:00Z
  1308  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1309  
  1310  AXNpZw==`))
  1311  	c.Assert(err, IsNil)
  1312  	samePubSlotDecl := a.(*asserts.SnapDeclaration)
  1313  
  1314  	cand = policy.ConnectCandidate{
  1315  		Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs["same-plug-publisher-id"], nil, nil),
  1316  		PlugSnapDeclaration: s.plugDecl,
  1317  		Slot:                interfaces.NewConnectedSlot(samePubSlotSnap.Slots["same-plug-publisher-id"], nil, nil),
  1318  		SlotSnapDeclaration: samePubSlotDecl,
  1319  		BaseDeclaration:     s.baseDecl,
  1320  	}
  1321  	c.Check(cand.Check(), IsNil)
  1322  }
  1323  
  1324  func (s *policySuite) TestDollarSlotPublisherIDCheckConnection(c *C) {
  1325  	// no known publishers
  1326  	cand := policy.ConnectCandidate{
  1327  		Plug:            interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil),
  1328  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil),
  1329  		BaseDeclaration: s.baseDecl,
  1330  	}
  1331  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1332  
  1333  	// no plug-side declaration
  1334  	cand = policy.ConnectCandidate{
  1335  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil),
  1336  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil),
  1337  		SlotSnapDeclaration: s.slotDecl,
  1338  		BaseDeclaration:     s.baseDecl,
  1339  	}
  1340  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1341  
  1342  	// plug-side declaration, wrong publisher-id
  1343  	cand = policy.ConnectCandidate{
  1344  		Plug:                interfaces.NewConnectedPlug(s.randomSnap.Plugs["same-slot-publisher-id"], nil, nil),
  1345  		PlugSnapDeclaration: s.randomDecl,
  1346  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil),
  1347  		SlotSnapDeclaration: s.slotDecl,
  1348  		BaseDeclaration:     s.baseDecl,
  1349  	}
  1350  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  1351  
  1352  	// plug publisher id == slot publisher id
  1353  	samePubPlugSnap := snaptest.MockInfo(c, `
  1354  name: same-pub-plug-snap
  1355  version: 0
  1356  plugs:
  1357    same-slot-publisher-id:
  1358  `, nil)
  1359  
  1360  	a, err := asserts.Decode([]byte(`type: snap-declaration
  1361  authority-id: canonical
  1362  series: 16
  1363  snap-name: same-pub-plug-snap
  1364  snap-id: samepublplugsnapidididididididid
  1365  publisher-id: slot-publisher
  1366  timestamp: 2016-09-30T12:00:00Z
  1367  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1368  
  1369  AXNpZw==`))
  1370  	c.Assert(err, IsNil)
  1371  	samePubPlugDecl := a.(*asserts.SnapDeclaration)
  1372  
  1373  	cand = policy.ConnectCandidate{
  1374  		Plug:                interfaces.NewConnectedPlug(samePubPlugSnap.Plugs["same-slot-publisher-id"], nil, nil),
  1375  		PlugSnapDeclaration: samePubPlugDecl,
  1376  		Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots["same-slot-publisher-id"], nil, nil),
  1377  		SlotSnapDeclaration: s.slotDecl,
  1378  		BaseDeclaration:     s.baseDecl,
  1379  	}
  1380  	c.Check(cand.Check(), IsNil)
  1381  }
  1382  
  1383  func (s *policySuite) TestBaselineDefaultIsAllowInstallation(c *C) {
  1384  	installSnap := snaptest.MockInfo(c, `
  1385  name: install-slot-snap
  1386  version: 0
  1387  slots:
  1388    random1:
  1389  plugs:
  1390    random2:
  1391  `, nil)
  1392  
  1393  	cand := policy.InstallCandidate{
  1394  		Snap:            installSnap,
  1395  		BaseDeclaration: s.baseDecl,
  1396  	}
  1397  
  1398  	c.Check(cand.Check(), IsNil)
  1399  }
  1400  
  1401  func (s *policySuite) TestBaseDeclAllowDenyInstallation(c *C) {
  1402  
  1403  	tests := []struct {
  1404  		installYaml string
  1405  		expected    string // "" => no error
  1406  	}{
  1407  		{`name: install-snap
  1408  version: 0
  1409  slots:
  1410    innocuous:
  1411    install-slot-coreonly:
  1412  `, `installation not allowed by "install-slot-coreonly" slot rule of interface "install-slot-coreonly"`},
  1413  		{`name: install-snap
  1414  version: 0
  1415  slots:
  1416    install-slot-attr-ok:
  1417      attr: ok
  1418  `, ""},
  1419  		{`name: install-snap
  1420  version: 0
  1421  slots:
  1422    install-slot-attr-deny:
  1423      trust: trusted
  1424  `, `installation denied by "install-slot-attr-deny" slot rule of interface "install-slot-attr-deny"`},
  1425  		{`name: install-snap
  1426  version: 0
  1427  plugs:
  1428    install-plug-attr-ok:
  1429      attr: ok
  1430  `, ""},
  1431  		{`name: install-snap
  1432  version: 0
  1433  plugs:
  1434    install-plug-attr-ok:
  1435      attr: not-ok
  1436  `, `installation not allowed by "install-plug-attr-ok" plug rule of interface "install-plug-attr-ok"`},
  1437  		{`name: install-snap
  1438  version: 0
  1439  plugs:
  1440    install-plug-gadget-only:
  1441  `, `installation not allowed by "install-plug-gadget-only" plug rule of interface "install-plug-gadget-only"`},
  1442  		{`name: install-gadget
  1443  version: 0
  1444  type: gadget
  1445  plugs:
  1446    install-plug-gadget-only:
  1447  `, ""},
  1448  		{`name: install-gadget
  1449  version: 0
  1450  type: gadget
  1451  plugs:
  1452    install-plug-or:
  1453       p: P2`, `installation denied by "install-plug-or" plug rule.*`},
  1454  		{`name: install-snap
  1455  version: 0
  1456  plugs:
  1457    install-plug-or:
  1458       p: P1`, `installation denied by "install-plug-or" plug rule.*`},
  1459  		{`name: install-snap
  1460  version: 0
  1461  plugs:
  1462    install-plug-or:
  1463       p: P3`, ""},
  1464  		{`name: install-gadget
  1465  version: 0
  1466  type: gadget
  1467  slots:
  1468    install-slot-or:
  1469       p: P2`, `installation denied by "install-slot-or" slot rule.*`},
  1470  		{`name: install-snap
  1471  version: 0
  1472  slots:
  1473    install-slot-or:
  1474       p: P1`, `installation denied by "install-slot-or" slot rule.*`},
  1475  		{`name: install-snap
  1476  version: 0
  1477  slots:
  1478    install-slot-or:
  1479       p: P3`, ""},
  1480  	}
  1481  
  1482  	for _, t := range tests {
  1483  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  1484  
  1485  		cand := policy.InstallCandidate{
  1486  			Snap:            installSnap,
  1487  			BaseDeclaration: s.baseDecl,
  1488  		}
  1489  
  1490  		err := cand.Check()
  1491  		if t.expected == "" {
  1492  			c.Check(err, IsNil)
  1493  		} else {
  1494  			c.Check(err, ErrorMatches, t.expected)
  1495  		}
  1496  	}
  1497  }
  1498  
  1499  func (s *policySuite) TestSnapDeclAllowDenyInstallation(c *C) {
  1500  
  1501  	tests := []struct {
  1502  		installYaml string
  1503  		plugsSlots  string
  1504  		expected    string // "" => no error
  1505  	}{
  1506  		{`name: install-snap
  1507  version: 0
  1508  slots:
  1509    install-slot-base-allow-snap-deny:
  1510      have: yes # bool
  1511  `, `slots:
  1512    install-slot-base-allow-snap-deny:
  1513      deny-installation:
  1514        slot-attributes:
  1515          have: true
  1516  `, `installation denied by "install-slot-base-allow-snap-deny" slot rule of interface "install-slot-base-allow-snap-deny" for "install-snap" snap`},
  1517  		{`name: install-snap
  1518  version: 0
  1519  slots:
  1520    install-slot-base-allow-snap-not-allow:
  1521      have: yes # bool
  1522  `, `slots:
  1523    install-slot-base-allow-snap-not-allow:
  1524      allow-installation:
  1525        slot-attributes:
  1526          have: false
  1527  `, `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`},
  1528  		{`name: install-snap
  1529  version: 0
  1530  slots:
  1531    install-slot-base-deny-snap-allow:
  1532      have: yes
  1533  `, `slots:
  1534    install-slot-base-deny-snap-allow:
  1535      allow-installation: true
  1536  `, ""},
  1537  		{`name: install-snap
  1538  version: 0
  1539  plugs:
  1540    install-plug-base-allow-snap-deny:
  1541      attr: give-me
  1542  `, `plugs:
  1543    install-plug-base-allow-snap-deny:
  1544      deny-installation:
  1545        plug-attributes:
  1546          attr: .*
  1547  `, `installation denied by "install-plug-base-allow-snap-deny" plug rule of interface "install-plug-base-allow-snap-deny" for "install-snap" snap`},
  1548  		{`name: install-snap
  1549  version: 0
  1550  plugs:
  1551    install-plug-base-allow-snap-not-allow:
  1552      attr: give-me
  1553  `, `plugs:
  1554    install-plug-base-allow-snap-not-allow:
  1555      allow-installation:
  1556        plug-attributes:
  1557          attr: minimal
  1558  `, `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`},
  1559  		{`name: install-snap
  1560  version: 0
  1561  plugs:
  1562    install-plug-base-deny-snap-allow:
  1563      attr: attrvalue
  1564  `, `plugs:
  1565    install-plug-base-deny-snap-allow:
  1566      allow-installation:
  1567        plug-attributes:
  1568          attr: attrvalue
  1569  `, ""},
  1570  	}
  1571  
  1572  	for _, t := range tests {
  1573  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  1574  
  1575  		a, err := asserts.Decode([]byte(strings.Replace(`type: snap-declaration
  1576  authority-id: canonical
  1577  series: 16
  1578  snap-name: install-snap
  1579  snap-id: installsnap6idididididididididid
  1580  publisher-id: publisher
  1581  @plugsSlots@
  1582  timestamp: 2016-09-30T12:00:00Z
  1583  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1584  
  1585  AXNpZw==`, "@plugsSlots@", strings.TrimSpace(t.plugsSlots), 1)))
  1586  		c.Assert(err, IsNil)
  1587  		snapDecl := a.(*asserts.SnapDeclaration)
  1588  
  1589  		cand := policy.InstallCandidate{
  1590  			Snap:            installSnap,
  1591  			SnapDeclaration: snapDecl,
  1592  			BaseDeclaration: s.baseDecl,
  1593  		}
  1594  
  1595  		err = cand.Check()
  1596  		if t.expected == "" {
  1597  			c.Check(err, IsNil)
  1598  		} else {
  1599  			c.Check(err, ErrorMatches, t.expected)
  1600  		}
  1601  	}
  1602  }
  1603  
  1604  func (s *policySuite) TestBaseDeclAllowDenyInstallationMinimalCheck(c *C) {
  1605  	tests := []struct {
  1606  		installYaml string
  1607  		expected    string // "" => no error
  1608  	}{
  1609  		{`name: install-snap
  1610  version: 0
  1611  slots:
  1612    innocuous:
  1613    install-slot-coreonly:
  1614  `, `installation not allowed by "install-slot-coreonly" slot rule of interface "install-slot-coreonly"`},
  1615  		{`name: install-gadget
  1616  version: 0
  1617  type: gadget
  1618  slots:
  1619    install-slot-or:
  1620  `, `installation denied by "install-slot-or" slot rule.*`},
  1621  		{`name: install-snap
  1622  version: 0
  1623  slots:
  1624    install-slot-or:
  1625  `, ""},
  1626  		{`name: install-snap
  1627  version: 0
  1628  plugs:
  1629    install-plug-gadget-only:
  1630  `, ``}, // plug is not validated with minimal installation check
  1631  	}
  1632  
  1633  	for _, t := range tests {
  1634  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  1635  
  1636  		cand := policy.InstallCandidateMinimalCheck{
  1637  			Snap:            installSnap,
  1638  			BaseDeclaration: s.baseDecl,
  1639  		}
  1640  
  1641  		err := cand.Check()
  1642  		if t.expected == "" {
  1643  			c.Check(err, IsNil)
  1644  		} else {
  1645  			c.Check(err, ErrorMatches, t.expected)
  1646  		}
  1647  	}
  1648  }
  1649  
  1650  func (s *policySuite) TestOnClassicMinimalInstallationCheck(c *C) {
  1651  	r1 := release.MockOnClassic(false)
  1652  	defer r1()
  1653  	r2 := release.MockReleaseInfo(&release.ReleaseInfo)
  1654  	defer r2()
  1655  
  1656  	tests := []struct {
  1657  		distro      string // "" => not classic
  1658  		installYaml string
  1659  		err         string // "" => no error
  1660  	}{
  1661  		{"", `name: install-snap
  1662  version: 0
  1663  slots:
  1664    install-slot-on-classic-distros:`, `installation not allowed by "install-slot-on-classic-distros" slot rule.*`},
  1665  		{"debian", `name: install-snap
  1666  version: 0
  1667  slots:
  1668    install-slot-on-classic-distros:`, ""},
  1669  		{"", `name: install-snap
  1670  version: 0
  1671  plugs:
  1672    install-plug-on-classic-distros:`, ""}, // plug is not validated with minimal installation check
  1673  		{"debian", `name: install-snap
  1674  version: 0
  1675  plugs:
  1676    install-plug-on-classic-distros:`, ""},
  1677  	}
  1678  
  1679  	for _, t := range tests {
  1680  		if t.distro == "" {
  1681  			release.OnClassic = false
  1682  		} else {
  1683  			release.OnClassic = true
  1684  			release.ReleaseInfo = release.OS{
  1685  				ID: t.distro,
  1686  			}
  1687  		}
  1688  
  1689  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  1690  
  1691  		cand := policy.InstallCandidateMinimalCheck{
  1692  			Snap:            installSnap,
  1693  			BaseDeclaration: s.baseDecl,
  1694  		}
  1695  		err := cand.Check()
  1696  		if t.err == "" {
  1697  			c.Check(err, IsNil)
  1698  		} else {
  1699  			c.Check(err, ErrorMatches, t.err)
  1700  		}
  1701  	}
  1702  }
  1703  
  1704  func (s *policySuite) TestPlugOnClassicCheckConnection(c *C) {
  1705  	r1 := release.MockOnClassic(false)
  1706  	defer r1()
  1707  	r2 := release.MockReleaseInfo(&release.ReleaseInfo)
  1708  	defer r2()
  1709  
  1710  	tests := []struct {
  1711  		distro string // "" => not classic
  1712  		iface  string
  1713  		err    string // "" => no error
  1714  	}{
  1715  		{"ubuntu", "plug-on-classic-true", ""},
  1716  		{"", "plug-on-classic-true", `connection not allowed by plug rule of interface "plug-on-classic-true"`},
  1717  		{"", "plug-on-classic-false", ""},
  1718  		{"ubuntu", "plug-on-classic-false", "connection not allowed.*"},
  1719  		{"ubuntu", "plug-on-classic-distros", ""},
  1720  		{"debian", "plug-on-classic-distros", ""},
  1721  		{"", "plug-on-classic-distros", "connection not allowed.*"},
  1722  		{"other", "plug-on-classic-distros", "connection not allowed.*"},
  1723  	}
  1724  
  1725  	for _, t := range tests {
  1726  		if t.distro == "" {
  1727  			release.OnClassic = false
  1728  		} else {
  1729  			release.OnClassic = true
  1730  			release.ReleaseInfo = release.OS{
  1731  				ID: t.distro,
  1732  			}
  1733  		}
  1734  		cand := policy.ConnectCandidate{
  1735  			Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1736  			Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1737  			BaseDeclaration: s.baseDecl,
  1738  		}
  1739  		err := cand.Check()
  1740  		if t.err == "" {
  1741  			c.Check(err, IsNil)
  1742  		} else {
  1743  			c.Check(err, ErrorMatches, t.err)
  1744  		}
  1745  	}
  1746  }
  1747  
  1748  func (s *policySuite) TestSlotOnClassicCheckConnection(c *C) {
  1749  	r1 := release.MockOnClassic(false)
  1750  	defer r1()
  1751  	r2 := release.MockReleaseInfo(&release.ReleaseInfo)
  1752  	defer r2()
  1753  
  1754  	tests := []struct {
  1755  		distro string // "" => not classic
  1756  		iface  string
  1757  		err    string // "" => no error
  1758  	}{
  1759  		{"ubuntu", "slot-on-classic-true", ""},
  1760  		{"", "slot-on-classic-true", `connection not allowed by slot rule of interface "slot-on-classic-true"`},
  1761  		{"", "slot-on-classic-false", ""},
  1762  		{"ubuntu", "slot-on-classic-false", "connection not allowed.*"},
  1763  		{"ubuntu", "slot-on-classic-distros", ""},
  1764  		{"debian", "slot-on-classic-distros", ""},
  1765  		{"", "slot-on-classic-distros", "connection not allowed.*"},
  1766  		{"other", "slot-on-classic-distros", "connection not allowed.*"},
  1767  	}
  1768  
  1769  	for _, t := range tests {
  1770  		if t.distro == "" {
  1771  			release.OnClassic = false
  1772  		} else {
  1773  			release.OnClassic = true
  1774  			release.ReleaseInfo = release.OS{
  1775  				ID: t.distro,
  1776  			}
  1777  		}
  1778  		cand := policy.ConnectCandidate{
  1779  			Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1780  			Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1781  			BaseDeclaration: s.baseDecl,
  1782  		}
  1783  		err := cand.Check()
  1784  		if t.err == "" {
  1785  			c.Check(err, IsNil)
  1786  		} else {
  1787  			c.Check(err, ErrorMatches, t.err)
  1788  		}
  1789  	}
  1790  }
  1791  
  1792  func (s *policySuite) TestOnClassicInstallation(c *C) {
  1793  	r1 := release.MockOnClassic(false)
  1794  	defer r1()
  1795  	r2 := release.MockReleaseInfo(&release.ReleaseInfo)
  1796  	defer r2()
  1797  
  1798  	tests := []struct {
  1799  		distro      string // "" => not classic
  1800  		installYaml string
  1801  		err         string // "" => no error
  1802  	}{
  1803  		{"", `name: install-snap
  1804  version: 0
  1805  slots:
  1806    install-slot-on-classic-distros:`, `installation not allowed by "install-slot-on-classic-distros" slot rule.*`},
  1807  		{"debian", `name: install-snap
  1808  version: 0
  1809  slots:
  1810    install-slot-on-classic-distros:`, ""},
  1811  		{"", `name: install-snap
  1812  version: 0
  1813  plugs:
  1814    install-plug-on-classic-distros:`, `installation not allowed by "install-plug-on-classic-distros" plug rule.*`},
  1815  		{"debian", `name: install-snap
  1816  version: 0
  1817  plugs:
  1818    install-plug-on-classic-distros:`, ""},
  1819  	}
  1820  
  1821  	for _, t := range tests {
  1822  		if t.distro == "" {
  1823  			release.OnClassic = false
  1824  		} else {
  1825  			release.OnClassic = true
  1826  			release.ReleaseInfo = release.OS{
  1827  				ID: t.distro,
  1828  			}
  1829  		}
  1830  
  1831  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  1832  
  1833  		cand := policy.InstallCandidate{
  1834  			Snap:            installSnap,
  1835  			BaseDeclaration: s.baseDecl,
  1836  		}
  1837  		err := cand.Check()
  1838  		if t.err == "" {
  1839  			c.Check(err, IsNil)
  1840  		} else {
  1841  			c.Check(err, ErrorMatches, t.err)
  1842  		}
  1843  	}
  1844  }
  1845  
  1846  var (
  1847  	otherModel *asserts.Model
  1848  	myModel1   *asserts.Model
  1849  	myModel2   *asserts.Model
  1850  	myModel3   *asserts.Model
  1851  
  1852  	substore1 *asserts.Store
  1853  )
  1854  
  1855  func init() {
  1856  	a, err := asserts.Decode([]byte(`type: model
  1857  authority-id: other-brand
  1858  series: 16
  1859  brand-id: other-brand
  1860  model: other-model
  1861  classic: true
  1862  gadget: gadget
  1863  timestamp: 2018-09-12T12:00:00Z
  1864  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1865  
  1866  AXNpZw==`))
  1867  	if err != nil {
  1868  		panic(err)
  1869  	}
  1870  	otherModel = a.(*asserts.Model)
  1871  
  1872  	a, err = asserts.Decode([]byte(`type: model
  1873  authority-id: my-brand
  1874  series: 16
  1875  brand-id: my-brand
  1876  model: my-model1
  1877  store: store1
  1878  architecture: armhf
  1879  kernel: krnl
  1880  gadget: gadget
  1881  timestamp: 2018-09-12T12:00:00Z
  1882  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1883  
  1884  AXNpZw==`))
  1885  	if err != nil {
  1886  		panic(err)
  1887  	}
  1888  	myModel1 = a.(*asserts.Model)
  1889  
  1890  	a, err = asserts.Decode([]byte(`type: model
  1891  authority-id: my-brand-subbrand
  1892  series: 16
  1893  brand-id: my-brand-subbrand
  1894  model: my-model2
  1895  store: store2
  1896  architecture: armhf
  1897  kernel: krnl
  1898  gadget: gadget
  1899  timestamp: 2018-09-12T12:00:00Z
  1900  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1901  
  1902  AXNpZw==`))
  1903  	if err != nil {
  1904  		panic(err)
  1905  	}
  1906  	myModel2 = a.(*asserts.Model)
  1907  
  1908  	a, err = asserts.Decode([]byte(`type: model
  1909  authority-id: my-brand
  1910  series: 16
  1911  brand-id: my-brand
  1912  model: my-model3
  1913  store: substore1
  1914  architecture: armhf
  1915  kernel: krnl
  1916  gadget: gadget
  1917  timestamp: 2018-09-12T12:00:00Z
  1918  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1919  
  1920  AXNpZw==`))
  1921  	if err != nil {
  1922  		panic(err)
  1923  	}
  1924  	myModel3 = a.(*asserts.Model)
  1925  
  1926  	a, err = asserts.Decode([]byte(`type: store
  1927  store: substore1
  1928  authority-id: canonical
  1929  operator-id: canonical
  1930  friendly-stores:
  1931    - a-store
  1932    - store1
  1933    - store2
  1934  timestamp: 2018-09-12T12:00:00Z
  1935  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  1936  
  1937  AXNpZw==`))
  1938  	if err != nil {
  1939  		panic(err)
  1940  	}
  1941  	substore1 = a.(*asserts.Store)
  1942  }
  1943  
  1944  func (s *policySuite) TestPlugDeviceScopeCheckAutoConnection(c *C) {
  1945  	tests := []struct {
  1946  		model *asserts.Model
  1947  		iface string
  1948  		err   string // "" => no error
  1949  	}{
  1950  		{nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1951  		{otherModel, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1952  		{myModel1, "auto-plug-on-store1", ""},
  1953  		{myModel2, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1954  		{otherModel, "auto-plug-on-my-brand", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-brand" for "plug-snap" snap`},
  1955  		{myModel1, "auto-plug-on-my-brand", ""},
  1956  		{myModel2, "auto-plug-on-my-brand", ""},
  1957  		{otherModel, "auto-plug-on-my-model2", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-model2" for "plug-snap" snap`},
  1958  		{myModel1, "auto-plug-on-my-model2", `auto-connection not allowed by plug rule of interface "auto-plug-on-my-model2" for "plug-snap" snap`},
  1959  		{myModel2, "auto-plug-on-my-model2", ""},
  1960  		// on-store/on-brand/on-model are ANDed for consistency!
  1961  		{otherModel, "auto-plug-on-multi", `auto-connection not allowed by plug rule of interface "auto-plug-on-multi" for "plug-snap" snap`},
  1962  		{myModel1, "auto-plug-on-multi", ""},
  1963  		{myModel2, "auto-plug-on-multi", `auto-connection not allowed by plug rule of interface "auto-plug-on-multi" for "plug-snap" snap`},
  1964  	}
  1965  
  1966  	for _, t := range tests {
  1967  		cand := policy.ConnectCandidate{
  1968  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  1969  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  1970  			PlugSnapDeclaration: s.plugDecl,
  1971  			SlotSnapDeclaration: s.slotDecl,
  1972  
  1973  			BaseDeclaration: s.baseDecl,
  1974  
  1975  			Model: t.model,
  1976  		}
  1977  		arity, err := cand.CheckAutoConnect()
  1978  		if t.err == "" {
  1979  			c.Check(err, IsNil)
  1980  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  1981  		} else {
  1982  			c.Check(err, ErrorMatches, t.err)
  1983  		}
  1984  	}
  1985  }
  1986  
  1987  func (s *policySuite) TestPlugDeviceScopeFriendlyStoreCheckAutoConnection(c *C) {
  1988  	tests := []struct {
  1989  		model *asserts.Model
  1990  		store *asserts.Store
  1991  		iface string
  1992  		err   string // "" => no error
  1993  	}{
  1994  		{nil, nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1995  		{myModel3, nil, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1996  		{myModel3, substore1, "auto-plug-on-store1", ""},
  1997  		{myModel2, substore1, "auto-plug-on-store1", `auto-connection not allowed by plug rule of interface "auto-plug-on-store1" for "plug-snap" snap`},
  1998  	}
  1999  
  2000  	for _, t := range tests {
  2001  		cand := policy.ConnectCandidate{
  2002  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  2003  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  2004  			PlugSnapDeclaration: s.plugDecl,
  2005  			SlotSnapDeclaration: s.slotDecl,
  2006  
  2007  			BaseDeclaration: s.baseDecl,
  2008  
  2009  			Model: t.model,
  2010  			Store: t.store,
  2011  		}
  2012  		arity, err := cand.CheckAutoConnect()
  2013  		if t.err == "" {
  2014  			c.Check(err, IsNil)
  2015  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  2016  		} else {
  2017  			c.Check(err, ErrorMatches, t.err)
  2018  		}
  2019  	}
  2020  }
  2021  
  2022  func (s *policySuite) TestSlotDeviceScopeCheckAutoConnection(c *C) {
  2023  	tests := []struct {
  2024  		model *asserts.Model
  2025  		iface string
  2026  		err   string // "" => no error
  2027  	}{
  2028  		{nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2029  		{otherModel, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2030  		{myModel1, "auto-slot-on-store1", ""},
  2031  		{myModel2, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2032  		{otherModel, "auto-slot-on-my-brand", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-brand" for "slot-snap" snap`},
  2033  		{myModel1, "auto-slot-on-my-brand", ""},
  2034  		{myModel2, "auto-slot-on-my-brand", ""},
  2035  		{otherModel, "auto-slot-on-my-model2", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-model2" for "slot-snap" snap`},
  2036  		{myModel1, "auto-slot-on-my-model2", `auto-connection not allowed by slot rule of interface "auto-slot-on-my-model2" for "slot-snap" snap`},
  2037  		{myModel2, "auto-slot-on-my-model2", ""},
  2038  		// on-store/on-brand/on-model are ANDed for consistency!
  2039  		{otherModel, "auto-slot-on-multi", `auto-connection not allowed by slot rule of interface "auto-slot-on-multi" for "slot-snap" snap`},
  2040  		{myModel1, "auto-slot-on-multi", ""},
  2041  		{myModel2, "auto-slot-on-multi", `auto-connection not allowed by slot rule of interface "auto-slot-on-multi" for "slot-snap" snap`},
  2042  	}
  2043  
  2044  	for _, t := range tests {
  2045  		cand := policy.ConnectCandidate{
  2046  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  2047  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  2048  			PlugSnapDeclaration: s.plugDecl,
  2049  			SlotSnapDeclaration: s.slotDecl,
  2050  
  2051  			BaseDeclaration: s.baseDecl,
  2052  
  2053  			Model: t.model,
  2054  		}
  2055  		arity, err := cand.CheckAutoConnect()
  2056  		if t.err == "" {
  2057  			c.Check(err, IsNil)
  2058  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  2059  		} else {
  2060  			c.Check(err, ErrorMatches, t.err)
  2061  		}
  2062  	}
  2063  }
  2064  
  2065  func (s *policySuite) TestSlotDeviceScopeFriendlyStoreCheckAutoConnection(c *C) {
  2066  	tests := []struct {
  2067  		model *asserts.Model
  2068  		store *asserts.Store
  2069  		iface string
  2070  		err   string // "" => no error
  2071  	}{
  2072  		{nil, nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2073  		{myModel3, nil, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2074  		{myModel3, substore1, "auto-slot-on-store1", ""},
  2075  		{myModel2, substore1, "auto-slot-on-store1", `auto-connection not allowed by slot rule of interface "auto-slot-on-store1" for "slot-snap" snap`},
  2076  	}
  2077  
  2078  	for _, t := range tests {
  2079  		cand := policy.ConnectCandidate{
  2080  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  2081  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  2082  			PlugSnapDeclaration: s.plugDecl,
  2083  			SlotSnapDeclaration: s.slotDecl,
  2084  
  2085  			BaseDeclaration: s.baseDecl,
  2086  
  2087  			Model: t.model,
  2088  			Store: t.store,
  2089  		}
  2090  		arity, err := cand.CheckAutoConnect()
  2091  		if t.err == "" {
  2092  			c.Check(err, IsNil)
  2093  			c.Check(arity.SlotsPerPlugAny(), Equals, false)
  2094  		} else {
  2095  			c.Check(err, ErrorMatches, t.err)
  2096  		}
  2097  	}
  2098  }
  2099  
  2100  func (s *policySuite) TestDeviceScopeInstallation(c *C) {
  2101  	const plugSnap = `name: install-snap
  2102  version: 0
  2103  plugs:
  2104    install-plug-device-scope:`
  2105  
  2106  	const slotSnap = `name: install-snap
  2107  version: 0
  2108  slots:
  2109    install-slot-device-scope:`
  2110  
  2111  	const plugOnStore1 = `plugs:
  2112    install-plug-device-scope:
  2113      allow-installation:
  2114        on-store:
  2115          - store1
  2116  `
  2117  	const plugOnMulti = `plugs:
  2118    install-plug-device-scope:
  2119      allow-installation:
  2120        on-brand:
  2121          - my-brand
  2122          - my-brand-subbrand
  2123        on-store:
  2124          - store1
  2125          - other-store
  2126        on-model:
  2127          - my-brand/my-model1
  2128          - my-brand-subbrand/my-model2
  2129  `
  2130  	const slotOnStore2 = `slots:
  2131    install-slot-device-scope:
  2132      allow-installation:
  2133        on-store:
  2134          - store2
  2135  `
  2136  
  2137  	tests := []struct {
  2138  		model       *asserts.Model
  2139  		store       *asserts.Store
  2140  		installYaml string
  2141  		plugsSlots  string
  2142  		err         string // "" => no error
  2143  	}{
  2144  		{nil, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2145  		{otherModel, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2146  		{myModel1, nil, plugSnap, plugOnStore1, ""},
  2147  		{myModel2, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2148  		{otherModel, nil, plugSnap, plugOnMulti, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2149  		{myModel1, nil, plugSnap, plugOnMulti, ""},
  2150  		{myModel2, nil, plugSnap, plugOnMulti, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2151  		{otherModel, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for "install-snap" snap`},
  2152  		{myModel1, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for "install-snap" snap`},
  2153  		{myModel2, nil, slotSnap, slotOnStore2, ""},
  2154  		// friendly-stores
  2155  		{myModel3, nil, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2156  		{myModel3, substore1, plugSnap, plugOnStore1, ""},
  2157  		{myModel2, substore1, plugSnap, plugOnStore1, `installation not allowed by "install-plug-device-scope" plug rule of interface "install-plug-device-scope" for "install-snap" snap`},
  2158  		{myModel3, nil, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for \"install-snap\" snap`},
  2159  		{myModel3, substore1, slotSnap, slotOnStore2, ""},
  2160  		{myModel2, substore1, slotSnap, slotOnStore2, `installation not allowed by "install-slot-device-scope" slot rule of interface "install-slot-device-scope" for \"install-snap\" snap`},
  2161  	}
  2162  
  2163  	for _, t := range tests {
  2164  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  2165  
  2166  		a, err := asserts.Decode([]byte(strings.Replace(`type: snap-declaration
  2167  authority-id: canonical
  2168  series: 16
  2169  snap-name: install-snap
  2170  snap-id: installsnap6idididididididididid
  2171  publisher-id: publisher
  2172  @plugsSlots@
  2173  timestamp: 2016-09-30T12:00:00Z
  2174  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  2175  
  2176  AXNpZw==`, "@plugsSlots@", strings.TrimSpace(t.plugsSlots), 1)))
  2177  		c.Assert(err, IsNil)
  2178  		snapDecl := a.(*asserts.SnapDeclaration)
  2179  
  2180  		cand := policy.InstallCandidate{
  2181  			Snap:            installSnap,
  2182  			SnapDeclaration: snapDecl,
  2183  			BaseDeclaration: s.baseDecl,
  2184  			Model:           t.model,
  2185  			Store:           t.store,
  2186  		}
  2187  		err = cand.Check()
  2188  		if t.err == "" {
  2189  			c.Check(err, IsNil)
  2190  		} else {
  2191  			c.Check(err, ErrorMatches, t.err)
  2192  		}
  2193  	}
  2194  }
  2195  
  2196  func (s *policySuite) TestSlotDollarSlotAttrConnection(c *C) {
  2197  	// no corresponding attr
  2198  	cand := policy.ConnectCandidate{
  2199  		Plug:            interfaces.NewConnectedPlug(s.randomSnap.Plugs["slot-slot-attr"], nil, nil),
  2200  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil),
  2201  		BaseDeclaration: s.baseDecl,
  2202  	}
  2203  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2204  
  2205  	// different attr values
  2206  	cand = policy.ConnectCandidate{
  2207  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-slot-attr-mismatch"], nil, nil),
  2208  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil),
  2209  		BaseDeclaration: s.baseDecl,
  2210  	}
  2211  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2212  
  2213  	// plug attr == slot attr
  2214  	cand = policy.ConnectCandidate{
  2215  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-slot-attr-match"], nil, nil),
  2216  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-slot-attr"], nil, nil),
  2217  		BaseDeclaration: s.baseDecl,
  2218  	}
  2219  	c.Check(cand.Check(), IsNil)
  2220  }
  2221  
  2222  func (s *policySuite) TestSlotDollarPlugAttrConnection(c *C) {
  2223  	// different attr values
  2224  	cand := policy.ConnectCandidate{
  2225  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-mismatch"], nil, nil),
  2226  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil),
  2227  		BaseDeclaration: s.baseDecl,
  2228  	}
  2229  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2230  
  2231  	// plug attr == slot attr
  2232  	cand = policy.ConnectCandidate{
  2233  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-match"], nil, nil),
  2234  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil),
  2235  		BaseDeclaration: s.baseDecl,
  2236  	}
  2237  	c.Check(cand.Check(), IsNil)
  2238  }
  2239  
  2240  func (s *policySuite) TestPlugDollarPlugAttrConnection(c *C) {
  2241  	// different attr values
  2242  	cand := policy.ConnectCandidate{
  2243  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil),
  2244  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-mismatch"], nil, nil),
  2245  		BaseDeclaration: s.baseDecl,
  2246  	}
  2247  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2248  
  2249  	// plug attr == slot attr
  2250  	cand = policy.ConnectCandidate{
  2251  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil),
  2252  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-match"], nil, nil),
  2253  		BaseDeclaration: s.baseDecl,
  2254  	}
  2255  	c.Check(cand.Check(), IsNil)
  2256  }
  2257  
  2258  func (s *policySuite) TestPlugDollarSlotAttrConnection(c *C) {
  2259  	// different attr values
  2260  	cand := policy.ConnectCandidate{
  2261  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-slot-attr"], nil, nil),
  2262  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-slot-attr-mismatch"], nil, nil),
  2263  		BaseDeclaration: s.baseDecl,
  2264  	}
  2265  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2266  
  2267  	// plug attr == slot attr
  2268  	cand = policy.ConnectCandidate{
  2269  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-slot-attr"], nil, nil),
  2270  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-slot-attr-match"], nil, nil),
  2271  		BaseDeclaration: s.baseDecl,
  2272  	}
  2273  	c.Check(cand.Check(), IsNil)
  2274  }
  2275  
  2276  func (s *policySuite) TestDollarMissingConnection(c *C) {
  2277  	// not missing
  2278  	cand := policy.ConnectCandidate{
  2279  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-missing-mismatch"], nil, nil),
  2280  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-missing"], nil, nil),
  2281  		BaseDeclaration: s.baseDecl,
  2282  	}
  2283  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2284  
  2285  	// missing
  2286  	cand = policy.ConnectCandidate{
  2287  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-missing-match"], nil, nil),
  2288  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-missing"], nil, nil),
  2289  		BaseDeclaration: s.baseDecl,
  2290  	}
  2291  	c.Check(cand.Check(), IsNil)
  2292  }
  2293  
  2294  func (s *policySuite) TestSlotDollarPlugDynamicAttrConnection(c *C) {
  2295  	// "c" attribute of the plug missing
  2296  	cand := policy.ConnectCandidate{
  2297  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-dynamic"], nil, map[string]interface{}{}),
  2298  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil),
  2299  		BaseDeclaration: s.baseDecl,
  2300  	}
  2301  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2302  
  2303  	// plug attr == slot attr, "c" attribute of the plug provided by dynamic attribute
  2304  	cand = policy.ConnectCandidate{
  2305  		Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["slot-plug-attr-dynamic"], nil, map[string]interface{}{
  2306  			"c": "C",
  2307  		}),
  2308  
  2309  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["slot-plug-attr"], nil, nil),
  2310  		BaseDeclaration: s.baseDecl,
  2311  	}
  2312  	c.Check(cand.Check(), IsNil)
  2313  }
  2314  
  2315  func (s *policySuite) TestPlugDollarSlotDynamicAttrConnection(c *C) {
  2316  	// "c" attribute of the slot missing
  2317  	cand := policy.ConnectCandidate{
  2318  		Plug:            interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil),
  2319  		Slot:            interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-dynamic"], nil, map[string]interface{}{}),
  2320  		BaseDeclaration: s.baseDecl,
  2321  	}
  2322  	c.Check(cand.Check(), ErrorMatches, "connection not allowed.*")
  2323  
  2324  	// plug attr == slot attr, "c" attribute of the slot provided by dynamic attribute
  2325  	cand = policy.ConnectCandidate{
  2326  		Plug: interfaces.NewConnectedPlug(s.plugSnap.Plugs["plug-plug-attr"], nil, nil),
  2327  		Slot: interfaces.NewConnectedSlot(s.slotSnap.Slots["plug-plug-attr-dynamic"], nil, map[string]interface{}{
  2328  			"c": "C",
  2329  		}),
  2330  
  2331  		BaseDeclaration: s.baseDecl,
  2332  	}
  2333  	c.Check(cand.Check(), IsNil)
  2334  }
  2335  
  2336  func (s *policySuite) TestSlotsArityAutoConnection(c *C) {
  2337  	tests := []struct {
  2338  		iface string
  2339  		any   bool
  2340  	}{
  2341  		{"slots-arity-default", false},
  2342  		{"slots-arity-slot-any", true},
  2343  		{"slots-arity-plug-any", true},
  2344  		{"slots-arity-slot-any-plug-one", false},
  2345  		{"slots-arity-slot-any-plug-two", false},
  2346  		{"slots-arity-slot-any-plug-default", false},
  2347  		{"slots-arity-slot-one-plug-any", true},
  2348  	}
  2349  
  2350  	for _, t := range tests {
  2351  		cand := policy.ConnectCandidate{
  2352  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.iface], nil, nil),
  2353  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.iface], nil, nil),
  2354  			PlugSnapDeclaration: s.plugDecl,
  2355  			SlotSnapDeclaration: s.slotDecl,
  2356  
  2357  			BaseDeclaration: s.baseDecl,
  2358  		}
  2359  		arity, err := cand.CheckAutoConnect()
  2360  		c.Assert(err, IsNil)
  2361  		c.Check(arity.SlotsPerPlugAny(), Equals, t.any)
  2362  	}
  2363  }
  2364  
  2365  func (s *policySuite) TestNameConstraintsInstallation(c *C) {
  2366  	const plugSnap = `name: install-snap
  2367  version: 0
  2368  plugs:
  2369    install-plug-name-bound:`
  2370  
  2371  	const plugOtherNameSnap = `name: install-snap
  2372  version: 0
  2373  plugs:
  2374    install-plug-name-bound-other:
  2375      interface: install-plug-name-bound
  2376  `
  2377  
  2378  	const slotSnap = `name: install-snap
  2379  version: 0
  2380  slots:
  2381    install-slot-name-bound:`
  2382  
  2383  	const slotOtherNameSnap = `name: install-snap
  2384  version: 0
  2385  slots:
  2386    install-slot-name-bound-other:
  2387      interface: install-slot-name-bound
  2388  `
  2389  
  2390  	const plugOtherName = `plugs:
  2391    install-plug-name-bound:
  2392      allow-installation:
  2393        plug-names:
  2394          - install-plug-name-bound-other`
  2395  
  2396  	tests := []struct {
  2397  		installYaml string
  2398  		plugsSlots  string
  2399  		err         string // "" => no error
  2400  	}{
  2401  		{plugSnap, "", ""},
  2402  		{plugOtherNameSnap, "", `installation not allowed by "install-plug-name-bound-other" plug rule of interface "install-plug-name-bound"`},
  2403  		{plugOtherNameSnap, plugOtherName, ""},
  2404  		{slotSnap, "", ""},
  2405  		{slotOtherNameSnap, "", `installation not allowed by "install-slot-name-bound-other" slot rule of interface "install-slot-name-bound"`},
  2406  	}
  2407  
  2408  	for _, t := range tests {
  2409  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  2410  
  2411  		plugsSlots := strings.TrimSpace(t.plugsSlots)
  2412  		if plugsSlots != "" {
  2413  			plugsSlots = "\n" + plugsSlots
  2414  		}
  2415  
  2416  		a, err := asserts.Decode([]byte(strings.Replace(`type: snap-declaration
  2417  authority-id: canonical
  2418  series: 16
  2419  snap-name: install-snap
  2420  snap-id: installsnap6idididididididididid
  2421  publisher-id: publisher
  2422  @plugsSlots@
  2423  timestamp: 2016-09-30T12:00:00Z
  2424  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  2425  
  2426  AXNpZw==`, "\n@plugsSlots@", plugsSlots, 1)))
  2427  		c.Assert(err, IsNil)
  2428  		snapDecl := a.(*asserts.SnapDeclaration)
  2429  
  2430  		cand := policy.InstallCandidate{
  2431  			Snap:            installSnap,
  2432  			SnapDeclaration: snapDecl,
  2433  			BaseDeclaration: s.baseDecl,
  2434  		}
  2435  		err = cand.Check()
  2436  		if t.err == "" {
  2437  			c.Check(err, IsNil)
  2438  		} else {
  2439  			c.Check(err, ErrorMatches, t.err)
  2440  		}
  2441  	}
  2442  }
  2443  
  2444  func (s *policySuite) TestNameConstraintsAutoConnection(c *C) {
  2445  	tests := []struct {
  2446  		plug, slot string
  2447  		ok         bool
  2448  	}{
  2449  		{"plugs-name-bound-p1", "plugs-name-bound-s1", false},
  2450  		{"plugs-name-bound-p2", "plugs-name-bound-s1", false},
  2451  		{"plugs-name-bound-p1", "plugs-name-bound-s2", true},
  2452  		{"plugs-name-bound-p2", "plugs-name-bound-s2", false},
  2453  		{"slots-name-bound-p1", "slots-name-bound-s1", false},
  2454  		{"slots-name-bound-p2", "slots-name-bound-s1", false},
  2455  		{"slots-name-bound-p1", "slots-name-bound-s2", false},
  2456  		{"slots-name-bound-p2", "slots-name-bound-s2", true},
  2457  	}
  2458  
  2459  	for _, t := range tests {
  2460  		cand := policy.ConnectCandidate{
  2461  			Plug:                interfaces.NewConnectedPlug(s.plugSnap.Plugs[t.plug], nil, nil),
  2462  			Slot:                interfaces.NewConnectedSlot(s.slotSnap.Slots[t.slot], nil, nil),
  2463  			PlugSnapDeclaration: s.plugDecl,
  2464  			SlotSnapDeclaration: s.slotDecl,
  2465  
  2466  			BaseDeclaration: s.baseDecl,
  2467  		}
  2468  		_, err := cand.CheckAutoConnect()
  2469  		if t.ok {
  2470  			c.Check(err, IsNil, Commentf("%s:%s", t.plug, t.slot))
  2471  		} else {
  2472  			var expected string
  2473  			if cand.Plug.Interface() == "plugs-name-bound" {
  2474  				expected = `auto-connection not allowed by plug rule of interface "plugs-name-bound".*`
  2475  			} else {
  2476  				// slots-name-bound
  2477  				expected = `auto-connection not allowed by slot rule of interface "slots-name-bound".*`
  2478  			}
  2479  			c.Check(err, ErrorMatches, expected)
  2480  		}
  2481  	}
  2482  
  2483  }
  2484  
  2485  // Test miscellaneous store patterns when base declaration has
  2486  // 'allow-installation: false' and we grant based on interface attributes
  2487  // such as with personal-files, system-files, etc.
  2488  //
  2489  // While this is also tested elsewhere, combining this into a single test
  2490  // makes it easy to verify correctness of a related set of patterns
  2491  //
  2492  // Eg, if base decl has:
  2493  //   slots:
  2494  //     system-files:
  2495  //       allow-installation:
  2496  //         slot-snap-type:
  2497  //           - core
  2498  //   plugs:
  2499  //     system-files:
  2500  //       allow-installation: false
  2501  //
  2502  // then test snap decls of the form:
  2503  //   plugs:
  2504  //     system-files:
  2505  //       allow-installation:
  2506  //         plug-attributes:
  2507  //           write: ...
  2508  // or:
  2509  //   plugs:
  2510  //     system-files:
  2511  //       allow-installation:
  2512  //         -
  2513  //           plug-attributes:
  2514  //             write: ...
  2515  // or:
  2516  //   plugs:
  2517  //     system-files:
  2518  //       allow-installation:
  2519  //         -
  2520  //           plug-attributes:
  2521  //             write: ...
  2522  //         -
  2523  //           plug-attributes:
  2524  //             write: ...
  2525  //
  2526  func (s *policySuite) TestSnapDeclListAttribWithBaseAllowInstallationFalse(c *C) {
  2527  	baseDeclStr := `type: base-declaration
  2528  authority-id: canonical
  2529  series: 16
  2530  slots:
  2531    base-allow-install-false:
  2532      allow-installation:
  2533        slot-snap-type:
  2534          - core
  2535  plugs:
  2536    base-allow-install-false:
  2537      allow-installation: false
  2538  timestamp: 2016-09-30T12:00:00Z
  2539  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  2540  
  2541  AXNpZw==`
  2542  	a, err := asserts.Decode([]byte(baseDeclStr))
  2543  	c.Assert(err, IsNil)
  2544  	baseDecl := a.(*asserts.BaseDeclaration)
  2545  
  2546  	tests := []struct {
  2547  		installYaml        string
  2548  		snapDeclPlugsSlots string
  2549  		expected           string // "" => no error
  2550  	}{
  2551  		// expected match
  2552  		{`name: install-snap
  2553  version: 0
  2554  plugs:
  2555    p1:
  2556      interface: base-allow-install-false
  2557      write:
  2558      - /path1
  2559  `, `plugs:
  2560    base-allow-install-false:
  2561      allow-installation:
  2562        plug-attributes:
  2563          write: /path1
  2564  `, ``},
  2565  		{`name: install-snap
  2566  version: 0
  2567  plugs:
  2568    p1:
  2569      interface: base-allow-install-false
  2570      write:
  2571      - /path1
  2572  `, `plugs:
  2573    base-allow-install-false:
  2574      allow-installation:
  2575        plug-attributes:
  2576          write: /path1a?
  2577  `, ``},
  2578  		{`name: install-snap
  2579  version: 0
  2580  plugs:
  2581    p1:
  2582      interface: base-allow-install-false
  2583      write:
  2584      - /path1a
  2585  `, `plugs:
  2586    base-allow-install-false:
  2587      allow-installation:
  2588        plug-attributes:
  2589          write: /path1a?
  2590  `, ``},
  2591  		{`name: install-snap
  2592  version: 0
  2593  plugs:
  2594    p1:
  2595      interface: base-allow-install-false
  2596      write:
  2597      - /path1
  2598      - /path1a
  2599  `, `plugs:
  2600    base-allow-install-false:
  2601      allow-installation:
  2602        plug-attributes:
  2603          write: /path1a?
  2604  `, ``},
  2605  
  2606  		// expected match single alternation
  2607  		{`name: install-snap
  2608  version: 0
  2609  plugs:
  2610    p1:
  2611      interface: base-allow-install-false
  2612      write:
  2613      - /path1
  2614  `, `plugs:
  2615    base-allow-install-false:
  2616      allow-installation:
  2617        -
  2618          plug-attributes:
  2619            write: /path1
  2620  `, ``},
  2621  		{`name: install-snap
  2622  version: 0
  2623  plugs:
  2624    p1:
  2625      interface: base-allow-install-false
  2626      write:
  2627      - /path1
  2628  `, `plugs:
  2629    base-allow-install-false:
  2630      allow-installation:
  2631        -
  2632          plug-attributes:
  2633            write: /path1a?
  2634  `, ``},
  2635  		{`name: install-snap
  2636  version: 0
  2637  plugs:
  2638    p1:
  2639      interface: base-allow-install-false
  2640      write:
  2641      - /path1a
  2642  `, `plugs:
  2643    base-allow-install-false:
  2644      allow-installation:
  2645        -
  2646          plug-attributes:
  2647            write: /path1a?
  2648  `, ``},
  2649  
  2650  		{`name: install-snap
  2651  version: 0
  2652  plugs:
  2653    p1:
  2654      interface: base-allow-install-false
  2655      write:
  2656      - /path1
  2657      - /path1a
  2658  `, `plugs:
  2659    base-allow-install-false:
  2660      allow-installation:
  2661        -
  2662          plug-attributes:
  2663            write: /path1a?
  2664  `, ``},
  2665  		// expected match two
  2666  		{`name: install-snap
  2667  version: 0
  2668  plugs:
  2669    p1:
  2670      interface: base-allow-install-false
  2671      write:
  2672      - /path1
  2673    p2:
  2674      interface: base-allow-install-false
  2675      write:
  2676      - /path1a
  2677  `, `plugs:
  2678    base-allow-install-false:
  2679      allow-installation:
  2680        plug-attributes:
  2681          write: /path1a?
  2682  `, ``},
  2683  		{`name: install-snap
  2684  version: 0
  2685  plugs:
  2686    p1:
  2687      interface: base-allow-install-false
  2688      write:
  2689      - /path1
  2690    p2:
  2691      interface: base-allow-install-false
  2692      write:
  2693      - /path1a
  2694  `, `plugs:
  2695    base-allow-install-false:
  2696      allow-installation:
  2697        -
  2698          plug-attributes:
  2699            write: /path1a?
  2700  `, ``},
  2701  		{`name: install-snap
  2702  version: 0
  2703  plugs:
  2704    p1:
  2705      interface: base-allow-install-false
  2706      write:
  2707      - /path1
  2708    p2:
  2709      interface: base-allow-install-false
  2710      write:
  2711      - /path1a
  2712  `, `plugs:
  2713    base-allow-install-false:
  2714      allow-installation:
  2715        -
  2716          plug-attributes:
  2717            write: /path1
  2718        -
  2719          plug-attributes:
  2720            write: /path1a
  2721  `, ``},
  2722  		// expected no match
  2723  		{`name: install-snap
  2724  version: 0
  2725  plugs:
  2726    p1:
  2727      interface: base-allow-install-false
  2728      write:
  2729      - /path1
  2730      - /path1a
  2731  `, `plugs:
  2732    base-allow-install-false:
  2733      allow-installation:
  2734        plug-attributes:
  2735          write: /path1
  2736  `, `installation not allowed by "p1" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2737  		{`name: install-snap
  2738  version: 0
  2739  plugs:
  2740    p1:
  2741      interface: base-allow-install-false
  2742      write:
  2743      - /path1
  2744      - /path1a
  2745  `, `plugs:
  2746    base-allow-install-false:
  2747      allow-installation:
  2748        -
  2749          plug-attributes:
  2750            write: /path1
  2751  `, `installation not allowed by "p1" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2752  		{`name: install-snap
  2753  version: 0
  2754  plugs:
  2755    p1:
  2756      interface: base-allow-install-false
  2757      write:
  2758      - /path1
  2759    p2:
  2760      interface: base-allow-install-false
  2761      write:
  2762      - /path1nomatch
  2763  `, `plugs:
  2764    base-allow-install-false:
  2765      allow-installation:
  2766        -
  2767          plug-attributes:
  2768            write: /path1a?
  2769  `, `installation not allowed by "p2" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2770  		{`name: install-snap
  2771  version: 0
  2772  plugs:
  2773    p1:
  2774      interface: base-allow-install-false
  2775      write:
  2776      - /path1
  2777    p2:
  2778      interface: base-allow-install-false
  2779      write:
  2780      - /path1nomatch
  2781  `, `plugs:
  2782    base-allow-install-false:
  2783      allow-installation:
  2784        -
  2785          plug-attributes:
  2786            write: /path1
  2787        -
  2788          plug-attributes:
  2789            write: /path1a
  2790  `, `installation not allowed by "p2" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2791  		{`name: install-snap
  2792  version: 0
  2793  plugs:
  2794    p1:
  2795      interface: base-allow-install-false
  2796  `, `plugs:
  2797    base-allow-install-false:
  2798      allow-installation:
  2799        plug-attributes:
  2800          write: /path1
  2801  `, `installation not allowed by "p1" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2802  		{`name: install-snap
  2803  version: 0
  2804  plugs:
  2805    p1:
  2806      interface: base-allow-install-false
  2807      write: /path2
  2808  `, `plugs:
  2809    base-allow-install-false:
  2810      allow-installation:
  2811        plug-attributes:
  2812          read: /path1
  2813          write: /path2
  2814  `, `installation not allowed by "p1" plug rule of interface "base-allow-install-false" for "install-snap" snap`},
  2815  	}
  2816  
  2817  	for _, t := range tests {
  2818  		installSnap := snaptest.MockInfo(c, t.installYaml, nil)
  2819  
  2820  		snapDeclStr := strings.Replace(`type: snap-declaration
  2821  authority-id: canonical
  2822  series: 16
  2823  snap-name: install-snap
  2824  snap-id: installsnap6idididididididididid
  2825  publisher-id: publisher
  2826  @plugsSlots@
  2827  timestamp: 2016-09-30T12:00:00Z
  2828  sign-key-sha3-384: Jv8_JiHiIzJVcO9M55pPdqSDWUvuhfDIBJUS-3VW7F_idjix7Ffn5qMxB21ZQuij
  2829  
  2830  AXNpZw==`, "@plugsSlots@", strings.TrimSpace(t.snapDeclPlugsSlots), 1)
  2831  		b, err := asserts.Decode([]byte(snapDeclStr))
  2832  		c.Assert(err, IsNil)
  2833  		snapDecl := b.(*asserts.SnapDeclaration)
  2834  
  2835  		cand := policy.InstallCandidate{
  2836  			Snap:            installSnap,
  2837  			SnapDeclaration: snapDecl,
  2838  			BaseDeclaration: baseDecl,
  2839  		}
  2840  
  2841  		err = cand.Check()
  2842  		if t.expected == "" {
  2843  			c.Check(err, IsNil)
  2844  		} else {
  2845  			c.Check(err, ErrorMatches, t.expected)
  2846  		}
  2847  	}
  2848  }