Get keyring at runtime. By @samuel-w (#635)

This commit is contained in:
Samuel Woon 2020-09-27 02:19:39 -05:00 committed by GitHub
parent 38406f4c59
commit 9568a1b410
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 35 additions and 25 deletions

View File

@ -13,7 +13,8 @@ from subprocess import Popen, PIPE
from vorta.i18n import trans_late
from vorta.models import EventLogModel, BackupProfileMixin
from vorta.utils import keyring, borg_compat, pretty_bytes
from vorta.utils import borg_compat, pretty_bytes
from vorta.keyring.abc import get_keyring
from vorta.keyring.db import VortaDBKeyring
mutex = QtCore.QMutex()
@ -117,6 +118,7 @@ class BorgThread(QtCore.QThread, BackupProfileMixin):
return ret
# Try to get password from chosen keyring backend.
keyring = get_keyring()
logger.debug("Using %s keyring to store passwords.", keyring.__class__.__name__)
ret['password'] = keyring.get_password('vorta-repo', profile.repo.url)

View File

@ -1,7 +1,7 @@
from collections import namedtuple
from .borg_thread import BorgThread
from vorta.models import RepoModel
from vorta.utils import keyring
from vorta.keyring.abc import get_keyring
import os
FakeRepo = namedtuple('Repo', ['url', 'id', 'extra_borg_arguments'])
@ -60,7 +60,7 @@ class BorgInfoThread(BorgThread):
if 'encryption' in result['data']:
new_repo.encryption = result['data']['encryption']['mode']
if new_repo.encryption != 'none':
keyring.set_password("vorta-repo", new_repo.url, result['params']['password'])
get_keyring().set_password("vorta-repo", new_repo.url, result['params']['password'])
new_repo.extra_borg_arguments = result['params']['extra_borg_arguments']

View File

@ -1,7 +1,7 @@
from .borg_thread import BorgThread
from .info import FakeProfile, FakeRepo
from vorta.models import RepoModel
from vorta.utils import keyring
from vorta.keyring.abc import get_keyring
class BorgInitThread(BorgThread):
@ -44,5 +44,5 @@ class BorgInitThread(BorgThread):
}
)
if new_repo.encryption != 'none':
keyring.set_password("vorta-repo", new_repo.url, result['params']['password'])
get_keyring().set_password("vorta-repo", new_repo.url, result['params']['password'])
new_repo.save()

View File

@ -5,23 +5,10 @@ fall back to a simple database keystore if needed.
"""
import sys
_keyring = None
class VortaKeyring:
@classmethod
def get_keyring(cls):
if sys.platform == 'darwin': # Use Keychain on macOS
from .darwin import VortaDarwinKeyring
return VortaDarwinKeyring()
else: # Try to use DBus and Gnome-Keyring (available on Linux and *BSD)
import secretstorage
from .secretstorage import VortaSecretStorageKeyring
try:
return VortaSecretStorageKeyring()
# Save passwords in DB, if all else fails.
except secretstorage.SecretServiceNotAvailableException:
from .db import VortaDBKeyring
return VortaDBKeyring()
def set_password(self, service, repo_url, password):
raise NotImplementedError
@ -38,3 +25,25 @@ class VortaKeyring:
rather than a fallback (like our own VortaDBKeyring).
"""
return True
def get_keyring():
"""
Attempts to get secure keyring at runtime if current keyring is insecure.
Once it finds a secure keyring, it wil always use that keyring
"""
global _keyring
if _keyring is None or not _keyring.is_primary:
if sys.platform == 'darwin': # Use Keychain on macOS
from .darwin import VortaDarwinKeyring
return VortaDarwinKeyring()
else: # Try to use DBus and Gnome-Keyring (available on Linux and *BSD)
import secretstorage
from .secretstorage import VortaSecretStorageKeyring
try:
_keyring = VortaSecretStorageKeyring()
# Save passwords in DB, if all else fails.
except secretstorage.SecretServiceNotAvailableException:
from .db import VortaDBKeyring
_keyring = VortaDBKeyring()
return _keyring

View File

@ -20,15 +20,12 @@ from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from vorta.borg._compatibility import BorgCompatibility
from vorta.keyring.abc import VortaKeyring
from vorta.log import logger
from vorta.network_status.abc import NetworkStatusMonitor
QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) # enable highdpi scaling
QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) # use highdpi icons
keyring = VortaKeyring.get_keyring()
logger.info('Using %s Keyring implementation.', keyring.__class__.__name__)
borg_compat = BorgCompatibility()

View File

@ -65,7 +65,8 @@ def test_repo_add_success(qapp, qtbot, mocker, borg_json_output):
assert EventLogModel.select().count() == 1
assert RepoModel.get(id=2).url == test_repo_url
from vorta.utils import keyring
from vorta.keyring.abc import get_keyring
keyring = get_keyring()
assert keyring.get_password("vorta-repo", RepoModel.get(id=2).url) == LONG_PASSWORD

View File

@ -1,10 +1,11 @@
import uuid
from vorta.utils import keyring
from vorta.keyring.abc import get_keyring
def test_keyring(qapp):
UNICODE_PW = 'kjalsdfüadsfäadsfß'
REPO = f'vorta-test-repo.{uuid.uuid4()}.com:repo' # Random repo URL
keyring = get_keyring()
keyring.set_password('vorta-repo', REPO, UNICODE_PW)
assert keyring.get_password("vorta-repo", REPO) == UNICODE_PW