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.db import transaction
|
||||||
from django.utils.translation import gettext_lazy as _
|
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 import get_request_ip, get_logger
|
||||||
from common.utils.encode import Singleton
|
from common.utils.encode import Singleton
|
||||||
from common.utils.timezone import as_current_tz
|
from common.utils.timezone import as_current_tz
|
||||||
|
@ -109,19 +109,29 @@ class OperatorLogHandler(metaclass=Singleton):
|
||||||
return ','.join(value)
|
return ','.join(value)
|
||||||
return json.dumps(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):
|
def __data_processing(self, dict_item, loop=True):
|
||||||
encrypt_value = '******'
|
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):
|
if isinstance(value, bool):
|
||||||
value = _('Yes') if value else _('No')
|
value = _('Yes') if value else _('No')
|
||||||
elif isinstance(value, (list, tuple)):
|
elif isinstance(value, (list, tuple)):
|
||||||
value = self.serialized_value(value)
|
value = self.serialized_value(value)
|
||||||
elif isinstance(value, dict) and loop:
|
elif isinstance(value, dict) and loop:
|
||||||
self.__data_processing(value, loop=False)
|
self.__data_processing(value, loop=False)
|
||||||
if key in encrypted_field_set:
|
if self.__similar_check(field_name):
|
||||||
value = encrypt_value
|
value = encrypt_value
|
||||||
dict_item[key] = value
|
new_data[label] = value
|
||||||
return dict_item
|
return new_data
|
||||||
|
|
||||||
def data_processing(self, before, after):
|
def data_processing(self, before, after):
|
||||||
if before:
|
if before:
|
||||||
|
|
|
@ -82,7 +82,9 @@ def _get_instance_field_value(
|
||||||
elif isinstance(f, GenericForeignKey):
|
elif isinstance(f, GenericForeignKey):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
data.setdefault(str(f.verbose_name), value)
|
data.setdefault(
|
||||||
|
str(f.verbose_name), {'name': getattr(f, 'column', ''), 'value': value}
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f.__dict__)
|
print(f.__dict__)
|
||||||
raise e
|
raise e
|
||||||
|
@ -106,7 +108,9 @@ def model_to_dict_for_operate_log(
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name
|
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:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ from django.db.models import Q, Manager, QuerySet
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework.utils.encoders import JSONEncoder
|
from rest_framework.utils.encoders import JSONEncoder
|
||||||
|
|
||||||
from common.local import add_encrypted_field_set
|
|
||||||
from common.utils import contains_ip
|
from common.utils import contains_ip
|
||||||
from .utils import Encryptor
|
from .utils import Encryptor
|
||||||
from .validators import PortRangeValidator
|
from .validators import PortRangeValidator
|
||||||
|
@ -168,7 +167,6 @@ class EncryptTextField(EncryptMixin, models.TextField):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
add_encrypted_field_set(self.verbose_name)
|
|
||||||
|
|
||||||
|
|
||||||
class EncryptCharField(EncryptMixin, models.CharField):
|
class EncryptCharField(EncryptMixin, models.CharField):
|
||||||
|
@ -184,7 +182,6 @@ class EncryptCharField(EncryptMixin, models.CharField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.change_max_length(kwargs)
|
self.change_max_length(kwargs)
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
add_encrypted_field_set(self.verbose_name)
|
|
||||||
|
|
||||||
def deconstruct(self):
|
def deconstruct(self):
|
||||||
name, path, args, kwargs = super().deconstruct()
|
name, path, args, kwargs = super().deconstruct()
|
||||||
|
@ -198,13 +195,11 @@ class EncryptCharField(EncryptMixin, models.CharField):
|
||||||
class EncryptJsonDictTextField(EncryptMixin, JsonDictTextField):
|
class EncryptJsonDictTextField(EncryptMixin, JsonDictTextField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
add_encrypted_field_set(self.verbose_name)
|
|
||||||
|
|
||||||
|
|
||||||
class EncryptJsonDictCharField(EncryptMixin, JsonDictCharField):
|
class EncryptJsonDictCharField(EncryptMixin, JsonDictCharField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
add_encrypted_field_set(self.verbose_name)
|
|
||||||
|
|
||||||
|
|
||||||
class PortField(models.IntegerField):
|
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()
|
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):
|
def _find(attr):
|
||||||
return getattr(thread_local, attr, None)
|
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 rest_framework.fields import ChoiceField, empty
|
||||||
|
|
||||||
from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
|
from common.db.fields import TreeChoices, JSONManyToManyField as ModelJSONManyToManyField
|
||||||
from common.local import add_encrypted_field_set
|
|
||||||
from common.utils import decrypt_password
|
from common.utils import decrypt_password
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -47,9 +46,7 @@ class EncryptedField(serializers.CharField):
|
||||||
if write_only is None:
|
if write_only is None:
|
||||||
write_only = True
|
write_only = True
|
||||||
kwargs["write_only"] = write_only
|
kwargs["write_only"] = write_only
|
||||||
encrypted_key = kwargs.pop('encrypted_key', None)
|
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
add_encrypted_field_set(encrypted_key or self.label)
|
|
||||||
|
|
||||||
def to_internal_value(self, value):
|
def to_internal_value(self, value):
|
||||||
value = super().to_internal_value(value)
|
value = super().to_internal_value(value)
|
||||||
|
|
Loading…
Reference in New Issue