New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
interfaces/builtin: add dbus interface #1613
Conversation
Test with: go build -tags=excludeintegration -v github.com/snapcore/snapd/... && go test -tags=excludeintegration -v github.com/snapcore/snapd/interfaces/builtin
dot_re := regexp.MustCompile("\\.") | ||
var pathBuf bytes.Buffer | ||
pathBuf.WriteString(`"/`) | ||
pathBuf.WriteString(dot_re.ReplaceAllString(name, "/")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the bit stands that this could be just strings.Replace(name, ".", "/", -1)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
// Obtain yaml-specified bus well-known name | ||
func (iface *DbusInterface) getAttribs(attribs map[string]interface{}) (string, string, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be better to use named results here: (bus, name string, err error)
} | ||
|
||
// ensure that we only connect to slot with matching attributes | ||
if bus != busPlug || name != namePlug { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
return "", "", fmt.Errorf("DBus bus name must not end with -NUMBER") | ||
} | ||
|
||
if bus == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pedronis, you are right. These are a holdover from a refactor. Removed.
@pedronis, I believe I addressed your comments. |
@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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks reasonable given the current infra limitations
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. |
bus=###DBUS_BUS### | ||
path=/org/freedesktop/DBus | ||
interface=org.freedesktop.DBus | ||
member="GetConnectionUnix{ProcessID,User}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a good point. Done
var ifaceBuf bytes.Buffer | ||
ifaceBuf.WriteString(`"`) | ||
ifaceBuf.WriteString(name) | ||
ifaceBuf.WriteString(`{,.*}"`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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(`{,/**}"`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above comment. We intentionally left out path configuration in this initial implementation.
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:
|
Thanks especially @niemeyer for your time on this and thank you to all reviewers and commenters for your input and reviews! :) |
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