Following my last post lines, I’ll show today how we can implement a wrapper class to "control" the Gnome Keyring. This isn’t the most secure way, since we store the keyring password in a variable. But is better then let your keyring open for all other applications.
First we need to create a class that creates a "Keyring Manager", responsible for:
- consulting the existing keyrings;
- create keyrings;
- delete keyrings;
- set the default keyring;
- lock all keyrings.
Secondly, we need a wrapper for the Keyring. Since the keyring has many features and is not my intention to wrap all those I’ll just show the essentials. My keyring wrapper is able to:
- lock the keyring;
- unlock the keyring;
- show if the keyring is locked
- list it’s item ids;
- give access to the GnomeKeyringInfo;
- change the keyring password;
- list the keyring’s item attributes;
- show the keyring’s item secret.
In my code, I’ve used some decorators to ensure that some informations will be updated before/after some task or to lock/unlock the keyring. This is my code:
import gnomekeyring as gk
import glib
APP_NAME = 'MyApp'
glib.set_application_name(APP_NAME)
if not gk.is_available():
print 'Gnome Keyring is unavailable!'
exit()
class KeyringManager:
def __init__(self):
self.default_keyring = gk.get_default_keyring_sync()
self.keyrings = gk.list_keyring_names_sync()
def __update_keyring_names(when):
def func(f):
def func_params(self, *args, **kwargs):
if when == 'before':
self.keyrings = gk.list_keyring_names_sync()
ret = f(self, *args, **kwargs)
if when == 'after':
self.keyrings = gk.list_keyring_names_sync()
return ret
return func_params
return func
@__update_keyring_names('after')
def create_keyring(self, name, password):
gk.create_sync(name, password)
@__update_keyring_names('after')
def delete_keyring(self, name):
gk.delete_sync(name)
def lock_all_keyrings(self):
gk.lock_all_sync()
def set_default_keyring(self, name):
gk.set_default_keyring_sync(name)
self.default_keyring = gk.get_default_keyring_sync()
@__update_keyring_names('before')
def __contains__(self, name):
return name in self.keyrings
@__update_keyring_names('before')
def __getitem__(self, name):
if name in self:
return Keyring(name)
return None
class Keyring:
def __init__(self, name):
self.name = name
self.info = gk.get_info_sync(name)
self.passwd = None
if not self.info.get_is_locked():
self.lock()
def lock(self):
gk.lock_sync(self.name)
def unlock(self, passwd):
gk.unlock_sync(self.name, passwd)
self.passwd = passwd
def __lock_unlock_dec(func):
def decorator(self, *args, **kwargs):
self.unlock(self.passwd)
ret = func(self, *args, **kwargs)
self.lock()
return ret
return decorator
@__lock_unlock_dec
def list_items_id(self):
self.items_id = gk.list_item_ids_sync(self.name)
return self.items_id
def is_locked(self):
self.update_info()
return self.info.get_is_locked()
def update_info(self):
self.info = gk.get_info_sync(self.name)
def change_password(self, old_passwd, new_passwd):
gk.change_password_sync(self.name, old_passwd, new_passwd)
@__lock_unlock_dec
def __getitem__(self, count):
item_id = gk.list_item_ids_sync(self.name)[count]
attr = gk.item_get_attributes_sync(self.name, item_id)
attr['id'] = item_id
return attr
@__lock_unlock_dec
def get_item_secret(self, item_id):
item_info = gk.item_get_info_sync(self.name, item_id)
return item_info.get_secret()
if __name__ == '__main__':
km = KeyringManager()
print km.keyrings
mykey = km['MyKeyring']
mykey.passwd = 'mypasswd'
print mykey.list_items_id()
print '#'*10
for item in mykey:
print item
print '#'*10
print mykey[0]
print 'item', mykey[0]['id'], 'secret:', mykey.get_item_secret(mykey[0]['id'])
I’ve saved this code as KeyringWrapper.py, it’s execution gives me the following output:
$ python KeyringWrapper.py
['Beholder', 'login', 'MyKeyring', 'session']
[1L, 2L, 3L]
##########
{'username': 'magnun', 'protocol': 'ssh', 'port': '22', 'application': 'MyApp', 'server': 'Neptune', 'id': 1L}
{'username': 'guest', 'protocol': 'ssh', 'port': '22', 'application': 'MyApp', 'server': 'Neptune', 'id': 2L}
{'username': 'magnun', 'protocol': 'ssh', 'port': '22', 'application': 'MyApp', 'server': 'Jupiter', 'id': 3L}
##########
{'username': 'magnun', 'protocol': 'ssh', 'port': '22', 'application': 'MyApp', 'server': 'Neptune', 'id': 1L}
item 1 secret: mypasswd
This code is just some basis. It’s necessary to expand it to wrap essential writing functions like item_set_attributes, set_info_sync, item_create and others. But as I said, this isn’t the most secure way, so I don’t think that write those wappers don’t worth the spent time.
Comments
comments powered by Disqus