固化七月迭代审计治理进展以隔离线上热修
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:
@@ -3,8 +3,7 @@ package systemconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
@@ -13,6 +12,7 @@ import (
|
||||
configinfra "github.com/break/junhong_cmp_fiber/internal/infrastructure/systemconfig"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/auditfailure"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/middleware"
|
||||
@@ -24,13 +24,17 @@ type ChangeAudit struct {
|
||||
OperationType string
|
||||
Description string
|
||||
ConfigKey string
|
||||
Module string
|
||||
BeforeData map[string]any
|
||||
AfterData map[string]any
|
||||
RequestID string
|
||||
CorrelationID string
|
||||
Result string
|
||||
ErrorCode string
|
||||
ErrorSummary string
|
||||
}
|
||||
|
||||
// AuditWriter 可选接收系统配置事务内审计事实。
|
||||
// AuditWriter 接收系统配置事务内审计事实。
|
||||
type AuditWriter interface {
|
||||
WriteConfigChange(ctx context.Context, tx *gorm.DB, audit ChangeAudit) error
|
||||
}
|
||||
@@ -69,14 +73,29 @@ func (s *UpdateService) Execute(ctx context.Context, key string, request dto.Upd
|
||||
if operatorID == 0 || key == "" {
|
||||
return nil, errors.New(errors.CodeInvalidParam)
|
||||
}
|
||||
if s.audit == nil {
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "系统配置审计接缝未配置")
|
||||
}
|
||||
definition, registered := s.registry.Get(key)
|
||||
if !registered {
|
||||
return nil, errors.New(errors.CodeInvalidParam, "系统配置 Key 未注册")
|
||||
}
|
||||
if definition.Readonly {
|
||||
s.recordFailure(ctx, ChangeAudit{
|
||||
OperatorID: operatorID, OperationType: constants.AuditOperationSystemConfigUpdate,
|
||||
Description: "拒绝更新只读系统配置", ConfigKey: key, Module: definition.Module,
|
||||
Result: constants.AuditResultDenied, ErrorCode: strconv.Itoa(errors.CodeInvalidStatus),
|
||||
ErrorSummary: "系统配置为只读,更新请求已拒绝",
|
||||
})
|
||||
return nil, errors.New(errors.CodeInvalidStatus, "系统配置为只读,不能更新")
|
||||
}
|
||||
if err := configinfra.ValidateValue(definition, request.Value); err != nil {
|
||||
s.recordFailure(ctx, ChangeAudit{
|
||||
OperatorID: operatorID, OperationType: constants.AuditOperationSystemConfigUpdate,
|
||||
Description: "拒绝非法系统配置值", ConfigKey: key, Module: definition.Module,
|
||||
Result: constants.AuditResultDenied, ErrorCode: strconv.Itoa(errors.CodeInvalidParam),
|
||||
ErrorSummary: "系统配置值不符合注册规则",
|
||||
})
|
||||
return nil, errors.New(errors.CodeInvalidParam, "系统配置值不符合注册规则")
|
||||
}
|
||||
now := s.now().UTC()
|
||||
@@ -121,21 +140,24 @@ func (s *UpdateService) Execute(ctx context.Context, key string, request dto.Upd
|
||||
if value := middleware.GetRequestIDFromContext(ctx); value != nil {
|
||||
requestID = *value
|
||||
}
|
||||
if s.audit != nil {
|
||||
if err := s.audit.WriteConfigChange(ctx, tx, ChangeAudit{
|
||||
OperatorID: operatorID, OperationType: "system_config_update", Description: "更新受控系统配置",
|
||||
ConfigKey: key,
|
||||
BeforeData: map[string]any{"config_key": key, "value": auditValue(definition, beforeValue)},
|
||||
AfterData: map[string]any{"config_key": key, "value": auditValue(definition, request.Value)},
|
||||
RequestID: requestID, CorrelationID: requestID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.audit.WriteConfigChange(ctx, tx, ChangeAudit{
|
||||
OperatorID: operatorID, OperationType: constants.AuditOperationSystemConfigUpdate, Description: "更新受控系统配置",
|
||||
ConfigKey: key, Module: definition.Module,
|
||||
BeforeData: auditData(definition, beforeValue), AfterData: auditData(definition, request.Value),
|
||||
RequestID: requestID, CorrelationID: requestID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
saved = existing
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
s.recordFailure(ctx, ChangeAudit{
|
||||
OperatorID: operatorID, OperationType: constants.AuditOperationSystemConfigUpdate,
|
||||
Description: "系统配置更新失败", ConfigKey: key, Module: definition.Module,
|
||||
Result: constants.AuditResultFailed, ErrorCode: strconv.Itoa(errors.CodeDatabaseError),
|
||||
ErrorSummary: "系统配置更新事务已回滚",
|
||||
})
|
||||
return nil, errors.Wrap(errors.CodeDatabaseError, err, "更新系统配置失败")
|
||||
}
|
||||
s.registry.Remember(key, request.Value)
|
||||
@@ -159,10 +181,24 @@ func (s *UpdateService) Execute(ctx context.Context, key string, request dto.Upd
|
||||
}, nil
|
||||
}
|
||||
|
||||
func auditValue(definition configinfra.Definition, value string) string {
|
||||
if !definition.Sensitive {
|
||||
return value
|
||||
func (s *UpdateService) recordFailure(ctx context.Context, audit ChangeAudit) {
|
||||
if value := middleware.GetRequestIDFromContext(ctx); value != nil {
|
||||
audit.RequestID = *value
|
||||
audit.CorrelationID = *value
|
||||
}
|
||||
err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
return s.audit.WriteConfigChange(ctx, tx, audit)
|
||||
})
|
||||
if err != nil {
|
||||
auditfailure.RecordSecondaryWriteFailure(
|
||||
audit.OperationType, audit.ConfigKey, audit.RequestID, audit.CorrelationID, audit.ErrorCode, err,
|
||||
)
|
||||
}
|
||||
sum := sha256.Sum256([]byte(value))
|
||||
return "[敏感值 sha256:" + hex.EncodeToString(sum[:8]) + "]"
|
||||
}
|
||||
|
||||
func auditData(definition configinfra.Definition, value string) map[string]any {
|
||||
if definition.Sensitive {
|
||||
return map[string]any{"credentials_configured": value != ""}
|
||||
}
|
||||
return map[string]any{"value": value}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user