github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/dbus_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 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 builtin_test
    21  
    22  import (
    23  	. "gopkg.in/check.v1"
    24  
    25  	"github.com/snapcore/snapd/interfaces"
    26  	"github.com/snapcore/snapd/interfaces/apparmor"
    27  	"github.com/snapcore/snapd/interfaces/builtin"
    28  	"github.com/snapcore/snapd/interfaces/dbus"
    29  	"github.com/snapcore/snapd/interfaces/seccomp"
    30  	"github.com/snapcore/snapd/release"
    31  	"github.com/snapcore/snapd/snap"
    32  	"github.com/snapcore/snapd/snap/snaptest"
    33  	"github.com/snapcore/snapd/testutil"
    34  )
    35  
    36  type DbusInterfaceSuite struct {
    37  	testutil.BaseTest
    38  	iface interfaces.Interface
    39  
    40  	snapInfo *snap.Info
    41  
    42  	sessionPlugInfo          *snap.PlugInfo
    43  	sessionPlug              *interfaces.ConnectedPlug
    44  	systemPlugInfo           *snap.PlugInfo
    45  	systemPlug               *interfaces.ConnectedPlug
    46  	connectedSessionPlugInfo *snap.PlugInfo
    47  	connectedSessionPlug     *interfaces.ConnectedPlug
    48  	connectedSystemPlugInfo  *snap.PlugInfo
    49  	connectedSystemPlug      *interfaces.ConnectedPlug
    50  
    51  	sessionSlotInfo          *snap.SlotInfo
    52  	sessionSlot              *interfaces.ConnectedSlot
    53  	systemSlotInfo           *snap.SlotInfo
    54  	systemSlot               *interfaces.ConnectedSlot
    55  	connectedSessionSlotInfo *snap.SlotInfo
    56  	connectedSessionSlot     *interfaces.ConnectedSlot
    57  	connectedSystemSlotInfo  *snap.SlotInfo
    58  	connectedSystemSlot      *interfaces.ConnectedSlot
    59  }
    60  
    61  var _ = Suite(&DbusInterfaceSuite{
    62  	iface: builtin.MustInterface("dbus"),
    63  })
    64  
    65  func (s *DbusInterfaceSuite) SetUpSuite(c *C) {
    66  	s.snapInfo = snaptest.MockInfo(c, `
    67  name: test-dbus
    68  version: 0
    69  slots:
    70    test-session-slot:
    71      interface: dbus
    72      bus: session
    73      name: org.test-session-slot
    74    test-system-slot:
    75      interface: dbus
    76      bus: system
    77      name: org.test-system-slot
    78    test-system-connected-slot:
    79      interface: dbus
    80      bus: system
    81      name: org.test-system-connected
    82    test-session-connected-slot:
    83      interface: dbus
    84      bus: session
    85      name: org.test-session-connected
    86  
    87  plugs:
    88    test-session-plug:
    89      interface: dbus
    90      bus: session
    91      name: org.test-session-plug
    92    test-system-plug:
    93      interface: dbus
    94      bus: system
    95      name: org.test-system-plug
    96    test-system-connected-plug:
    97      interface: dbus
    98      bus: system
    99      name: org.test-system-connected
   100    test-session-connected-plug:
   101      interface: dbus
   102      bus: session
   103      name: org.test-session-connected
   104  
   105  apps:
   106    test-session-provider:
   107      slots:
   108      - test-session-slot
   109    test-system-provider:
   110      slots:
   111      - test-system-slot
   112    test-session-consumer:
   113      plugs:
   114      - test-session-plug
   115    test-system-consumer:
   116      plugs:
   117      - test-system-plug
   118  `, nil)
   119  }
   120  
   121  func (s *DbusInterfaceSuite) SetUpTest(c *C) {
   122  	s.sessionSlotInfo = s.snapInfo.Slots["test-session-slot"]
   123  	s.sessionSlot = interfaces.NewConnectedSlot(s.sessionSlotInfo, nil, nil)
   124  	s.systemSlotInfo = s.snapInfo.Slots["test-system-slot"]
   125  	s.systemSlot = interfaces.NewConnectedSlot(s.systemSlotInfo, nil, nil)
   126  	s.connectedSessionSlotInfo = s.snapInfo.Slots["test-session-connected-slot"]
   127  	s.connectedSessionSlot = interfaces.NewConnectedSlot(s.connectedSessionSlotInfo, nil, nil)
   128  	s.connectedSystemSlotInfo = s.snapInfo.Slots["test-system-connected-slot"]
   129  	s.connectedSystemSlot = interfaces.NewConnectedSlot(s.connectedSystemSlotInfo, nil, nil)
   130  
   131  	s.sessionPlugInfo = s.snapInfo.Plugs["test-session-plug"]
   132  	s.sessionPlug = interfaces.NewConnectedPlug(s.sessionPlugInfo, nil, nil)
   133  	s.systemPlugInfo = s.snapInfo.Plugs["test-system-plug"]
   134  	s.systemPlug = interfaces.NewConnectedPlug(s.systemPlugInfo, nil, nil)
   135  	s.connectedSessionPlugInfo = s.snapInfo.Plugs["test-session-connected-plug"]
   136  	s.connectedSessionPlug = interfaces.NewConnectedPlug(s.connectedSessionPlugInfo, nil, nil)
   137  	s.connectedSystemPlugInfo = s.snapInfo.Plugs["test-system-connected-plug"]
   138  	s.connectedSystemPlug = interfaces.NewConnectedPlug(s.connectedSystemPlugInfo, nil, nil)
   139  }
   140  
   141  func (s *DbusInterfaceSuite) TestName(c *C) {
   142  	c.Assert(s.iface.Name(), Equals, "dbus")
   143  }
   144  
   145  func (s *DbusInterfaceSuite) TestValidSessionBusName(c *C) {
   146  	var mockSnapYaml = `name: dbus-snap
   147  version: 1.0
   148  slots:
   149   dbus-slot:
   150    interface: dbus
   151    bus: session
   152    name: org.dbus-snap.session-a
   153  `
   154  
   155  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   156  
   157  	slot := info.Slots["dbus-slot"]
   158  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), IsNil)
   159  }
   160  
   161  func (s *DbusInterfaceSuite) TestValidSystemBusName(c *C) {
   162  	var mockSnapYaml = `name: dbus-snap
   163  version: 1.0
   164  slots:
   165   dbus-slot:
   166    interface: dbus
   167    bus: system
   168    name: org.dbus-snap.system-a
   169  `
   170  
   171  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   172  
   173  	slot := info.Slots["dbus-slot"]
   174  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), IsNil)
   175  }
   176  
   177  func (s *DbusInterfaceSuite) TestValidFullBusName(c *C) {
   178  	var mockSnapYaml = `name: dbus-snap
   179  version: 1.0
   180  slots:
   181   dbus-slot:
   182    interface: dbus
   183    bus: system
   184    name: org.dbus-snap.foo.bar.baz.n0rf_qux
   185  `
   186  
   187  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   188  
   189  	slot := info.Slots["dbus-slot"]
   190  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), IsNil)
   191  }
   192  
   193  func (s *DbusInterfaceSuite) TestNonexistentBusName(c *C) {
   194  	var mockSnapYaml = `name: dbus-snap
   195  version: 1.0
   196  slots:
   197   dbus-slot:
   198    interface: dbus
   199    bus: nonexistent
   200    name: org.dbus-snap
   201  `
   202  
   203  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   204  
   205  	slot := info.Slots["dbus-slot"]
   206  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), ErrorMatches, "bus 'nonexistent' must be one of 'session' or 'system'")
   207  }
   208  
   209  // If this test is failing, be sure to verify the AppArmor rules for binding to
   210  // a well-known name to avoid overlaps.
   211  func (s *DbusInterfaceSuite) TestInvalidBusNameEndsWithDashInt(c *C) {
   212  	var mockSnapYaml = `name: dbus-snap
   213  version: 1.0
   214  slots:
   215   dbus-slot:
   216    interface: dbus
   217    bus: session
   218    name: org.dbus-snap.session-12345
   219  `
   220  
   221  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   222  
   223  	slot := info.Slots["dbus-slot"]
   224  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), ErrorMatches, "DBus bus name must not end with -NUMBER")
   225  }
   226  
   227  func (s *DbusInterfaceSuite) TestSanitizeSlotSystem(c *C) {
   228  	var mockSnapYaml = `name: dbus-snap
   229  version: 1.0
   230  slots:
   231   dbus-slot:
   232    interface: dbus
   233    bus: system
   234    name: org.dbus-snap.system
   235  `
   236  
   237  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   238  
   239  	slot := info.Slots["dbus-slot"]
   240  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), IsNil)
   241  }
   242  
   243  func (s *DbusInterfaceSuite) TestSanitizeSlotSession(c *C) {
   244  	var mockSnapYaml = `name: dbus-snap
   245  version: 1.0
   246  slots:
   247   dbus-slot:
   248    interface: dbus
   249    bus: session
   250    name: org.dbus-snap.session
   251  `
   252  
   253  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   254  
   255  	slot := info.Slots["dbus-slot"]
   256  	c.Assert(interfaces.BeforePrepareSlot(s.iface, slot), IsNil)
   257  }
   258  
   259  func (s *DbusInterfaceSuite) TestSanitizePlugSystem(c *C) {
   260  	var mockSnapYaml = `name: dbus-snap
   261  version: 1.0
   262  plugs:
   263   dbus-plug:
   264    interface: dbus
   265    bus: system
   266    name: org.dbus-snap.system
   267  `
   268  
   269  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   270  
   271  	plug := info.Plugs["dbus-plug"]
   272  	c.Assert(interfaces.BeforePreparePlug(s.iface, plug), IsNil)
   273  }
   274  
   275  func (s *DbusInterfaceSuite) TestSanitizePlugSession(c *C) {
   276  	var mockSnapYaml = `name: dbus-snap
   277  version: 1.0
   278  plugs:
   279   dbus-plug:
   280    interface: dbus
   281    bus: session
   282    name: org.dbus-snap.session
   283  `
   284  
   285  	info := snaptest.MockInfo(c, mockSnapYaml, nil)
   286  
   287  	plug := info.Plugs["dbus-plug"]
   288  	c.Assert(interfaces.BeforePreparePlug(s.iface, plug), IsNil)
   289  }
   290  
   291  func (s *DbusInterfaceSuite) TestPermanentSlotAppArmorSession(c *C) {
   292  	apparmorSpec := &apparmor.Specification{}
   293  	err := apparmorSpec.AddPermanentSlot(s.iface, s.sessionSlotInfo)
   294  	c.Assert(err, IsNil)
   295  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-provider"})
   296  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-session-provider")
   297  
   298  	// verify abstraction rule
   299  	c.Check(snippet, testutil.Contains, "#include <abstractions/dbus-session-strict>\n")
   300  
   301  	// verify shared permanent slot policy
   302  	c.Check(snippet, testutil.Contains, "dbus (send)\n    bus=session\n    path=/org/freedesktop/DBus\n    interface=org.freedesktop.DBus\n    member=\"{Request,Release}Name\"\n    peer=(name=org.freedesktop.DBus, label=unconfined),\n")
   303  
   304  	// verify individual bind rules
   305  	c.Check(snippet, testutil.Contains, "dbus (bind)\n    bus=session\n    name=org.test-session-slot,\n")
   306  
   307  	// verify individual path in rules
   308  	c.Check(snippet, testutil.Contains, "path=\"/org/test-session-slot{,/**}\"\n")
   309  
   310  	// verify interface in rule
   311  	c.Check(snippet, testutil.Contains, "interface=\"org.test-session-slot{,.*}\"\n")
   312  }
   313  
   314  func (s *DbusInterfaceSuite) TestPermanentSlotAppArmorSessionNative(c *C) {
   315  	restore := release.MockOnClassic(false)
   316  	defer restore()
   317  
   318  	apparmorSpec := &apparmor.Specification{}
   319  	err := apparmorSpec.AddPermanentSlot(s.iface, s.sessionSlotInfo)
   320  	c.Assert(err, IsNil)
   321  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-provider"})
   322  
   323  	// verify classic rule not present
   324  	c.Check(apparmorSpec.SnippetForTag("snap.test-dbus.test-session-provider"), Not(testutil.Contains), "# allow us to respond to unconfined clients via \"org.test-session-slot{,.*}\"\n")
   325  }
   326  
   327  func (s *DbusInterfaceSuite) TestPermanentSlotAppArmorSessionClassic(c *C) {
   328  	restore := release.MockOnClassic(true)
   329  	defer restore()
   330  
   331  	apparmorSpec := &apparmor.Specification{}
   332  	err := apparmorSpec.AddPermanentSlot(s.iface, s.sessionSlotInfo)
   333  	c.Assert(err, IsNil)
   334  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-provider"})
   335  
   336  	// verify classic rule
   337  	c.Check(apparmorSpec.SnippetForTag("snap.test-dbus.test-session-provider"), testutil.Contains, "# allow us to respond to unconfined clients via \"org.test-session-slot{,.*}\"\n")
   338  }
   339  
   340  func (s *DbusInterfaceSuite) TestPermanentSlotAppArmorSystem(c *C) {
   341  	apparmorSpec := &apparmor.Specification{}
   342  	err := apparmorSpec.AddPermanentSlot(s.iface, s.systemSlotInfo)
   343  	c.Assert(err, IsNil)
   344  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-system-provider"})
   345  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-system-provider")
   346  
   347  	// verify abstraction rule
   348  	c.Check(snippet, testutil.Contains, "#include <abstractions/dbus-strict>\n")
   349  
   350  	// verify bind rule
   351  	c.Check(snippet, testutil.Contains, "dbus (bind)\n    bus=system\n    name=org.test-system-slot,\n")
   352  
   353  	// verify path in rule
   354  	c.Check(snippet, testutil.Contains, "path=\"/org/test-system-slot{,/**}\"\n")
   355  
   356  	// verify interface in rule
   357  	c.Check(snippet, testutil.Contains, "interface=\"org.test-system-slot{,.*}\"\n")
   358  
   359  	// verify dbus-daemon introspection rule
   360  	c.Check(snippet, testutil.Contains, "dbus (send)\n    bus=system\n    interface=org.freedesktop.DBus.Introspectable\n    member=Introspect\n    peer=(name=org.freedesktop.DBus, label=unconfined),\n")
   361  }
   362  
   363  func (s *DbusInterfaceSuite) TestPermanentSlotDBusSession(c *C) {
   364  	dbusSpec := &dbus.Specification{}
   365  	err := dbusSpec.AddPermanentSlot(s.iface, s.sessionSlotInfo)
   366  	c.Assert(err, IsNil)
   367  	c.Assert(dbusSpec.SecurityTags(), HasLen, 0)
   368  }
   369  
   370  func (s *DbusInterfaceSuite) TestPermanentSlotDBusSystem(c *C) {
   371  	dbusSpec := &dbus.Specification{}
   372  	err := dbusSpec.AddPermanentSlot(s.iface, s.systemSlotInfo)
   373  	c.Assert(err, IsNil)
   374  	c.Assert(dbusSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-system-provider"})
   375  	snippet := dbusSpec.SnippetForTag("snap.test-dbus.test-system-provider")
   376  	c.Check(snippet, testutil.Contains, "<policy user=\"root\">\n    <allow own=\"org.test-system-slot\"/>")
   377  	c.Check(snippet, testutil.Contains, "<policy context=\"default\">\n    <allow send_destination=\"org.test-system-slot\"/>")
   378  }
   379  
   380  func (s *DbusInterfaceSuite) TestPermanentSlotSecCompSystem(c *C) {
   381  	seccompSpec := &seccomp.Specification{}
   382  	err := seccompSpec.AddPermanentSlot(s.iface, s.systemSlotInfo)
   383  	c.Assert(err, IsNil)
   384  	c.Assert(seccompSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-system-provider"})
   385  	snippet := seccompSpec.SnippetForTag("snap.test-dbus.test-system-provider")
   386  	c.Check(snippet, testutil.Contains, "listen\naccept\naccept4\n")
   387  }
   388  
   389  func (s *DbusInterfaceSuite) TestPermanentSlotSecCompSession(c *C) {
   390  	seccompSpec := &seccomp.Specification{}
   391  	err := seccompSpec.AddPermanentSlot(s.iface, s.sessionSlotInfo)
   392  	c.Assert(err, IsNil)
   393  	c.Assert(seccompSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-provider"})
   394  	snippet := seccompSpec.SnippetForTag("snap.test-dbus.test-session-provider")
   395  	c.Check(snippet, testutil.Contains, "listen\naccept\naccept4\n")
   396  }
   397  
   398  func (s *DbusInterfaceSuite) TestConnectedSlotAppArmorSession(c *C) {
   399  	apparmorSpec := &apparmor.Specification{}
   400  	err := apparmorSpec.AddConnectedSlot(s.iface, s.connectedSessionPlug, s.connectedSessionSlot)
   401  	c.Assert(err, IsNil)
   402  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-consumer", "snap.test-dbus.test-session-provider", "snap.test-dbus.test-system-consumer", "snap.test-dbus.test-system-provider"})
   403  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-session-provider")
   404  
   405  	// verify introspectable rule
   406  	c.Check(snippet, testutil.Contains, "dbus (receive)\n    bus=session\n    interface=org.freedesktop.DBus.Introspectable\n    member=Introspect\n    peer=(label=\"snap.test-dbus.*\"),\n")
   407  
   408  	// verify bind rule not present
   409  	c.Check(snippet, Not(testutil.Contains), "dbus (bind)")
   410  
   411  	// verify individual path in rules
   412  	c.Check(snippet, testutil.Contains, "path=\"/org/test-session-connected{,/**}\"\n")
   413  
   414  	// verify interface in rule
   415  	c.Check(snippet, testutil.Contains, "interface=\"org.test-session-connected{,.*}\"\n")
   416  }
   417  
   418  func (s *DbusInterfaceSuite) TestConnectedSlotAppArmorSystem(c *C) {
   419  	apparmorSpec := &apparmor.Specification{}
   420  	err := apparmorSpec.AddConnectedSlot(s.iface, s.connectedSystemPlug, s.connectedSystemSlot)
   421  	c.Assert(err, IsNil)
   422  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-consumer", "snap.test-dbus.test-session-provider", "snap.test-dbus.test-system-consumer", "snap.test-dbus.test-system-provider"})
   423  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-session-provider")
   424  
   425  	// verify introspectable rule
   426  	c.Check(snippet, testutil.Contains, "dbus (receive)\n    bus=system\n    interface=org.freedesktop.DBus.Introspectable\n    member=Introspect\n    peer=(label=\"snap.test-dbus.*\"),\n")
   427  
   428  	// verify bind rule not present
   429  	c.Check(snippet, Not(testutil.Contains), "dbus (bind)")
   430  
   431  	// verify individual path in rules
   432  	c.Check(snippet, testutil.Contains, "path=\"/org/test-system-connected{,/**}\"\n")
   433  
   434  	// verify interface in rule
   435  	c.Check(snippet, testutil.Contains, "interface=\"org.test-system-connected{,.*}\"\n")
   436  }
   437  
   438  func (s *DbusInterfaceSuite) TestConnectedPlugAppArmorSession(c *C) {
   439  	apparmorSpec := &apparmor.Specification{}
   440  	err := apparmorSpec.AddConnectedPlug(s.iface, s.connectedSessionPlug, s.connectedSessionSlot)
   441  	c.Assert(err, IsNil)
   442  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-consumer", "snap.test-dbus.test-session-provider", "snap.test-dbus.test-system-consumer", "snap.test-dbus.test-system-provider"})
   443  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-session-consumer")
   444  
   445  	// verify introspectable rule
   446  	c.Check(string(snippet), testutil.Contains, "dbus (send)\n    bus=session\n    interface=org.freedesktop.DBus.Introspectable\n    member=Introspect\n    peer=(label=\"snap.test-dbus.*\"),\n")
   447  
   448  	// verify bind rule not present
   449  	c.Check(string(snippet), Not(testutil.Contains), "dbus (bind)")
   450  
   451  	// verify well-known connection in rule
   452  	c.Check(string(snippet), testutil.Contains, "peer=(name=org.test-session-connected, label=")
   453  
   454  	// verify interface in rule
   455  
   456  	// verify individual path in rules
   457  	c.Check(string(snippet), testutil.Contains, "path=\"/org/test-session-connected{,/**}\"\n")
   458  
   459  	// verify interface in rule
   460  	c.Check(string(snippet), testutil.Contains, "interface=\"org.test-session-connected{,.*}\"\n")
   461  }
   462  
   463  func (s *DbusInterfaceSuite) TestConnectedPlugAppArmorSystem(c *C) {
   464  	apparmorSpec := &apparmor.Specification{}
   465  	err := apparmorSpec.AddConnectedPlug(s.iface, s.connectedSystemPlug, s.connectedSystemSlot)
   466  	c.Assert(err, IsNil)
   467  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.test-dbus.test-session-consumer", "snap.test-dbus.test-session-provider", "snap.test-dbus.test-system-consumer", "snap.test-dbus.test-system-provider"})
   468  	snippet := apparmorSpec.SnippetForTag("snap.test-dbus.test-session-consumer")
   469  
   470  	// verify introspectable rule
   471  	c.Check(string(snippet), testutil.Contains, "dbus (send)\n    bus=system\n    interface=org.freedesktop.DBus.Introspectable\n    member=Introspect\n    peer=(label=\"snap.test-dbus.*\"),\n")
   472  
   473  	// verify bind rule not present
   474  	c.Check(string(snippet), Not(testutil.Contains), "dbus (bind)")
   475  
   476  	// verify well-known connection in rule
   477  	c.Check(string(snippet), testutil.Contains, "peer=(name=org.test-system-connected, label=")
   478  
   479  	// verify individual path in rules
   480  	c.Check(string(snippet), testutil.Contains, "path=\"/org/test-system-connected{,/**}\"\n")
   481  
   482  	// verify interface in rule
   483  	c.Check(string(snippet), testutil.Contains, "interface=\"org.test-system-connected{,.*}\"\n")
   484  }
   485  
   486  func (s *DbusInterfaceSuite) TestConnectionFirst(c *C) {
   487  	const plugYaml = `name: plugger
   488  version: 1.0
   489  plugs:
   490   this:
   491    interface: dbus
   492    bus: session
   493    name: org.slotter.session
   494  apps:
   495   app:
   496    command: foo
   497  `
   498  	const slotYaml = `name: slotter
   499  version: 1.0
   500  slots:
   501   this:
   502    interface: dbus
   503    bus: session
   504    name: org.slotter.session
   505   that:
   506    interface: dbus
   507    bus: system
   508    name: org.slotter.other-session
   509  `
   510  
   511  	plugInfo := snaptest.MockInfo(c, plugYaml, nil)
   512  	matchingPlug := interfaces.NewConnectedPlug(plugInfo.Plugs["this"], nil, nil)
   513  
   514  	slotInfo := snaptest.MockInfo(c, slotYaml, nil)
   515  	matchingSlot := interfaces.NewConnectedSlot(slotInfo.Slots["this"], nil, nil)
   516  	nonmatchingSlot := interfaces.NewConnectedSlot(slotInfo.Slots["that"], nil, nil)
   517  
   518  	apparmorSpec := &apparmor.Specification{}
   519  	err := apparmorSpec.AddConnectedPlug(s.iface, matchingPlug, matchingSlot)
   520  	c.Assert(err, IsNil)
   521  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.plugger.app"})
   522  	snippet := apparmorSpec.SnippetForTag("snap.plugger.app")
   523  
   524  	c.Check(snippet, testutil.Contains, "org.slotter.session")
   525  	c.Check(snippet, testutil.Contains, "bus=session")
   526  	c.Check(snippet, Not(testutil.Contains), "org.slotter.other-session")
   527  	c.Check(snippet, Not(testutil.Contains), "bus=system")
   528  
   529  	apparmorSpec = &apparmor.Specification{}
   530  	err = apparmorSpec.AddConnectedPlug(s.iface, matchingPlug, nonmatchingSlot)
   531  	c.Assert(err, IsNil)
   532  	c.Assert(apparmorSpec.SecurityTags(), HasLen, 0)
   533  }
   534  
   535  func (s *DbusInterfaceSuite) TestConnectionSecond(c *C) {
   536  	const plugYaml = `name: plugger
   537  version: 1.0
   538  plugs:
   539   that:
   540    interface: dbus
   541    bus: system
   542    name: org.slotter.other-session
   543  apps:
   544   app:
   545    command: foo
   546  `
   547  	const slotYaml = `name: slotter
   548  version: 1.0
   549  slots:
   550   this:
   551    interface: dbus
   552    bus: session
   553    name: org.slotter.session
   554   that:
   555    interface: dbus
   556    bus: system
   557    name: org.slotter.other-session
   558  `
   559  
   560  	plugInfo := snaptest.MockInfo(c, plugYaml, nil)
   561  	matchingPlug := interfaces.NewConnectedPlug(plugInfo.Plugs["that"], nil, nil)
   562  
   563  	slotInfo := snaptest.MockInfo(c, slotYaml, nil)
   564  	matchingSlot := interfaces.NewConnectedSlot(slotInfo.Slots["that"], nil, nil)
   565  	nonmatchingSlot := interfaces.NewConnectedSlot(slotInfo.Slots["this"], nil, nil)
   566  
   567  	apparmorSpec := &apparmor.Specification{}
   568  	err := apparmorSpec.AddConnectedPlug(s.iface, matchingPlug, matchingSlot)
   569  	c.Assert(err, IsNil)
   570  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.plugger.app"})
   571  	snippet := apparmorSpec.SnippetForTag("snap.plugger.app")
   572  
   573  	c.Check(snippet, testutil.Contains, "org.slotter.other-session")
   574  	c.Check(snippet, testutil.Contains, "bus=system")
   575  	c.Check(snippet, Not(testutil.Contains), "org.slotter.session")
   576  	c.Check(snippet, Not(testutil.Contains), "bus=session")
   577  
   578  	apparmorSpec = &apparmor.Specification{}
   579  	err = apparmorSpec.AddConnectedPlug(s.iface, matchingPlug, nonmatchingSlot)
   580  	c.Assert(err, IsNil)
   581  	c.Assert(apparmorSpec.SecurityTags(), HasLen, 0)
   582  }
   583  
   584  func (s *DbusInterfaceSuite) TestConnectionBoth(c *C) {
   585  	const plugYaml = `name: plugger
   586  version: 1.0
   587  plugs:
   588   that:
   589    interface: dbus
   590    bus: system
   591    name: org.slotter.other-session
   592   this:
   593    interface: dbus
   594    bus: session
   595    name: org.slotter.session
   596  apps:
   597   app:
   598    command: foo
   599  `
   600  	const slotYaml = `name: slotter
   601  version: 1.0
   602  slots:
   603   this:
   604    interface: dbus
   605    bus: session
   606    name: org.slotter.session
   607   that:
   608    interface: dbus
   609    bus: system
   610    name: org.slotter.other-session
   611  `
   612  
   613  	plugInfo := snaptest.MockInfo(c, plugYaml, nil)
   614  	matchingPlug1 := interfaces.NewConnectedPlug(plugInfo.Plugs["this"], nil, nil)
   615  	matchingPlug2 := interfaces.NewConnectedPlug(plugInfo.Plugs["that"], nil, nil)
   616  
   617  	slotInfo := snaptest.MockInfo(c, slotYaml, nil)
   618  	matchingSlot1 := interfaces.NewConnectedSlot(slotInfo.Slots["this"], nil, nil)
   619  	matchingSlot2 := interfaces.NewConnectedSlot(slotInfo.Slots["that"], nil, nil)
   620  
   621  	apparmorSpec := &apparmor.Specification{}
   622  	err := apparmorSpec.AddConnectedPlug(s.iface, matchingPlug1, matchingSlot1)
   623  	c.Assert(err, IsNil)
   624  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.plugger.app"})
   625  	snippet := apparmorSpec.SnippetForTag("snap.plugger.app")
   626  	c.Check(snippet, testutil.Contains, "org.slotter.session")
   627  	c.Check(snippet, testutil.Contains, "bus=session")
   628  
   629  	apparmorSpec = &apparmor.Specification{}
   630  	err = apparmorSpec.AddConnectedPlug(s.iface, matchingPlug2, matchingSlot2)
   631  	c.Assert(err, IsNil)
   632  	c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.plugger.app"})
   633  	snippet = apparmorSpec.SnippetForTag("snap.plugger.app")
   634  	c.Check(snippet, testutil.Contains, "org.slotter.other-session")
   635  	c.Check(snippet, testutil.Contains, "bus=system")
   636  }
   637  
   638  func (s *DbusInterfaceSuite) TestConnectionMismatchBus(c *C) {
   639  	const plugYaml = `name: plugger
   640  version: 1.0
   641  plugs:
   642   this:
   643    interface: dbus
   644    bus: session
   645    name: org.slotter.session
   646  `
   647  	const slotYaml = `name: slotter
   648  version: 1.0
   649  slots:
   650   this:
   651    interface: dbus
   652    bus: system
   653    name: org.slotter.session
   654  `
   655  
   656  	plugInfo := snaptest.MockInfo(c, plugYaml, nil)
   657  	plug := interfaces.NewConnectedPlug(plugInfo.Plugs["this"], nil, nil)
   658  
   659  	slotInfo := snaptest.MockInfo(c, slotYaml, nil)
   660  	slot := interfaces.NewConnectedSlot(slotInfo.Slots["this"], nil, nil)
   661  
   662  	apparmorSpec := &apparmor.Specification{}
   663  	err := apparmorSpec.AddConnectedPlug(s.iface, plug, slot)
   664  	c.Assert(err, IsNil)
   665  	c.Assert(apparmorSpec.SecurityTags(), HasLen, 0)
   666  }
   667  
   668  func (s *DbusInterfaceSuite) TestConnectionMismatchName(c *C) {
   669  	const plugYaml = `name: plugger
   670  version: 1.0
   671  plugs:
   672   this:
   673    interface: dbus
   674    bus: session
   675    name: org.slotter.session
   676  `
   677  	const slotYaml = `name: slotter
   678  version: 1.0
   679  slots:
   680   this:
   681    interface: dbus
   682    bus: session
   683    name: org.slotter.nomatch
   684  `
   685  
   686  	plugInfo := snaptest.MockInfo(c, plugYaml, nil)
   687  	plug := interfaces.NewConnectedPlug(plugInfo.Plugs["this"], nil, nil)
   688  
   689  	slotInfo := snaptest.MockInfo(c, slotYaml, nil)
   690  	slot := interfaces.NewConnectedSlot(slotInfo.Slots["this"], nil, nil)
   691  
   692  	apparmorSpec := &apparmor.Specification{}
   693  	err := apparmorSpec.AddConnectedPlug(s.iface, plug, slot)
   694  	c.Assert(err, IsNil)
   695  	c.Assert(apparmorSpec.SecurityTags(), HasLen, 0)
   696  }
   697  
   698  func (s *DbusInterfaceSuite) TestInterfaces(c *C) {
   699  	c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
   700  }