X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=meta-starlingx%2Fmeta-stx-cloud%2Frecipes-devtools%2Fpython%2Ffiles%2Fpython-keyring%2Fuse_new_lock.patch;fp=meta-starlingx%2Fmeta-stx-cloud%2Frecipes-devtools%2Fpython%2Ffiles%2Fpython-keyring%2Fuse_new_lock.patch;h=0000000000000000000000000000000000000000;hb=6fc6934434f70595536a387ece31bc30141cafb5;hp=d298c20ea8be6b018f78117d4b4317d5a93cdb09;hpb=eb1e26510491ba49de693ab3b0498edcb06be6c5;p=pti%2Frtp.git diff --git a/meta-starlingx/meta-stx-cloud/recipes-devtools/python/files/python-keyring/use_new_lock.patch b/meta-starlingx/meta-stx-cloud/recipes-devtools/python/files/python-keyring/use_new_lock.patch deleted file mode 100644 index d298c20..0000000 --- a/meta-starlingx/meta-stx-cloud/recipes-devtools/python/files/python-keyring/use_new_lock.patch +++ /dev/null @@ -1,243 +0,0 @@ -Index: keyring-5.3/keyring/backends/file.py -=================================================================== ---- keyring-5.3.orig/keyring/backends/file.py -+++ keyring-5.3/keyring/backends/file.py -@@ -7,6 +7,8 @@ import sys - import json - import abc - import time -+import logging -+import shutil - - from ..py27compat import configparser - -@@ -14,6 +16,7 @@ from ..errors import PasswordDeleteError - from ..backend import KeyringBackend - from ..util import platform_, properties - from ..util.escape import escape as escape_for_ini -+from oslo_concurrency import lockutils - - - class FileBacked(object): -@@ -31,6 +34,13 @@ class FileBacked(object): - """ - return os.path.join(platform_.data_root(), self.filename) - -+ @properties.NonDataProperty -+ def backup_file_path(self): -+ """ -+ The path to the file where passwords are stored. This property -+ may be overridden by the subclass or at the instance level. -+ """ -+ return os.path.join(platform_.data_root(), self.backup_filename) - - class BaseKeyring(FileBacked, KeyringBackend): - """ -@@ -78,6 +88,16 @@ class BaseKeyring(FileBacked, KeyringBac - password = None - return password - -+ -+ def filecopy(self,src,dest): -+ """copy file src to dest with default buffer size -+ """ -+ with open(src, 'r') as f1: -+ with open(dest, 'w') as f2: -+ shutil.copyfileobj(f1,f2) -+ f2.flush() -+ -+ - def set_password(self, service, username, password): - """Write the password in the file. - """ -@@ -89,37 +109,56 @@ class BaseKeyring(FileBacked, KeyringBac - # encode with base64 - password_base64 = base64.encodestring(password_encrypted).decode() - -- # ensure the file exists -- self._ensure_file_path() - -- # obtain lock for the keyring file -- lock = '' -- i = 60 -- while i: -- if not os.path.isfile('/tmp/.keyringlock'): -- lock = open('/tmp/.keyringlock', 'w') -- break -- else: -- time.sleep(0.500) -- i=i-1 -+ with lockutils.lock("keyringlock",external=True,lock_path="/tmp"): - -+ # ensure the file exists -+ self._ensure_file_path() -+ -+ config = None -+ try: -+ # Load the keyring from the disk -+ config = configparser.RawConfigParser() -+ config.read(self.file_path) -+ except configparser.ParsingError as e: -+ logging.warning("set_password: keyring file corrupted, Reverting to Backup") -+ # Revert to the backup file (copy backup over current file) -+ try: -+ src = self.backup_file_path -+ dest = self.file_path -+ self.filecopy(src,dest) -+ except shutil.Error as e: -+ logging.warning("set_password: Revert from Backup failed. Error: %s" % e) -+ raise -+ # Load the keyring from the disk, if this fails exception is raised -+ try: -+ config = configparser.RawConfigParser() -+ config.read(self.file_path) -+ except: -+ e = sys.exc_info()[0] -+ logging.warning("set_password: Both keyring files are non useable. Error: %s" % e) -+ raise - -- if i: -- # Load the keyring from the disk -- config = configparser.RawConfigParser() -- config.read(self.file_path) - - # Update the keyring with the password - if not config.has_section(service): - config.add_section(service) - config.set(service, username, password_base64) - -+ # Make a back up of the keyring file here -+ try: -+ src = self.file_path -+ dest = self.backup_file_path -+ self.filecopy(src,dest) -+ except shutil.Error as e: -+ logging.warning("set_password: Backup failed. Error: %s" % e) -+ - # Save the keyring back to the file - with open(self.file_path, 'w') as config_file: - config.write(config_file) - -- lock.close() -- os.remove('/tmp/.keyringlock') -+ -+ - - - def _ensure_file_path(self): -@@ -142,17 +181,18 @@ class BaseKeyring(FileBacked, KeyringBac - """ - service = escape_for_ini(service) - username = escape_for_ini(username) -- config = configparser.RawConfigParser() -- if os.path.exists(self.file_path): -- config.read(self.file_path) -- try: -- if not config.remove_option(service, username): -+ with lockutils.lock("keyringlock",external=True,lock_path="/tmp"): -+ config = configparser.RawConfigParser() -+ if os.path.exists(self.file_path): -+ config.read(self.file_path) -+ try: -+ if not config.remove_option(service, username): -+ raise PasswordDeleteError("Password not found") -+ except configparser.NoSectionError: - raise PasswordDeleteError("Password not found") -- except configparser.NoSectionError: -- raise PasswordDeleteError("Password not found") -- # update the file -- with open(self.file_path, 'w') as config_file: -- config.write(config_file) -+ # update the file -+ with open(self.file_path, 'w') as config_file: -+ config.write(config_file) - - class PlaintextKeyring(BaseKeyring): - """Simple File Keyring with no encryption""" -@@ -161,6 +201,7 @@ class PlaintextKeyring(BaseKeyring): - "Applicable for all platforms, but not recommended" - - filename = 'keyring_pass.cfg' -+ backup_filename = 'crypted_pass_backup.cfg' - - def encrypt(self, password): - """Directly return the password itself. -@@ -214,6 +255,7 @@ class EncryptedKeyring(Encrypted, BaseKe - """PyCrypto File Keyring""" - - filename = 'crypted_pass.cfg' -+ backup_filename = 'crypted_pass_backup.cfg' - pw_prefix = 'pw:'.encode() - - @properties.ClassProperty -@@ -247,6 +289,19 @@ class EncryptedKeyring(Encrypted, BaseKe - self.keyring_key = self._get_new_password() - # set a reference password, used to check that the password provided - # matches for subsequent checks. -+ -+ # try to pre-create the /tmp/keyringlock if it doesn't exist -+ lockfile = "/tmp/keyringlock" -+ if os.geteuid() == 0 and (not os.path.exists(lockfile)): -+ from pwd import getpwnam -+ import stat -+ nonrootuser = "sysadmin" -+ with open(lockfile, 'w'): -+ pass -+ # must have the lock file with the correct group permissisions g+rw -+ os.chmod(lockfile, stat.S_IRWXG | stat.S_IRWXU) -+ -+ - self.set_password('keyring-setting', 'password reference', - 'password reference value') - -@@ -257,15 +312,41 @@ class EncryptedKeyring(Encrypted, BaseKe - if not os.path.exists(self.file_path): - return False - self._migrate() -- config = configparser.RawConfigParser() -- config.read(self.file_path) -- try: -- config.get( -- escape_for_ini('keyring-setting'), -- escape_for_ini('password reference'), -- ) -- except (configparser.NoSectionError, configparser.NoOptionError): -- return False -+ -+ # lock access to the file_path here, make sure it's not being written -+ # to while while we're checking for keyring-setting -+ with lockutils.lock("keyringlock",external=True,lock_path="/tmp"): -+ config = configparser.RawConfigParser() -+ config.read(self.file_path) -+ try: -+ config.get( -+ escape_for_ini('keyring-setting'), -+ escape_for_ini('password reference'), -+ ) -+ except (configparser.NoSectionError, configparser.NoOptionError): -+ # The current file doesn't have the keyring-setting, check the backup -+ logging.warning("_check_file: The current file doesn't have the keyring-setting, check the backup") -+ if os.path.exists(self.backup_file_path): -+ config = configparser.RawConfigParser() -+ config.read(self.backup_file_path) -+ try: -+ config.get( -+ escape_for_ini('keyring-setting'), -+ escape_for_ini('password reference'), -+ ) -+ except (configparser.NoSectionError, configparser.NoOptionError): -+ return False -+ # backup file has it, let's use it -+ try: -+ src = self.backup_file_path -+ dest = self.file_path -+ shutil.copy(src,dest) -+ except shutil.Error as e: -+ logging.warning("Revert from Backup failed. Error: %s" % e) -+ return False -+ else: -+ return False -+ - return True - - def _unlock(self):