[#1574] ape: Extend ChainRouterError

* Introduce new fields and getters for them;
* Introduce `MarshalLogObject` for `ChainRouterError`;
* Fix `CheckAPE` in `checkerCoreImpl` at `newChainRouterError`.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
Airat Arifullin 2025-02-24 19:30:05 +03:00
parent 00faa9f854
commit a991c9d6a9
2 changed files with 122 additions and 15 deletions

View file

@ -104,7 +104,7 @@ func (c *checkerCoreImpl) CheckAPE(ctx context.Context, prm CheckPrm) error {
if found && status == apechain.Allow {
return nil
}
return newChainRouterError(prm.Request.Operation(), status)
return newChainRouterError(rt, prm.Request, status)
}
// isValidBearer checks whether bearer token was correctly signed by authorized

View file

@ -3,31 +3,138 @@ 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"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"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 {
operation string
status apechain.Status
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.Operation(), e.Status())
return fmt.Sprintf("access to operation %s is denied by access policy engine: %s", e.request.Operation(), e.status)
}
func (e *ChainRouterError) Operation() string {
return e.operation
}
func (e *ChainRouterError) Status() apechain.Status {
return e.status
}
func newChainRouterError(operation string, status apechain.Status) *ChainRouterError {
func newChainRouterError(target policyengine.RequestTarget, request aperequest.Request, status apechain.Status) *ChainRouterError {
return &ChainRouterError{
operation: operation,
status: status,
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(e.marshalRequest)); 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(e.marshalTarget)); err != nil {
return err
}
if err := enc.AddObject("properties", zapcore.ObjectMarshalerFunc(
func(innerEnc zapcore.ObjectEncoder) error {
marshalProperties(innerEnc, e.request.Properties())
return nil
})); err != nil {
return err
}
if err := enc.AddObject("resource", zapcore.ObjectMarshalerFunc(e.marshalResource)); 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 {
marshalProperties(innerEnc, resource.Properties())
return nil
})); err != nil {
return err
}
return nil
}
func marshalProperties(enc zapcore.ObjectEncoder, props map[string]string) {
// For some properties, we can display the value in a shorter format.
const shortFormatLength = 15
for key, value := range props {
switch key {
case nativeschema.PropertyKeyObjectPayloadHash,
nativeschema.PropertyKeyObjectHomomorphicHash,
nativeschema.PropertyKeyActorPublicKey:
if len(value) >= shortFormatLength {
value = value[:shortFormatLength] + "..."
}
default:
}
enc.AddString(key, value)
}
}