package router import ( "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) func newTarget(ct ape.ChainTarget) (policyengine.Target, error) { var target policyengine.Target switch ct.TargetType { case ape.TargetTypeContainer: var cid cidSDK.ID err := cid.DecodeString(ct.Name) if err != nil { return target, fmt.Errorf("invalid cid format: %s", target.Name) } target.Type = policyengine.Container case ape.TargetTypeGroup: target.Type = policyengine.Group case ape.TargetTypeNamespace: target.Type = policyengine.Namespace case ape.TargetTypeUser: target.Type = policyengine.User default: return target, fmt.Errorf("unsupported target type: %v", ct.TargetType) } target.Name = ct.Name return target, nil } type morphReaderDecorator struct { policyengine.MorphRuleChainStorageReader bearerTokenTarget policyengine.Target bearerTokenChains []*chain.Chain } func newMorphReaderDecorator(r policyengine.MorphRuleChainStorageReader, override bearer.APEOverride) (*morphReaderDecorator, error) { if r == nil { return nil, errors.New("empty morph chain rule reader") } t, err := newTarget(override.Target) if err != nil { return nil, err } bearerTokenChains := make([]*chain.Chain, len(override.Chains)) for i := range override.Chains { chain := new(chain.Chain) if err := chain.DecodeBytes(override.Chains[i].Raw); err != nil { return nil, fmt.Errorf("invalid ape chain: %w", err) } bearerTokenChains[i] = chain } return &morphReaderDecorator{ MorphRuleChainStorageReader: r, bearerTokenTarget: t, bearerTokenChains: bearerTokenChains, }, nil } func (m *morphReaderDecorator) ListMorphRuleChains(name chain.Name, target policyengine.Target) ([]*chain.Chain, error) { if len(m.bearerTokenChains) > 0 && m.bearerTokenTarget.Type == target.Type { if m.bearerTokenTarget.Name != target.Name { return nil, fmt.Errorf("unexpected bearer token target: %s", m.bearerTokenTarget.Name) } return m.bearerTokenChains, nil } return m.MorphRuleChainStorageReader.ListMorphRuleChains(name, target) } // BearerChainFeedRouter creates a chain router emplacing bearer token rule chains. // Bearer token chains override only container target chains within Policy contract. This means the order of checking // is as follows: // // 1. Local overrides; // 2. Policy contract chains for a namespace target (as namespace chains have higher priority); // 3. Bearer token chains for a container target - if they're not defined, then it checks Policy contract chains; // 4. Checks for the remaining targets. func BearerChainFeedRouter(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, override bearer.APEOverride) (policyengine.ChainRouter, error) { mr, err := newMorphReaderDecorator(morphChainStorage, override) if err != nil { return nil, fmt.Errorf("create morph reader with bearer override error: %w", err) } return policyengine.NewDefaultChainRouterWithLocalOverrides(mr, localOverrideStorage), nil }