Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added operation audit for data source and users #1987

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 23 additions & 71 deletions src/bk-user/bkuser/apis/web/data_source/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@
LocalDataSourceImportInputSLZ,
)
from bkuser.apis.web.mixins import CurrentUserTenantMixin
from bkuser.apps.audit.constants import ObjectTypeEnum, OperationEnum
from bkuser.apps.audit.recorder import add_audit_record
from bkuser.apps.data_source.constants import DataSourceTypeEnum
from bkuser.apps.data_source.models import (
DataSource,
Expand All @@ -70,6 +68,7 @@
from bkuser.apps.sync.managers import DataSourceSyncManager
from bkuser.apps.sync.models import DataSourceSyncTask, TenantSyncTask
from bkuser.apps.tenant.models import TenantDepartment, TenantUser
from bkuser.biz.auditor import DataSourceAuditor
from bkuser.biz.data_source import DataSourceHandler
from bkuser.biz.exporters import DataSourceUserExporter
from bkuser.biz.tenant import TenantUserHandler
Expand Down Expand Up @@ -186,19 +185,10 @@ def post(self, request, *args, **kwargs):
updater=current_user,
)

# 审计记录
add_audit_record(
operator=current_user,
tenant_id=current_tenant_id,
operation=OperationEnum.CREATE_DATA_SOURCE,
object_type=ObjectTypeEnum.DATA_SOURCE,
object_id=ds.id,
extras={
"plugin_config": ds.plugin_config,
"field_mapping": ds.field_mapping,
"sync_config": ds.sync_config,
},
)
# 【审计】创建数据源审计对象并记录
auditor = DataSourceAuditor(request.user.username, current_tenant_id, ds)
# 【审计】将审计记录保存至数据库
auditor.record_create()

