Files
lijiaoqiao/supply-api/internal/audit/model/audit_event.go

357 lines
10 KiB
Go
Raw Normal View History

package model
import (
"strings"
"time"
"github.com/google/uuid"
)
// 事件类别常量
const (
CategoryCRED = "CRED"
CategoryAUTH = "AUTH"
CategoryDATA = "DATA"
CategoryCONFIG = "CONFIG"
CategorySECURITY = "SECURITY"
)
// 凭证事件子类别
const (
SubCategoryCredExpose = "EXPOSE"
SubCategoryCredIngress = "INGRESS"
SubCategoryCredRotate = "ROTATE"
SubCategoryCredRevoke = "REVOKE"
SubCategoryCredValidate = "VALIDATE"
SubCategoryCredDirect = "DIRECT"
)
// 凭证类型
const (
CredentialTypePlatformToken = "platform_token"
CredentialTypeQueryKey = "query_key"
CredentialTypeUpstreamAPIKey = "upstream_api_key"
CredentialTypeNone = "none"
)
// 操作者类型
const (
OperatorTypeUser = "user"
OperatorTypeSystem = "system"
OperatorTypeAdmin = "admin"
)
// 租户类型
const (
TenantTypeSupplier = "supplier"
TenantTypeConsumer = "consumer"
TenantTypePlatform = "platform"
)
// SecurityFlags 安全标记
type SecurityFlags struct {
HasCredential bool `json:"has_credential"` // 是否包含凭证
CredentialExposed bool `json:"credential_exposed"` // 凭证是否暴露
Desensitized bool `json:"desensitized"` // 是否已脱敏
Scanned bool `json:"scanned"` // 是否已扫描
ScanPassed bool `json:"scan_passed"` // 扫描是否通过
ViolationTypes []string `json:"violation_types"` // 违规类型列表
}
// NewSecurityFlags 创建默认安全标记
func NewSecurityFlags() *SecurityFlags {
return &SecurityFlags{
HasCredential: false,
CredentialExposed: false,
Desensitized: false,
Scanned: false,
ScanPassed: false,
ViolationTypes: []string{},
}
}
// HasViolation 检查是否有违规
func (sf *SecurityFlags) HasViolation() bool {
return len(sf.ViolationTypes) > 0
}
// HasViolationOfType 检查是否有指定类型的违规
func (sf *SecurityFlags) HasViolationOfType(violationType string) bool {
for _, v := range sf.ViolationTypes {
if v == violationType {
return true
}
}
return false
}
// AddViolationType 添加违规类型
func (sf *SecurityFlags) AddViolationType(violationType string) {
sf.ViolationTypes = append(sf.ViolationTypes, violationType)
}
// AuditEvent 统一审计事件
type AuditEvent struct {
// 基础标识
EventID string `json:"event_id"` // 事件唯一ID (UUID)
EventName string `json:"event_name"` // 事件名称 (e.g., "CRED-EXPOSE")
EventCategory string `json:"event_category"` // 事件大类 (e.g., "CRED")
EventSubCategory string `json:"event_sub_category"` // 事件子类
// 时间戳
Timestamp time.Time `json:"timestamp"` // 事件发生时间
TimestampMs int64 `json:"timestamp_ms"` // 毫秒时间戳
// 请求上下文
RequestID string `json:"request_id"` // 请求追踪ID
TraceID string `json:"trace_id"` // 分布式追踪ID
SpanID string `json:"span_id"` // Span ID
// 幂等性
IdempotencyKey string `json:"idempotency_key,omitempty"` // 幂等键
// 操作者信息
OperatorID int64 `json:"operator_id"` // 操作者ID
OperatorType string `json:"operator_type"` // 操作者类型 (user/system/admin)
OperatorRole string `json:"operator_role"` // 操作者角色
// 租户信息
TenantID int64 `json:"tenant_id"` // 租户ID
TenantType string `json:"tenant_type"` // 租户类型 (supplier/consumer/platform)
// 对象信息
ObjectType string `json:"object_type"` // 对象类型 (account/package/settlement)
ObjectID int64 `json:"object_id"` // 对象ID
// 操作信息
Action string `json:"action"` // 操作类型 (create/update/delete)
ActionDetail string `json:"action_detail"` // 操作详情
// 凭证信息 (M-013/M-014/M-015/M-016 关键)
CredentialType string `json:"credential_type"` // 凭证类型 (platform_token/query_key/upstream_api_key/none)
CredentialID string `json:"credential_id,omitempty"` // 凭证标识 (脱敏)
CredentialFingerprint string `json:"credential_fingerprint,omitempty"` // 凭证指纹
// 来源信息
SourceType string `json:"source_type"` // 来源类型 (api/ui/cron/internal)
SourceIP string `json:"source_ip"` // 来源IP
SourceRegion string `json:"source_region"` // 来源区域
UserAgent string `json:"user_agent,omitempty"` // User Agent
// 目标信息 (用于直连检测 M-015)
TargetType string `json:"target_type,omitempty"` // 目标类型
TargetEndpoint string `json:"target_endpoint,omitempty"` // 目标端点
TargetDirect bool `json:"target_direct"` // 是否直连
// 结果信息
ResultCode string `json:"result_code"` // 结果码
ResultMessage string `json:"result_message,omitempty"` // 结果消息
Success bool `json:"success"` // 是否成功
// 状态变更 (用于溯源)
BeforeState map[string]any `json:"before_state,omitempty"` // 操作前状态
AfterState map[string]any `json:"after_state,omitempty"` // 操作后状态
// 安全标记 (M-013 关键)
SecurityFlags SecurityFlags `json:"security_flags"` // 安全标记
RiskScore int `json:"risk_score"` // 风险评分 0-100
// 合规信息
ComplianceTags []string `json:"compliance_tags,omitempty"` // 合规标签 (e.g., ["GDPR", "SOC2"])
InvariantRule string `json:"invariant_rule,omitempty"` // 触发的不变量规则
// 扩展字段
Extensions map[string]any `json:"extensions,omitempty"` // 扩展数据
// 元数据
Version int `json:"version"` // 事件版本
CreatedAt time.Time `json:"created_at"` // 创建时间
}
// NewAuditEvent 创建审计事件
func NewAuditEvent(
eventName string,
eventCategory string,
eventSubCategory string,
metricName string,
requestID string,
traceID string,
operatorID int64,
operatorType string,
operatorRole string,
tenantID int64,
tenantType string,
objectType string,
objectID int64,
action string,
credentialType string,
sourceType string,
sourceIP string,
success bool,
resultCode string,
resultMessage string,
) *AuditEvent {
now := time.Now()
event := &AuditEvent{
EventID: uuid.New().String(),
EventName: eventName,
EventCategory: eventCategory,
EventSubCategory: eventSubCategory,
Timestamp: now,
TimestampMs: now.UnixMilli(),
RequestID: requestID,
TraceID: traceID,
OperatorID: operatorID,
OperatorType: operatorType,
OperatorRole: operatorRole,
TenantID: tenantID,
TenantType: tenantType,
ObjectType: objectType,
ObjectID: objectID,
Action: action,
CredentialType: credentialType,
SourceType: sourceType,
SourceIP: sourceIP,
Success: success,
ResultCode: resultCode,
ResultMessage: resultMessage,
Version: 1,
CreatedAt: now,
SecurityFlags: *NewSecurityFlags(),
ComplianceTags: []string{},
}
// 根据凭证类型设置安全标记
if credentialType != CredentialTypeNone && credentialType != "" {
event.SecurityFlags.HasCredential = true
}
// 根据事件名称设置凭证暴露标记M-013
if IsM013Event(eventName) {
event.SecurityFlags.CredentialExposed = true
}
// 根据事件名称设置指标名称到扩展字段
if metricName != "" {
if event.Extensions == nil {
event.Extensions = make(map[string]any)
}
event.Extensions["metric_name"] = metricName
}
return event
}
// NewAuditEventWithSecurityFlags 创建带完整安全标记的审计事件
func NewAuditEventWithSecurityFlags(
eventName string,
eventCategory string,
eventSubCategory string,
metricName string,
requestID string,
traceID string,
operatorID int64,
operatorType string,
operatorRole string,
tenantID int64,
tenantType string,
objectType string,
objectID int64,
action string,
credentialType string,
sourceType string,
sourceIP string,
success bool,
resultCode string,
resultMessage string,
securityFlags SecurityFlags,
riskScore int,
) *AuditEvent {
event := NewAuditEvent(
eventName,
eventCategory,
eventSubCategory,
metricName,
requestID,
traceID,
operatorID,
operatorType,
operatorRole,
tenantID,
tenantType,
objectType,
objectID,
action,
credentialType,
sourceType,
sourceIP,
success,
resultCode,
resultMessage,
)
event.SecurityFlags = securityFlags
event.RiskScore = riskScore
return event
}
// SetIdempotencyKey 设置幂等键
func (e *AuditEvent) SetIdempotencyKey(key string) {
e.IdempotencyKey = key
}
// SetTarget 设置目标信息用于M-015直连检测
func (e *AuditEvent) SetTarget(targetType, targetEndpoint string, targetDirect bool) {
e.TargetType = targetType
e.TargetEndpoint = targetEndpoint
e.TargetDirect = targetDirect
}
// SetInvariantRule 设置不变量规则用于SECURITY事件
func (e *AuditEvent) SetInvariantRule(rule string) {
e.InvariantRule = rule
// 添加合规标签
e.ComplianceTags = append(e.ComplianceTags, "XR-001")
}
// GetMetricName 获取指标名称
func (e *AuditEvent) GetMetricName() string {
if e.Extensions != nil {
if metricName, ok := e.Extensions["metric_name"].(string); ok {
return metricName
}
}
// 根据事件名称推断指标
switch e.EventName {
case "CRED-EXPOSE-RESPONSE", "CRED-EXPOSE-LOG", "CRED-EXPOSE":
return "supplier_credential_exposure_events"
case "CRED-INGRESS-PLATFORM", "CRED-INGRESS":
return "platform_credential_ingress_coverage_pct"
case "CRED-DIRECT-SUPPLIER", "CRED-DIRECT":
return "direct_supplier_call_by_consumer_events"
case "AUTH-QUERY-KEY", "AUTH-QUERY-REJECT", "AUTH-QUERY":
return "query_key_external_reject_rate_pct"
default:
return ""
}
}
// IsM013Event 判断是否为M-013凭证暴露事件
func IsM013Event(eventName string) bool {
return strings.HasPrefix(eventName, "CRED-EXPOSE")
}
// IsM014Event 判断是否为M-014凭证入站事件
func IsM014Event(eventName string) bool {
return strings.HasPrefix(eventName, "CRED-INGRESS")
}
// IsM015Event 判断是否为M-015直连绕过事件
func IsM015Event(eventName string) bool {
return strings.HasPrefix(eventName, "CRED-DIRECT")
}
// IsM016Event 判断是否为M-016 query key拒绝事件
func IsM016Event(eventName string) bool {
return strings.HasPrefix(eventName, "AUTH-QUERY")
}