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
fit2bot 2024-07-09 14:52:00 +08:00 committed by GitHub
parent d14d8869ac
commit ba8d3be9a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 27 additions and 25 deletions

View File

@ -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:

View File

@ -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

View File

@ -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):

View File

@ -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))

View File

@ -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)