forked from TrueCloudLab/policy-engine
[#21] router: Make Deny the highest priority
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
156018bcba
commit
1375e8f7fd
2 changed files with 91 additions and 11 deletions
|
@ -2,8 +2,14 @@ package iam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"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"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -428,3 +434,69 @@ func TestValidatePolicies(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProcessDenyFirst(t *testing.T) {
|
||||||
|
identityBasedPolicyStr := `
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {
|
||||||
|
"AWS": [ "arn:aws:iam::root:user/user-name" ]
|
||||||
|
},
|
||||||
|
"Action": ["s3:PutObject" ],
|
||||||
|
"Resource": "arn:aws:s3:::*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
resourceBasedPolicyStr := `
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Deny",
|
||||||
|
"Principal": "*",
|
||||||
|
"Action": "s3:*",
|
||||||
|
"Resource": [ "arn:aws:s3:::test-bucket/*" ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
var identityPolicy Policy
|
||||||
|
err := json.Unmarshal([]byte(identityBasedPolicyStr), &identityPolicy)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var resourcePolicy Policy
|
||||||
|
err = json.Unmarshal([]byte(resourceBasedPolicyStr), &resourcePolicy)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
mockResolver := newMockUserResolver([]string{"root/user-name"}, []string{"test-bucket"})
|
||||||
|
|
||||||
|
identityNativePolicy, err := ConvertToNativeChain(identityPolicy, mockResolver)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resourceNativePolicy, err := ConvertToNativeChain(resourcePolicy, mockResolver)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
s := inmemory.NewInMemory()
|
||||||
|
|
||||||
|
target := engine.NamespaceTarget("ns")
|
||||||
|
|
||||||
|
_, _, err = s.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, target, identityNativePolicy)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, _, err = s.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, target, resourceNativePolicy)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resource := testutil.NewResource(fmt.Sprintf(native.ResourceFormatRootContainerObjects, mockResolver.buckets["test-bucket"]), nil)
|
||||||
|
request := testutil.NewRequest("PutObject", resource, map[string]string{native.PropertyKeyActorPublicKey: mockResolver.users["root/user-name"]})
|
||||||
|
|
||||||
|
status, found, err := s.IsAllowed(chain.Ingress, engine.NewRequestTarget("ns", ""), request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, chain.AccessDenied, status)
|
||||||
|
}
|
||||||
|
|
|
@ -86,23 +86,31 @@ func (dr *defaultChainRouter) matchLocalOverrides(name chain.Name, target Target
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, c := range localOverrides {
|
status, ruleFound = dr.getStatusFromChains(localOverrides, r)
|
||||||
if status, ruleFound = c.Match(r); ruleFound && status != chain.Allow {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dr *defaultChainRouter) matchMorphRuleChains(name chain.Name, target Target, r resource.Request) (status chain.Status, ruleFound bool, err error) {
|
func (dr *defaultChainRouter) matchMorphRuleChains(name chain.Name, target Target, r resource.Request) (status chain.Status, ruleFound bool, err error) {
|
||||||
namespaceChains, err := dr.morph.ListMorphRuleChains(name, target)
|
namespaceChains, err := dr.morph.ListMorphRuleChains(name, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return chain.NoRuleFound, false, err
|
||||||
}
|
|
||||||
for _, c := range namespaceChains {
|
|
||||||
if status, ruleFound = c.Match(r); ruleFound {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
status, ruleFound = dr.getStatusFromChains(namespaceChains, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dr *defaultChainRouter) getStatusFromChains(chains []*chain.Chain, r resource.Request) (chain.Status, bool) {
|
||||||
|
var allow bool
|
||||||
|
for _, c := range chains {
|
||||||
|
if status, found := c.Match(r); found {
|
||||||
|
if status != chain.Allow {
|
||||||
|
return status, true
|
||||||
|
}
|
||||||
|
allow = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if allow {
|
||||||
|
return chain.Allow, true
|
||||||
|
}
|
||||||
|
return chain.NoRuleFound, false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue