interfaces/builtin: support time and date settings via 'org.freedesktop.timedate1 #1832

Merged
merged 21 commits into from Sep 28, 2016
Jump to file or symbol
Failed to load files and symbols.
+295 −1
Split
View
@@ -463,9 +463,15 @@ trusted apps.
* Auto-Connect: no
+### time-control
+
+Can set system time and date and query systemd-timedated for time information.
+
+* Auto-Connect: no
+
### timeserver-control
-Can manage timeservers directly separate from ``config core``.
+Can manage timeservers via systemd-timedated and directly separate from ``config core``
* Auto-Connect: no
@@ -75,6 +75,7 @@ var allInterfaces = []interfaces.Interface{
NewBluetoothControlInterface(),
NewKernelModuleControlInterface(),
NewFuseSupportInterface(),
+ NewTimeControlInterface(),
NewLibvirtInterface(),
}
@@ -76,4 +76,5 @@ func (s *AllSuite) TestInterfaces(c *C) {
c.Check(all, DeepContains, builtin.NewCameraInterface())
c.Check(all, DeepContains, builtin.NewKernelModuleControlInterface())
c.Check(all, DeepContains, builtin.NewFuseSupportInterface())
+ c.Check(all, DeepContains, builtin.NewTimeControlInterface())
}
@@ -0,0 +1,84 @@
+// -*- 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 "github.com/snapcore/snapd/interfaces"
+
+const timeControlConnectedPlugAppArmor = `
+# Description: Can set time and date via systemd' timedated D-Bus interface.
+# Can read all properties of /org/freedesktop/timedate1 D-Bus object; see
+# https://www.freedesktop.org/wiki/Software/systemd/timedated/
+# Usage: reserved
+
+#include <abstractions/dbus-strict>
+
+# Introspection of org.freedesktop.timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Introspectable
+ member=Introspect
+ peer=(label=unconfined),
+
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.timedate1
+ member="Set{Time,LocalRTC}"
+ peer=(label=unconfined),
+
+# Read all properties from timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=Get{,All}
+ peer=(label=unconfined),
+
+# Receive timedate1 property changed events
+dbus (receive)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=PropertiesChanged
+ peer=(label=unconfined),
+`
+const timeControlConnectedPlugSecComp = `
+# dbus
+connect
+getsockname
+recvmsg
+recvfrom
+send
+sendto
+sendmsg
+socket
+`
+
+// NewTimeDateControlInterface returns a new "time-control" interface.
+func NewTimeControlInterface() interfaces.Interface {
+ return &commonInterface{
+ name: "time-control",
+ connectedPlugAppArmor: timeControlConnectedPlugAppArmor,
+ connectedPlugSecComp: timeControlConnectedPlugSecComp,
+ reservedForOS: true,
+ autoConnect: false,
+ }
+}
@@ -0,0 +1,94 @@
+// -*- 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_test
+
+import (
+ . "gopkg.in/check.v1"
+
+ "github.com/snapcore/snapd/interfaces"
+ "github.com/snapcore/snapd/interfaces/builtin"
+ "github.com/snapcore/snapd/snap"
+)
+
+type TimeControlTestInterfaceSuite struct {
+ iface interfaces.Interface
+ slot *interfaces.Slot
+ plug *interfaces.Plug
+}
+
+var _ = Suite(&TimeControlTestInterfaceSuite{
+ iface: builtin.NewTimeControlInterface(),
+ slot: &interfaces.Slot{
+ SlotInfo: &snap.SlotInfo{
+ Snap: &snap.Info{SuggestedName: "ubuntu-core", Type: snap.TypeOS},
+ Name: "time-control",
+ Interface: "time-control",
+ },
+ },
+ plug: &interfaces.Plug{
+ PlugInfo: &snap.PlugInfo{
+ Snap: &snap.Info{SuggestedName: "other"},
+ Name: "time-control",
+ Interface: "time-control",
+ },
+ },
+})
+
+func (s *TimeControlTestInterfaceSuite) TestName(c *C) {
+ c.Assert(s.iface.Name(), Equals, "time-control")
+}
+
+func (s *TimeControlTestInterfaceSuite) TestSanitizeSlot(c *C) {
+ err := s.iface.SanitizeSlot(s.slot)
+ c.Assert(err, IsNil)
+ err = s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{
+ Snap: &snap.Info{SuggestedName: "some-snap"},
+ Name: "time-control",
+ Interface: "time-control",
+ }})
+ c.Assert(err, ErrorMatches, "time-control slots are reserved for the operating system snap")
+}
+
+func (s *TimeControlTestInterfaceSuite) TestSanitizePlug(c *C) {
+ err := s.iface.SanitizePlug(s.plug)
+ c.Assert(err, IsNil)
+}
+
+func (s *TimeControlTestInterfaceSuite) TestSanitizeIncorrectInterface(c *C) {
+ c.Assert(func() { s.iface.SanitizeSlot(&interfaces.Slot{SlotInfo: &snap.SlotInfo{Interface: "other"}}) },
+ PanicMatches, `slot is not of interface "time-control"`)
+ c.Assert(func() { s.iface.SanitizePlug(&interfaces.Plug{PlugInfo: &snap.PlugInfo{Interface: "other"}}) },
+ PanicMatches, `plug is not of interface "time-control"`)
+}
+
+func (s *TimeControlTestInterfaceSuite) TestUsedSecuritySystems(c *C) {
+ // connected plugs have a non-nil security snippet for apparmor
+ snippet, err := s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityAppArmor)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
+ // connected plugs have a non-nil security snippet for seccomp
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecuritySecComp)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
+}
+
+func (s *TimeControlTestInterfaceSuite) TestAutoConnect(c *C) {
+ c.Check(s.iface.AutoConnect(), Equals, false)
+}
@@ -26,18 +26,66 @@ import (
// http://bazaar.launchpad.net/~ubuntu-security/ubuntu-core-security/trunk/view/head:/data/apparmor/policygroups/ubuntu-core/16.04/timeserver-control
const timeserverControlConnectedPlugAppArmor = `
# Description: Can manage timeservers directly separate from config ubuntu-core.
+# Can enable system clock NTP synchronization via timedated D-Bus interface,
+# Can read all properties of /org/freedesktop/timedate1 D-Bus object; see
+# https://www.freedesktop.org/wiki/Software/systemd/timedated/
# Usage: reserved
+#include <abstractions/dbus-strict>
+
# Won't work until LP: #1504657 is fixed. Requires reboot until timesyncd
# notices the change or systemd restarts it.
/etc/systemd/timesyncd.conf rw,
+
+# Introspection of org.freedesktop.timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Introspectable
+ member=Introspect
+ peer=(label=unconfined),
+
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.timedate1
+ member="SetNTP"
+ peer=(label=unconfined),
+
+# Read all properties from timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=Get{,All}
+ peer=(label=unconfined),
+
+# Receive timedate1 property changed events
+dbus (receive)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=PropertiesChanged
+ peer=(label=unconfined),
+`
+const timeserverControlConnectedPlugSecComp = `
+# dbus
+connect
+getsockname
+recvmsg
+recvfrom
+send
+sendto
+sendmsg
+socket
`
// NewTimeserverControlInterface returns a new "timeserver-control" interface.
func NewTimeserverControlInterface() interfaces.Interface {
return &commonInterface{
name: "timeserver-control",
connectedPlugAppArmor: timeserverControlConnectedPlugAppArmor,
+ connectedPlugSecComp: timeserverControlConnectedPlugSecComp,
reservedForOS: true,
}
}
@@ -83,6 +83,11 @@ func (s *TimeserverControlInterfaceSuite) TestUsedSecuritySystems(c *C) {
snippet, err := s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityAppArmor)
c.Assert(err, IsNil)
c.Assert(snippet, Not(IsNil))
+
+ // connected plugs have a non-nil security snippet for seccomp
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecuritySecComp)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
}
func (s *TimeserverControlInterfaceSuite) TestAutoConnect(c *C) {
@@ -26,18 +26,67 @@ import (
// http://bazaar.launchpad.net/~ubuntu-security/ubuntu-core-security/trunk/view/head:/data/apparmor/policygroups/ubuntu-core/16.04/timezone-control
const timezoneControlConnectedPlugAppArmor = `
# Description: Can manage timezones directly separate from 'config ubuntu-core'.
+# Can change timezone via timedated D-Bus interface,
+# Can read all properties of /org/freedesktop/timedate1 D-Bus object, see:
+# https://www.freedesktop.org/wiki/Software/systemd/timedated/
# Usage: reserved
+#include <abstractions/dbus-strict>
+
/usr/share/zoneinfo/ r,
/usr/share/zoneinfo/** r,
/etc/{,writable/}timezone rw,
+
+# Introspection of org.freedesktop.timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Introspectable
+ member=Introspect
+ peer=(label=unconfined),
+
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.timedate1
+ member="SetTimezone"
+ peer=(label=unconfined),
+
+# Read all properties from timedate1
+dbus (send)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=Get{,All}
+ peer=(label=unconfined),
+
+# Receive timedate1 property changed events
+dbus (receive)
+ bus=system
+ path=/org/freedesktop/timedate1
+ interface=org.freedesktop.DBus.Properties
+ member=PropertiesChanged
+ peer=(label=unconfined),
+`
+
+const timezoneControlConnectedPlugSecComp = `
+# dbus
+connect
+getsockname
+recvmsg
+recvfrom
+send
+sendto
+sendmsg
+socket
`
// NewTimezoneControlInterface returns a new "timezone-control" interface.
func NewTimezoneControlInterface() interfaces.Interface {
return &commonInterface{
name: "timezone-control",
connectedPlugAppArmor: timezoneControlConnectedPlugAppArmor,
+ connectedPlugSecComp: timezoneControlConnectedPlugSecComp,
reservedForOS: true,
}
}
@@ -83,6 +83,11 @@ func (s *TimezoneControlInterfaceSuite) TestUsedSecuritySystems(c *C) {
snippet, err := s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityAppArmor)
c.Assert(err, IsNil)
c.Assert(snippet, Not(IsNil))
+
+ // connected plugs have a non-nil security snippet for seccomp
+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecuritySecComp)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
}
func (s *TimezoneControlInterfaceSuite) TestAutoConnect(c *C) {
View
@@ -50,6 +50,7 @@ var implicitSlots = []string{
"snapd-control",
"system-observe",
"system-trace",
+ "time-control",
"timeserver-control",
"timezone-control",
"tpm",