return Response(
DataSourceCreateOutputSLZ(instance={"id": ds.id}).data,
Expand Down Expand Up @@ -252,12 +242,9 @@ def put(self, request, *args, **kwargs):
slz.is_valid(raise_exception=True)
data = slz.validated_data

# 【审计】记录变更前数据
data_before = {
"plugin_config": data_source.plugin_config,
"field_mapping": data_source.field_mapping,
"sync_config": data_source.sync_config,
}
# 【审计】创建数据源审计对象,并记录变更前数据
auditor = DataSourceAuditor(request.user.username, data_source.owner_tenant_id, data_source)
auditor.pre_record_data_before()

with transaction.atomic():
data_source.field_mapping = data["field_mapping"]
Expand All @@ -267,15 +254,8 @@ def put(self, request, *args, **kwargs):
# 由于需要替换敏感信息,因此需要独立调用 set_plugin_cfg 方法
data_source.set_plugin_cfg(data["plugin_config"])

# 审计记录
add_audit_record(
operator=data_source.updater,
tenant_id=data_source.owner_tenant_id,
operation=OperationEnum.MODIFY_DATA_SOURCE,
object_type=ObjectTypeEnum.DATA_SOURCE,
object_id=data_source.id,
extras={"data_before": data_before},
)
# 【审计】将审计记录保存至数据库
auditor.record_update(data_source)

return Response(status=status.HTTP_204_NO_CONTENT)

Expand Down Expand Up @@ -308,14 +288,9 @@ def delete(self, request, *args, **kwargs):
# 待删除的认证源
waiting_delete_idps = Idp.objects.filter(**idp_filters)

# 【审计】记录变更前数据,数据删除后便无法获取
idps_before_delete = list(
waiting_delete_idps.values("id", "name", "status", "plugin_config", "data_source_match_rules")
)
data_source_id = data_source.id
plugin_config = data_source.plugin_config
field_mapping = data_source.field_mapping
sync_config = data_source.sync_config
# 【审计】创建数据源审计对象,并记录变更前数据
auditor = DataSourceAuditor(request.user.username, data_source.owner_tenant_id, data_source)
auditor.pre_record_data_before(list(waiting_delete_idps))

with transaction.atomic():
# 删除认证源敏感信息
Expand All @@ -334,21 +309,8 @@ def delete(self, request, *args, **kwargs):
# 删除数据源 & 关联资源数据
DataSourceHandler.delete_data_source_and_related_resources(data_source)

# 审计记录
add_audit_record(
operator=request.user.username,
tenant_id=self.get_current_tenant_id(),
operation=OperationEnum.DELETE_DATA_SOURCE,
object_type=ObjectTypeEnum.DATA_SOURCE,
object_id=data_source_id,
extras={
"is_delete_idp": is_delete_idp,
"plugin_config": plugin_config,
"field_mapping": field_mapping,
"sync_config": sync_config,
"idps_before_delete": idps_before_delete,
},
)
# 【审计】将审计记录保存至数据库
auditor.record_delete()

return Response(status=status.HTTP_204_NO_CONTENT)

Expand Down Expand Up @@ -543,15 +505,10 @@ def post(self, request, *args, **kwargs):
logger.exception("本地数据源 %s 导入失败", data_source.id)
raise error_codes.DATA_SOURCE_IMPORT_FAILED.f(str(e))

# 审计记录
add_audit_record(
operator=task.operator,
tenant_id=data_source.owner_tenant_id,
operation=OperationEnum.SYNC_DATA_SOURCE,
object_type=ObjectTypeEnum.DATA_SOURCE,
object_id=data_source.id,
extras={"overwrite": options.overwrite, "incremental": options.incremental, "trigger": options.trigger},
)
# 【审计】创建数据源审计对象并记录
auditor = DataSourceAuditor(request.user.username, data_source.owner_tenant_id, data_source)
# 【审计】将审计记录保存至数据库
auditor.record_sync(options)

return Response(
DataSourceImportOrSyncOutputSLZ(
Expand Down Expand Up @@ -596,15 +553,10 @@ def post(self, request, *args, **kwargs):
logger.exception("创建下发数据源 %s 同步任务失败", data_source.id)
raise error_codes.DATA_SOURCE_SYNC_TASK_CREATE_FAILED.f(str(e))

# 审计记录
add_audit_record(
operator=task.operator,
tenant_id=data_source.owner_tenant_id,
operation=OperationEnum.SYNC_DATA_SOURCE,
object_type=ObjectTypeEnum.DATA_SOURCE,
object_id=data_source.id,
extras={"overwrite": options.overwrite, "incremental": options.incremental, "trigger": options.trigger},
)
# 【审计】创建数据源审计对象并记录
auditor = DataSourceAuditor(request.user.username, data_source.owner_tenant_id, data_source)
# 【审计】将审计记录保存至数据库
auditor.record_sync(options)

return Response(
DataSourceImportOrSyncOutputSLZ(
Expand Down
50 changes: 50 additions & 0 deletions src/bk-user/bkuser/apis/web/organization/views/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@
TenantDeptUserRelationBatchUpdateInputSLZ,
)
from bkuser.apis.web.organization.views.mixins import CurrentUserTenantDataSourceMixin
from bkuser.apps.audit.constants import OperationEnum
from bkuser.apps.data_source.models import DataSourceDepartmentUserRelation
from bkuser.apps.permission.constants import PermAction
from bkuser.apps.permission.permissions import perm_class
from bkuser.apps.tenant.models import TenantDepartment, TenantUser
from bkuser.biz.auditor import TenantUserDepartmentRelationsAuditor


class TenantDeptUserRelationBatchCreateApi(CurrentUserTenantDataSourceMixin, generics.CreateAPIView):
Expand Down Expand Up @@ -66,6 +68,15 @@ def post(self, request, *args, **kwargs):
id__in=data["user_ids"],
).values_list("data_source_user_id", flat=True)

# 【审计】创建审计对象并记录变更前的数据
auditor = TenantUserDepartmentRelationsAuditor(
request.user.username,
cur_tenant_id,
data_source_user_ids,
OperationEnum.CREATE_USER_DEPARTMENT,
)
auditor.pre_record_data_before()

# 复制操作:为数据源部门 & 用户添加关联边,但是不会影响存量的关联边
relations = [
DataSourceDepartmentUserRelation(user_id=user_id, department_id=dept_id, data_source=data_source)
Expand All @@ -74,6 +85,9 @@ def post(self, request, *args, **kwargs):
# 由于复制操作不会影响存量的关联边,所以需要忽略冲突,避免出现用户复选的情况
DataSourceDepartmentUserRelation.objects.bulk_create(relations, ignore_conflicts=True)

# 【审计】将审计记录保存至数据库
auditor.record(extras={"department_ids": list(data_source_dept_ids)})

return Response(status=status.HTTP_204_NO_CONTENT)


Expand Down Expand Up @@ -107,6 +121,15 @@ def put(self, request, *args, **kwargs):
id__in=data["user_ids"],
).values_list("data_source_user_id", flat=True)

# 【审计】创建审计对象并记录变更前的数据
auditor = TenantUserDepartmentRelationsAuditor(
request.user.username,
cur_tenant_id,
data_source_user_ids,
OperationEnum.MODIFY_USER_DEPARTMENT,
)
auditor.pre_record_data_before()

# 移动操作:为数据源部门 & 用户添加关联边,但是会删除这批用户所有的存量关联边
with transaction.atomic():
# 先删除
Expand All @@ -118,6 +141,9 @@ def put(self, request, *args, **kwargs):
]
DataSourceDepartmentUserRelation.objects.bulk_create(relations)

# 【审计】将审计记录保存至数据库
auditor.record(extras={"department_ids": list(data_source_dept_ids)})

return Response(status=status.HTTP_204_NO_CONTENT)

@swagger_auto_schema(
Expand Down Expand Up @@ -147,6 +173,15 @@ def patch(self, request, *args, **kwargs):
id__in=data["user_ids"],
).values_list("data_source_user_id", flat=True)

# 【审计】创建审计对象
auditor = TenantUserDepartmentRelationsAuditor(
request.user.username,
cur_tenant_id,
data_source_user_ids,
OperationEnum.MODIFY_USER_DEPARTMENT,
)
auditor.pre_record_data_before()

# 移动操作:为数据源部门 & 用户添加关联边,但是会删除这批用户在当前部门的存量关联边
with transaction.atomic():
# 先删除(仅限于指定部门)
Expand All @@ -160,6 +195,9 @@ def patch(self, request, *args, **kwargs):
]
DataSourceDepartmentUserRelation.objects.bulk_create(relations, ignore_conflicts=True)

# 【审计】将审计记录保存至数据库
auditor.record(extras={"department_id": source_data_source_dept.id})

return Response(status=status.HTTP_204_NO_CONTENT)


Expand Down Expand Up @@ -191,8 +229,20 @@ def delete(self, request, *args, **kwargs):
id__in=data["user_ids"],
).values_list("data_source_user_id", flat=True)

# 【审计】创建审计对象
auditor = TenantUserDepartmentRelationsAuditor(
request.user.username,
cur_tenant_id,
data_source_user_ids,
OperationEnum.DELETE_USER_DEPARTMENT,
)
auditor.pre_record_data_before()

DataSourceDepartmentUserRelation.objects.filter(
user_id__in=data_source_user_ids, department=source_data_source_dept
).delete()

# 【审计】将审计记录保存至数据库
auditor.record(extras={"department_id": source_data_source_dept.id})

return Response(status=status.HTTP_204_NO_CONTENT)
Loading