github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/systemd/backend_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 systemd_test 21 22 import ( 23 "os" 24 "path/filepath" 25 26 . "gopkg.in/check.v1" 27 28 "github.com/snapcore/snapd/dirs" 29 "github.com/snapcore/snapd/interfaces" 30 "github.com/snapcore/snapd/interfaces/ifacetest" 31 "github.com/snapcore/snapd/interfaces/systemd" 32 "github.com/snapcore/snapd/snap" 33 34 sysd "github.com/snapcore/snapd/systemd" 35 ) 36 37 type backendSuite struct { 38 ifacetest.BackendSuite 39 40 systemctlArgs [][]string 41 systemctlRestorer func() 42 } 43 44 var _ = Suite(&backendSuite{}) 45 46 var testedConfinementOpts = []interfaces.ConfinementOptions{ 47 {}, 48 {DevMode: true}, 49 {JailMode: true}, 50 {Classic: true}, 51 } 52 53 func (s *backendSuite) SetUpTest(c *C) { 54 s.Backend = &systemd.Backend{} 55 s.BackendSuite.SetUpTest(c) 56 c.Assert(s.Repo.AddBackend(s.Backend), IsNil) 57 s.systemctlRestorer = sysd.MockSystemctl(func(args ...string) ([]byte, error) { 58 s.systemctlArgs = append(s.systemctlArgs, append([]string{"systemctl"}, args...)) 59 return []byte("ActiveState=inactive"), nil 60 }) 61 } 62 63 func (s *backendSuite) TearDownTest(c *C) { 64 s.systemctlRestorer() 65 s.BackendSuite.TearDownTest(c) 66 } 67 68 func (s *backendSuite) TestName(c *C) { 69 c.Check(s.Backend.Name(), Equals, interfaces.SecuritySystemd) 70 } 71 72 func (s *backendSuite) TestInstallingSnapWritesStartsServices(c *C) { 73 var sysdLog [][]string 74 75 r := sysd.MockSystemctl(func(cmd ...string) ([]byte, error) { 76 sysdLog = append(sysdLog, cmd) 77 if cmd[0] == "show" { 78 return []byte("ActiveState=inactive\n"), nil 79 } 80 return []byte{}, nil 81 }) 82 defer r() 83 84 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 85 return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 86 } 87 s.InstallSnap(c, interfaces.ConfinementOptions{}, "", ifacetest.SambaYamlV1, 1) 88 service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service") 89 // the service file was created 90 _, err := os.Stat(service) 91 c.Check(err, IsNil) 92 // the service was also started (whee) 93 c.Check(sysdLog, DeepEquals, [][]string{ 94 {"daemon-reload"}, 95 {"enable", "snap.samba.interface.foo.service"}, 96 {"stop", "snap.samba.interface.foo.service"}, 97 {"show", "--property=ActiveState", "snap.samba.interface.foo.service"}, 98 {"start", "snap.samba.interface.foo.service"}, 99 }) 100 } 101 102 func (s *backendSuite) TestRemovingSnapRemovesAndStopsServices(c *C) { 103 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 104 return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 105 } 106 for _, opts := range testedConfinementOpts { 107 snapInfo := s.InstallSnap(c, opts, "", ifacetest.SambaYamlV1, 1) 108 s.systemctlArgs = nil 109 s.RemoveSnap(c, snapInfo) 110 service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service") 111 // the service file was removed 112 _, err := os.Stat(service) 113 c.Check(os.IsNotExist(err), Equals, true) 114 // the service was stopped 115 c.Check(s.systemctlArgs, DeepEquals, [][]string{ 116 {"systemctl", "disable", "snap.samba.interface.foo.service"}, 117 {"systemctl", "stop", "snap.samba.interface.foo.service"}, 118 {"systemctl", "show", "--property=ActiveState", "snap.samba.interface.foo.service"}, 119 {"systemctl", "daemon-reload"}, 120 }) 121 } 122 } 123 124 func (s *backendSuite) TestSettingUpSecurityWithFewerServices(c *C) { 125 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 126 err := spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 127 if err != nil { 128 return err 129 } 130 return spec.AddService("snap.samba.interface.bar.service", &systemd.Service{ExecStart: "/bin/false"}) 131 } 132 snapInfo := s.InstallSnap(c, interfaces.ConfinementOptions{}, "", ifacetest.SambaYamlV1, 1) 133 s.systemctlArgs = nil 134 serviceFoo := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service") 135 serviceBar := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.bar.service") 136 // the services were created 137 _, err := os.Stat(serviceFoo) 138 c.Check(err, IsNil) 139 _, err = os.Stat(serviceBar) 140 c.Check(err, IsNil) 141 142 // Change what the interface returns to simulate some useful change 143 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 144 return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 145 } 146 // Update over to the same snap to regenerate security 147 s.UpdateSnap(c, snapInfo, interfaces.ConfinementOptions{}, ifacetest.SambaYamlV1, 0) 148 // The bar service should have been stopped 149 c.Check(s.systemctlArgs, DeepEquals, [][]string{ 150 {"systemctl", "disable", "snap.samba.interface.bar.service"}, 151 {"systemctl", "stop", "snap.samba.interface.bar.service"}, 152 {"systemctl", "show", "--property=ActiveState", "snap.samba.interface.bar.service"}, 153 {"systemctl", "daemon-reload"}, 154 }) 155 } 156 157 func (s *backendSuite) TestSandboxFeatures(c *C) { 158 c.Assert(s.Backend.SandboxFeatures(), IsNil) 159 } 160 161 func (s *backendSuite) TestInstallingSnapWhenPreseeding(c *C) { 162 s.Backend = &systemd.Backend{} 163 opts := &interfaces.SecurityBackendOptions{Preseed: true} 164 s.Backend.Initialize(opts) 165 166 var sysdLog [][]string 167 r := sysd.MockSystemctl(func(cmd ...string) ([]byte, error) { 168 sysdLog = append(sysdLog, cmd) 169 return []byte{}, nil 170 }) 171 defer r() 172 173 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 174 return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 175 } 176 s.InstallSnap(c, interfaces.ConfinementOptions{}, "", ifacetest.SambaYamlV1, 1) 177 service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service") 178 // the service file was created 179 _, err := os.Stat(service) 180 c.Check(err, IsNil) 181 // the service was enabled but not started 182 c.Check(sysdLog, DeepEquals, [][]string{ 183 {"--root", dirs.GlobalRootDir, "enable", "snap.samba.interface.foo.service"}, 184 }) 185 } 186 187 // not a viable scenario, but tested for completness 188 func (s *backendSuite) TestRemovingSnapWhenPreseeding(c *C) { 189 s.Backend = &systemd.Backend{} 190 opts := &interfaces.SecurityBackendOptions{Preseed: true} 191 s.Backend.Initialize(opts) 192 193 s.Iface.SystemdPermanentSlotCallback = func(spec *systemd.Specification, slot *snap.SlotInfo) error { 194 return spec.AddService("snap.samba.interface.foo.service", &systemd.Service{ExecStart: "/bin/true"}) 195 } 196 for _, opts := range testedConfinementOpts { 197 snapInfo := s.InstallSnap(c, opts, "", ifacetest.SambaYamlV1, 1) 198 s.systemctlArgs = nil 199 s.RemoveSnap(c, snapInfo) 200 service := filepath.Join(dirs.SnapServicesDir, "snap.samba.interface.foo.service") 201 // the service file was removed 202 _, err := os.Stat(service) 203 c.Check(os.IsNotExist(err), Equals, true) 204 // the service was disabled (but no other systemctl calls) 205 c.Check(s.systemctlArgs, DeepEquals, [][]string{ 206 {"systemctl", "--root", dirs.GlobalRootDir, "disable", "snap.samba.interface.foo.service"}, 207 }) 208 } 209 }