diff --git a/apps/common/cache.py b/apps/common/cache.py index 168f9e9d3..b988a8673 100644 --- a/apps/common/cache.py +++ b/apps/common/cache.py @@ -1,11 +1,9 @@ import time -from redis import Redis - from common.utils.lock import DistributedLock +from common.utils.connection import get_redis_client from common.utils import lazyproperty from common.utils import get_logger -from jumpserver.const import CONFIG logger = get_logger(__file__) @@ -58,7 +56,7 @@ class Cache(metaclass=CacheType): def __init__(self): self._data = None - self.redis = Redis(host=CONFIG.REDIS_HOST, port=CONFIG.REDIS_PORT, password=CONFIG.REDIS_PASSWORD) + self.redis = get_redis_client() def __getitem__(self, item): return self.field_desc_mapper[item] diff --git a/apps/common/utils/connection.py b/apps/common/utils/connection.py index 22625c8ad..22030c809 100644 --- a/apps/common/utils/connection.py +++ b/apps/common/utils/connection.py @@ -1,23 +1,29 @@ import json import threading -import redis +from redis import Redis from django.conf import settings +from jumpserver.const import CONFIG +from common.http import is_true from common.db.utils import safe_db_connection from common.utils import get_logger logger = get_logger(__name__) -def get_redis_client(db): - rc = redis.StrictRedis( - host=settings.REDIS_HOST, - port=settings.REDIS_PORT, - password=settings.REDIS_PASSWORD, - db=db - ) - return rc +def get_redis_client(db=0): + params = { + 'host': CONFIG.REDIS_HOST, + 'port': CONFIG.REDIS_PORT, + 'password': CONFIG.REDIS_PASSWORD, + 'db': db, + "ssl": is_true(CONFIG.REDIS_USE_SSL), + 'ssl_keyfile': getattr(settings, 'REDIS_SSL_KEYFILE'), + 'ssl_certfile': getattr(settings, 'REDIS_SSL_CERTFILE'), + 'ssl_ca_certs': getattr(settings, 'REDIS_SSL_CA_CERTS'), + } + return Redis(**params) class Subscription: @@ -99,5 +105,3 @@ class RedisPubSub: data_json = json.dumps(data) self.redis.publish(self.ch, data_json) return True - - diff --git a/apps/common/utils/lock.py b/apps/common/utils/lock.py index c9e4e9734..a14fe1184 100644 --- a/apps/common/utils/lock.py +++ b/apps/common/utils/lock.py @@ -10,6 +10,7 @@ from django.db import transaction from common.utils import get_logger from common.utils.inspect import copy_function_args +from common.utils.connection import get_redis_client from jumpserver.const import CONFIG from common.local import thread_local @@ -44,7 +45,7 @@ class DistributedLock(RedisLock): 是否可重入 """ self.kwargs_copy = copy_function_args(self.__init__, locals()) - redis = Redis(host=CONFIG.REDIS_HOST, port=CONFIG.REDIS_PORT, password=CONFIG.REDIS_PASSWORD) + redis = get_redis_client() if expire is None: expire = auto_renewal_seconds diff --git a/apps/jumpserver/rewriting/session.py b/apps/jumpserver/rewriting/session.py index d0e698070..7b5ee150e 100644 --- a/apps/jumpserver/rewriting/session.py +++ b/apps/jumpserver/rewriting/session.py @@ -1,8 +1,39 @@ -from redis_sessions.session import force_unicode, SessionStore as RedisSessionStore -from redis import exceptions +from redis_sessions.session import ( + force_unicode, SessionStore as RedisSessionStore, + RedisServer as RedisRedisServer, settings as redis_setting +) +from redis import exceptions, Redis +from django.conf import settings + +from jumpserver.const import CONFIG + + +class RedisServer(RedisRedisServer): + __redis = {} + + def get(self): + if self.connection_key in self.__redis: + return self.__redis[self.connection_key] + + ssl_params = {} + if CONFIG.REDIS_USE_SSL: + ssl_params = { + 'ssl_keyfile': getattr(settings, 'REDIS_SSL_KEYFILE'), + 'ssl_certfile': getattr(settings, 'REDIS_SSL_CERTFILE'), + 'ssl_ca_certs': getattr(settings, 'REDIS_SSL_CA_CERTS'), + } + # 只根据 redis_url 方式连接 + self.__redis[self.connection_key] = Redis.from_url( + redis_setting.SESSION_REDIS_URL, **ssl_params + ) + + return self.__redis[self.connection_key] class SessionStore(RedisSessionStore): + def __init__(self, session_key=None): + super(SessionStore, self).__init__(session_key) + self.server = RedisServer(session_key).get() def load(self): try: diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index d81089a6d..cb77177ec 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -135,10 +135,13 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE = CONFIG.SESSION_EXPIRE_AT_BROWSER_CLOSE_F SESSION_SAVE_EVERY_REQUEST = CONFIG.SESSION_SAVE_EVERY_REQUEST SESSION_ENGINE = 'jumpserver.rewriting.session' SESSION_REDIS = { - 'host': CONFIG.REDIS_HOST, - 'port': CONFIG.REDIS_PORT, - 'password': CONFIG.REDIS_PASSWORD, - 'db': CONFIG.REDIS_DB_SESSION, + 'url': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % { + 'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis', + 'password': CONFIG.REDIS_PASSWORD, + 'host': CONFIG.REDIS_HOST, + 'port': CONFIG.REDIS_PORT, + 'db': CONFIG.REDIS_DB_CACHE, + }, 'prefix': 'auth_session', 'socket_timeout': 1, 'retry_on_timeout': False @@ -246,18 +249,28 @@ FILE_UPLOAD_PERMISSIONS = 0o644 FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755 # Cache use redis +REDIS_SSL_KEYFILE = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_client.key') +REDIS_SSL_CERTFILE = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_client.crt') +REDIS_SSL_CA_CERTS = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_ca.crt') + CACHES = { 'default': { # 'BACKEND': 'redis_cache.RedisCache', 'BACKEND': 'redis_lock.django_cache.RedisCache', - 'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % { + 'LOCATION': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % { + 'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis', 'password': CONFIG.REDIS_PASSWORD, 'host': CONFIG.REDIS_HOST, 'port': CONFIG.REDIS_PORT, 'db': CONFIG.REDIS_DB_CACHE, }, 'OPTIONS': { - "REDIS_CLIENT_KWARGS": {"health_check_interval": 30} + "REDIS_CLIENT_KWARGS": {"health_check_interval": 30}, + "CONNECTION_POOL_KWARGS": { + "ssl_keyfile": REDIS_SSL_KEYFILE, + "ssl_certfile": REDIS_SSL_CERTFILE, + "ssl_ca_certs": REDIS_SSL_CA_CERTS + } if CONFIG.REDIS_USE_SSL else {} } } } diff --git a/apps/jumpserver/settings/libs.py b/apps/jumpserver/settings/libs.py index eb7b5a9eb..9bd56122b 100644 --- a/apps/jumpserver/settings/libs.py +++ b/apps/jumpserver/settings/libs.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # import os +import ssl + +from .base import REDIS_SSL_CA_CERTS, REDIS_SSL_CERTFILE, REDIS_SSL_KEYFILE from ..const import CONFIG, PROJECT_DIR REST_FRAMEWORK = { @@ -82,16 +85,24 @@ BOOTSTRAP3 = { # Django channels support websocket -CHANNEL_REDIS = "redis://:{}@{}:{}/{}".format( - CONFIG.REDIS_PASSWORD, CONFIG.REDIS_HOST, CONFIG.REDIS_PORT, - CONFIG.REDIS_DB_WS, -) +if not CONFIG.REDIS_USE_SSL: + context = None +else: + context = ssl.SSLContext() + context.check_hostname = False + context.load_verify_locations(REDIS_SSL_CA_CERTS) + context.load_cert_chain(REDIS_SSL_CERTFILE, REDIS_SSL_KEYFILE) CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { - "hosts": [CHANNEL_REDIS], + "hosts": [{ + 'address': (CONFIG.REDIS_HOST, CONFIG.REDIS_PORT), + 'db': CONFIG.REDIS_DB_WS, + 'password': CONFIG.REDIS_PASSWORD, + 'ssl': context + }], }, }, } @@ -102,7 +113,8 @@ ASGI_APPLICATION = 'jumpserver.routing.application' CELERY_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'celery') # Celery using redis as broker -CELERY_BROKER_URL = 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % { +CELERY_BROKER_URL = '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % { + 'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis', 'password': CONFIG.REDIS_PASSWORD, 'host': CONFIG.REDIS_HOST, 'port': CONFIG.REDIS_PORT, @@ -125,6 +137,13 @@ CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO" # CELERY_WORKER_HIJACK_ROOT_LOGGER = True # CELERY_WORKER_MAX_TASKS_PER_CHILD = 40 CELERY_TASK_SOFT_TIME_LIMIT = 3600 +if CONFIG.REDIS_USE_SSL: + CELERY_BROKER_USE_SSL = CELERY_REDIS_BACKEND_USE_SSL = { + 'ssl_cert_reqs': 'required', + 'ssl_ca_certs': REDIS_SSL_CA_CERTS, + 'ssl_certfile': REDIS_SSL_CERTFILE, + 'ssl_keyfile': REDIS_SSL_KEYFILE + } ANSIBLE_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'ansible') diff --git a/utils/start_celery_beat.py b/utils/start_celery_beat.py index 236a61ba8..714dbd826 100644 --- a/utils/start_celery_beat.py +++ b/utils/start_celery_beat.py @@ -18,7 +18,20 @@ os.environ.setdefault('PYTHONOPTIMIZE', '1') if os.getuid() == 0: os.environ.setdefault('C_FORCE_ROOT', '1') -redis = Redis(host=CONFIG.REDIS_HOST, port=CONFIG.REDIS_PORT, password=CONFIG.REDIS_PASSWORD) +REDIS_SSL_KEYFILE = os.path.join(BASE_DIR, 'data', 'certs', 'redis_client.key') +REDIS_SSL_CERTFILE = os.path.join(BASE_DIR, 'data', 'certs', 'redis_client.crt') +REDIS_SSL_CA_CERTS = os.path.join(BASE_DIR, 'data', 'certs', 'redis_ca.crt') + +params = { + 'host': CONFIG.REDIS_HOST, + 'port': CONFIG.REDIS_PORT, + 'password': CONFIG.REDIS_PASSWORD, + "ssl": CONFIG.REDIS_USE_SSL, + "ssl_keyfile": REDIS_SSL_KEYFILE, + "ssl_certfile": REDIS_SSL_CERTFILE, + "ssl_ca_certs": REDIS_SSL_CA_CERTS +} +redis = Redis(**params) scheduler = "django_celery_beat.schedulers:DatabaseScheduler" cmd = [