package ape import ( "fmt" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "go.uber.org/zap/zapcore" ) // ChainRouterError is returned when chain router validation prevents // the APE request from being processed (no rule found, access denied, etc.). type ChainRouterError struct { target policyengine.RequestTarget request aperequest.Request status apechain.Status } func (e *ChainRouterError) Error() string { return fmt.Sprintf("access to operation %s is denied by access policy engine: %s", e.request.Operation(), e.status) } func NewChainRouterError(target policyengine.RequestTarget, request aperequest.Request, status apechain.Status) *ChainRouterError { return &ChainRouterError{ target: target, request: request, status: status, } } func (e *ChainRouterError) MarshalLogObject(enc zapcore.ObjectEncoder) error { enc.AddString("status", e.status.String()) if err := enc.AddObject("request", zapcore.ObjectMarshalerFunc( func(innerEnc zapcore.ObjectEncoder) error { return e.marshalRequest(innerEnc) })); err != nil { return err } return nil } func (e *ChainRouterError) marshalTarget(enc zapcore.ObjectEncoder) error { target := e.target hasNamespace := target.Namespace != nil hasContainer := target.Container != nil hasUser := target.User != nil hasGroups := len(target.Groups) > 0 if !hasNamespace && !hasContainer && !hasUser && !hasGroups { enc.AddString("type", "empty") return nil } if hasNamespace { enc.AddString("namespace", target.Namespace.Name) } if hasContainer { enc.AddString("container", target.Container.Name) } if hasUser { enc.AddString("user", target.User.Name) } if hasGroups { if err := enc.AddArray("groups", zapcore.ArrayMarshalerFunc( func(arrayEnc zapcore.ArrayEncoder) error { for i := range target.Groups { arrayEnc.AppendString(target.Groups[i].Name) } return nil })); err != nil { return err } } return nil } func (e *ChainRouterError) marshalRequest(enc zapcore.ObjectEncoder) error { enc.AddString("operation", e.request.Operation()) if err := enc.AddObject("target", zapcore.ObjectMarshalerFunc( func(innerEnc zapcore.ObjectEncoder) error { return e.marshalTarget(innerEnc) })); err != nil { return err } if err := enc.AddObject("properties", zapcore.ObjectMarshalerFunc( func(innerEnc zapcore.ObjectEncoder) error { for key, value := range e.request.Properties() { innerEnc.AddString(key, value) } return nil })); err != nil { return err } if err := enc.AddObject("resource", zapcore.ObjectMarshalerFunc( func(innerEnc zapcore.ObjectEncoder) error { return e.marshalResource(innerEnc) })); err != nil { return err } return nil } func (e *ChainRouterError) marshalResource(enc zapcore.ObjectEncoder) error { resource, ok := e.request.Resource().(aperequest.Resource) if !ok { return nil } enc.AddString("name", resource.Name()) if err := enc.AddObject("properties", zapcore.ObjectMarshalerFunc( func(innerEnc zapcore.ObjectEncoder) error { for key, value := range resource.Properties() { innerEnc.AddString(key, value) } return nil })); err != nil { return err } return nil }