keyring: Convert to Secrets DBUS API

This fixes keyring support since the gnome bindings are busted, while
also giving us a chance of working natively on KDE.

I haven't added an explicit dep on libsecret in the spec, since this is
such minor functionality it's not worth pulling the dep, which should
be there on all modern desktops anyways.
This commit is contained in:
Cole Robinson 2013-04-16 16:20:58 -04:00
parent c60ad16b3b
commit 22c3bd62b3
3 changed files with 60 additions and 77 deletions

View File

@ -5,7 +5,6 @@
check all XXX/TODO in the code, make sure nothing important is missing check all XXX/TODO in the code, make sure nothing important is missing
revive import blacklist for virtinst code, maybe just a unittest that checks Gtk isn't in globals ? revive import blacklist for virtinst code, maybe just a unittest that checks Gtk isn't in globals ?
break out osdistro bits so we don't need to carry virt-install.pod break out osdistro bits so we don't need to carry virt-install.pod
gnome keyring entirely over dbus?
is tui working? maybe just remove it, check with mcpierce is tui working? maybe just remove it, check with mcpierce
gsettings port (or fix gconf bindings) gsettings port (or fix gconf bindings)

View File

@ -79,17 +79,6 @@ Requires: gnome-python2-gconf >= 1.99.11-7
# This version not strictly required: virt-manager should work with older, # This version not strictly required: virt-manager should work with older,
# however varying amounts of functionality will not be enabled. # however varying amounts of functionality will not be enabled.
Requires: libvirt-python >= 0.7.0 Requires: libvirt-python >= 0.7.0
%if 0%{?rhel} > 6
# Might work with earlier, but this is what we've tested
Requires: gnome-keyring >= 0.4.9
%else
Requires: libgnome-keyring
%endif
# Minimum we've tested with
# Although if you don't have this, comment it out and the app
# will work just fine - keyring functionality will simply be
# disabled
Requires: gnome-python2-gnomekeyring >= 2.15.4
# Minimum we've tested with # Minimum we've tested with
Requires: libxml2-python >= 2.6.23 Requires: libxml2-python >= 2.6.23
# Earlier vte had broken python binding module # Earlier vte had broken python binding module

View File

@ -20,103 +20,98 @@
import logging import logging
try: # pylint: disable=E0611
from gi.repository import GnomeKeyring # pylint: disable=E0611 from gi.repository import Gio
except: from gi.repository import GLib
GnomeKeyring = None # pylint: enable=E0611
logging.debug("GnomeKeyring bindings not installed, no keyring support")
class vmmSecret(object): class vmmSecret(object):
def __init__(self, name, secret=None, attributes=None): def __init__(self, name, secret=None, attributes=None):
self.name = name self.name = name
self.secret = secret self.secret = secret
self.attributes = attributes
self.attributes = {}
if isinstance(attributes, dict):
self.attributes = attributes
elif isinstance(attributes, list):
for attr in attributes:
self.attributes[attr.name] = attr.get_string()
def get_secret(self): def get_secret(self):
return self.secret return self.secret
def get_name(self): def get_name(self):
return self.name return self.name
def get_attributes_for_keyring(self):
attrs = GnomeKeyring.attribute_list_new()
for key, value in self.attributes.items():
GnomeKeyring.attribute_list_append_string(attrs, key, value)
return attrs
class vmmKeyring(object): class vmmKeyring(object):
def __init__(self): def __init__(self):
self.keyring = None self._collection = None
if GnomeKeyring is None:
return
try: try:
result = GnomeKeyring.get_default_keyring_sync() self._dbus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
if result and result[0] == GnomeKeyring.Result.OK: self._service = Gio.DBusProxy.new_sync(self._dbus, 0, None,
self.keyring = result[1] "org.freedesktop.secrets",
"/org/freedesktop/secrets",
"org.freedesktop.Secret.Service", None)
if self.keyring is None: self._session = self._service.OpenSession("(sv)", "plain",
self.keyring = 'default' GLib.Variant("s", ""))[1]
logging.debug("No default keyring, creating '%s'",
self.keyring) self._collection = Gio.DBusProxy.new_sync(self._dbus, 0, None,
try: "org.freedesktop.secrets",
GnomeKeyring.create_sync(self.keyring, None) "/org/freedesktop/secrets/aliases/default",
except GnomeKeyring.AlreadyExistsError: "org.freedesktop.Secret.Collection", None)
pass
logging.debug("Using keyring session %s", self._session)
except: except:
logging.exception("Error determining keyring") logging.exception("Error determining keyring")
self.keyring = None
##############
# Public API #
##############
def is_available(self): def is_available(self):
return not (self.keyring is None) return not (self._collection is None)
def add_secret(self, secret): def add_secret(self, secret):
_id = None ret = None
try: try:
result, _id = GnomeKeyring.item_create_sync( props = {
self.keyring, "org.freedesktop.Secret.Item.Label" : GLib.Variant("s", secret.get_name()),
GnomeKeyring.ItemType.GENERIC_SECRET, "org.freedesktop.Secret.Item.Attributes" : GLib.Variant("a{ss}", secret.attributes),
secret.get_name(), }
secret.get_attributes_for_keyring(), params = (self._session, [],
secret.get_secret(), [ord(v) for v in secret.get_secret()],
True) "text/plain; charset=utf8")
replace = True
if result != GnomeKeyring.Result.OK: _id = self._collection.CreateItem("(a{sv}(oayays)b)",
raise RuntimeError("Creating keyring item failed with: %s" % props, params, replace)[0]
repr(result)) ret = int(_id.rsplit("/")[-1])
except: except:
logging.exception("Failed to add keyring secret") logging.exception("Failed to add keyring secret")
return _id return ret
def get_secret(self, _id): def get_secret(self, _id):
""" ret = None
ignore, item = GnomeKeyring.item_get_info_sync(self.keyring, _id)
if item is None:
return
sec = None
try: try:
result, attrs = GnomeKeyring.item_get_attributes_sync( path = self._collection.get_object_path() + "/" + str(_id)
self.keyring, _id) iface = Gio.DBusProxy.new_sync(self._dbus, 0, None,
if result != GnomeKeyring.Result.OK: "org.freedesktop.secrets", path,
raise RuntimeError("Fetching keyring attributes failed " "org.freedesktop.Secret.Item", None)
"with %s" % result)
sec = vmmSecret(item.get_display_name(), item.get_secret(), attrs) secretbytes = iface.GetSecret("(o)", self._session)[2]
label = iface.get_cached_property("Label").unpack().strip("'")
dbusattrs = iface.get_cached_property("Attributes").unpack()
secret = u"".join([unichr(c) for c in secretbytes])
attrs = {}
for key, val in dbusattrs.items():
if key not in ["hvuri", "uuid"]:
continue
attrs["%s" % key] = "%s" % val
ret = vmmSecret(label, secret, attrs)
except: except:
logging.exception("Failed to lookup keyring item %s", item) logging.exception("Failed to get keyring secret id=%s", _id)
return sec return ret
"""
# FIXME: Uncomment this once gnome-keyring is fixed
# https://bugzilla.gnome.org/show_bug.cgi?id=691638
ignore = _id
return None