95 lines
3.3 KiB
Go
95 lines
3.3 KiB
Go
|
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
|
||
|
}
|