Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
interfaces/builtin: add dbus interface #1613
Conversation
jdstrand
added some commits
Jun 22, 2016
jdstrand
referenced this pull request
Aug 1, 2016
Closed
interfaces/builtin: add dbus-bind interface #1446
mvo5
reviewed
Aug 3, 2016
| + } | ||
| + switch securitySystem { | ||
| + case interfaces.SecurityAppArmor: | ||
| + var snippets bytes.Buffer |
mvo5
Aug 3, 2016
Collaborator
(nitpick) You could write snippets := bytes.NewBufferString("") here to save 1 line.
mvo5
reviewed
Aug 3, 2016
| +} | ||
| + | ||
| +// verify that name for bus is in list | ||
| +func (iface *DbusAppInterface) verifyNameInAttributes(bus string, name string, attribs map[string]interface{}) bool { |
jdstrand
Aug 3, 2016
Contributor
No, you are right. This was used in the dbus-bind exploratory PR for making sure the slot side had an entry for the specified plug side. Removed. Thanks!
mvo5
reviewed
Aug 3, 2016
| +} | ||
| + | ||
| +func (iface *DbusAppInterface) AutoConnect() bool { | ||
| + return false |
mvo5
Aug 3, 2016
Collaborator
Maybe this just shows my ignorance, but earlier we have +Auto-Connect: yes in the docs and false here. Or is this a different auto-connect?
jdstrand
Aug 3, 2016
•
Contributor
Since we are implementing this in the permanent slot side it is auto-generated. There is no plugs side atm.
mvo5
reviewed
Aug 3, 2016
| + c.Assert(err, IsNil) | ||
| +} | ||
| + | ||
| +/* |
jdstrand
Aug 3, 2016
Contributor
Oh, this was meant to be removed-- it's a test for the plug side of the connection which we don't support in this PR (perhaps in the future as per description in this PR).
|
Looks good, thanks for doing this work! Some questions inline but no blockers. |
jdstrand
added some commits
Aug 3, 2016
|
@mvo5 I think I addressed all your questions. Thanks for the review! :) |
mvo5
reviewed
Aug 4, 2016
| + return err | ||
| +} | ||
| + | ||
| +// Since we only implement the permanent slot side, this is meaningless but |
|
Nice! Thank you, |
niemeyer
changed the title from
add dbus-app interface (LP: #1590679)
to
interfaces/builtin: add dbus-object interface
Aug 6, 2016
niemeyer
changed the title from
interfaces/builtin: add dbus-object interface
to
interfaces/builtin: add dbus-app interface
Aug 6, 2016
|
@jdstrand I still feel like there's something not quite right with this interface. The whole logic seems to focus on the slot side only. What happens if someone connects to that slot? How do we even hint to the user what can be connected to what? How do we prevent an app from binding? If the answers are respectively "nothing", "we don't know", and "we can't", then something is wrong. Taking our lesson from our conversation this week, isn't this actually more correct as dbus-support, where the settings are done on the plug side, and only when actually granted via a connection? |
niemeyer
added
Reviewed
Blocked
labels
Aug 8, 2016
|
(s/dbus-setup/dbus-support) |
niemeyer
added
the
Decaying
label
Aug 26, 2016
jdstrand
removed
the
Decaying
label
Sep 13, 2016
|
Well, even if it can, that won't quite work as intended, as we won't be able to match plug and slot. I don't understand how this is being used.. how can it use a pid as part of the interface? What is the dbus client doing to talk to this server object? This misunderstanding may be fundamental to the overall feature, so let's make sure to clear this up before we move on with this plan. |
|
@niemeyer - ktuberling is abusing the dbus bind and only having part of the name be well-known. I'm guessing the reason why they are doing this is so that multiple instances of ktuberling can be launched within the same session and that KDE apps will register themselves with some KDE service and other KDE apps will use that service to find the various ktuberlings to access them. GNOME doesn't do this and is compliant with the freedesktop.org spec: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names I don't think this a misunderstanding of the overall feature, but we have to think about how to support it for KDE. We can support the pid in the security policy by simply adding an alternation to the rule. Eg, slot still has 'name: org.kde.ktuberling' but we create a bind rule for it like so:
While it is somewhat unfortunate the way that KDE apps are misusing the well-known name, we can deal with it. There is a problem with the above in that if KDE creates 'ktuberling' and I create 'ktuberling-12345' then due to the above rules, we have an overlap:
This could be addressed in a few ways:
UPDATE:
|
|
I suggest for the time being we don't allow the name attribute to end with -[0-9]+ in snapd and add the alternation unconditionally then see how real people use the interface. |
|
FYI, the introspection rule needs to be adjusted for KDE, but that is less of a concern. |
jdstrand
added some commits
Nov 22, 2016
|
In the interest of time, I've added an alternation rule that allows KDE snaps to bind to org.kde.foo-12345 when they simply declare 'name: org.kde.foo'. I also adjusted ValidateDBusBusName() in interfaces/core.go to not allow bus names ending with '-[0-9]+'. These changes can be easily reverted if needed or iterated on in the future. |
jdstrand
added some commits
Nov 22, 2016
niemeyer
requested changes
Nov 22, 2016
A few more comments, but the direction and approach LGTM. Thanks for pushing this forward.
| + deny-connection: | ||
| + slot-attributes: | ||
| + name: .+ | ||
| + deny-auto-connection: true |
niemeyer
Nov 22, 2016
Contributor
Why the denials here? This will prevent people from using the interface altogether until explicitly allowed.
jdstrand
Nov 22, 2016
Contributor
Yes. I thought we agreed that people would need to have their well-known dbus name approved in the store. This will trigger a manual review and enforce the use of a snap declaration to claim the well-known name.
jdstrand
Nov 22, 2016
Contributor
Also, it doesn't prevent them from using the interface-- they can install a snap that slots this interface and get the bind rules needed to run; it is just that you can't connect other snaps to this interface until a snap declaration is present.
I think this is the right approach for this interface and others in general, but it sheds a light on a developer pain point as described in https://bugs.launchpad.net/snappy/+bug/1640874. I think this is perhaps solved by a locally signed snap declaration, but that needs your input (see my comments in the bug).
niemeyer
Nov 23, 2016
Contributor
We'd indeed not auto-connect it, but is there a reason to disable the manual connection altogether? This would be the user manually establishing the allowance for dbus communication between two separate snaps, over a well defined API. I can't quite see why we'd reject this yet.
jdstrand
Nov 23, 2016
•
Contributor
We reject it because the snap has not claimed the name via the store and doesn't yet have a snap declaration. On initial upload with using this interface, the reviewer will issue a snap declaration that allows the connection, and then all is well for connections and subsequent uploads. I think this is in line with everything we've discussed regarding the base declaration and snap declarations-- slot implementations (typically) need some sort of snap declaration since they (typically) allow privileged access to the system. In this case the privilege is to claim a well-known name.
On a related note, the review tools are now considering the base declaration and prompting for manual review due to this constraint. If we remove the constraint today, the tools would let this through without prompting for manual review. If we decide that the constraint should not be there, then the tools will have to be modified to prompt for manual review based on factors outside of the base declaration for an interface review (which is totally doable, but I thought one goal of the base declaration was to be the one place the review tools would consult for how interface reviews should be performed).
| +func (iface *DbusInterface) getAttribs(attribs map[string]interface{}) (string, string, error) { | ||
| + bus := "" | ||
| + name := "" | ||
| + for attr := range attribs { |
niemeyer
Nov 22, 2016
Contributor
This is a map.. we can access the attributes we care about directly with the following, and drop all the code below I think:
bus, ok := attribs["bus"].(string)
if !ok {
... error ...
}
name, ok := attribs["name"].(string)
if !ok {
... error ...
}
| + name := "" | ||
| + for attr := range attribs { | ||
| + if attr != "bus" && attr != "name" { | ||
| + return "", "", fmt.Errorf("unknown attribute '%s'", attr) |
niemeyer
Nov 22, 2016
Contributor
This breaks future compatibility, meaning we cannot ever add anything at all in this interface without it permanently breaking every old client. In practice, this renders the interface completely immutable, so it's something we should try to avoid on this and in other interfaces I think.
| + snippet = bytes.Replace(snippet, old, new, -1) | ||
| + | ||
| + // convert name to AppArmor dbus path (eg 'org.foo' to '/org/foo{,/**}') | ||
| + dot_re := regexp.MustCompile("\\.") |
niemeyer
Nov 22, 2016
Contributor
Isn't that just Replace(sinppet, ".", "/", -1)?
That said, why is it doing that? Isn't DBUS_PATH supposed to be gone? I thought we had agreed not to guess?
jdstrand
Nov 22, 2016
•
Contributor
I found that I couldn't get rid of dbus path entirely due to snaps using the org.freedesktop.* interfaces and so instead have:
dbus (receive, send)
bus=###DBUS_BUS###
interface=###DBUS_INTERFACE###
peer=(label=###SLOT_SECURITY_TAGS###),
dbus (receive, send)
bus=###DBUS_BUS###
path=###DBUS_PATH###
peer=(label=###SLOT_SECURITY_TAGS###),
This allows us to match by either interface (and security peer label) or path (and security peer label) and avoids the problems of trying to specify them both at the same time. In other words, still have the rule you mention that doesn't require guessing, but then have another rule that allows using the org.freedesktop.DBus interface in predictable ways.
I discussed this with @tyhicks and we agreed on the approach.
niemeyer
Nov 23, 2016
Contributor
That still doesn't look right. This is an interface name, not a path. If we are translating from one to the other, we're doing guess work which can be wrong, because after all those are two different fields in the dbus system instead of a single one. If the interface matching doesn't work for some cases which require a path instead of an interface, let's please raise that and talk about it in those terms.
jdstrand
Dec 6, 2016
•
Contributor
@niemeyer - It's actually a well-known connection name, not an interface name nor a path. I am deriving the path and the interface from the well-known name because this interface in its current form is not meant to cover the entire dbus system, but rather traditional desktop applications until we better understand what people want from this interface for the entire dbus system. This should work for observed applications from GNOME and KDE and is consistent with how these toolkits setup the DBus interfaces. For example, GNOME applications use DBUS_PATH very regularly and this implementation allows them to work. The goal of this PR as implemented is to a) allow dbus binds to work and b) allow connections to work when the dbus api is well-formed.
A benefit of this approach as implemented is that the dbus interface and path is namespaced to the slot implementation (eg, bind to org.foo.bar but can't offer interfaces for org.baz.norf or paths on /org/baz/norf). This seems reasonable considering that we don't quite yet know the future of this interface.
We could simply allow the bind to the well-known name and then only mediate on the peer label for connected snaps like this:
# ConnectedPlug
dbus (receive, send)
bus=session
peer=(name=###DBUS_NAME###,label=###SLOT_SECURITY_TAGS###),
which is exactly what I think you are asking for on the plugs side. Unfortunately in practice dbus accesses are never quite this clean. For example, we can't use a similar rule on the slots side because the 'name' used in the peer (connecting client) is not well-known and is of the form ':[0-9]*' so the slot side needs this rule:
# ConnectedSlot
dbus (receive, send)
bus=session
peer=(label=###PLUG_SECURITY_TAGS###),
which means that the slot can send and receive any interface, path and method to a connected client. There is a mismatch here I'd rather avoid if we can: the plugging side can send and receive to a process with the slot's label and well-known name, but the slot can send anything to a process with the plug's label which is imprecise and makes the policy somewhat ambiguous, both of which make me little uncomfortable considering that unlike privileged slot implementations, snaps slotting this interface are not meant to be considered particularly special beyond claiming the well-known name. Maybe in the future we can add 'interface' and 'path' attributes that will be used instead of our derived paths; maybe the ambiguous rules are where we want to go instead. For the first cut I was leaning towards usable but slightly stricter since it is easier to add wider permissions, but it would be impossible to remove them later.
(I'm pretty sure both sides are going to need more than the above two rules anyway. I'll take a look at that next.)
jdstrand
Dec 6, 2016
Contributor
"(I'm pretty sure both sides are going to need more than the above two rules anyway. I'll take a look at that next.)"
Indeed, on the plugs side I tried just this rule:
dbus (receive, send)
bus=session
peer=(name=###DBUS_NAME###, label=###SLOT_SECURITY_TAGS###),
and found that the org.gtk.Actions and org.gtk.Menus interfaces were blocked to connected snaps due to the missing ###DBUS_PATH### rule because the communication is happening via a non-well-known, non-snap-specific connection name. Without ###DBUS_PATH###, this rule is required:
dbus (send)
bus=session
peer=(name=:[0-9].[0-9]*, label=###SLOT_SECURITY_TAGS###),
The corresponding slot side rule becomes:
dbus (receive)
bus=session
peer=(name=:[0-9].[0-9]*, label=###SLOT_SECURITY_TAGS###),
The two combined mean that the plugging side can connect to the slot side via any non-well-known connection name with any interface, path or method.
With these rules that omit interface and path, the snaps are allowed to communicate with each other but the mediation is imprecise due to overlapping mediation. Eg, with the following slot yaml:
slots:
foo:
bus: session
name: org.foo
bar:
bus: session
name: org.bar
apps:
daemon:
slots: [ foo, bar ]
and the following plug yaml:
plugs:
foo:
bus: session
name: org.foo
and then snap connect plugging-snap:foo slotting-snap:foo results in this on the plugs side:
dbus (receive, send)
bus=session
peer=(name=org.foo, label=snap.slotting-snap.daemon),
dbus (send)
bus=session
peer=(name=:[0-9].[0-9]*, label=snap.slotting-snap.daemon),
which means that the plugging snap can talk to daemon service's non-well-known connection names corresponding to the org.bar service. This is precisely why I wanted the interface and path rules.
We have a few choices:
- stick with the current PR with the two extra derived interface and path rules. This allows all communications via the well-known connection name as well as non-well-known connection names when a path or interface corresponds with the well-known name
- only allow the plugs side to use
peer=(name=###DBUS_NAME###, ###SLOT_SECURITY_TAGS###), remove the non-well-known rule from the plugging side, but leave it in the slot side - use ambiguous rules as described in this comment
'1' is strict but allows both sides and works with GNOME and KDE. '2' is stricter on the plugs side which allows communications only via the well-known name. '3' works but is lenient regarding non-well-known connection name communications.
I prefer 1 or 2. If we go with '2', we will break certain DBus APIs (eg, org.gtk.Menus, org.gtk.Actions) and the future use of these slot snaps in snapped desktop environments like unity, gnome and plasma, but we can document this today and add other interfaces (or augment this one) to handle these cases when the need arises (of course, then the combined rules will be similar to what we have with '1').
(Note: the issues surrounding this is because we are applying the untrusted app trust model onto applications designed for the user session trust model).
niemeyer
Dec 12, 2016
Contributor
Okay, sounds fine. We can always include an additional path field if we need to be explicit.
| + new = pathBuf.Bytes() | ||
| + snippet = bytes.Replace(snippet, old, new, -1) | ||
| + | ||
| + // convert name to AppArmor dbus interface (eg, 'org.foo' to 'org.foo{,.*}') |
jdstrand
Nov 22, 2016
Contributor
No, it is accurate. It takes 'name' which might be 'org.foo' and turns it into the glob 'org.foo{,.*}'.
| + } | ||
| + | ||
| + // ensure that we only connect to slot with matching attributes | ||
| + if bus != busPlug || name != namePlug { |
niemeyer
Nov 22, 2016
Contributor
This should be an error. We should not even allow that connection to be established.
jdstrand
Nov 22, 2016
Contributor
I initially had this as an error but throwing an error here means that situations like TestConnectionFirst() and TestConnectionSecond() in dbus_test.go throw an error, but they should not. I'm trying to discard 'the other' one so just skip it. Is there a better way?
niemeyer
Nov 23, 2016
Contributor
Why they should not? I feel like I'm missing something important, perhaps unrelated to this PR. If we're running the connection code for things which are incompatible and that should not be auto-connected, erroring seems sane. If it's blowing up in a place it shouldn't, definitely curious to hear about it.
jdstrand
Dec 5, 2016
•
Contributor
@niemeyer - I haven't looked at this terribly closely, but it looks like this is cause by ResolveConnect() in interfaces/repo.go:
func (r *Repository) ResolveConnect(plugSnapName, plugName, slotSnapName, slotName string) (ConnRef, error) {
...
if slotName == "" {
// Find the unambiguous slot that satisfies plug requirements
var candidates []string
for candidateSlotName, candidateSlot := range r.slots[slotSnapName] {
// TODO: use some smarter matching (e.g. against $attrs)
if candidateSlot.Interface == plug.Interface {
candidates = append(candidates, candidateSlotName)
}
}
Note // TODO: use some smarter matching (e.g. against $attrs) - it isn't matching against attrs so the interface code must when matching like this. This makes sense with my observations that I could not error and instead must silently ignore attribute mismatches since Connected*Snippet was getting each combination.
niemeyer
Dec 12, 2016
Contributor
Okay, we need to look into the auto-connection rule based on attributes soon anyway, so let's not block on this.
pedronis
Dec 12, 2016
Contributor
yes, it looks like that code in repo.go should use the policy checks, especially once we have attribute comparision
pedronis
Dec 13, 2016
Contributor
@jdstrand could you replace that TODO there with use interface/policy Checkers
| +} | ||
| + | ||
| +// Since we only implement the permanent slot side, this is meaningless but | ||
| +// we have to supply the method, so set it to something safe. |
jdstrand
Nov 22, 2016
Contributor
Oh, that comment is bogus. It is a holdover from LegacyConnect and earlier iterations of this interface. Removed.
jdstrand
added some commits
Nov 22, 2016
| +<policy context="default"> | ||
| + <allow send_destination="###DBUS_NAME###"/> | ||
| +</policy> | ||
| +` |
jdstrand
Nov 23, 2016
•
Contributor
dbusPermanentSlotDBus wasn't in the original PR but it is needed for 'bus=system'. @niemeyer and @tyhicks: the question then becomes, should non-root be allowed to talk to it? As implemented (in a separate commit for easy reverting), the answer is 'yes' because snapd should allow a non-root snap command to be able to connect to a root daemon within the same command and it is up to the snap to perform any uid checks. However, because of the dbusPermanentSlotAppArmorClassic policy for on classic (and the lack of policykit in the core snap) this means that unconfined non-root can talk to the snap-- this needs discussion but consider that this interface does alone not grant extra access to the system, b) this interface in combination with privileged ones (eg, network-control) requires a user to connect the interfaces and c) unconfined non-root can aa_change_profile() to something that would allow the access.
'b' is somewhat mediated in the initial store upload since the base declaration requires that to use this interface you need to claim the name and receive a snap declaration. However, the tools aren't considering combinations of interfaces and it would be a shame if a root-running system service slot implementation has say, network-control and exposes a DBus API but doesn't perform uid checks so non-root users could escalate privileges to change networking via the poorly implemented snap. Granted, there is nothing saying this poorly written snap couldn't expose a named unix socket in SNAP_DATA world read/write and do the same thing without this interface, so this is probably one of those things where this poorly written snap gets poor reviews and/or bug report and we exercise store policies to compel the developer to fix it (or revoke the snap).
@niemeyer and @tyhicks, put simply, should non-root be able to contact a dbus system service via this interface?
(sorry for the second email on this, I made a change and the comment was hidden so I deleted the first and added this one)
jdstrand
added some commits
Dec 5, 2016
pedronis
self-assigned this
Dec 12, 2016
jdstrand
added some commits
Dec 12, 2016
|
The trusty issue is unrelated to this PR: |
jdstrand
added this to the 2.20 milestone
Dec 13, 2016
|
Added the 2.20 milestone since AIUI all this needs is one more review and this interface has been lingering. @pedronis - AIUI you will be doing that review, is that correct? |
| +} | ||
| + | ||
| +// Obtain yaml-specified bus well-known name | ||
| +func (iface *DbusInterface) getAttribs(attribs map[string]interface{}) (string, string, error) { |
pedronis
Dec 13, 2016
Contributor
would be better to use named results here: (bus, name string, err error)
| + return "", "", fmt.Errorf("DBus bus name must not end with -NUMBER") | ||
| + } | ||
| + | ||
| + if bus == "" { |
pedronis
Dec 13, 2016
Contributor
I'm confused by these checks, it doesn't seem that bus == "" would pass the previous check being equal session or system, same for name == "" and ValidateDBusName ?
jdstrand
Dec 13, 2016
Contributor
@pedronis, you are right. These are a holdover from a refactor. Removed.
| + dot_re := regexp.MustCompile("\\.") | ||
| + var pathBuf bytes.Buffer | ||
| + pathBuf.WriteString(`"/`) | ||
| + pathBuf.WriteString(dot_re.ReplaceAllString(name, "/")) |
pedronis
Dec 13, 2016
Contributor
the bit stands that this could be just strings.Replace(name, ".", "/", -1)
| + } | ||
| + | ||
| + // ensure that we only connect to slot with matching attributes | ||
| + if bus != busPlug || name != namePlug { |
niemeyer
Nov 22, 2016
Contributor
This should be an error. We should not even allow that connection to be established.
jdstrand
Nov 22, 2016
Contributor
I initially had this as an error but throwing an error here means that situations like TestConnectionFirst() and TestConnectionSecond() in dbus_test.go throw an error, but they should not. I'm trying to discard 'the other' one so just skip it. Is there a better way?
niemeyer
Nov 23, 2016
Contributor
Why they should not? I feel like I'm missing something important, perhaps unrelated to this PR. If we're running the connection code for things which are incompatible and that should not be auto-connected, erroring seems sane. If it's blowing up in a place it shouldn't, definitely curious to hear about it.
jdstrand
Dec 5, 2016
•
Contributor
@niemeyer - I haven't looked at this terribly closely, but it looks like this is cause by ResolveConnect() in interfaces/repo.go:
func (r *Repository) ResolveConnect(plugSnapName, plugName, slotSnapName, slotName string) (ConnRef, error) {
...
if slotName == "" {
// Find the unambiguous slot that satisfies plug requirements
var candidates []string
for candidateSlotName, candidateSlot := range r.slots[slotSnapName] {
// TODO: use some smarter matching (e.g. against $attrs)
if candidateSlot.Interface == plug.Interface {
candidates = append(candidates, candidateSlotName)
}
}
Note // TODO: use some smarter matching (e.g. against $attrs) - it isn't matching against attrs so the interface code must when matching like this. This makes sense with my observations that I could not error and instead must silently ignore attribute mismatches since Connected*Snippet was getting each combination.
niemeyer
Dec 12, 2016
Contributor
Okay, we need to look into the auto-connection rule based on attributes soon anyway, so let's not block on this.
pedronis
Dec 12, 2016
Contributor
yes, it looks like that code in repo.go should use the policy checks, especially once we have attribute comparision
pedronis
Dec 13, 2016
Contributor
@jdstrand could you replace that TODO there with use interface/policy Checkers
| + | ||
| +func (iface *DbusInterface) AutoConnect(*interfaces.Plug, *interfaces.Slot) bool { | ||
| + // allow what declarations allowed | ||
| + return true |
pedronis
Dec 13, 2016
Contributor
the check // ensure that we only connect to slot with matching attributes
- if bus != busPlug || name != namePlug {
should probably be done here? instead?
that's what content is doing atm btw, until we don't have support for specifying attribute matching in the basedecl
jdstrand
Dec 13, 2016
Contributor
AutoConnect() isn't the right place for the check for the dbus interface because the check needs to happen at connection, not auto connection and at connection we only connect when bus and name match. The content interface is different in that while the content attribute must match for auto-connect, the content attribute is not used as part of the connected snippets, only read and write which aren't part of the content interface's plugging attributes.
Note that the dbus interface design and its attributes are approved.
jdstrand
added some commits
Dec 13, 2016
|
@pedronis, I believe I addressed your comments. |
jdstrand
added some commits
Dec 13, 2016
|
@pedronis and I discussed the 'if bus != busPlug || name != namePlug' part on irc and agreed that what is implemented is the best we can do without the attribute matching. The code will ensure that the correct security policy is generated. I updated the comment to reflect this. |
|
The security policy looks good to me. Thanks for making the adjustments we spoke about over IRC. |
|
The travis testsuite failure is unrelated:
|
|
The trusty failure is unrelated: |
|
The zesty failures are unrelated:
|
|
Retrying the travis tests since there seem to be intermittent failures. |
jdstrand
referenced this pull request
Dec 14, 2016
Merged
interfaces: support network namespaces via 'ip netns' in network-control (LP: #1624675) #2450
| + bus=###DBUS_BUS### | ||
| + path=/org/freedesktop/DBus | ||
| + interface=org.freedesktop.DBus | ||
| + member="GetConnectionUnix{ProcessID,User}" |
jhenstridge
Dec 14, 2016
Contributor
Would it make sense to also include org.freedesktop.DBus.GetConnectionCredentials here? That seems to be the replacement for the above two if you need both.
| + var ifaceBuf bytes.Buffer | ||
| + ifaceBuf.WriteString(`"`) | ||
| + ifaceBuf.WriteString(name) | ||
| + ifaceBuf.WriteString(`{,.*}"`) |
jhenstridge
Dec 14, 2016
Contributor
This might make sense as a default value, but interface names are not the same as bus names in the general case. For my work on storage-framework, we have a number of daemons that all implement the same D-Bus interface, but will register on the bus with different well known names.
I believe MPRIS works similarly.
Also, what if the service exposes method calls or signals on more than one interface? I imagine it'd be quite common for an app to want to respond to method calls on the org.freedesktop.DBus.Properties interface, but I think it'd be a mistake to simply special case it.
jdstrand
Dec 14, 2016
•
Contributor
As mentioned on the mailing list: https://lists.ubuntu.com/archives/snapcraft/2016-December/001998.html this initial implementation of the interface intentionally does not address complex dbus services. It is meant to address leaf applications (eg, GNOME and KDE) that bind to a well-known name.
I'd prefer not to delay this PR any longer by adding more functionality to it. @niemeyer and I agreed in this PR that we would implement what we have and then see how people are using it and potentially add DBus paths, interfaces, activation, complex bus policy, etc down the line. Do keep in mind that generic interfaces like this one are a new concept in snappy that is in some ways counter to the initial goals of interfaces, and we want to make sure we design and implement them in a controlled fashion.
As for storage framework in particular, if you haven't already, I suggest reading the aforementioned thread. At this time, it will need to be its own interface (and that's ok-- it's easy getting interfaces into snappy :). Perhaps at a future date the dbus interface will get to the point to support all DBus services generically, but not just yet.
jhenstridge
Dec 14, 2016
Contributor
If you don't want to make it configurable, then I'd strongly consider allowing at least org.freedesktop.DBus.Properties as an extra one unconditionally. Without it, it is impossible to access APIs using the standard D-Bus property system.
To get property "A" on interface "I", you call org.freedesktop.DBus.Properties.Get("I", "A") -- not a method call on the interface declaring the property.
jdstrand
Dec 14, 2016
•
Contributor
To be clear, we do want to make it configurable-- at some point. There is an urgency to this PR as it is blocking GNOME and KDE devs from targeting stable. This PR specifically addresses that use case. Other use cases can come in other PRs.
As for Properties, this is already handled by the path rule without an interface:
# allow connected snaps to all interfaces via ###DBUS_PATH### (eg,
# org.freedesktop.*, org.gtk.Application, etc) to allow full integration with
# connected snaps.
dbus (receive, send)
bus=###DBUS_BUS###
path=###DBUS_PATH###
peer=(label=###SLOT_SECURITY_TAGS###),
This was a tested condition for the leaf applications we are trying to address.
| + var pathBuf bytes.Buffer | ||
| + pathBuf.WriteString(`"/`) | ||
| + pathBuf.WriteString(strings.Replace(name, ".", "/", -1)) | ||
| + pathBuf.WriteString(`{,/**}"`) |
jhenstridge
Dec 14, 2016
Contributor
Similar to the comment about interface names, you can't necessarily derive the paths a D-Bus service uses from the bus name it will try to acquire. If you're going to restrict object paths (which seems a bit dubious), shouldn't it be configurable on the slot?
jdstrand
Dec 14, 2016
Contributor
See above comment. We intentionally left out path configuration in this initial implementation.
jdstrand
added some commits
Dec 14, 2016
|
Travis failure is unrelated: linode:ubuntu-core-16-64-fixme:tests/main/ubuntu-core-upgrade-no-gc Trusty autopkgtest failure is unrelated Zesty autopkgtest failures are unrelated (and same as before): |
|
From IRC:
|
niemeyer
changed the title from
interfaces/builtin: add dbus interface (LP: #1590679)
to
interfaces/builtin: add dbus interface
Dec 15, 2016
mvo5
merged commit c1ff793
into
snapcore:master
Dec 15, 2016
4 of 6 checks passed
|
Thanks especially @niemeyer for your time on this and thank you to all reviewers and commenters for your input and reviews! :) |
jdstrand commentedAug 1, 2016
•
Edited 1 time
-
niemeyer
Aug 1, 2016
This implements dbus in support of 'Apps can't own session bus names'. Specifically, snaps may specify a slot using this interface which grants access to bind. Eg:
This will allow the snap to own the well-known bus name 'org.gnome.Logs' and also integrate into the classic environment.
This also implements the plugs side and allows other snaps to connect to the interface with something like:
Upon snap connect, this allows foo to introspect gnome-logs-udt and use its entire DBus API.
Please see #1613 (comment) for complete details.
LP: #1590679