package control import ( "context" "encoding/hex" "strings" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) var _ control.ControlServiceServer = (*auditService)(nil) type auditService struct { next *Server log *logger.Logger enabled *atomic.Bool } func NewAuditService(next *Server, log *logger.Logger, enabled *atomic.Bool) control.ControlServiceServer { return &auditService{ next: next, log: log, enabled: enabled, } } // HealthCheck implements control.ControlServiceServer. func (a *auditService) HealthCheck(ctx context.Context, req *control.HealthCheckRequest) (*control.HealthCheckResponse, error) { res, err := a.next.HealthCheck(ctx, req) if !a.enabled.Load() { return res, err } audit.LogRequestWithKey(a.log, control.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) return res, err } // RemoveContainer implements control.ControlServiceServer. func (a *auditService) RemoveContainer(ctx context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) { res, err := a.next.RemoveContainer(ctx, req) if !a.enabled.Load() { return res, err } sb := &strings.Builder{} var withConatiner bool if len(req.GetBody().GetContainerId()) > 0 { withConatiner = true sb.WriteString("containerID:") var containerID cid.ID if err := containerID.Decode(req.GetBody().GetContainerId()); err != nil { sb.WriteString(audit.InvalidValue) } else { sb.WriteString(containerID.EncodeToString()) } } if len(req.GetBody().GetOwner()) > 0 { if withConatiner { sb.WriteString(";") } sb.WriteString("owner:") var ownerID refs.OwnerID if err := ownerID.Unmarshal(req.GetBody().GetOwner()); err != nil { sb.WriteString(audit.InvalidValue) } else { var owner user.ID if err := owner.ReadFromV2(ownerID); err != nil { sb.WriteString(audit.InvalidValue) } else { sb.WriteString(owner.EncodeToString()) } } } audit.LogRequestWithKey(a.log, control.ControlService_RemoveContainer_FullMethodName, req.GetSignature().GetKey(), sb, err == nil) return res, err } // RemoveNode implements control.ControlServiceServer. func (a *auditService) RemoveNode(ctx context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) { res, err := a.next.RemoveNode(ctx, req) if !a.enabled.Load() { return res, err } audit.LogRequestWithKey(a.log, control.ControlService_RemoveNode_FullMethodName, req.GetSignature().GetKey(), audit.TargetFromString(hex.EncodeToString(req.GetBody().GetKey())), err == nil) return res, err } // TickEpoch implements control.ControlServiceServer. func (a *auditService) TickEpoch(ctx context.Context, req *control.TickEpochRequest) (*control.TickEpochResponse, error) { res, err := a.next.TickEpoch(ctx, req) if !a.enabled.Load() { return res, err } audit.LogRequestWithKey(a.log, control.ControlService_TickEpoch_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) return res, err }