github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/interfaces/builtin/utils_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 "fmt" 24 25 . "gopkg.in/check.v1" 26 27 "github.com/snapcore/snapd/interfaces" 28 "github.com/snapcore/snapd/interfaces/builtin" 29 "github.com/snapcore/snapd/interfaces/ifacetest" 30 "github.com/snapcore/snapd/snap" 31 "github.com/snapcore/snapd/snap/snaptest" 32 ) 33 34 type utilsSuite struct { 35 iface interfaces.Interface 36 slotOS *snap.SlotInfo 37 slotApp *snap.SlotInfo 38 slotSnapd *snap.SlotInfo 39 slotGadget *snap.SlotInfo 40 conSlotOS *interfaces.ConnectedSlot 41 conSlotSnapd *interfaces.ConnectedSlot 42 conSlotApp *interfaces.ConnectedSlot 43 } 44 45 var _ = Suite(&utilsSuite{ 46 iface: &ifacetest.TestInterface{InterfaceName: "iface"}, 47 slotOS: &snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeOS}}, 48 slotApp: &snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeApp}}, 49 slotSnapd: &snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeSnapd, SuggestedName: "snapd"}}, 50 slotGadget: &snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeGadget}}, 51 conSlotOS: interfaces.NewConnectedSlot(&snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeOS}}, nil, nil), 52 conSlotSnapd: interfaces.NewConnectedSlot(&snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeSnapd}}, nil, nil), 53 conSlotApp: interfaces.NewConnectedSlot(&snap.SlotInfo{Snap: &snap.Info{SnapType: snap.TypeApp}}, nil, nil), 54 }) 55 56 func (s *utilsSuite) TestIsSlotSystemSlot(c *C) { 57 c.Assert(builtin.ImplicitSystemPermanentSlot(s.slotApp), Equals, false) 58 c.Assert(builtin.ImplicitSystemPermanentSlot(s.slotOS), Equals, true) 59 c.Assert(builtin.ImplicitSystemPermanentSlot(s.slotSnapd), Equals, true) 60 } 61 62 func (s *utilsSuite) TestImplicitSystemConnectedSlot(c *C) { 63 c.Assert(builtin.ImplicitSystemConnectedSlot(s.conSlotApp), Equals, false) 64 c.Assert(builtin.ImplicitSystemConnectedSlot(s.conSlotOS), Equals, true) 65 c.Assert(builtin.ImplicitSystemConnectedSlot(s.conSlotSnapd), Equals, true) 66 } 67 68 const yaml = `name: test-snap 69 version: 1 70 plugs: 71 x11: 72 slots: 73 opengl: 74 apps: 75 app1: 76 command: bin/test1 77 plugs: [home] 78 slots: [unity8] 79 app2: 80 command: bin/test2 81 plugs: [home] 82 hooks: 83 install: 84 plugs: [network,network-manager] 85 post-refresh: 86 plugs: [network,network-manager] 87 ` 88 89 func (s *utilsSuite) TestLabelExpr(c *C) { 90 info := snaptest.MockInfo(c, yaml, nil) 91 92 // all apps and all hooks 93 label := builtin.LabelExpr(info.Apps, info.Hooks, info) 94 c.Check(label, Equals, `"snap.test-snap.*"`) 95 96 // all apps, no hooks 97 label = builtin.LabelExpr(info.Apps, nil, info) 98 c.Check(label, Equals, `"snap.test-snap.{app1,app2}"`) 99 100 // one app, no hooks 101 label = builtin.LabelExpr(map[string]*snap.AppInfo{"app1": info.Apps["app1"]}, nil, info) 102 c.Check(label, Equals, `"snap.test-snap.app1"`) 103 104 // no apps, one hook 105 label = builtin.LabelExpr(nil, map[string]*snap.HookInfo{"install": info.Hooks["install"]}, info) 106 c.Check(label, Equals, `"snap.test-snap.hook.install"`) 107 108 // one app, all hooks 109 label = builtin.LabelExpr(map[string]*snap.AppInfo{"app1": info.Apps["app1"]}, info.Hooks, info) 110 c.Check(label, Equals, `"snap.test-snap.{app1,hook.install,hook.post-refresh}"`) 111 112 // only hooks 113 label = builtin.LabelExpr(nil, info.Hooks, info) 114 c.Check(label, Equals, `"snap.test-snap.{hook.install,hook.post-refresh}"`) 115 116 // nothing 117 label = builtin.LabelExpr(nil, nil, info) 118 c.Check(label, Equals, `"snap.test-snap."`) 119 } 120 121 func (s *utilsSuite) TestPlugLabelExpr(c *C) { 122 connectedPlug, _ := MockConnectedPlug(c, yaml, nil, "network") 123 label := builtin.PlugAppLabelExpr(connectedPlug) 124 c.Check(label, Equals, `"snap.test-snap.{hook.install,hook.post-refresh}"`) 125 126 connectedPlug, _ = MockConnectedPlug(c, yaml, nil, "home") 127 label = builtin.PlugAppLabelExpr(connectedPlug) 128 c.Check(label, Equals, `"snap.test-snap.{app1,app2}"`) 129 130 connectedPlug, _ = MockConnectedPlug(c, yaml, nil, "x11") 131 label = builtin.PlugAppLabelExpr(connectedPlug) 132 c.Check(label, Equals, `"snap.test-snap.*"`) 133 } 134 135 func (s *utilsSuite) TestSlotLabelExpr(c *C) { 136 connectedSlot, _ := MockConnectedSlot(c, yaml, nil, "unity8") 137 label := builtin.SlotAppLabelExpr(connectedSlot) 138 c.Check(label, Equals, `"snap.test-snap.app1"`) 139 140 connectedSlot, _ = MockConnectedSlot(c, yaml, nil, "opengl") 141 label = builtin.SlotAppLabelExpr(connectedSlot) 142 c.Check(label, Equals, `"snap.test-snap.*"`) 143 } 144 145 func (s *utilsSuite) TestAareExclusivePatterns(c *C) { 146 res := builtin.AareExclusivePatterns("foo-bar") 147 c.Check(res, DeepEquals, []string{ 148 "[^f]*", 149 "f[^o]*", 150 "fo[^o]*", 151 "foo[^-]*", 152 "foo-[^b]*", 153 "foo-b[^a]*", 154 "foo-ba[^r]*", 155 }) 156 } 157 158 func (s *utilsSuite) TestAareExclusivePatternsInstance(c *C) { 159 res := builtin.AareExclusivePatterns("foo-bar+baz") 160 c.Check(res, DeepEquals, []string{ 161 "[^f]*", 162 "f[^o]*", 163 "fo[^o]*", 164 "foo[^-]*", 165 "foo-[^b]*", 166 "foo-b[^a]*", 167 "foo-ba[^r]*", 168 "foo-bar[^+]*", 169 "foo-bar+[^b]*", 170 "foo-bar+b[^a]*", 171 "foo-bar+ba[^z]*", 172 }) 173 } 174 175 func (s *utilsSuite) TestAareExclusivePatternsInvalid(c *C) { 176 bad := []string{ 177 // AARE in name (man apparmor.d: AARE = ?*[]{}^) 178 "bad{", 179 "ba}d", 180 "b[ad", 181 "]bad", 182 "b^d", 183 "b*d", 184 "b?d", 185 "bad{+good", 186 "ba}d+good", 187 "b[ad+good", 188 "]bad+good", 189 "b^d+good", 190 "b*d+good", 191 "b?d+good", 192 // AARE in instance (man apparmor.d: AARE = ?*[]{}^) 193 "good+bad{", 194 "good+ba}d", 195 "good+b[ad", 196 "good+]bad", 197 "good+b^d", 198 "good+b*d", 199 "good+b?d", 200 // various other unexpected in name 201 "+good", 202 "/bad", 203 "bad,", 204 ".bad.", 205 "ba'd", 206 "b\"ad", 207 "=bad", 208 "b\\0d", 209 "b\ad", 210 "(bad", 211 "bad)", 212 "b<ad", 213 "b>ad", 214 "bad!", 215 "b#d", 216 ":bad", 217 "b@d", 218 "@{BAD}", 219 "b**d", 220 "bad -> evil", 221 "b a d", 222 // various other unexpected in instance 223 "good+", 224 "good+/bad", 225 "good+bad,", 226 "good+.bad.", 227 "good+ba'd", 228 "good+b\"ad", 229 "good+=bad", 230 "good+b\\0d", 231 "good+b\ad", 232 "good+(bad", 233 "good+bad)", 234 "good+b<ad", 235 "good+b>ad", 236 "good+bad!", 237 "good+b#d", 238 "good+:bad", 239 "good+b@d", 240 "good+@{BAD}", 241 "good+b**d", 242 "good+bad -> evil", 243 } 244 245 for _, s := range bad { 246 res := builtin.AareExclusivePatterns(s) 247 c.Check(res, IsNil) 248 } 249 } 250 251 func (s *utilsSuite) TestGetDesktopFileRules(c *C) { 252 res := builtin.GetDesktopFileRules("foo-bar") 253 c.Check(res, DeepEquals, []string{ 254 "# Support applications which use the unity messaging menu, xdg-mime, etc", 255 "# This leaks the names of snaps with desktop files", 256 "/var/lib/snapd/desktop/applications/ r,", 257 "# Allowing reading only our desktop files (required by (at least) the unity", 258 "# messaging menu).", 259 "# parallel-installs: this leaks read access to desktop files owned by keyed", 260 "# instances of @{SNAP_NAME} to @{SNAP_NAME} snap", 261 "/var/lib/snapd/desktop/applications/@{SNAP_INSTANCE_DESKTOP}_*.desktop r,", 262 "# Explicitly deny access to other snap's desktop files", 263 "deny /var/lib/snapd/desktop/applications/@{SNAP_INSTANCE_DESKTOP}[^_.]*.desktop r,", 264 "deny /var/lib/snapd/desktop/applications/[^f]* r,", 265 "deny /var/lib/snapd/desktop/applications/f[^o]* r,", 266 "deny /var/lib/snapd/desktop/applications/fo[^o]* r,", 267 "deny /var/lib/snapd/desktop/applications/foo[^-]* r,", 268 "deny /var/lib/snapd/desktop/applications/foo-[^b]* r,", 269 "deny /var/lib/snapd/desktop/applications/foo-b[^a]* r,", 270 "deny /var/lib/snapd/desktop/applications/foo-ba[^r]* r,", 271 }) 272 } 273 274 func MockPlug(c *C, yaml string, si *snap.SideInfo, plugName string) *snap.PlugInfo { 275 return builtin.MockPlug(c, yaml, si, plugName) 276 } 277 278 func MockSlot(c *C, yaml string, si *snap.SideInfo, slotName string) *snap.SlotInfo { 279 return builtin.MockSlot(c, yaml, si, slotName) 280 } 281 282 func MockConnectedPlug(c *C, yaml string, si *snap.SideInfo, plugName string) (*interfaces.ConnectedPlug, *snap.PlugInfo) { 283 info := snaptest.MockInfo(c, yaml, si) 284 if plugInfo, ok := info.Plugs[plugName]; ok { 285 return interfaces.NewConnectedPlug(plugInfo, nil, nil), plugInfo 286 } 287 panic(fmt.Sprintf("cannot find plug %q in snap %q", plugName, info.InstanceName())) 288 } 289 290 func MockConnectedSlot(c *C, yaml string, si *snap.SideInfo, slotName string) (*interfaces.ConnectedSlot, *snap.SlotInfo) { 291 info := snaptest.MockInfo(c, yaml, si) 292 if slotInfo, ok := info.Slots[slotName]; ok { 293 return interfaces.NewConnectedSlot(slotInfo, nil, nil), slotInfo 294 } 295 panic(fmt.Sprintf("cannot find slot %q in snap %q", slotName, info.InstanceName())) 296 } 297 298 func MockHotplugSlot(c *C, yaml string, si *snap.SideInfo, hotplugKey snap.HotplugKey, ifaceName, slotName string, staticAttrs map[string]interface{}) *snap.SlotInfo { 299 info := snaptest.MockInfo(c, yaml, si) 300 if _, ok := info.Slots[slotName]; ok { 301 panic(fmt.Sprintf("slot %q already present in the snap yaml", slotName)) 302 } 303 return &snap.SlotInfo{ 304 Snap: info, 305 Name: slotName, 306 Attrs: staticAttrs, 307 HotplugKey: hotplugKey, 308 } 309 }