gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/udisks2_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 builtin_test 21 22 import ( 23 "fmt" 24 25 . "gopkg.in/check.v1" 26 27 "gitee.com/mysnapcore/mysnapd/dirs" 28 "gitee.com/mysnapcore/mysnapd/interfaces" 29 "gitee.com/mysnapcore/mysnapd/interfaces/apparmor" 30 "gitee.com/mysnapcore/mysnapd/interfaces/builtin" 31 "gitee.com/mysnapcore/mysnapd/interfaces/dbus" 32 "gitee.com/mysnapcore/mysnapd/interfaces/seccomp" 33 "gitee.com/mysnapcore/mysnapd/interfaces/udev" 34 "gitee.com/mysnapcore/mysnapd/release" 35 "gitee.com/mysnapcore/mysnapd/snap" 36 "gitee.com/mysnapcore/mysnapd/testutil" 37 ) 38 39 type UDisks2InterfaceSuite struct { 40 iface interfaces.Interface 41 slotInfo *snap.SlotInfo 42 slot *interfaces.ConnectedSlot 43 classicSlotInfo *snap.SlotInfo 44 classicSlot *interfaces.ConnectedSlot 45 plugInfo *snap.PlugInfo 46 plug *interfaces.ConnectedPlug 47 } 48 49 var _ = Suite(&UDisks2InterfaceSuite{ 50 iface: builtin.MustInterface("udisks2"), 51 }) 52 53 const udisks2ConsumerYaml = `name: consumer 54 version: 0 55 apps: 56 app: 57 plugs: [udisks2] 58 ` 59 60 const udisks2ConsumerTwoAppsYaml = `name: consumer 61 version: 0 62 apps: 63 app1: 64 plugs: [udisks2] 65 app2: 66 plugs: [udisks2] 67 ` 68 69 const udisks2ConsumerThreeAppsYaml = `name: consumer 70 version: 0 71 apps: 72 app1: 73 plugs: [udisks2] 74 app2: 75 plugs: [udisks2] 76 app3: 77 ` 78 79 const udisks2ProducerYaml = `name: producer 80 version: 0 81 apps: 82 app: 83 slots: [udisks2] 84 ` 85 86 const udisks2ProducerTwoAppsYaml = `name: producer 87 version: 0 88 apps: 89 app1: 90 slots: [udisks2] 91 app2: 92 slots: [udisks2] 93 ` 94 95 const udisks2ProducerThreeAppsYaml = `name: producer 96 version: 0 97 apps: 98 app1: 99 slots: [udisks2] 100 app2: 101 app3: 102 slots: [udisks2] 103 ` 104 105 const udisks2ClassicYaml = `name: core 106 version: 0 107 type: os 108 slots: 109 udisks2: 110 interface: udisks2 111 ` 112 113 func (s *UDisks2InterfaceSuite) SetUpTest(c *C) { 114 s.plug, s.plugInfo = MockConnectedPlug(c, udisks2ConsumerYaml, nil, "udisks2") 115 s.slot, s.slotInfo = MockConnectedSlot(c, udisks2ProducerYaml, nil, "udisks2") 116 s.classicSlot, s.classicSlotInfo = MockConnectedSlot(c, udisks2ClassicYaml, nil, "udisks2") 117 } 118 119 func (s *UDisks2InterfaceSuite) TestName(c *C) { 120 c.Assert(s.iface.Name(), Equals, "udisks2") 121 } 122 123 func (s *UDisks2InterfaceSuite) TestSanitizeSlot(c *C) { 124 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.slotInfo), IsNil) 125 c.Assert(interfaces.BeforePrepareSlot(s.iface, s.classicSlotInfo), IsNil) 126 } 127 128 func (s *UDisks2InterfaceSuite) TestAppArmorSpec(c *C) { 129 // on a core system with udisks2 slot coming from a regular app snap. 130 restore := release.MockOnClassic(false) 131 defer restore() 132 133 // The label uses short form when exactly one app is bound to the udisks2 slot 134 spec := &apparmor.Specification{} 135 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) 136 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) 137 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `peer=(label="snap.producer.app"),`) 138 139 // The label glob when all apps are bound to the udisks2 slot 140 slot, _ := MockConnectedSlot(c, udisks2ProducerTwoAppsYaml, nil, "udisks2") 141 spec = &apparmor.Specification{} 142 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, slot), IsNil) 143 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) 144 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `peer=(label="snap.producer.*"),`) 145 146 // The label uses alternation when some, but not all, apps is bound to the udisks2 slot 147 slot, _ = MockConnectedSlot(c, udisks2ProducerThreeAppsYaml, nil, "udisks2") 148 spec = &apparmor.Specification{} 149 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, slot), IsNil) 150 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) 151 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `peer=(label="snap.producer.{app1,app3}"),`) 152 153 // The label uses short form when exactly one app is bound to the udisks2 plug 154 spec = &apparmor.Specification{} 155 c.Assert(spec.AddConnectedSlot(s.iface, s.plug, s.slot), IsNil) 156 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.producer.app"}) 157 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `peer=(label="snap.consumer.app"),`) 158 159 // The label glob when all apps are bound to the udisks2 plug 160 plug, _ := MockConnectedPlug(c, udisks2ConsumerTwoAppsYaml, nil, "udisks2") 161 spec = &apparmor.Specification{} 162 c.Assert(spec.AddConnectedSlot(s.iface, plug, s.slot), IsNil) 163 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.producer.app"}) 164 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `peer=(label="snap.consumer.*"),`) 165 166 // The label uses alternation when some, but not all, apps is bound to the udisks2 plug 167 plug, _ = MockConnectedPlug(c, udisks2ConsumerThreeAppsYaml, nil, "udisks2") 168 spec = &apparmor.Specification{} 169 c.Assert(spec.AddConnectedSlot(s.iface, plug, s.slot), IsNil) 170 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.producer.app"}) 171 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `peer=(label="snap.consumer.{app1,app2}"),`) 172 173 // permanent slot have a non-nil security snippet for apparmor 174 spec = &apparmor.Specification{} 175 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) 176 c.Assert(spec.AddPermanentSlot(s.iface, s.slotInfo), IsNil) 177 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app", "snap.producer.app"}) 178 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `peer=(label="snap.producer.app"),`) 179 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `peer=(label=unconfined),`) 180 } 181 182 func (s *UDisks2InterfaceSuite) TestAppArmorSpecOnClassic(c *C) { 183 // on a core system with udisks2 slot coming from a the classic distro. 184 restore := release.MockOnClassic(true) 185 defer restore() 186 187 // connected plug to core slot 188 spec := &apparmor.Specification{} 189 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.classicSlot), IsNil) 190 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) 191 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `peer=(label=unconfined),`) 192 193 // connected classic slot to plug 194 spec = &apparmor.Specification{} 195 c.Assert(spec.AddConnectedSlot(s.iface, s.plug, s.classicSlot), IsNil) 196 c.Assert(spec.SecurityTags(), HasLen, 0) 197 198 // permanent classic slot 199 spec = &apparmor.Specification{} 200 c.Assert(spec.AddPermanentSlot(s.iface, s.classicSlotInfo), IsNil) 201 c.Assert(spec.SecurityTags(), HasLen, 0) 202 } 203 204 func (s *UDisks2InterfaceSuite) TestDBusSpec(c *C) { 205 // on a core system with udisks2 slot coming from a regular app snap. 206 restore := release.MockOnClassic(false) 207 defer restore() 208 209 spec := &dbus.Specification{} 210 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) 211 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) 212 c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `<policy context="default">`) 213 214 spec = &dbus.Specification{} 215 c.Assert(spec.AddPermanentSlot(s.iface, s.slotInfo), IsNil) 216 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.producer.app"}) 217 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `<policy user="root">`) 218 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, `send_interface="org.freedesktop.DBus.Introspectable"`) 219 } 220 221 func (s *UDisks2InterfaceSuite) TestDBusSpecOnClassic(c *C) { 222 // on a core system with udisks2 slot coming from a the classic distro. 223 restore := release.MockOnClassic(true) 224 defer restore() 225 226 // connected plug to core slot 227 spec := &dbus.Specification{} 228 c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.classicSlot), IsNil) 229 c.Assert(spec.SecurityTags(), HasLen, 0) 230 c.Assert(spec.AddPermanentSlot(s.iface, s.classicSlotInfo), IsNil) 231 c.Assert(spec.SecurityTags(), HasLen, 0) 232 } 233 234 func (s *UDisks2InterfaceSuite) TestUDevSpec(c *C) { 235 // on a core system with udisks2 slot coming from a regular app snap. 236 restore := release.MockOnClassic(false) 237 defer restore() 238 239 spec := &udev.Specification{} 240 c.Assert(spec.AddPermanentSlot(s.iface, s.slotInfo), IsNil) 241 c.Assert(spec.Snippets(), HasLen, 4) 242 c.Assert(spec.Snippets()[0], testutil.Contains, `LABEL="udisks_probe_end"`) 243 c.Assert(spec.Snippets(), testutil.Contains, `# udisks2 244 SUBSYSTEM=="block", TAG+="snap_producer_app"`) 245 c.Assert(spec.Snippets(), testutil.Contains, `# udisks2 246 SUBSYSTEM=="usb", TAG+="snap_producer_app"`) 247 c.Assert(spec.Snippets(), testutil.Contains, fmt.Sprintf(`TAG=="snap_producer_app", RUN+="%v/snap-device-helper $env{ACTION} snap_producer_app $devpath $major:$minor"`, dirs.DistroLibExecDir)) 248 } 249 250 func (s *UDisks2InterfaceSuite) TestUDevSpecOnClassic(c *C) { 251 // on a core system with udisks2 slot coming from a the classic distro. 252 restore := release.MockOnClassic(true) 253 defer restore() 254 255 spec := &udev.Specification{} 256 c.Assert(spec.AddPermanentSlot(s.iface, s.classicSlotInfo), IsNil) 257 c.Assert(spec.Snippets(), HasLen, 0) 258 } 259 260 func (s *UDisks2InterfaceSuite) TestSecCompSpec(c *C) { 261 // on a core system with udisks2 slot coming from a regular app snap. 262 restore := release.MockOnClassic(false) 263 defer restore() 264 265 spec := &seccomp.Specification{} 266 c.Assert(spec.AddPermanentSlot(s.iface, s.slotInfo), IsNil) 267 c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.producer.app"}) 268 c.Assert(spec.SnippetForTag("snap.producer.app"), testutil.Contains, "mount\n") 269 } 270 271 func (s *UDisks2InterfaceSuite) TestSecCompSpecOnClassic(c *C) { 272 // on a core system with udisks2 slot coming from a the classic distro. 273 restore := release.MockOnClassic(true) 274 defer restore() 275 276 spec := &seccomp.Specification{} 277 c.Assert(spec.AddPermanentSlot(s.iface, s.classicSlotInfo), IsNil) 278 c.Assert(spec.SecurityTags(), HasLen, 0) 279 } 280 281 func (s *UDisks2InterfaceSuite) TestStaticInfo(c *C) { 282 si := interfaces.StaticInfoOf(s.iface) 283 c.Assert(si.ImplicitOnCore, Equals, false) 284 c.Assert(si.ImplicitOnClassic, Equals, true) 285 c.Assert(si.Summary, Equals, `allows operating as or interacting with the UDisks2 service`) 286 c.Assert(si.BaseDeclarationSlots, testutil.Contains, "udisks2") 287 } 288 289 func (s *UDisks2InterfaceSuite) TestAutoConnect(c *C) { 290 c.Assert(s.iface.AutoConnect(s.plugInfo, s.slotInfo), Equals, true) 291 } 292 293 func (s *UDisks2InterfaceSuite) TestInterfaces(c *C) { 294 c.Assert(builtin.Interfaces(), testutil.DeepContains, s.iface) 295 }