From 7339dc032d45f90b5a753c7c76aa2033b0d357b5 Mon Sep 17 00:00:00 2001 From: David Pilnik Date: Sun, 10 Dec 2023 21:13:02 +0200 Subject: [PATCH] Add Redis ACL support --- src/swsssdk/__init__.py | 4 +++- src/swsssdk/interface.py | 11 ++++++++++- src/swsssdk/sonic_db_dump_load.py | 1 + src/swsssdk/util.py | 24 ++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/swsssdk/__init__.py b/src/swsssdk/__init__.py index c1360b21c..529a2178f 100644 --- a/src/swsssdk/__init__.py +++ b/src/swsssdk/__init__.py @@ -10,7 +10,9 @@ if ('unittest' not in sys.modules.keys() and 'mockredis' not in sys.modules.keys() and - 'mock' not in sys.modules.keys()): + 'mock' not in sys.modules.keys() and + 'netq_agent' not in sys.modules.keys()): + # netq_agent temporary fix until move to swsscommon lib. msg = "sonic-py-swsssdk been deprecated, please switch to sonic-swss-common." logger.exception(msg) raise ImportError("sonic-py-swsssdk been deprecated, please switch to sonic-swss-common.") diff --git a/src/swsssdk/interface.py b/src/swsssdk/interface.py index d88318001..308460ff2 100644 --- a/src/swsssdk/interface.py +++ b/src/swsssdk/interface.py @@ -1,5 +1,6 @@ import time from functools import wraps +from . import util import redis from redis import RedisError @@ -143,6 +144,8 @@ class DBInterface(object): ACS Redis db mainly uses hash, therefore h is selected. """ + ACL_PW_PATH = '/etc/shadow_redis_dir/shadow_redis_admin' + def __init__(self, **kwargs): super(DBInterface, self).__init__() @@ -151,7 +154,13 @@ def __init__(self, **kwargs): self.redis_kwargs = kwargs if len(self.redis_kwargs) == 0: self.redis_kwargs['unix_socket_path'] = self.REDIS_UNIX_SOCKET_PATH - + self.redis_kwargs['username'] = 'admin' + if 'password' not in self.redis_kwargs: + self.redis_kwargs['password'] = util.read_from_file(self.ACL_PW_PATH) + redis_shadow_tls_ca="/etc/shadow_redis_dir/certs_redis/ca.crt" + self.redis_kwargs['ssl'] = True + self.redis_kwargs['ssl_cert_reqs'] = None + self.redis_kwargs['ssl_ca_certs'] = redis_shadow_tls_ca # For thread safety as recommended by python-redis # Create a separate client for each database self.redis_clients = DBRegistry() diff --git a/src/swsssdk/sonic_db_dump_load.py b/src/swsssdk/sonic_db_dump_load.py index acf5e5db5..103afa5be 100644 --- a/src/swsssdk/sonic_db_dump_load.py +++ b/src/swsssdk/sonic_db_dump_load.py @@ -97,6 +97,7 @@ def do_load(options, args): usage += "\nfrom standard input." parser = optparse.OptionParser(usage=usage) parser.add_option('-w', '--password', help='connect with PASSWORD') + parser.add_option('-u', '--username', help='connect with USERNAME') if help == DUMP: parser.add_option('-n', '--dbname', help='dump DATABASE (APPL_DB/ASIC_DB...)') parser.add_option('-t', '--conntype', help='indicate redis connection type (tcp[default] or unix_socket)', default='tcp') diff --git a/src/swsssdk/util.py b/src/swsssdk/util.py index a63c98a38..4e7a05a5b 100644 --- a/src/swsssdk/util.py +++ b/src/swsssdk/util.py @@ -65,3 +65,27 @@ def setup_logging(config_file_path, log_level=logging.INFO): logging.root.exception( "Could not load specified logging configuration '{}'. Verify the filepath exists and is compliant with: " "[https://docs.python.org/3/library/logging.config.html#object-connections]".format(config_file_path)) + + +def read_from_file(file_path, target_type=str): + """ + Read content from file and convert to target type + :param file_path: File path + :param target_type: target type + :return: content of the file according the target type. + """ + value = None + try: + with open(file_path, 'r') as f: + value = f.read() + if value is None: + # None return value is not allowed in any case, so we log error here for further debug. + logging.error('Failed to read from {}, value is None, errno is {}'.format(file_path, ctypes.get_errno())) + # Raise ValueError for the except statement to handle this as a normal exception + raise ValueError('File content of {} is None'.format(file_path)) + else: + value = target_type(value.strip()) + except (ValueError, IOError) as e: + logging.error('Failed to read from {}, errno is {}'.format(file_path, str(e))) + + return value