Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Already on GitHub? Sign in to your account
add ssh-keys, ssh-public-keys, gpg-keys and gpg-public keys interfaces #4100
Merged
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
38120fd
add ssh-keys interface
jdstrand 0b80bd2
add ssh-public-keys interface
jdstrand 260568f
add gpg-keys interface
jdstrand 9afb3f5
add gpg-public-keys interface
jdstrand 5767458
update gpg{,_public}_keys for /usr/share/gnupg/options.skel
jdstrand 35295e0
update ssh-keys to allow reading /etc/ssh/config
jdstrand 2606753
allow updating random-seed in gpg-keys
jdstrand 520350c
add gpg binaries to gpg keys and ssh binaries to ssh keys interfaces
jdstrand bda3931
Merge remote-tracking branch 'upstream/master' into ssh-gpg-keys-inte…
jdstrand a2fef9c
add gpg and ssh interfaces to test-snapd-policy-app-consumer
jdstrand 9c17c9d
update tests for modern practices
jdstrand 407ed6d
add comment on why random_seed is needed and also add 'k'
jdstrand a65717d
add gpgv/gpg1, add comments, deny trustdb writes, remove lock files
jdstrand 595b022
Merge remote-tracking branch 'upstream/master' into ssh-gpg-keys-inte…
jdstrand 3af0f57
update tests for recent PRs
jdstrand
Jump to file or symbol
Failed to load files and symbols.
| @@ -0,0 +1,59 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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 | ||
| + | ||
| +const gpgKeysSummary = `allows reading gpg user configuration and keys` | ||
| + | ||
| +const gpgKeysBaseDeclarationSlots = ` | ||
| + gpg-keys: | ||
| + allow-installation: | ||
| + slot-snap-type: | ||
| + - core | ||
| + deny-auto-connection: true | ||
| +` | ||
| + | ||
| +const gpgKeysConnectedPlugAppArmor = ` | ||
| +# Description: Can read gpg user configuration as well as public and private | ||
| +# keys. | ||
| + | ||
| +# Allow gpg encrypt, decrypt, list-keys, verify, sign, etc | ||
| +/usr/bin/gpg{,1,2,v} ixr, | ||
| +/usr/share/gnupg/options.skel r, | ||
| + | ||
| +owner @{HOME}/.gnupg/{,**} r, | ||
| +# gpg sometimes updates the trustdb to decide whether or not to update the | ||
| +# trustdb. For now, silence the denial since no other policy references this | ||
| +deny @{HOME}/.gnupg/trustdb.gpg w, | ||
| + | ||
| +# 'wk' is required for gpg encrypt and sign | ||
| +owner @{HOME}/.gnupg/random_seed wk, | ||
| +` | ||
| + | ||
| +func init() { | ||
| + registerIface(&commonInterface{ | ||
| + name: "gpg-keys", | ||
| + summary: gpgKeysSummary, | ||
| + implicitOnCore: true, | ||
| + implicitOnClassic: true, | ||
| + baseDeclarationSlots: gpgKeysBaseDeclarationSlots, | ||
| + connectedPlugAppArmor: gpgKeysConnectedPlugAppArmor, | ||
| + reservedForOS: true, | ||
| + }) | ||
| +} |
| @@ -0,0 +1,102 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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/apparmor" | ||
| + "github.com/snapcore/snapd/interfaces/builtin" | ||
| + "github.com/snapcore/snapd/snap" | ||
| + "github.com/snapcore/snapd/testutil" | ||
| +) | ||
| + | ||
| +type GpgKeysInterfaceSuite struct { | ||
| + iface interfaces.Interface | ||
| + slotInfo *snap.SlotInfo | ||
| + slot *interfaces.ConnectedSlot | ||
| + plugInfo *snap.PlugInfo | ||
| + plug *interfaces.ConnectedPlug | ||
| +} | ||
| + | ||
| +var _ = Suite(&GpgKeysInterfaceSuite{ | ||
| + iface: builtin.MustInterface("gpg-keys"), | ||
| +}) | ||
| + | ||
| +const gpgKeysConsumerYaml = `name: consumer | ||
| +apps: | ||
| + app: | ||
| + plugs: [gpg-keys] | ||
| + ` | ||
| + | ||
| +const gpgKeysCoreYaml = `name: core | ||
| +type: os | ||
| +slots: | ||
| + gpg-keys: | ||
| +` | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) SetUpTest(c *C) { | ||
| + s.plug, s.plugInfo = MockConnectedPlug(c, gpgKeysConsumerYaml, nil, "gpg-keys") | ||
| + s.slot, s.slotInfo = MockConnectedSlot(c, gpgKeysCoreYaml, nil, "gpg-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestName(c *C) { | ||
| + c.Assert(s.iface.Name(), Equals, "gpg-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestSanitizeSlot(c *C) { | ||
| + c.Assert(interfaces.BeforePrepareSlot(s.iface, s.slotInfo), IsNil) | ||
| + slotInfo := &snap.SlotInfo{ | ||
| + Snap: &snap.Info{SuggestedName: "some-snap"}, | ||
| + Name: "gpg-keys", | ||
| + Interface: "gpg-keys", | ||
| + } | ||
| + c.Assert(interfaces.BeforePrepareSlot(s.iface, slotInfo), ErrorMatches, | ||
| + "gpg-keys slots are reserved for the core snap") | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestSanitizePlug(c *C) { | ||
| + c.Assert(interfaces.BeforePreparePlug(s.iface, s.plugInfo), IsNil) | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestAppArmorSpec(c *C) { | ||
| + spec := &apparmor.Specification{} | ||
| + c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) | ||
| + c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) | ||
| + c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `owner @{HOME}/.gnupg/{,**} r,`) | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestStaticInfo(c *C) { | ||
| + si := interfaces.StaticInfoOf(s.iface) | ||
| + c.Assert(si.ImplicitOnCore, Equals, true) | ||
| + c.Assert(si.ImplicitOnClassic, Equals, true) | ||
| + c.Assert(si.Summary, Equals, `allows reading gpg user configuration and keys`) | ||
| + c.Assert(si.BaseDeclarationSlots, testutil.Contains, "gpg-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestAutoConnect(c *C) { | ||
| + // FIXME: fix AutoConnect | ||
| + c.Assert(s.iface.AutoConnect(&interfaces.Plug{PlugInfo: s.plugInfo}, &interfaces.Slot{SlotInfo: s.slotInfo}), Equals, true) | ||
| +} | ||
| + | ||
| +func (s *GpgKeysInterfaceSuite) TestInterfaces(c *C) { | ||
| + c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface) | ||
| +} |
| @@ -0,0 +1,62 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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 | ||
| + | ||
| +const gpgPublicKeysSummary = `allows reading gpg public keys and non-sensitive configuration` | ||
| + | ||
| +const gpgPublicKeysBaseDeclarationSlots = ` | ||
| + gpg-public-keys: | ||
| + allow-installation: | ||
| + slot-snap-type: | ||
| + - core | ||
| + deny-auto-connection: true | ||
| +` | ||
| + | ||
| +const gpgPublicKeysConnectedPlugAppArmor = ` | ||
| +# Description: Can read gpg public keys and non-sensitive configuration | ||
| + | ||
| +# Allow gpg encrypt, list-keys, verify, etc | ||
| +/usr/bin/gpg{,1,2,v} ixr, | ||
| +/usr/share/gnupg/options.skel r, | ||
| + | ||
| +owner @{HOME}/.gnupg/ r, | ||
| +owner @{HOME}/.gnupg/gpg.conf r, | ||
| +owner @{HOME}/.gnupg/openpgp-revocs.d/{,*} r, | ||
| +owner @{HOME}/.gnupg/pubring.gpg r, | ||
| +owner @{HOME}/.gnupg/pubring.kbx r, | ||
| +owner @{HOME}/.gnupg/trustedkeys.gpg r, | ||
| + | ||
| +owner @{HOME}/.gnupg/trustdb.gpg r, | ||
| +# gpg sometimes updates the trustdb to decide whether or not to update the | ||
| +# trustdb. For now, silence the denial since no other policy references this | ||
| +deny @{HOME}/.gnupg/trustdb.gpg w, | ||
| +` | ||
| + | ||
| +func init() { | ||
| + registerIface(&commonInterface{ | ||
| + name: "gpg-public-keys", | ||
| + summary: gpgPublicKeysSummary, | ||
| + implicitOnCore: true, | ||
| + implicitOnClassic: true, | ||
| + baseDeclarationSlots: gpgPublicKeysBaseDeclarationSlots, | ||
| + connectedPlugAppArmor: gpgPublicKeysConnectedPlugAppArmor, | ||
| + reservedForOS: true, | ||
| + }) | ||
| +} |
| @@ -0,0 +1,102 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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/apparmor" | ||
| + "github.com/snapcore/snapd/interfaces/builtin" | ||
| + "github.com/snapcore/snapd/snap" | ||
| + "github.com/snapcore/snapd/testutil" | ||
| +) | ||
| + | ||
| +type GpgPublicKeysInterfaceSuite struct { | ||
| + iface interfaces.Interface | ||
| + slotInfo *snap.SlotInfo | ||
| + slot *interfaces.ConnectedSlot | ||
| + plugInfo *snap.PlugInfo | ||
| + plug *interfaces.ConnectedPlug | ||
| +} | ||
| + | ||
| +var _ = Suite(&GpgPublicKeysInterfaceSuite{ | ||
| + iface: builtin.MustInterface("gpg-public-keys"), | ||
| +}) | ||
| + | ||
| +const gpgPublicKeysConsumerYaml = `name: consumer | ||
| +apps: | ||
| + app: | ||
| + plugs: [gpg-public-keys] | ||
| + ` | ||
| + | ||
| +const gpgPublicKeysCoreYaml = `name: core | ||
| +type: os | ||
| +slots: | ||
| + gpg-public-keys: | ||
| +` | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) SetUpTest(c *C) { | ||
| + s.plug, s.plugInfo = MockConnectedPlug(c, gpgPublicKeysConsumerYaml, nil, "gpg-public-keys") | ||
| + s.slot, s.slotInfo = MockConnectedSlot(c, gpgPublicKeysCoreYaml, nil, "gpg-public-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestName(c *C) { | ||
| + c.Assert(s.iface.Name(), Equals, "gpg-public-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestSanitizeSlot(c *C) { | ||
| + c.Assert(interfaces.BeforePrepareSlot(s.iface, s.slotInfo), IsNil) | ||
| + slotInfo := &snap.SlotInfo{ | ||
| + Snap: &snap.Info{SuggestedName: "some-snap"}, | ||
| + Name: "gpg-public-keys", | ||
| + Interface: "gpg-public-keys", | ||
| + } | ||
| + c.Assert(interfaces.BeforePrepareSlot(s.iface, slotInfo), ErrorMatches, | ||
| + "gpg-public-keys slots are reserved for the core snap") | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestSanitizePlug(c *C) { | ||
| + c.Assert(interfaces.BeforePreparePlug(s.iface, s.plugInfo), IsNil) | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestAppArmorSpec(c *C) { | ||
| + spec := &apparmor.Specification{} | ||
| + c.Assert(spec.AddConnectedPlug(s.iface, s.plug, s.slot), IsNil) | ||
| + c.Assert(spec.SecurityTags(), DeepEquals, []string{"snap.consumer.app"}) | ||
| + c.Assert(spec.SnippetForTag("snap.consumer.app"), testutil.Contains, `owner @{HOME}/.gnupg/gpg.conf r,`) | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestStaticInfo(c *C) { | ||
| + si := interfaces.StaticInfoOf(s.iface) | ||
| + c.Assert(si.ImplicitOnCore, Equals, true) | ||
| + c.Assert(si.ImplicitOnClassic, Equals, true) | ||
| + c.Assert(si.Summary, Equals, `allows reading gpg public keys and non-sensitive configuration`) | ||
| + c.Assert(si.BaseDeclarationSlots, testutil.Contains, "gpg-public-keys") | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestAutoConnect(c *C) { | ||
| + // FIXME: fix AutoConnect | ||
| + c.Assert(s.iface.AutoConnect(&interfaces.Plug{PlugInfo: s.plugInfo}, &interfaces.Slot{SlotInfo: s.slotInfo}), Equals, true) | ||
| +} | ||
| + | ||
| +func (s *GpgPublicKeysInterfaceSuite) TestInterfaces(c *C) { | ||
| + c.Check(builtin.Interfaces(), testutil.DeepContains, s.iface) | ||
| +} |
| @@ -0,0 +1,51 @@ | ||
| +// -*- Mode: Go; indent-tabs-mode: t -*- | ||
| + | ||
| +/* | ||
| + * Copyright (C) 2017 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 | ||
| + | ||
| +const sshKeysSummary = `allows reading ssh user configuration and keys` | ||
| + | ||
| +const sshKeysBaseDeclarationSlots = ` | ||
| + ssh-keys: | ||
| + allow-installation: | ||
| + slot-snap-type: | ||
| + - core | ||
| + deny-auto-connection: true | ||
| +` | ||
| + | ||
| +const sshKeysConnectedPlugAppArmor = ` | ||
| +# Description: Can read ssh user configuration as well as public and private | ||
| +# keys. | ||
| + | ||
| +/usr/bin/ssh ixr, | ||
| +/etc/ssh/ssh_config r, | ||
| +owner @{HOME}/.ssh/{,**} r, | ||
| +` | ||
| + | ||
| +func init() { | ||
| + registerIface(&commonInterface{ | ||
| + name: "ssh-keys", | ||
| + summary: sshKeysSummary, | ||
| + implicitOnCore: true, | ||
| + implicitOnClassic: true, | ||
| + baseDeclarationSlots: sshKeysBaseDeclarationSlots, | ||
| + connectedPlugAppArmor: sshKeysConnectedPlugAppArmor, | ||
| + reservedForOS: true, | ||
| + }) | ||
| +} |
Oops, something went wrong.