frostfs-node/pkg/ape/router/bearer_overrides_test.go
Airat Arifullin 47bcd346d3 [] ape: Introduce BearerChainFeedRouter
* Unlike default chain router, `BearerChainFedRouter` performs checks for
  overrides defined in the bearer token;
* Add unit-test for the introduced router.

Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
2024-07-05 18:26:48 +00:00

165 lines
5.3 KiB
Go

package router_test
import (
"fmt"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router"
apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory"
resourcetest "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
"github.com/stretchr/testify/require"
)
const (
container = "67ETTZzbzJC6WxdQhHHHsJNCttVMBqYrSoFaUFVDNfiX"
rootNs = ""
)
var (
allowBySourceIP = &chain.Chain{
Rules: []chain.Rule{
{
Status: chain.Allow,
Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}},
Resources: chain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container)}},
Condition: []chain.Condition{
{
Op: chain.CondStringEquals,
Kind: chain.KindRequest,
Key: "SourceIP",
Value: "10.122.1.20",
},
},
},
},
}
denyBySourceIP = &chain.Chain{
Rules: []chain.Rule{
{
Status: chain.AccessDenied,
Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}},
Resources: chain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container)}},
Condition: []chain.Condition{
{
Op: chain.CondStringEquals,
Kind: chain.KindRequest,
Key: "SourceIP",
Value: "10.122.1.20",
},
},
},
},
}
)
func TestBearerChainFedRouter(t *testing.T) {
t.Run("no bearer token overrides", func(t *testing.T) {
inmem := inmemory.NewInMemoryLocalOverrides()
inmem.LocalStorage().AddOverride(chain.Ingress, engine.ContainerTarget(container), denyBySourceIP)
inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP)
_, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bearerSDK.APEOverride{})
require.Error(t, err)
})
t.Run("allow by container with deny by bearer overrides", func(t *testing.T) {
inmem := inmemory.NewInMemoryLocalOverrides()
inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP)
bt := bearerSDK.APEOverride{
Target: apeSDK.ChainTarget{
TargetType: apeSDK.TargetTypeContainer,
Name: container,
},
Chains: []apeSDK.Chain{{
Raw: denyBySourceIP.Bytes(),
}},
}
r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt)
require.NoError(t, err)
req := resourcetest.NewRequest(nativeschema.MethodPutObject,
resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}),
map[string]string{
"SourceIP": "10.122.1.20",
"Actor": "someOwner",
},
)
st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, st, chain.AccessDenied)
})
t.Run("allow by namespace with deny by bearer overrides", func(t *testing.T) {
inmem := inmemory.NewInMemoryLocalOverrides()
inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP)
inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(rootNs), allowBySourceIP)
bt := bearerSDK.APEOverride{
Target: apeSDK.ChainTarget{
TargetType: apeSDK.TargetTypeContainer,
Name: container,
},
Chains: []apeSDK.Chain{{
Raw: denyBySourceIP.Bytes(),
}},
}
r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt)
require.NoError(t, err)
req := resourcetest.NewRequest(nativeschema.MethodPutObject,
resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}),
map[string]string{
"SourceIP": "10.122.1.20",
"Actor": "someOwner",
},
)
st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, st, chain.AccessDenied)
})
t.Run("deny by namespace with allow by bearer overrides", func(t *testing.T) {
inmem := inmemory.NewInMemoryLocalOverrides()
inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(rootNs), denyBySourceIP)
bt := bearerSDK.APEOverride{
Target: apeSDK.ChainTarget{
TargetType: apeSDK.TargetTypeContainer,
Name: container,
},
Chains: []apeSDK.Chain{{
Raw: allowBySourceIP.Bytes(),
}},
}
r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt)
require.NoError(t, err)
req := resourcetest.NewRequest(nativeschema.MethodPutObject,
resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}),
map[string]string{
"SourceIP": "10.122.1.20",
"Actor": "someOwner",
},
)
st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req)
require.NoError(t, err)
require.True(t, found)
require.Equal(t, st, chain.AccessDenied)
})
}