mirror of https://github.com/jumpserver/jumpserver
fix: Operatelog plaintext storage AKSK (#13506)
* fix: Operatelog plaintext storage AKSK * perf: Encrypt some field when saving operatelog * fix: Operatelog plaintext storage AKSK --------- Co-authored-by: jiangweidong <1053570670@qq.com>pull/13661/head
parent
d14d8869ac
commit
ba8d3be9a6
|
@ -5,7 +5,7 @@ from django.core.cache import cache
|
|||
from django.db import transaction
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.local import encrypted_field_set
|
||||
from common.local import similar_encrypted_pattern, exclude_encrypted_fields
|
||||
from common.utils import get_request_ip, get_logger
|
||||
from common.utils.encode import Singleton
|
||||
from common.utils.timezone import as_current_tz
|
||||
|
@ -109,19 +109,29 @@ class OperatorLogHandler(metaclass=Singleton):
|
|||
return ','.join(value)
|
||||
return json.dumps(value)
|
||||
|
||||
@staticmethod
|
||||
def __similar_check(key):
|
||||
if not key or key in exclude_encrypted_fields:
|
||||
return False
|
||||
|
||||
return bool(similar_encrypted_pattern.search(key))
|
||||
|
||||
def __data_processing(self, dict_item, loop=True):
|
||||
encrypt_value = '******'
|
||||
for key, value in dict_item.items():
|
||||
new_data = {}
|
||||
for label, item in dict_item.items():
|
||||
value = item.get('value', '')
|
||||
field_name = item.get('name', '')
|
||||
if isinstance(value, bool):
|
||||
value = _('Yes') if value else _('No')
|
||||
elif isinstance(value, (list, tuple)):
|
||||
value = self.serialized_value(value)
|
||||
elif isinstance(value, dict) and loop:
|
||||
self.__data_processing(value, loop=False)
|
||||
if key in encrypted_field_set:
|
||||
if self.__similar_check(field_name):
|
||||
value = encrypt_value
|
||||
dict_item[key] = value
|
||||
return dict_item
|
||||
new_data[label] = value
|
||||
return new_data
|
||||
|
||||
def data_processing(self, before, after):
|
||||
if before:
|
||||
|
|
|
@ -82,7 +82,9 @@ def _get_instance_field_value(
|
|||
elif isinstance(f, GenericForeignKey):
|
||||
continue
|
||||
try:
|
||||
data.setdefault(str(f.verbose_name), value)
|
||||
data.setdefault(
|
||||
str(f.verbose_name), {'name': getattr(f, 'column', ''), 'value': value}
|
||||
)
|
||||
except Exception as e:
|
||||
print(f.__dict__)
|
||||
raise e
|
||||
|
@ -106,7 +108,9 @@ def model_to_dict_for_operate_log(
|
|||
return
|
||||
try:
|
||||
field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name
|
||||
data.setdefault(str(field_key), value)
|
||||
data.setdefault(
|
||||
str(field_key), {'name': getattr(f, 'column', ''), 'value': value}
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ from django.db.models import Q, Manager, QuerySet
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.utils.encoders import JSONEncoder
|
||||
|
||||
from common.local import add_encrypted_field_set
|
||||
from common.utils import contains_ip
|
||||
from .utils import Encryptor
|
||||
from .validators import PortRangeValidator
|
||||
|
@ -168,7 +167,6 @@ class EncryptTextField(EncryptMixin, models.TextField):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
add_encrypted_field_set(self.verbose_name)
|
||||
|
||||
|
||||
class EncryptCharField(EncryptMixin, models.CharField):
|
||||
|
@ -184,7 +182,6 @@ class EncryptCharField(EncryptMixin, models.CharField):
|
|||
def __init__(self, *args, **kwargs):
|
||||
self.change_max_length(kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
add_encrypted_field_set(self.verbose_name)
|
||||
|
||||
def deconstruct(self):
|
||||
name, path, args, kwargs = super().deconstruct()
|
||||
|
@ -198,13 +195,11 @@ class EncryptCharField(EncryptMixin, models.CharField):
|
|||
class EncryptJsonDictTextField(EncryptMixin, JsonDictTextField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
add_encrypted_field_set(self.verbose_name)
|
||||
|
||||
|
||||
class EncryptJsonDictCharField(EncryptMixin, JsonDictCharField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
add_encrypted_field_set(self.verbose_name)
|
||||
|
||||
|
||||
class PortField(models.IntegerField):
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
from werkzeug.local import Local
|
||||
import re
|
||||
|
||||
from django.utils import translation
|
||||
from werkzeug.local import Local
|
||||
|
||||
|
||||
thread_local = Local()
|
||||
encrypted_field_set = {'password', 'secret'}
|
||||
exclude_encrypted_fields = ('secret_type', 'secret_strategy', 'password_rules')
|
||||
similar_encrypted_pattern = re.compile(
|
||||
'password|secret|token|passphrase|private|key|cert', re.IGNORECASE
|
||||
)
|
||||
|
||||
|
||||
def _find(attr):
|
||||
return getattr(thread_local, attr, None)
|
||||
|
||||
|
||||
def add_encrypted_field_set(label):
|
||||
return
|
||||
if label:
|
||||
with translation.override('en'):
|
||||
encrypted_field_set.add(str(label))
|
||||
|
|
|
@ -8,7 +8,6 @@ from rest_framework import serializers
|
|||
from rest_framework.fields import ChoiceField, empty
|
||||
|
||||
from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
|
||||
from common.local import add_encrypted_field_set
|
||||
from common.utils import decrypt_password
|
||||
|
||||
__all__ = [
|
||||
|
@ -47,9 +46,7 @@ class EncryptedField(serializers.CharField):
|
|||
if write_only is None:
|
||||
write_only = True
|
||||
kwargs["write_only"] = write_only
|
||||
encrypted_key = kwargs.pop('encrypted_key', None)
|
||||
super().__init__(**kwargs)
|
||||
add_encrypted_field_set(encrypted_key or self.label)
|
||||
|
||||
def to_internal_value(self, value):
|
||||
value = super().to_internal_value(value)
|
||||
|
|
Loading…
Reference in New Issue