interfaces/builtin: add storage-framework-service interface #2929

Merged
merged 10 commits into from May 10, 2017

Conversation

Projects
None yet
6 participants
Contributor

michihenning commented Feb 24, 2017

This adds a snapd interface for use by storage-framework. On the slot side, it allows use of aa_is_enabled() and binding to the storage framework registry and provider DBus interfaces. On the plug side, it allows clients to talk to these DBus interfaces.

Just two comments, I didn't review the policy yet

- "home": true,
- "lxd-support": true,
- "snapd-control": true,
+ "content": true,
@zyga

zyga Feb 24, 2017

Contributor

This seems unrelated, did you change it explicitly or did go ftm decided to do so?

@michihenning

michihenning Feb 27, 2017

Contributor

That wasn't me. I think go fmt is responsible.

interfaces/builtin/storage_framework.go
+type StorageFrameworkInterface struct{}
+
+func (iface *StorageFrameworkInterface) Name() string {
+ return "storage-framework"
@zyga

zyga Feb 24, 2017

Contributor

Storage framework is a generic name. Is there any documentation for what the canonical storage framework is doing?

@michihenning

michihenning Feb 27, 2017

Contributor

We have an lp project for it: lp:storage-framework. We are waiting for management to allocate time to write documentation.

Collaborator

mvo5 commented Mar 3, 2017

There is a test failure related to formating: https://travis-ci.org/snapcore/snapd/jobs/204858792#L408 - you may need to run gofmt -s -w on these file(s).

Collaborator

mvo5 commented Mar 6, 2017

I pushed the go fmt fix.

Contributor

michihenning commented Mar 8, 2017

I pushed the go fmt fix.

Thanks for that! My apologies for not replying sooner. Somehow, I missed the notification email for your comments.

Let's please call this interface storage-framework-service.

Rationale for this was provided in PR #2869.

@niemeyer niemeyer requested a review from jdstrand Mar 10, 2017

Contributor

niemeyer commented Mar 10, 2017

@jdstrand This should be an easy one.

@niemeyer niemeyer changed the title from Added storage-framework interface. to interfaces/builtin: add storage-framework-service interface Mar 10, 2017

Contributor

michihenning commented Mar 10, 2017

Just checking: the thumbnailer is a service too, and its interface is called "thumbnailer". I chose "storage-framework" for consistency. I don't mind changing it to "storage-framework-service". Just let me know.

Overall the direction and implementation is good, but there is an open question on ###PLUG_SNAP_NAME### and need a few more tests

interfaces/builtin/storage_framework.go
+ snippet := []byte(storageFrameworkConnectedSlotAppArmor)
+ old := []byte("###PLUG_SNAP_NAME###")
+ new := []byte(plug.Snap.Name())
+ snippet = bytes.Replace(snippet, old, new, -1)
@jdstrand

jdstrand Mar 10, 2017

Contributor

###PLUG_SNAP_NAME### isn't currently in storageFrameworkConnectedSlotAppArmor. Was it meant to be used as part of the path in this rule:

dbus (receive, send)
    bus=session
    interface=com.canonical.StorageFramework.Provider.*
    path=/provider/*
    peer=(label=###PLUG_SECURITY_TAGS###),

If so, then I like that idea a lot.

@michihenning

michihenning Mar 17, 2017

Contributor

The storage framework doesn't need access to any files on the plug side, so PLUG_SNAP_NAME isn't needed here.

@michihenning

michihenning Mar 17, 2017

Contributor

The substitution was a copy-and-paste error and was redundant. I've removed it.

+ snippet, err = s.iface.ConnectedPlugSnippet(s.plug, s.slot, interfaces.SecurityAppArmor)
+ c.Assert(err, IsNil)
+ c.Assert(snippet, Not(IsNil))
+}
@jdstrand

jdstrand Mar 10, 2017

Contributor

It would be nice to add a test that the rules you are adding for ConnectedSlot and ConnectedPlug policy are preset similar to thumbnailer_test.go in TestSlotGrantedAccessToPlugFiles().

@michihenning

michihenning Mar 17, 2017

Contributor

See above. Because the service doesn't access to anything on the plug side, there is no need to test whether access is granted.

Contributor

niemeyer commented Mar 13, 2017

@michihenning We can't have interfaces called "online-accounts" or "storage-framework" when they are talking about very specific software implementations. snapd is widely scoped and a multi-Linux-distribution project, so we need to think about how much sense it makes for someone to be siting at a console in a completely different place and looking at these names. "thumbnailer" feels bad as well, actually. I'd prefer to rename that one too.

michihenning added some commits Mar 17, 2017

Contributor

michihenning commented Mar 20, 2017

I think I've made all the changes. The autopkg test failures are unrelated to this pull request.

I'll do a separate pull request to rename thumbnailer -> thumbnailer-service.

Getting close, just a few more changes.

+ slot-snap-type:
+ - app
+ deny-connection: true
+ deny-auto-connection: true
@jdstrand

jdstrand Mar 24, 2017

Contributor

The base declaration LGTM.

+ "location-observe": true,
+ "lxd": true,
+ "maliit": true,
+ "mir": true,
@jdstrand

jdstrand Mar 24, 2017

Contributor

I think you need to run go fmt again to fix these.

+
+/sys/module/apparmor/parameters/enabled r,
+@{PROC}/@{pid}/mounts r,
+/sys/kernel/security/apparmor/.access rw,
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add a comment for this? I suggest:

# libapparmor query interface needs 'w' to perform the query and 'r' to
# read the result. This is an information leak because in addition to
# allowing querying policy for any label (precisely what
# storage-framework needs), it also allows checking the existence of
# any label.
/sys/kernel/security/apparmor/.access rw,
+ path=/provider/*
+ peer=(label=###SLOT_SECURITY_TAGS###),
+`
+
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add storageFrameworkServicePermanentSlotSecComp with the following:

const storageFrameworkServicePermanentSlotSeccomp = `
bind
`

Your storage-framework snap may be specifying 'plugs: [ network-bind ]' that is giving you this syscall, but the slots side should have it on its own to bind to the DBus well-known name.

@zyga

zyga May 10, 2017

Contributor

This is done

+func (iface *StorageFrameworkServiceInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *interfaces.Slot) error {
+ spec.AddSnippet(storageFrameworkServicePermanentSlotAppArmor)
+ return nil
+}
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add:

func (iface *StorageFrameworkServiceInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *interfaces.Slot) error {
	spec.AddSnippet(storageFrameworkServicePermanentSlotSecComp)
	return nil
}
@zyga

zyga May 10, 2017

Contributor

This is done

+func (iface *StorageFrameworkServiceInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.Plug, slot *interfaces.Slot) error {
+ snippet := storageFrameworkServiceConnectedSlotAppArmor
+ old := "###PLUG_SECURITY_TAGS###"
+ new := slotAppLabelExpr(slot)
@jdstrand

jdstrand Mar 24, 2017

Contributor

This should be:

new := plugAppLabelExpr(plug)
+slots:
+ storage-framework-service:
+ interface: storage-framework-service
+`
@jdstrand

jdstrand Mar 24, 2017

Contributor

You should drop storageFrameworkServiceMockClassicSlotSnapInfoYaml because the storage-framework-service interface is not an implicit interface and the basedeclaration says only snaps of type 'app' may slot this interface.

+ s.coreSlot = &interfaces.Slot{SlotInfo: snapInfo.Slots["storage-framework-service"]}
+ // storage-framework-service slot on a core snap in a classic install.
+ snapInfo = snaptest.MockInfo(c, storageFrameworkServiceMockClassicSlotSnapInfoYaml, nil)
+ s.classicSlot = &interfaces.Slot{SlotInfo: snapInfo.Slots["storage-framework-service"]}
@jdstrand

jdstrand Mar 24, 2017

Contributor

Please remove these classic checks (see above).

+ apparmorSpec := &apparmor.Specification{}
+ err := apparmorSpec.AddConnectedSlot(s.iface, s.plug, s.coreSlot)
+ c.Assert(err, IsNil)
+ c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
@jdstrand

jdstrand Mar 24, 2017

Contributor

This will need to be changed to "snap.client.app" due to the requested changes in AppArmorConnectedSlot() (see above).

+ err = apparmorSpec.AddConnectedSlot(s.iface, s.plug, s.classicSlot)
+ c.Assert(err, IsNil)
+ c.Assert(apparmorSpec.SecurityTags(), HasLen, 0)
+
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add corresponding tests for apparmorSpec.AddConnectedPlug?

+ err = apparmorSpec.AddPermanentSlot(s.iface, s.coreSlot)
+ c.Assert(err, IsNil)
+ c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
+ c.Assert(apparmorSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, `member={RequestName,ReleaseName,GetConnectionCredentials}`)
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you also check for the seccomp "bind". Eg:

seccompSpec := &seccomp.Specification{}
err := seccompSpec.AddPermanentSlot(s.iface, s.coreSlot)
c.Assert(err, IsNil)
c.Assert(seccompSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
c.Check(seccompSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, "bind\n")
@michihenning

michihenning Mar 31, 2017

Contributor

Thanks for the review Jamie! I apologize for being so clumsy. Much of this is new to me.
I take it that it is OK not to assign to classicSlot? (This is the one thing I'm not sure about. I think all the other changes you asked for are there now.)

@jdstrand

jdstrand Apr 18, 2017

Contributor

It is fine to not assign to classicSlot AFAICS. In fact, you could probably remove it from StorageFrameworkServiceInterfaceSuite since you aren't doing anything with it. If it is decided that storage-framework-service would be provided outside of a snap, then we can start considering classic distro policy.

@zyga

zyga May 10, 2017

Contributor

I iterated on the unit tests. Please have a look if anything is missing.

stolowski and others added some commits Mar 28, 2017

Contributor

zyga commented Apr 4, 2017

Hey @michihenning can you please merge master into this branch?
@niemeyer / @jdstrand can you please re-review this?

jdstrand approved these changes Apr 18, 2017 edited

Thanks for your work on this!

+ err = apparmorSpec.AddPermanentSlot(s.iface, s.coreSlot)
+ c.Assert(err, IsNil)
+ c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
+ c.Assert(apparmorSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, `member={RequestName,ReleaseName,GetConnectionCredentials}`)
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you also check for the seccomp "bind". Eg:

seccompSpec := &seccomp.Specification{}
err := seccompSpec.AddPermanentSlot(s.iface, s.coreSlot)
c.Assert(err, IsNil)
c.Assert(seccompSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
c.Check(seccompSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, "bind\n")
@michihenning

michihenning Mar 31, 2017

Contributor

Thanks for the review Jamie! I apologize for being so clumsy. Much of this is new to me.
I take it that it is OK not to assign to classicSlot? (This is the one thing I'm not sure about. I think all the other changes you asked for are there now.)

@jdstrand

jdstrand Apr 18, 2017

Contributor

It is fine to not assign to classicSlot AFAICS. In fact, you could probably remove it from StorageFrameworkServiceInterfaceSuite since you aren't doing anything with it. If it is decided that storage-framework-service would be provided outside of a snap, then we can start considering classic distro policy.

@zyga

zyga May 10, 2017

Contributor

I iterated on the unit tests. Please have a look if anything is missing.

zyga added some commits May 10, 2017

interfaces/builtin: tweak unit tests for storage-framework-service
The tests are split per tested method. This lends itself to shorter
variable names and more clarity in case something fails.

Signed-off-by: Zygmunt Krynicki <zygmunt.krynicki@canonical.com>

zyga approved these changes May 10, 2017

I did a pass over this branch and made it suitable for landing.

+ path=/provider/*
+ peer=(label=###SLOT_SECURITY_TAGS###),
+`
+
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add storageFrameworkServicePermanentSlotSecComp with the following:

const storageFrameworkServicePermanentSlotSeccomp = `
bind
`

Your storage-framework snap may be specifying 'plugs: [ network-bind ]' that is giving you this syscall, but the slots side should have it on its own to bind to the DBus well-known name.

@zyga

zyga May 10, 2017

Contributor

This is done

+func (iface *StorageFrameworkServiceInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *interfaces.Slot) error {
+ spec.AddSnippet(storageFrameworkServicePermanentSlotAppArmor)
+ return nil
+}
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you add:

func (iface *StorageFrameworkServiceInterface) SecCompPermanentSlot(spec *seccomp.Specification, slot *interfaces.Slot) error {
	spec.AddSnippet(storageFrameworkServicePermanentSlotSecComp)
	return nil
}
@zyga

zyga May 10, 2017

Contributor

This is done

+ err = apparmorSpec.AddPermanentSlot(s.iface, s.coreSlot)
+ c.Assert(err, IsNil)
+ c.Assert(apparmorSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
+ c.Assert(apparmorSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, `member={RequestName,ReleaseName,GetConnectionCredentials}`)
@jdstrand

jdstrand Mar 24, 2017

Contributor

Can you also check for the seccomp "bind". Eg:

seccompSpec := &seccomp.Specification{}
err := seccompSpec.AddPermanentSlot(s.iface, s.coreSlot)
c.Assert(err, IsNil)
c.Assert(seccompSpec.SecurityTags(), DeepEquals, []string{"snap.storage-framework-service.app"})
c.Check(seccompSpec.SnippetForTag("snap.storage-framework-service.app"), testutil.Contains, "bind\n")
@michihenning

michihenning Mar 31, 2017

Contributor

Thanks for the review Jamie! I apologize for being so clumsy. Much of this is new to me.
I take it that it is OK not to assign to classicSlot? (This is the one thing I'm not sure about. I think all the other changes you asked for are there now.)

@jdstrand

jdstrand Apr 18, 2017

Contributor

It is fine to not assign to classicSlot AFAICS. In fact, you could probably remove it from StorageFrameworkServiceInterfaceSuite since you aren't doing anything with it. If it is decided that storage-framework-service would be provided outside of a snap, then we can start considering classic distro policy.

@zyga

zyga May 10, 2017

Contributor

I iterated on the unit tests. Please have a look if anything is missing.

@mvo5 mvo5 merged commit df0bd22 into snapcore:master May 10, 2017

6 of 7 checks passed

artful-amd64 autopkgtest finished (failure)
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
xenial-amd64 autopkgtest finished (success)
Details
xenial-i386 autopkgtest finished (success)
Details
xenial-ppc64el autopkgtest finished (success)
Details
yakkety-amd64 autopkgtest finished (success)
Details
zesty-amd64 autopkgtest finished (success)
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment