固化七月迭代审计治理进展以隔离线上热修
Constraint: 切换 main 前必须保存当前七月分支全部项目进展,套餐生效提案仅属于 Iteration/7-11。 Rejected: 将七月套餐修复直接移植到 main | 两个分支的可靠投递架构不同。 Confidence: medium Scope-risk: broad Directive: 不得将本提交整体 cherry-pick 到 main;main 套餐热修必须基于其纯 Asynq 代码独立实施。 Tested: git diff --check;openspec validate fix-package-activation-starvation --strict。 Not-tested: 按用户要求未运行自动化测试;go build ./... 因当前审计改造中的 Enterprise 模型字面量和 role.recordFailure 参数类型错误未通过。
This commit is contained in:
84
pkg/auditcontext/context.go
Normal file
84
pkg/auditcontext/context.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// Package auditcontext 提供跨 HTTP、异步任务和外部回调传播的审计上下文。
|
||||
package auditcontext
|
||||
|
||||
import "context"
|
||||
|
||||
type contextKey struct{}
|
||||
|
||||
// Context 保存入口提供的真实操作者与链路信息,不包含业务动作或资源事实。
|
||||
type Context struct {
|
||||
ActorKind string
|
||||
ActorID string
|
||||
ActorName string
|
||||
ActorShopID *uint
|
||||
ActorEnterpriseID *uint
|
||||
Source string
|
||||
RequestID string
|
||||
CorrelationID string
|
||||
ParentEventID string
|
||||
RequestPath string
|
||||
RequestMethod string
|
||||
IPAddress string
|
||||
UserAgent string
|
||||
}
|
||||
|
||||
// With 合并审计上下文;非空新值覆盖旧值,便于认证中间件覆盖 HTTP 基础信息。
|
||||
func With(ctx context.Context, value Context) context.Context {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
merged := From(ctx)
|
||||
merge(&merged, value)
|
||||
return context.WithValue(ctx, contextKey{}, merged)
|
||||
}
|
||||
|
||||
// From 读取审计上下文;未设置时返回零值。
|
||||
func From(ctx context.Context) Context {
|
||||
if ctx == nil {
|
||||
return Context{}
|
||||
}
|
||||
value, _ := ctx.Value(contextKey{}).(Context)
|
||||
return value
|
||||
}
|
||||
|
||||
func merge(target *Context, value Context) {
|
||||
if value.ActorKind != "" {
|
||||
target.ActorKind = value.ActorKind
|
||||
}
|
||||
if value.ActorID != "" {
|
||||
target.ActorID = value.ActorID
|
||||
}
|
||||
if value.ActorName != "" {
|
||||
target.ActorName = value.ActorName
|
||||
}
|
||||
if value.ActorShopID != nil {
|
||||
target.ActorShopID = value.ActorShopID
|
||||
}
|
||||
if value.ActorEnterpriseID != nil {
|
||||
target.ActorEnterpriseID = value.ActorEnterpriseID
|
||||
}
|
||||
if value.Source != "" {
|
||||
target.Source = value.Source
|
||||
}
|
||||
if value.RequestID != "" {
|
||||
target.RequestID = value.RequestID
|
||||
}
|
||||
if value.CorrelationID != "" {
|
||||
target.CorrelationID = value.CorrelationID
|
||||
}
|
||||
if value.ParentEventID != "" {
|
||||
target.ParentEventID = value.ParentEventID
|
||||
}
|
||||
if value.RequestPath != "" {
|
||||
target.RequestPath = value.RequestPath
|
||||
}
|
||||
if value.RequestMethod != "" {
|
||||
target.RequestMethod = value.RequestMethod
|
||||
}
|
||||
if value.IPAddress != "" {
|
||||
target.IPAddress = value.IPAddress
|
||||
}
|
||||
if value.UserAgent != "" {
|
||||
target.UserAgent = value.UserAgent
|
||||
}
|
||||
}
|
||||
33
pkg/auditfailure/observer.go
Normal file
33
pkg/auditfailure/observer.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Package auditfailure 提供失败审计二次写入故障的最小进程内观测。
|
||||
package auditfailure
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/logger"
|
||||
)
|
||||
|
||||
var secondaryWriteFailures atomic.Uint64
|
||||
|
||||
// RecordSecondaryWriteFailure 累计失败审计二次写入故障并记录 critical 安全日志。
|
||||
func RecordSecondaryWriteFailure(action, resourceKey, requestID, correlationID, originalErrorCode string, err error) {
|
||||
count := secondaryWriteFailures.Add(1)
|
||||
logger.GetAppLogger().Error(
|
||||
"失败或拒绝审计二次写入失败",
|
||||
zap.String("severity", "critical"),
|
||||
zap.String("action", action),
|
||||
zap.String("resource_key", resourceKey),
|
||||
zap.String("request_id", requestID),
|
||||
zap.String("correlation_id", correlationID),
|
||||
zap.String("original_error_code", originalErrorCode),
|
||||
zap.Uint64("secondary_write_failure_count", count),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
// SecondaryWriteFailureCount 返回当前进程累计的失败审计二次写入故障数。
|
||||
func SecondaryWriteFailureCount() uint64 {
|
||||
return secondaryWriteFailures.Load()
|
||||
}
|
||||
303
pkg/constants/audit.go
Normal file
303
pkg/constants/audit.go
Normal file
@@ -0,0 +1,303 @@
|
||||
package constants
|
||||
|
||||
const (
|
||||
// AuditActionAccountCreated 表示创建账号。
|
||||
AuditActionAccountCreated = "account.created"
|
||||
// AuditActionAccountUpdated 表示更新账号基础资料或状态。
|
||||
AuditActionAccountUpdated = "account.updated"
|
||||
// AuditActionAccountDeleted 表示软删除账号。
|
||||
AuditActionAccountDeleted = "account.deleted"
|
||||
// AuditActionAccountPasswordReset 表示管理员重置账号密码。
|
||||
AuditActionAccountPasswordReset = "account.update_password"
|
||||
// AuditActionAccountPasswordChanged 表示账号本人修改密码。
|
||||
AuditActionAccountPasswordChanged = "auth.change_password"
|
||||
// AuditActionAccountWeComBound 表示绑定账号企业微信身份。
|
||||
AuditActionAccountWeComBound = "account.bind_we_com"
|
||||
// AuditActionAuthLogin 表示后台账号登录。
|
||||
AuditActionAuthLogin = "auth.login"
|
||||
// AuditActionAuthLogout 表示后台账号退出登录。
|
||||
AuditActionAuthLogout = "auth.logout"
|
||||
// AuditActionAuthTokenRefreshed 表示后台账号刷新访问令牌。
|
||||
AuditActionAuthTokenRefreshed = "auth.refresh_token"
|
||||
// AuditActionAccountRolesAssigned 表示为账号分配角色。
|
||||
AuditActionAccountRolesAssigned = "account.assign_roles"
|
||||
// AuditActionAccountRoleRemoved 表示移除账号角色。
|
||||
AuditActionAccountRoleRemoved = "account.remove_role"
|
||||
// AuditActionShopRolesAssigned 表示为店铺分配角色。
|
||||
AuditActionShopRolesAssigned = "shop.assign_shop_roles"
|
||||
// AuditActionShopRoleDeleted 表示移除店铺角色。
|
||||
AuditActionShopRoleDeleted = "shop.delete_shop_role"
|
||||
// AuditActionShopCreated 表示创建店铺。
|
||||
AuditActionShopCreated = "shop.create"
|
||||
// AuditActionShopUpdated 表示更新店铺基础资料。
|
||||
AuditActionShopUpdated = "shop.update"
|
||||
// AuditActionShopEnabled 表示启用店铺。
|
||||
AuditActionShopEnabled = "shop.enable"
|
||||
// AuditActionShopDisabled 表示禁用店铺。
|
||||
AuditActionShopDisabled = "shop.disable"
|
||||
// AuditActionShopDeleted 表示删除店铺。
|
||||
AuditActionShopDeleted = "shop.delete"
|
||||
// AuditActionShopBusinessOwnerUpdated 表示更新店铺业务员归属。
|
||||
AuditActionShopBusinessOwnerUpdated = "shop.update_business_owner"
|
||||
// AuditActionShopClientLoginLimitUpdated 表示更新店铺 C 端登录限制。
|
||||
AuditActionShopClientLoginLimitUpdated = "shop.update_client_login_limit"
|
||||
// AuditActionEnterpriseCreated 表示创建企业及初始企业账号。
|
||||
AuditActionEnterpriseCreated = "enterprise.create"
|
||||
// AuditActionEnterpriseUpdated 表示更新企业基础资料。
|
||||
AuditActionEnterpriseUpdated = "enterprise.update"
|
||||
// AuditActionEnterpriseStatusUpdated 表示更新企业及企业账号状态。
|
||||
AuditActionEnterpriseStatusUpdated = "enterprise.update_status"
|
||||
// AuditActionEnterprisePasswordUpdated 表示更新企业账号密码。
|
||||
AuditActionEnterprisePasswordUpdated = "enterprise.update_password"
|
||||
// AuditActionEnterpriseCardsAllocated 表示向企业授权独立卡。
|
||||
AuditActionEnterpriseCardsAllocated = "enterprise_card.allocate_cards"
|
||||
// AuditActionEnterpriseCardsRecalled 表示回收企业独立卡授权。
|
||||
AuditActionEnterpriseCardsRecalled = "enterprise_card.recall_cards"
|
||||
// AuditActionEnterpriseCardRemarkUpdated 表示更新企业卡授权备注。
|
||||
AuditActionEnterpriseCardRemarkUpdated = "enterprise_card.update_record_remark"
|
||||
// AuditActionEnterpriseDevicesAllocated 表示向企业授权设备及其绑定卡。
|
||||
AuditActionEnterpriseDevicesAllocated = "enterprise_device.allocate_devices"
|
||||
// AuditActionEnterpriseDevicesRecalled 表示回收企业设备及其绑定卡授权。
|
||||
AuditActionEnterpriseDevicesRecalled = "enterprise_device.recall_devices"
|
||||
// AuditActionPersonalCustomerProfileUpdated 表示个人客户更新资料。
|
||||
AuditActionPersonalCustomerProfileUpdated = "personal_customer.update_profile"
|
||||
// AuditActionPersonalCustomerPhoneBound 表示个人客户绑定手机号。
|
||||
AuditActionPersonalCustomerPhoneBound = "personal_customer.bind_phone"
|
||||
// AuditActionPersonalCustomerPhoneChanged 表示个人客户更换手机号。
|
||||
AuditActionPersonalCustomerPhoneChanged = "personal_customer.change_phone"
|
||||
// AuditActionPersonalCustomerWechatIdentityUpdated 表示创建或同步个人客户微信主体。
|
||||
AuditActionPersonalCustomerWechatIdentityUpdated = "personal_customer.update_wechat_identity"
|
||||
// AuditActionSystemConfigUpdated 表示更新受控系统配置。
|
||||
AuditActionSystemConfigUpdated = "system_config.updated"
|
||||
// AuditActionOutboxReplayed 表示人工重放 Outbox 事件。
|
||||
AuditActionOutboxReplayed = "outbox.replayed"
|
||||
// AuditActionOutboxExpiredLeaseReleased 表示人工释放 Outbox 过期租约。
|
||||
AuditActionOutboxExpiredLeaseReleased = "outbox.expired_lease_released"
|
||||
// AuditActionDeviceBatchAllocationCompleted 表示设备批量分配根事件。
|
||||
AuditActionDeviceBatchAllocationCompleted = "device.batch_allocation.completed"
|
||||
// AuditActionDeviceBatchAllocationItem 表示设备批量分配资源子事件。
|
||||
AuditActionDeviceBatchAllocationItem = "device.batch_allocation.item"
|
||||
// AuditActionWeComCredentialsRead 表示读取企业微信应用明文凭据。
|
||||
AuditActionWeComCredentialsRead = "wecom.application.credentials_read"
|
||||
// AuditActionRoleCreated 表示创建角色。
|
||||
AuditActionRoleCreated = "role.create"
|
||||
// AuditActionRoleUpdated 表示更新角色。
|
||||
AuditActionRoleUpdated = "role.update"
|
||||
// AuditActionRoleStatusUpdated 表示更新角色状态。
|
||||
AuditActionRoleStatusUpdated = "role.update_status"
|
||||
// AuditActionRoleDefaultCreditUpdated 表示更新角色默认信用额度。
|
||||
AuditActionRoleDefaultCreditUpdated = "role.update_default_credit"
|
||||
// AuditActionRoleDeleted 表示删除角色。
|
||||
AuditActionRoleDeleted = "role.delete"
|
||||
// AuditActionRolePermissionsAssigned 表示配置角色权限。
|
||||
AuditActionRolePermissionsAssigned = "role.assign_permissions"
|
||||
// AuditActionRolePermissionRemoved 表示移除单个角色权限。
|
||||
AuditActionRolePermissionRemoved = "role.remove_permission"
|
||||
// AuditActionRolePermissionsBatchRemoved 表示批量移除角色权限。
|
||||
AuditActionRolePermissionsBatchRemoved = "role.batch_remove_permissions"
|
||||
// AuditActionPermissionCreated 表示创建权限。
|
||||
AuditActionPermissionCreated = "permission.create"
|
||||
// AuditActionPermissionUpdated 表示更新权限。
|
||||
AuditActionPermissionUpdated = "permission.update"
|
||||
// AuditActionPermissionDeleted 表示删除权限。
|
||||
AuditActionPermissionDeleted = "permission.delete"
|
||||
// AuditOperationSystemConfigUpdate 表示系统配置旧接缝传入的操作类型。
|
||||
AuditOperationSystemConfigUpdate = "system_config_update"
|
||||
// AuditOperationOutboxReplay 表示 Outbox 人工重放接缝操作类型。
|
||||
AuditOperationOutboxReplay = "outbox_replay"
|
||||
// AuditOperationOutboxReleaseExpiredLease 表示 Outbox 人工释放过期租约接缝操作类型。
|
||||
AuditOperationOutboxReleaseExpiredLease = "outbox_release_expired_lease"
|
||||
)
|
||||
|
||||
const (
|
||||
// AuditResourceSystemConfig 表示受控系统配置资源。
|
||||
AuditResourceSystemConfig = "system_config"
|
||||
// AuditResourceOutboxEvent 表示公共 Outbox 事件资源。
|
||||
AuditResourceOutboxEvent = "outbox_event"
|
||||
// AuditResourceDeviceBatchTask 表示设备批量分配任务资源。
|
||||
AuditResourceDeviceBatchTask = "device_batch_task"
|
||||
// AuditResourceDevice 表示设备资源。
|
||||
AuditResourceDevice = "device"
|
||||
// AuditResourceIotCard 表示 IoT 卡资源。
|
||||
AuditResourceIotCard = "iot_card"
|
||||
// AuditResourceShop 表示店铺资源。
|
||||
AuditResourceShop = "shop"
|
||||
// AuditResourceOrder 表示订单资源。
|
||||
AuditResourceOrder = "order"
|
||||
// AuditResourceRefund 表示退款资源。
|
||||
AuditResourceRefund = "refund"
|
||||
// AuditResourceAccount 表示后台账号资源。
|
||||
AuditResourceAccount = "account"
|
||||
// AuditResourceRole 表示后台角色资源。
|
||||
AuditResourceRole = "role"
|
||||
// AuditResourcePermission 表示后台权限资源。
|
||||
AuditResourcePermission = "permission"
|
||||
// AuditResourceEnterprise 表示企业资源。
|
||||
AuditResourceEnterprise = "enterprise"
|
||||
// AuditResourceDeviceSIMBinding 表示设备卡槽绑定资源。
|
||||
AuditResourceDeviceSIMBinding = "device_sim_binding"
|
||||
// AuditResourceAssetAllocationRecord 表示资产分配记录资源。
|
||||
AuditResourceAssetAllocationRecord = "asset_allocation_record"
|
||||
// AuditResourceExchangeOrder 表示换货单资源。
|
||||
AuditResourceExchangeOrder = "exchange_order"
|
||||
// AuditResourceAgentRecharge 表示代理充值单资源。
|
||||
AuditResourceAgentRecharge = "agent_recharge"
|
||||
// AuditResourceAssetWallet 表示资产钱包资源。
|
||||
AuditResourceAssetWallet = "asset_wallet"
|
||||
// AuditResourceApprovalInstance 表示审批实例资源。
|
||||
AuditResourceApprovalInstance = "approval_instance"
|
||||
// AuditResourceWeComApplication 表示企业微信应用配置资源。
|
||||
AuditResourceWeComApplication = "wecom_application"
|
||||
// AuditResourceAuthentication 表示不含 Token 或 Cookie 的认证状态资源。
|
||||
AuditResourceAuthentication = "authentication"
|
||||
// AuditResourceEnterpriseCardAuthorization 表示企业卡授权记录资源。
|
||||
AuditResourceEnterpriseCardAuthorization = "enterprise_card_authorization"
|
||||
// AuditResourceEnterpriseDeviceAuthorization 表示企业设备授权记录资源。
|
||||
AuditResourceEnterpriseDeviceAuthorization = "enterprise_device_authorization"
|
||||
// AuditResourcePersonalCustomer 表示个人客户资源。
|
||||
AuditResourcePersonalCustomer = "personal_customer"
|
||||
// AuditResourcePersonalCustomerPhone 表示个人客户手机号资源。
|
||||
AuditResourcePersonalCustomerPhone = "personal_customer_phone"
|
||||
// AuditResourcePersonalCustomerOpenID 表示个人客户微信 OpenID 资源。
|
||||
AuditResourcePersonalCustomerOpenID = "personal_customer_openid"
|
||||
// AuditResourceRelationPrimary 表示事件的主要资源。
|
||||
AuditResourceRelationPrimary = "primary"
|
||||
// AuditResourceRelationAffected 表示被本次动作改变的资源。
|
||||
AuditResourceRelationAffected = "affected"
|
||||
// AuditResourceRelationReference 表示本次动作引用但未改变的资源。
|
||||
AuditResourceRelationReference = "reference"
|
||||
// AuditResourceRoleConfig 表示配置资源角色。
|
||||
AuditResourceRoleConfig = "config"
|
||||
// AuditResourceRoleRecoveryTarget 表示人工恢复裁决的目标事件。
|
||||
AuditResourceRoleRecoveryTarget = "recovery_target"
|
||||
// AuditResourceRoleBatchTask 表示批量根事件的任务资源。
|
||||
AuditResourceRoleBatchTask = "batch_task"
|
||||
// AuditResourceRoleBatchItem 表示批量子事件的单项资源。
|
||||
AuditResourceRoleBatchItem = "batch_item"
|
||||
// AuditResourceRoleSensitiveReadTarget 表示敏感读取目标资源。
|
||||
AuditResourceRoleSensitiveReadTarget = "sensitive_read_target"
|
||||
// AuditResourceRoleAccountTarget 表示账号生命周期的目标账号。
|
||||
AuditResourceRoleAccountTarget = "account_target"
|
||||
// AuditResourceRoleAccountScope 表示账号归属的店铺或企业。
|
||||
AuditResourceRoleAccountScope = "account_scope"
|
||||
// AuditResourceRoleAccountRole 表示账号实际持有的角色。
|
||||
AuditResourceRoleAccountRole = "account_role"
|
||||
// AuditResourceRoleAuthentication 表示账号关联的认证状态。
|
||||
AuditResourceRoleAuthentication = "authentication"
|
||||
// AuditResourceRoleAccessRole 表示角色权限配置中的角色目标。
|
||||
AuditResourceRoleAccessRole = "role_target"
|
||||
// AuditResourceRoleAccessPermission 表示角色权限配置中的权限目标。
|
||||
AuditResourceRoleAccessPermission = "permission_target"
|
||||
// AuditResourceRoleShopRole 表示店铺实际持有的角色。
|
||||
AuditResourceRoleShopRole = "shop_role"
|
||||
// AuditResourceRoleShopTarget 表示店铺操作的主要目标。
|
||||
AuditResourceRoleShopTarget = "shop_target"
|
||||
// AuditResourceRoleShopParent 表示店铺的上级店铺。
|
||||
AuditResourceRoleShopParent = "shop_parent"
|
||||
// AuditResourceRoleShopAccount 表示店铺直接影响的账号。
|
||||
AuditResourceRoleShopAccount = "shop_account"
|
||||
// AuditResourceRoleShopBusinessOwner 表示店铺当前业务员账号。
|
||||
AuditResourceRoleShopBusinessOwner = "shop_business_owner"
|
||||
// AuditResourceRoleShopPreviousBusinessOwner 表示店铺原业务员账号。
|
||||
AuditResourceRoleShopPreviousBusinessOwner = "shop_previous_business_owner"
|
||||
// AuditResourceRoleEnterpriseTarget 表示企业操作的主要目标。
|
||||
AuditResourceRoleEnterpriseTarget = "enterprise_target"
|
||||
// AuditResourceRoleEnterpriseOwnerShop 表示企业归属店铺。
|
||||
AuditResourceRoleEnterpriseOwnerShop = "enterprise_owner_shop"
|
||||
// AuditResourceRoleEnterpriseAccount 表示企业关联账号。
|
||||
AuditResourceRoleEnterpriseAccount = "enterprise_account"
|
||||
// AuditResourceRoleEnterpriseAuthorizedCard 表示企业授权涉及的卡。
|
||||
AuditResourceRoleEnterpriseAuthorizedCard = "enterprise_authorized_card"
|
||||
// AuditResourceRoleEnterpriseCardAuthorization 表示企业卡授权记录。
|
||||
AuditResourceRoleEnterpriseCardAuthorization = "enterprise_card_authorization"
|
||||
// AuditResourceRoleEnterpriseAuthorizedDevice 表示企业授权涉及的设备。
|
||||
AuditResourceRoleEnterpriseAuthorizedDevice = "enterprise_authorized_device"
|
||||
// AuditResourceRoleEnterpriseDeviceBinding 表示企业设备授权涉及的卡槽绑定。
|
||||
AuditResourceRoleEnterpriseDeviceBinding = "enterprise_device_binding"
|
||||
// AuditResourceRoleEnterpriseDeviceAuthorization 表示企业设备授权记录。
|
||||
AuditResourceRoleEnterpriseDeviceAuthorization = "enterprise_device_authorization"
|
||||
// AuditResourceRolePersonalCustomerTarget 表示个人客户操作的主体目标。
|
||||
AuditResourceRolePersonalCustomerTarget = "personal_customer_target"
|
||||
// AuditResourceRolePersonalCustomerPhone 表示个人客户手机号关系。
|
||||
AuditResourceRolePersonalCustomerPhone = "personal_customer_phone"
|
||||
// AuditResourceRolePersonalCustomerWechatIdentity 表示个人客户微信主体关系。
|
||||
AuditResourceRolePersonalCustomerWechatIdentity = "personal_customer_wechat_identity"
|
||||
)
|
||||
|
||||
const (
|
||||
// AuditActorAccount 表示已认证人工账号。
|
||||
AuditActorAccount = "account"
|
||||
// AuditActorPersonalCustomer 表示已认证个人客户。
|
||||
AuditActorPersonalCustomer = "personal_customer"
|
||||
// AuditActorOpenAPI 表示通过代理 OpenAPI 调用的账号。
|
||||
AuditActorOpenAPI = "openapi"
|
||||
// AuditActorSystemTask 表示异步 Worker 执行的系统任务。
|
||||
AuditActorSystemTask = "system_task"
|
||||
// AuditActorScheduledJob 表示由 Scheduler 触发的计划任务。
|
||||
AuditActorScheduledJob = "scheduled_job"
|
||||
// AuditActorExternalSystem 表示经验证的外部系统回调。
|
||||
AuditActorExternalSystem = "external_system"
|
||||
// AuditSourceAdminAPI 表示后台管理 API 入口。
|
||||
AuditSourceAdminAPI = "admin_api"
|
||||
// AuditSourcePersonalAPI 表示个人客户 API 入口。
|
||||
AuditSourcePersonalAPI = "personal_api"
|
||||
// AuditSourceOpenAPI 表示代理 OpenAPI 入口。
|
||||
AuditSourceOpenAPI = "openapi"
|
||||
// AuditSourceWorker 表示异步 Worker 入口。
|
||||
AuditSourceWorker = "worker"
|
||||
// AuditSourceScheduler 表示计划任务入口。
|
||||
AuditSourceScheduler = "scheduler"
|
||||
// AuditSourceCallback 表示外部系统回调入口。
|
||||
AuditSourceCallback = "callback"
|
||||
// AuditScopePlatform 表示平台级业务范围。
|
||||
AuditScopePlatform = "platform"
|
||||
// AuditScopePersonalCustomer 表示个人客户本人业务范围。
|
||||
AuditScopePersonalCustomer = "personal_customer"
|
||||
)
|
||||
|
||||
const (
|
||||
// AuditResultSuccess 表示业务操作成功。
|
||||
AuditResultSuccess = "success"
|
||||
// AuditResultFailed 表示业务操作执行失败。
|
||||
AuditResultFailed = "failed"
|
||||
// AuditResultDenied 表示业务规则或权限拒绝。
|
||||
AuditResultDenied = "denied"
|
||||
// AuditResultPartial 表示批量操作部分成功。
|
||||
AuditResultPartial = "partial"
|
||||
// AuditResultUnknown 表示业务结果暂时无法确认。
|
||||
AuditResultUnknown = "unknown"
|
||||
)
|
||||
|
||||
const (
|
||||
// AuditRiskLow 表示低风险审计动作。
|
||||
AuditRiskLow = "low"
|
||||
// AuditRiskHigh 表示高风险审计动作。
|
||||
AuditRiskHigh = "high"
|
||||
// AuditRiskNormal 表示常规风险审计动作。
|
||||
AuditRiskNormal = "normal"
|
||||
// AuditRiskCritical 表示严重风险审计动作。
|
||||
AuditRiskCritical = "critical"
|
||||
// AuditCategoryConfiguration 表示关键配置类别。
|
||||
AuditCategoryConfiguration = "configuration"
|
||||
// AuditCategoryReliability 表示可靠事件运维类别。
|
||||
AuditCategoryReliability = "reliability"
|
||||
// AuditCategoryAsset 表示资产变更类别。
|
||||
AuditCategoryAsset = "asset"
|
||||
// AuditCategorySecurity 表示安全与敏感读取类别。
|
||||
AuditCategorySecurity = "security"
|
||||
// AuditCategoryIdentity 表示账号与权限身份类别。
|
||||
AuditCategoryIdentity = "identity"
|
||||
// AuditCategoryBusiness 表示通用业务配置类别。
|
||||
AuditCategoryBusiness = "business"
|
||||
// AuditSubjectInternalOnly 表示仅平台内部可见。
|
||||
AuditSubjectInternalOnly = "internal_only"
|
||||
// AuditSubjectResult 表示主体仅可查看安全业务结论。
|
||||
AuditSubjectResult = "subject_result"
|
||||
// AuditSubjectDetail 表示主体可查看注册表允许的结构化业务详情。
|
||||
AuditSubjectDetail = "subject_detail"
|
||||
)
|
||||
|
||||
const (
|
||||
// AuditJSONMaxBytes 是单个审计 JSON 字段允许的最大字节数。
|
||||
AuditJSONMaxBytes = 16 * 1024
|
||||
)
|
||||
@@ -2,6 +2,28 @@ package constants
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
// IntegrationIDMaxLength 是外部交互稳定ID的数据库长度上限。
|
||||
IntegrationIDMaxLength = 64
|
||||
// IntegrationTriggerSeriesMaxLength 是技术尝试序列ID的数据库长度上限。
|
||||
IntegrationTriggerSeriesMaxLength = 64
|
||||
// IntegrationCorrelationIDMaxLength 是跨业务链路关联ID的数据库长度上限。
|
||||
IntegrationCorrelationIDMaxLength = 100
|
||||
// IntegrationResourceIDMaxLength 是外部交互本地资源ID的数据库长度上限。
|
||||
IntegrationResourceIDMaxLength = 128
|
||||
// IntegrationResourceKeyMaxLength 是外部交互资源稳定Key的数据库长度上限。
|
||||
IntegrationResourceKeyMaxLength = 128
|
||||
// IntegrationProviderMessageMaxLength 是外部交互结果摘要的数据库长度上限。
|
||||
IntegrationProviderMessageMaxLength = 500
|
||||
// IntegrationSafeMessagePrefix 标识调用方已提供的受控可读业务结果摘要。
|
||||
IntegrationSafeMessagePrefix = "业务结果摘要:"
|
||||
|
||||
// IntegrationQueryMaxRange 是调查列表允许的最大连续时间范围。
|
||||
IntegrationQueryMaxRange = 31 * 24 * time.Hour
|
||||
// IntegrationPendingStaleAfter 是待处理尝试进入陈旧统计的时长。
|
||||
IntegrationPendingStaleAfter = 5 * time.Minute
|
||||
)
|
||||
|
||||
const (
|
||||
// IntegrationDirectionInbound 表示外部系统调用本系统。
|
||||
IntegrationDirectionInbound = "inbound"
|
||||
@@ -85,3 +107,86 @@ func IntegrationResultName(result string) string {
|
||||
}
|
||||
return names[result]
|
||||
}
|
||||
|
||||
const (
|
||||
// IntegrationResultCategoryProcessing 表示仍在处理。
|
||||
IntegrationResultCategoryProcessing = "processing"
|
||||
// IntegrationResultCategorySucceeded 表示外部请求实际成功。
|
||||
IntegrationResultCategorySucceeded = "succeeded"
|
||||
// IntegrationResultCategoryIndeterminate 表示结果无法确认。
|
||||
IntegrationResultCategoryIndeterminate = "indeterminate"
|
||||
// IntegrationResultCategoryFailed 表示外部请求或载荷明确失败。
|
||||
IntegrationResultCategoryFailed = "failed"
|
||||
// IntegrationResultCategoryNotSent 表示外部请求未发送。
|
||||
IntegrationResultCategoryNotSent = "not_sent"
|
||||
)
|
||||
|
||||
// IntegrationResultCategory 返回外部尝试的稳定派生类别。
|
||||
func IntegrationResultCategory(result string) string {
|
||||
switch result {
|
||||
case IntegrationResultPending:
|
||||
return IntegrationResultCategoryProcessing
|
||||
case IntegrationResultSuccess:
|
||||
return IntegrationResultCategorySucceeded
|
||||
case IntegrationResultUnknown:
|
||||
return IntegrationResultCategoryIndeterminate
|
||||
case IntegrationResultFailed, IntegrationResultNotFound, IntegrationResultInvalidPayload, IntegrationResultConflict:
|
||||
return IntegrationResultCategoryFailed
|
||||
case IntegrationResultIgnored, IntegrationResultMerged, IntegrationResultRateLimited, IntegrationResultCompleted, IntegrationResultCancelled:
|
||||
return IntegrationResultCategoryNotSent
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// IntegrationProviderName 返回外部提供方中文名称。
|
||||
func IntegrationProviderName(provider string) string {
|
||||
names := map[string]string{
|
||||
IntegrationProviderCTCC: "中国电信", IntegrationProviderCMCC: "中国移动",
|
||||
IntegrationProviderCUCC: "中国联通", IntegrationProviderWechatPay: "微信支付",
|
||||
IntegrationProviderAlipay: "支付宝", IntegrationProviderWeCom: "企业微信",
|
||||
IntegrationProviderGateway: "Gateway",
|
||||
}
|
||||
if name := names[provider]; name != "" {
|
||||
return name
|
||||
}
|
||||
return "未知提供方"
|
||||
}
|
||||
|
||||
// IntegrationDirectionName 返回外部交互方向中文名称。
|
||||
func IntegrationDirectionName(direction string) string {
|
||||
switch direction {
|
||||
case IntegrationDirectionInbound:
|
||||
return "入站"
|
||||
case IntegrationDirectionOutbound:
|
||||
return "出站"
|
||||
default:
|
||||
return "未知方向"
|
||||
}
|
||||
}
|
||||
|
||||
// IntegrationOperationName 返回已注册外部操作中文名称。
|
||||
func IntegrationOperationName(operation string) string {
|
||||
names := map[string]string{
|
||||
IntegrationOperationCTCCRealnameCallback: "接收实名结果回调",
|
||||
IntegrationOperationCUCCRealnameRemovalCallback: "接收解除实名回调",
|
||||
IntegrationOperationPaymentPreCreate: "支付预下单", IntegrationOperationPaymentQuery: "支付查单",
|
||||
IntegrationOperationPaymentCallback: "接收支付回调",
|
||||
IntegrationOperationWeComAccessToken: "获取企业微信访问令牌",
|
||||
IntegrationOperationWeComVisibleMembers: "查询企业微信可见成员",
|
||||
IntegrationOperationWeComVisibleDepartments: "查询企业微信可见部门",
|
||||
IntegrationOperationWeComTemplateDetail: "查询企业微信审批模板",
|
||||
IntegrationOperationWeComAttachmentUpload: "上传企业微信审批附件",
|
||||
IntegrationOperationWeComApprovalSubmit: "提交企业微信审批",
|
||||
IntegrationOperationWeComApprovalCallback: "接收企业微信审批回调",
|
||||
IntegrationOperationWeComApprovalDetail: "查询企业微信审批详情",
|
||||
IntegrationOperationWeComApprovalInfo: "查询企业微信审批单号",
|
||||
IntegrationOperationGatewayRealname: "查询实名状态", IntegrationOperationGatewayTraffic: "查询流量",
|
||||
IntegrationOperationGatewayNetwork: "查询卡网络状态", IntegrationOperationGatewayDeviceInfo: "查询设备信息",
|
||||
IntegrationOperationGatewaySpeedTier: "设置卡限速档位",
|
||||
}
|
||||
if name := names[operation]; name != "" {
|
||||
return name
|
||||
}
|
||||
return "未知外部操作"
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/sanitizer"
|
||||
"github.com/bytedance/sonic"
|
||||
@@ -154,8 +155,10 @@ func MiddlewareWithLogger(accessLogger *zap.Logger) fiber.Handler {
|
||||
|
||||
// 注入请求上下文,供 Service 层审计日志复用
|
||||
ctx := c.UserContext()
|
||||
requestID := ""
|
||||
if rid := c.Locals(constants.ContextKeyRequestID); rid != nil {
|
||||
if requestID, ok := rid.(string); ok && requestID != "" {
|
||||
if value, ok := rid.(string); ok && value != "" {
|
||||
requestID = value
|
||||
ctx = context.WithValue(ctx, constants.ContextKeyRequestID, requestID)
|
||||
}
|
||||
}
|
||||
@@ -163,6 +166,11 @@ func MiddlewareWithLogger(accessLogger *zap.Logger) fiber.Handler {
|
||||
ctx = context.WithValue(ctx, constants.ContextKeyUserAgent, c.Get("User-Agent"))
|
||||
ctx = context.WithValue(ctx, constants.ContextKeyRequestPath, c.Path())
|
||||
ctx = context.WithValue(ctx, constants.ContextKeyRequestMethod, c.Method())
|
||||
ctx = auditcontext.With(ctx, auditcontext.Context{
|
||||
RequestID: requestID, CorrelationID: requestID,
|
||||
RequestPath: c.Path(), RequestMethod: c.Method(),
|
||||
IPAddress: c.IP(), UserAgent: c.Get("User-Agent"),
|
||||
})
|
||||
c.SetUserContext(ctx)
|
||||
|
||||
// 获取请求 body(在 c.Next() 之前读取)
|
||||
@@ -182,7 +190,7 @@ func MiddlewareWithLogger(accessLogger *zap.Logger) fiber.Handler {
|
||||
duration := time.Since(startTime)
|
||||
|
||||
// 获取请求 ID(由 requestid 中间件设置)
|
||||
requestID := ""
|
||||
requestID = ""
|
||||
if rid := c.Locals(constants.ContextKeyRequestID); rid != nil {
|
||||
requestID = rid.(string)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditcontext"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/logger"
|
||||
@@ -37,6 +39,27 @@ func SetUserContext(ctx context.Context, info *UserContextInfo) context.Context
|
||||
if info.SubordinateShopIDs != nil {
|
||||
ctx = context.WithValue(ctx, constants.ContextKeySubordinateShopIDs, info.SubordinateShopIDs)
|
||||
}
|
||||
actorKind := constants.AuditActorAccount
|
||||
actorID := info.UserID
|
||||
source := constants.AuditSourceAdminAPI
|
||||
if info.UserType == constants.UserTypePersonalCustomer {
|
||||
actorKind = constants.AuditActorPersonalCustomer
|
||||
source = constants.AuditSourcePersonalAPI
|
||||
if info.CustomerID > 0 {
|
||||
actorID = info.CustomerID
|
||||
}
|
||||
}
|
||||
var shopID, enterpriseID *uint
|
||||
if info.ShopID > 0 {
|
||||
shopID = &info.ShopID
|
||||
}
|
||||
if info.EnterpriseID > 0 {
|
||||
enterpriseID = &info.EnterpriseID
|
||||
}
|
||||
ctx = auditcontext.With(ctx, auditcontext.Context{
|
||||
ActorKind: actorKind, ActorID: strconv.FormatUint(uint64(actorID), 10), ActorName: info.Username,
|
||||
ActorShopID: shopID, ActorEnterpriseID: enterpriseID, Source: source,
|
||||
})
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,7 @@ func BuildDocHandlers() *bootstrap.Handlers {
|
||||
ClientWechat: app.NewClientWechatHandler(nil, nil, nil),
|
||||
SuperAdmin: admin.NewSuperAdminHandler(nil),
|
||||
SystemConfig: admin.NewSystemConfigHandler(nil, nil),
|
||||
Audit: admin.NewAuditHandler(nil, nil),
|
||||
WeCom: admin.NewWeComHandler(nil, nil),
|
||||
AgentOpenAPI: openapiHandler.NewHandler(nil, nil),
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ var forbiddenFragments = []string{
|
||||
// IsForbiddenField 判断字段是否禁止进入普通日志、审计或外部交互摘要。
|
||||
func IsForbiddenField(key string) bool {
|
||||
normalized := strings.ToLower(strings.NewReplacer("-", "_", ".", "_").Replace(key))
|
||||
if normalized == "credentials_configured" {
|
||||
return false
|
||||
}
|
||||
for _, fragment := range forbiddenFragments {
|
||||
if strings.Contains(normalized, fragment) {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user