mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-15 10:47:49 -06:00
Store secrets as securely as possible
Use the keyring if allowed, available, otherwise use preference CURA-7180 keyring storage
This commit is contained in:
parent
47df060bee
commit
b604bbd255
2 changed files with 40 additions and 9 deletions
|
@ -53,7 +53,7 @@ class AuthorizationService:
|
||||||
|
|
||||||
self.onAuthStateChanged.connect(self._authChanged)
|
self.onAuthStateChanged.connect(self._authChanged)
|
||||||
|
|
||||||
self._secret_storage = SecretStorage()
|
self._secret_storage = None # type: Optional[SecretStorage]
|
||||||
|
|
||||||
def _authChanged(self, logged_in):
|
def _authChanged(self, logged_in):
|
||||||
if logged_in and self._unable_to_get_data_message is not None:
|
if logged_in and self._unable_to_get_data_message is not None:
|
||||||
|
@ -62,6 +62,7 @@ class AuthorizationService:
|
||||||
def initialize(self, preferences: Optional["Preferences"] = None) -> None:
|
def initialize(self, preferences: Optional["Preferences"] = None) -> None:
|
||||||
if preferences is not None:
|
if preferences is not None:
|
||||||
self._preferences = preferences
|
self._preferences = preferences
|
||||||
|
self._secret_storage = SecretStorage(preferences)
|
||||||
if self._preferences:
|
if self._preferences:
|
||||||
self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}")
|
self._preferences.addPreference(self._settings.AUTH_DATA_PREFERENCE_KEY, "{}")
|
||||||
|
|
||||||
|
@ -236,6 +237,7 @@ class AuthorizationService:
|
||||||
# Since we stored all the sensitive stuff in the keyring, restore that now.
|
# Since we stored all the sensitive stuff in the keyring, restore that now.
|
||||||
# Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
# Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
||||||
preferences_data["refresh_token"] = self._secret_storage["refresh_token"]
|
preferences_data["refresh_token"] = self._secret_storage["refresh_token"]
|
||||||
|
preferences_data["access_token"] = self._secret_storage["access_token"]
|
||||||
|
|
||||||
if preferences_data:
|
if preferences_data:
|
||||||
self._auth_data = AuthenticationResponse(**preferences_data)
|
self._auth_data = AuthenticationResponse(**preferences_data)
|
||||||
|
@ -267,11 +269,13 @@ class AuthorizationService:
|
||||||
# Store all the sensitive stuff in the keyring
|
# Store all the sensitive stuff in the keyring
|
||||||
# Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
# Don't store the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
||||||
self._secret_storage["refresh_token"] = auth_data.refresh_token
|
self._secret_storage["refresh_token"] = auth_data.refresh_token
|
||||||
|
self._secret_storage["access_token"] = auth_data.access_token
|
||||||
|
|
||||||
|
|
||||||
# And remove that data again so it isn't stored in the preferences.
|
# And remove that data again so it isn't stored in the preferences.
|
||||||
# Keep the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
# Keep the access_token, as it's very long and that (or tried workarounds) causes issues on Windows.
|
||||||
auth_data.refresh_token = None
|
auth_data.refresh_token = None
|
||||||
|
auth_data.access_token = None
|
||||||
|
|
||||||
self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(vars(auth_data)))
|
self._preferences.setValue(self._settings.AUTH_DATA_PREFERENCE_KEY, json.dumps(vars(auth_data)))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,20 +1,47 @@
|
||||||
import keyring
|
from typing import Optional
|
||||||
|
|
||||||
|
import keyring # TODO: Add to about as dependency
|
||||||
|
|
||||||
|
from UM.Logger import Logger
|
||||||
|
|
||||||
|
|
||||||
class SecretStorage:
|
class SecretStorage:
|
||||||
def __init__(self):
|
def __init__(self, preferences: Optional["Preferences"] = None):
|
||||||
self._stored_secrets = []
|
self._stored_secrets = {}
|
||||||
|
if preferences:
|
||||||
|
self._preferences = preferences
|
||||||
|
keys = self._preferences.getValue("general/keyring")
|
||||||
|
if keys is not None and keys != '':
|
||||||
|
self._stored_secrets = set(keys.split(";"))
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
if key in self._stored_secrets:
|
if key in self._stored_secrets:
|
||||||
del self._stored_secrets[key]
|
self._stored_secrets.remove(key)
|
||||||
|
self._preferences.setValue("general/keyring", ";".join(self._stored_secrets))
|
||||||
keyring.delete_password("cura", key)
|
keyring.delete_password("cura", key)
|
||||||
|
else:
|
||||||
|
# TODO: handle removal of secret from preferences
|
||||||
|
pass
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self._stored_secrets.append(key)
|
try:
|
||||||
keyring.set_password("cura", key, value)
|
keyring.set_password("cura", key, value)
|
||||||
|
self._stored_secrets.add(key)
|
||||||
|
self._preferences.setValue(f"general/{key}", None)
|
||||||
|
self._preferences.setValue("general/keyring", ";".join(self._stored_secrets))
|
||||||
|
except:
|
||||||
|
Logger.logException("w", f"Could not store {key} in keyring.")
|
||||||
|
self._preferences.setValue(f"general/{key}", value)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
|
secret = self._preferences.getValue(f"general/{key}")
|
||||||
if key in self._stored_secrets:
|
if key in self._stored_secrets:
|
||||||
return keyring.get_password("cura", key)
|
try:
|
||||||
return None
|
secret = keyring.get_password("cura", key)
|
||||||
|
except:
|
||||||
|
if secret:
|
||||||
|
Logger.logException("w",
|
||||||
|
f"{key} obtained from preferences, consider giving Cura access to the keyring")
|
||||||
|
if secret is None or secret == 'null':
|
||||||
|
Logger.logException("w", f"Could not load {key}")
|
||||||
|
return secret
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue