github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/builtin/greengrass_support_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 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 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/seccomp"
    29  	"github.com/snapcore/snapd/interfaces/udev"
    30  	"github.com/snapcore/snapd/release"
    31  	"github.com/snapcore/snapd/snap"
    32  	"github.com/snapcore/snapd/testutil"
    33  )
    34  
    35  type GreengrassSupportInterfaceSuite struct {
    36  	iface         interfaces.Interface
    37  	slotInfo      *snap.SlotInfo
    38  	slot          *interfaces.ConnectedSlot
    39  	plugInfo      *snap.PlugInfo
    40  	plug          *interfaces.ConnectedPlug
    41  	extraSlotInfo *snap.SlotInfo
    42  	extraSlot     *interfaces.ConnectedSlot
    43  	extraPlugInfo *snap.PlugInfo
    44  	extraPlug     *interfaces.ConnectedPlug
    45  
    46  	// for the process flavor
    47  	processModePlugInfo *snap.PlugInfo
    48  	processModePlug     *interfaces.ConnectedPlug
    49  
    50  	// for the container flavor
    51  	containerModePlugInfo *snap.PlugInfo
    52  	containerModePlug     *interfaces.ConnectedPlug
    53  }
    54  
    55  const coreSlotYaml = `name: core
    56  version: 0
    57  type: os
    58  slots:
    59    network-control:
    60    greengrass-support:
    61  `
    62  const ggMockPlugSnapInfoYaml = `name: other
    63  version: 1.0
    64  plugs:
    65   greengrass-support-legacy-container:
    66    interface: greengrass-support
    67    flavor: legacy-container
    68  apps:
    69   app2:
    70    command: foo
    71    plugs: [greengrass-support-legacy-container, greengrass-support, network-control]
    72  `
    73  
    74  const ggProcessModeMockPlugSnapInfoYaml = `name: other
    75  version: 1.0
    76  plugs:
    77   greengrass-support-no-container:
    78    interface: greengrass-support
    79    flavor: no-container
    80  apps:
    81   app2:
    82    command: foo
    83    plugs: [greengrass-support-no-container, network-control]
    84  `
    85  
    86  var _ = Suite(&GreengrassSupportInterfaceSuite{
    87  	iface: builtin.MustInterface("greengrass-support"),
    88  })
    89  
    90  func (s *GreengrassSupportInterfaceSuite) SetUpTest(c *C) {
    91  	s.plug, s.plugInfo = MockConnectedPlug(c, ggMockPlugSnapInfoYaml, nil, "greengrass-support")
    92  	s.slot, s.slotInfo = MockConnectedSlot(c, coreSlotYaml, nil, "greengrass-support")
    93  	s.extraPlug, s.extraPlugInfo = MockConnectedPlug(c, ggMockPlugSnapInfoYaml, nil, "network-control")
    94  	s.extraSlot, s.extraSlotInfo = MockConnectedSlot(c, coreSlotYaml, nil, "network-control")
    95  
    96  	s.processModePlug, s.processModePlugInfo = MockConnectedPlug(c, ggProcessModeMockPlugSnapInfoYaml, nil, "greengrass-support-no-container")
    97  
    98  	s.containerModePlug, s.containerModePlugInfo = MockConnectedPlug(c, ggMockPlugSnapInfoYaml, nil, "greengrass-support-legacy-container")
    99  
   100  }
   101  
   102  func (s *GreengrassSupportInterfaceSuite) TestName(c *C) {
   103  	c.Assert(s.iface.Name(), Equals, "greengrass-support")
   104  }
   105  
   106  func (s *GreengrassSupportInterfaceSuite) TestSanitizeSlot(c *C) {
   107  	c.Assert(interfaces.BeforePrepareSlot(s.iface, s.slotInfo), IsNil)
   108  }
   109  
   110  func (s *GreengrassSupportInterfaceSuite) TestSanitizePlug(c *C) {
   111  	c.Assert(interfaces.BeforePreparePlug(s.iface, s.plugInfo), IsNil)
   112  }
   113  
   114  func (s *GreengrassSupportInterfaceSuite) TestAppArmorSpec(c *C) {
   115  
   116  	for _, plug := range []*interfaces.ConnectedPlug{
   117  		s.plug,
   118  		s.containerModePlug,
   119  	} {
   120  		spec := &apparmor.Specification{}
   121  		c.Assert(spec.AddConnectedPlug(s.iface, plug, s.slot), IsNil)
   122  		c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.other.app2"})
   123  		c.Check(spec.SnippetForTag("snap.other.app2"), testutil.Contains, "mount options=(rw, bind) /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** ,\n")
   124  		c.Check(spec.UsesPtraceTrace(), Equals, true)
   125  	}
   126  }
   127  
   128  func (s *GreengrassSupportInterfaceSuite) TestProcessModeAppArmorSpec(c *C) {
   129  	spec := &apparmor.Specification{}
   130  	c.Assert(spec.AddConnectedPlug(s.iface, s.processModePlug, s.slot), IsNil)
   131  	c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.other.app2"})
   132  	c.Check(spec.SnippetForTag("snap.other.app2"), testutil.Contains, "/ ix,\n")
   133  	c.Check(spec.SnippetForTag("snap.other.app2"), Not(testutil.Contains), "mount options=(rw, bind) /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** -> /var/snap/{@{SNAP_NAME},@{SNAP_INSTANCE_NAME}}/** ,\n")
   134  	c.Check(spec.UsesPtraceTrace(), Equals, false)
   135  }
   136  
   137  func (s *GreengrassSupportInterfaceSuite) TestSecCompSpec(c *C) {
   138  	for _, plug := range []*interfaces.ConnectedPlug{
   139  		s.plug,
   140  		s.containerModePlug,
   141  	} {
   142  		spec := &seccomp.Specification{}
   143  		c.Assert(spec.AddConnectedPlug(s.iface, plug, s.slot), IsNil)
   144  		c.Check(spec.SnippetForTag("snap.other.app2"), testutil.Contains, "# for overlayfs and various bind mounts\nmount\numount2\npivot_root\n")
   145  	}
   146  }
   147  
   148  func (s *GreengrassSupportInterfaceSuite) TestProcessModeSecCompSpec(c *C) {
   149  	spec := &seccomp.Specification{}
   150  	c.Assert(spec.AddConnectedPlug(s.iface, s.processModePlug, s.slot), IsNil)
   151  	c.Check(spec.SnippetForTag("snap.other.app2"), Not(testutil.Contains), "# for overlayfs and various bind mounts\nmount\numount2\npivot_root\n")
   152  }
   153  
   154  func (s *GreengrassSupportInterfaceSuite) TestUdevTaggingDisablingRemoveLast(c *C) {
   155  	for _, plug := range []*interfaces.ConnectedPlug{
   156  		s.plug,
   157  		s.containerModePlug,
   158  	} {
   159  		// make a spec with network-control that has udev tagging
   160  		spec := &udev.Specification{}
   161  		c.Assert(spec.AddConnectedPlug(builtin.MustInterface("network-control"), s.extraPlug, s.extraSlot), IsNil)
   162  		c.Assert(spec.Snippets(), HasLen, 3)
   163  
   164  		// connect the greengrass-support interface and ensure the spec is now nil
   165  		c.Assert(spec.AddConnectedPlug(s.iface, plug, s.slot), IsNil)
   166  		c.Check(spec.Snippets(), HasLen, 0)
   167  	}
   168  }
   169  
   170  func (s *GreengrassSupportInterfaceSuite) TestProcessModeUdevTaggingWorks(c *C) {
   171  	spec := &udev.Specification{}
   172  	// connect the greengrass-support interface and ensure the spec is nil
   173  	c.Assert(spec.AddConnectedPlug(s.iface, s.processModePlug, s.slot), IsNil)
   174  	c.Check(spec.Snippets(), HasLen, 0)
   175  
   176  	// add network-control and now the spec is not nil
   177  	c.Assert(spec.AddConnectedPlug(builtin.MustInterface("network-control"), s.extraPlug, s.extraSlot), IsNil)
   178  	c.Assert(spec.Snippets(), Not(HasLen), 0)
   179  }
   180  
   181  func (s *GreengrassSupportInterfaceSuite) TestUdevTaggingDisablingRemoveFirst(c *C) {
   182  	for _, plug := range []*interfaces.ConnectedPlug{
   183  		s.plug,
   184  		s.containerModePlug,
   185  	} {
   186  		spec := &udev.Specification{}
   187  		// connect the greengrass-support interface and ensure the spec is nil
   188  		c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil)
   189  		c.Check(spec.Snippets(), HasLen, 0)
   190  
   191  		// add network-control and ensure the spec is still nil
   192  		c.Assert(spec.AddConnectedPlug(builtin.MustInterface("network-control"), plug, s.extraSlot), IsNil)
   193  		c.Assert(spec.Snippets(), HasLen, 0)
   194  	}
   195  }
   196  
   197  func (s *GreengrassSupportInterfaceSuite) TestInterfaces(c *C) {
   198  	c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface)
   199  }
   200  
   201  func (s *GreengrassSupportInterfaceSuite) TestPermanentSlotAppArmorSessionNative(c *C) {
   202  	restore := release.MockOnClassic(false)
   203  	defer restore()
   204  
   205  	for _, plug := range []*interfaces.ConnectedPlug{
   206  		s.plug,
   207  		s.containerModePlug,
   208  	} {
   209  		apparmorSpec := &apparmor.Specification{}
   210  		err := apparmorSpec.AddConnectedPlug(s.iface, plug, s.slot)
   211  		c.Assert(err, IsNil)
   212  		c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.other.app2"})
   213  
   214  		// verify core rule present
   215  		c.Check(apparmorSpec.SnippetForTag("snap.other.app2"), testutil.Contains, "# /system-data/var/snap/greengrass/x1/ggc-writable/packages/1.7.0/var/worker/overlays/$UUID/upper/\n")
   216  	}
   217  }
   218  
   219  func (s *GreengrassSupportInterfaceSuite) TestPermanentSlotAppArmorSessionClassic(c *C) {
   220  	restore := release.MockOnClassic(true)
   221  	defer restore()
   222  
   223  	for _, plug := range []*interfaces.ConnectedPlug{
   224  		s.plug,
   225  		s.containerModePlug,
   226  	} {
   227  		apparmorSpec := &apparmor.Specification{}
   228  		err := apparmorSpec.AddConnectedPlug(s.iface, plug, s.slot)
   229  		c.Assert(err, IsNil)
   230  		c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.other.app2"})
   231  
   232  		// verify core rule not present
   233  		c.Check(apparmorSpec.SnippetForTag("snap.other.app2"), Not(testutil.Contains), "# /system-data/var/snap/greengrass/x1/ggc-writable/packages/1.7.0/var/worker/overlays/$UUID/upper/\n")
   234  	}
   235  }
   236  
   237  func (s *GreengrassSupportInterfaceSuite) TestPermanentPlugServiceSnippets(c *C) {
   238  	for _, t := range []struct {
   239  		plug *snap.PlugInfo
   240  		exp  []string
   241  	}{
   242  		{s.plugInfo, []string{"Delegate=true"}},
   243  		{s.containerModePlugInfo, []string{"Delegate=true"}},
   244  		// the process-mode or no-container plug doesn't get Delegate=true
   245  		{s.processModePlugInfo, nil},
   246  	} {
   247  		snips, err := interfaces.PermanentPlugServiceSnippets(s.iface, t.plug)
   248  		c.Assert(err, IsNil)
   249  		c.Check(snips, DeepEquals, t.exp)
   250  	}
   251  }