Permalink
Browse files

interfaces: implement dbus-access interface

The dbus-access interface allows apps within the same snap to
communicate over dbus. It can be used in conjunction of the
dbus-name interface to setup up dbus service which don't need
to be accesible from another snap in the system.

Connecting the interface on between plugs and slots which are
not part of the same snap is prohibited and will cause the
interface connection to fail.

Signed-off-by: Simon Fels <simon.fels@canonical.com>
  • Loading branch information...
1 parent 7d4a725 commit 0489b6f23b190d817975247d460990f67e0c4d5c Simon Fels committed May 13, 2016
Showing with 115 additions and 0 deletions.
  1. +1 −0 interfaces/builtin/all.go
  2. +112 −0 interfaces/builtin/dbus_access.go
  3. +2 −0 interfaces/core.go
@@ -26,6 +26,7 @@ import (
var allInterfaces = []interfaces.Interface{
&BoolFileInterface{},
&BluezInterface{},
+ &DBusAccessInterface{},
&DBusNameInterface{},
&NetworkManagerInterface{},
NewFirewallControlInterface(),
@@ -0,0 +1,112 @@
+// -*- Mode: Go; indent-tabs-mode: t -*-
+
+/*
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package builtin
+
+import (
+ "fmt"
+ "bytes"
+
+ "github.com/ubuntu-core/snappy/interfaces"
+)
+
@zyga

zyga May 13, 2016

Could you please add docstrings to each new interface that clearly indicates how it is expected to be used. This will also help in the review process. Ideally this should go to docs/interfaces.md.

@morphis

morphis May 13, 2016

Owner

Sure. This is still work-in-progress and wanted to get a first feedback round from you guys before polishing this up. Before it ends up as PR I will add all those things.

+var dbusAccessPermanentSlotAppArmor = []byte(`
+#include <abstractions/dbus-strict>
+
+# Allow binding the service to the requested connection name
+dbus (receive, send)
+ bus=system
+ path=###SLOT_PATH_NAME###
+ peer=(label=###SLOT_SECURITY_TAGS##),
+`)
+
+type DBusAccessInterface struct{}
+
+func (iface *DBusAccessInterface) Name() string {
+ return "dbus-access"
+}
+
+func (iface *DBusAccessInterface) PermanentPlugSnippet(plug *interfaces.Plug, securitySystem interfaces.SecuritySystem) ([]byte, error) {
+ switch securitySystem {
+ case interfaces.SecurityAppArmor:
+ return nil, nil
+ case interfaces.SecurityDBus, interfaces.SecuritySecComp, interfaces.SecurityUDev:
+ return nil, nil
+ default:
+ return nil, interfaces.ErrUnknownSecurity
+ }
+}
+
+
+func (iface *DBusAccessInterface) ConnectedPlugSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
+ if plug.Snap.Name() != slot.Snap.Name() {
@zyga

zyga May 13, 2016

So the point of this interface is to let a snap use dbus for internal communication?

@morphis

morphis May 17, 2016

Owner

Exactly. I am thinking about things like this example:

We have now aethercast which implements WiFi Display support. We can do a snap for it which ships aethercast itself and a indicator-aethercast implementation. For both services to communicate which each other within the snap we don't want any specific interface inside snappy but rather something which allows this just internally where we're using things like the unity7 interface to use external connection points.

+ return nil, interfaces.ErrNotAllowed
+ }
+ switch securitySystem {
+ case interfaces.SecurityDBus:
+ return nil, nil
+ case interfaces.SecurityAppArmor:
+ return nil, nil
+ case interfaces.SecuritySecComp:
+ return dbusNameConnectedPlugSecComp, nil
+ case interfaces.SecurityUDev:
+ return nil, nil
+ default:
+ return nil, interfaces.ErrUnknownSecurity
+ }
+}
+
+func (iface *DBusAccessInterface) PermanentSlotSnippet(slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
+ path, _ := slot.Attrs["path"].(string)
+
+ switch securitySystem {
+ case interfaces.SecurityAppArmor:
+ snippet := bytes.Replace(dbusAccessPermanentSlotAppArmor, []byte("###SLOT_PATH_NAME###"), []byte(path), -1)
+ snippet = bytes.Replace(snippet, []byte("###SLOT_SECURITY_TAGS###"), slotAppLabelExpr(slot), -1)
+ return nil, nil
+ case interfaces.SecurityDBus, interfaces.SecuritySecComp, interfaces.SecurityUDev:
+ return nil, nil
+ default:
+ return nil, interfaces.ErrUnknownSecurity
+ }
+}
+
+func (iface *DBusAccessInterface) ConnectedSlotSnippet(plug *interfaces.Plug, slot *interfaces.Slot, securitySystem interfaces.SecuritySystem) ([]byte, error) {
+ switch securitySystem {
+ case interfaces.SecurityDBus, interfaces.SecurityAppArmor, interfaces.SecuritySecComp, interfaces.SecurityUDev:
+ return nil, nil
+ default:
+ return nil, interfaces.ErrUnknownSecurity
+ }
+}
+
+func (iface *DBusAccessInterface) SanitizePlug(plug *interfaces.Plug) error {
+ if iface.Name() != plug.Interface {
+ panic(fmt.Sprintf("plug is not of interface %q", iface))
+ }
+ return nil
+}
+
+func (iface *DBusAccessInterface) SanitizeSlot(slot *interfaces.Slot) error {
+ return nil
+}
+
+func (iface *DBusAccessInterface) AutoConnect() bool {
+ return false
+}
View
@@ -157,6 +157,8 @@ const (
var (
// ErrUnknownSecurity is reported when a interface is unable to deal with a given security system.
ErrUnknownSecurity = errors.New("unknown security system")
+ // ErrNotAllowed is reported when a slot/plug connection on the interface is not allowed
+ ErrNotAllowed = errors.New("interface connection is not allowed")
)
// Regular expression describing correct identifiers.

0 comments on commit 0489b6f

Please sign in to comment.