generated from TrueCloudLab/basic
[#60] chain: Support numeric conditions
DCO action / DCO (pull_request) Successful in 1m6s
Details
Tests and linters / Tests (1.21) (pull_request) Successful in 1m7s
Details
Tests and linters / Staticcheck (pull_request) Successful in 1m27s
Details
Tests and linters / Tests with -race (pull_request) Successful in 1m48s
Details
Tests and linters / Lint (pull_request) Successful in 2m16s
Details
Tests and linters / Tests (1.20) (pull_request) Successful in 47s
Details
DCO action / DCO (pull_request) Successful in 1m6s
Details
Tests and linters / Tests (1.21) (pull_request) Successful in 1m7s
Details
Tests and linters / Staticcheck (pull_request) Successful in 1m27s
Details
Tests and linters / Tests with -race (pull_request) Successful in 1m48s
Details
Tests and linters / Lint (pull_request) Successful in 2m16s
Details
Tests and linters / Tests (1.20) (pull_request) Successful in 47s
Details
Signed-off-by: Marina Biryukova <m.biryukova@yadro.com>
parent
1d51f2121d
commit
e5b7e1f763
|
@ -219,8 +219,7 @@ func getConditionTypeAndConverter(op string) (chain.ConditionType, convertFuncti
|
||||||
return 0, nil, fmt.Errorf("unsupported condition operator: '%s'", op)
|
return 0, nil, fmt.Errorf("unsupported condition operator: '%s'", op)
|
||||||
}
|
}
|
||||||
case strings.HasPrefix(op, "Numeric"):
|
case strings.HasPrefix(op, "Numeric"):
|
||||||
// TODO
|
return numericConditionTypeAndConverter(op)
|
||||||
return 0, nil, fmt.Errorf("currently nummeric conditions unsupported: '%s'", op)
|
|
||||||
case strings.HasPrefix(op, "Date"):
|
case strings.HasPrefix(op, "Date"):
|
||||||
switch op {
|
switch op {
|
||||||
case CondDateEquals:
|
case CondDateEquals:
|
||||||
|
@ -255,12 +254,39 @@ func getConditionTypeAndConverter(op string) (chain.ConditionType, convertFuncti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func numericConditionTypeAndConverter(op string) (chain.ConditionType, convertFunction, error) {
|
||||||
|
switch op {
|
||||||
|
case CondNumericEquals:
|
||||||
|
return chain.CondNumericEquals, numericConvertFunction, nil
|
||||||
|
case CondNumericNotEquals:
|
||||||
|
return chain.CondNumericNotEquals, numericConvertFunction, nil
|
||||||
|
case CondNumericLessThan:
|
||||||
|
return chain.CondNumericLessThan, numericConvertFunction, nil
|
||||||
|
case CondNumericLessThanEquals:
|
||||||
|
return chain.CondNumericLessThanEquals, numericConvertFunction, nil
|
||||||
|
case CondNumericGreaterThan:
|
||||||
|
return chain.CondNumericGreaterThan, numericConvertFunction, nil
|
||||||
|
case CondNumericGreaterThanEquals:
|
||||||
|
return chain.CondNumericGreaterThanEquals, numericConvertFunction, nil
|
||||||
|
default:
|
||||||
|
return 0, nil, fmt.Errorf("unsupported condition operator: '%s'", op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type convertFunction func(string) (string, error)
|
type convertFunction func(string) (string, error)
|
||||||
|
|
||||||
func noConvertFunction(val string) (string, error) {
|
func noConvertFunction(val string) (string, error) {
|
||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func numericConvertFunction(val string) (string, error) {
|
||||||
|
if _, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("invalid numeric value: '%s'", val)
|
||||||
|
}
|
||||||
|
|
||||||
func dateConvertFunction(val string) (string, error) {
|
func dateConvertFunction(val string) (string, error) {
|
||||||
if _, err := strconv.ParseInt(val, 10, 64); err == nil {
|
if _, err := strconv.ParseInt(val, 10, 64); err == nil {
|
||||||
return val, nil
|
return val, nil
|
||||||
|
|
|
@ -385,6 +385,12 @@ func TestConvertToChainCondition(t *testing.T) {
|
||||||
CondArnLike: {condKeyAWSPrincipalARN: {principal}},
|
CondArnLike: {condKeyAWSPrincipalARN: {principal}},
|
||||||
CondArnNotEquals: {"key18": {"val18"}},
|
CondArnNotEquals: {"key18": {"val18"}},
|
||||||
CondArnNotLike: {"key19": {"val19"}},
|
CondArnNotLike: {"key19": {"val19"}},
|
||||||
|
CondNumericEquals: {"key20": {"20"}},
|
||||||
|
CondNumericNotEquals: {"key21": {"21"}},
|
||||||
|
CondNumericLessThan: {"key22": {"22"}},
|
||||||
|
CondNumericLessThanEquals: {"key23": {"23"}},
|
||||||
|
CondNumericGreaterThan: {"key24": {"24"}},
|
||||||
|
CondNumericGreaterThanEquals: {"key25": {"25"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedCondition := []GroupedConditions{
|
expectedCondition := []GroupedConditions{
|
||||||
|
@ -549,11 +555,65 @@ func TestConvertToChainCondition(t *testing.T) {
|
||||||
Value: "val19",
|
Value: "val19",
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericEquals,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key20",
|
||||||
|
Value: "20",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericNotEquals,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key21",
|
||||||
|
Value: "21",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericLessThan,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key22",
|
||||||
|
Value: "22",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericLessThanEquals,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key23",
|
||||||
|
Value: "23",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericGreaterThan,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key24",
|
||||||
|
Value: "24",
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Conditions: []chain.Condition{{
|
||||||
|
Op: chain.CondNumericGreaterThanEquals,
|
||||||
|
Object: chain.ObjectRequest,
|
||||||
|
Key: "key25",
|
||||||
|
Value: "25",
|
||||||
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
actualCondition, err := convertToChainCondition(conditions)
|
actualCondition, err := convertToChainCondition(conditions)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.ElementsMatch(t, expectedCondition, actualCondition)
|
require.ElementsMatch(t, expectedCondition, actualCondition)
|
||||||
|
|
||||||
|
invalidCondition := Conditions{
|
||||||
|
CondNumericEquals: {"key": {"invalid"}},
|
||||||
|
}
|
||||||
|
_, err = convertToChainCondition(invalidCondition)
|
||||||
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParsePrincipalARN(t *testing.T) {
|
func TestParsePrincipalARN(t *testing.T) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource"
|
||||||
|
@ -150,7 +151,7 @@ func FormCondSliceContainsValue(values []string) string {
|
||||||
return strings.Join(values, condSliceContainsDelimiter)
|
return strings.Join(values, condSliceContainsDelimiter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Condition) Match(req resource.Request) bool {
|
func (c *Condition) Match(req resource.Request) (bool, error) {
|
||||||
var val string
|
var val string
|
||||||
switch c.Object {
|
switch c.Object {
|
||||||
case ObjectResource:
|
case ObjectResource:
|
||||||
|
@ -165,31 +166,63 @@ func (c *Condition) Match(req resource.Request) bool {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unimplemented: %d", c.Op))
|
panic(fmt.Sprintf("unimplemented: %d", c.Op))
|
||||||
case CondStringEquals:
|
case CondStringEquals:
|
||||||
return val == c.Value
|
return val == c.Value, nil
|
||||||
case CondStringNotEquals:
|
case CondStringNotEquals:
|
||||||
return val != c.Value
|
return val != c.Value, nil
|
||||||
case CondStringEqualsIgnoreCase:
|
case CondStringEqualsIgnoreCase:
|
||||||
return strings.EqualFold(val, c.Value)
|
return strings.EqualFold(val, c.Value), nil
|
||||||
case CondStringNotEqualsIgnoreCase:
|
case CondStringNotEqualsIgnoreCase:
|
||||||
return !strings.EqualFold(val, c.Value)
|
return !strings.EqualFold(val, c.Value), nil
|
||||||
case CondStringLike:
|
case CondStringLike:
|
||||||
return util.GlobMatch(val, c.Value)
|
return util.GlobMatch(val, c.Value), nil
|
||||||
case CondStringNotLike:
|
case CondStringNotLike:
|
||||||
return !util.GlobMatch(val, c.Value)
|
return !util.GlobMatch(val, c.Value), nil
|
||||||
case CondStringLessThan:
|
case CondStringLessThan:
|
||||||
return val < c.Value
|
return val < c.Value, nil
|
||||||
case CondStringLessThanEquals:
|
case CondStringLessThanEquals:
|
||||||
return val <= c.Value
|
return val <= c.Value, nil
|
||||||
case CondStringGreaterThan:
|
case CondStringGreaterThan:
|
||||||
return val > c.Value
|
return val > c.Value, nil
|
||||||
case CondStringGreaterThanEquals:
|
case CondStringGreaterThanEquals:
|
||||||
return val >= c.Value
|
return val >= c.Value, nil
|
||||||
case CondSliceContains:
|
case CondSliceContains:
|
||||||
return slices.Contains(strings.Split(val, condSliceContainsDelimiter), c.Value)
|
return slices.Contains(strings.Split(val, condSliceContainsDelimiter), c.Value), nil
|
||||||
|
case CondNumericEquals, CondNumericNotEquals, CondNumericLessThan, CondNumericLessThanEquals, CondNumericGreaterThan,
|
||||||
|
CondNumericGreaterThanEquals:
|
||||||
|
return c.matchNumeric(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) Match(req resource.Request) (status Status, matched bool) {
|
func (c *Condition) matchNumeric(val string) (bool, error) {
|
||||||
|
valInt, err := strconv.ParseInt(val, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("invalid integer value: %s", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
condVal, err := strconv.ParseInt(c.Value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("invalid integer value: %s", c.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.Op {
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unimplemented: %d", c.Op))
|
||||||
|
case CondNumericEquals:
|
||||||
|
return valInt == condVal, nil
|
||||||
|
case CondNumericNotEquals:
|
||||||
|
return valInt != condVal, nil
|
||||||
|
case CondNumericLessThan:
|
||||||
|
return valInt < condVal, nil
|
||||||
|
case CondNumericLessThanEquals:
|
||||||
|
return valInt <= condVal, nil
|
||||||
|
case CondNumericGreaterThan:
|
||||||
|
return valInt > condVal, nil
|
||||||
|
case CondNumericGreaterThanEquals:
|
||||||
|
return valInt >= condVal, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rule) Match(req resource.Request) (status Status, matched bool, err error) {
|
||||||
found := len(r.Resources.Names) == 0
|
found := len(r.Resources.Names) == 0
|
||||||
for i := range r.Resources.Names {
|
for i := range r.Resources.Names {
|
||||||
if util.GlobMatch(req.Resource().Name(), r.Resources.Names[i]) != r.Resources.Inverted {
|
if util.GlobMatch(req.Resource().Name(), r.Resources.Names[i]) != r.Resources.Inverted {
|
||||||
|
@ -198,42 +231,50 @@ func (r *Rule) Match(req resource.Request) (status Status, matched bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return NoRuleFound, false
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
for i := range r.Actions.Names {
|
for i := range r.Actions.Names {
|
||||||
if util.GlobMatch(req.Operation(), r.Actions.Names[i]) != r.Actions.Inverted {
|
if util.GlobMatch(req.Operation(), r.Actions.Names[i]) != r.Actions.Inverted {
|
||||||
return r.matchCondition(req)
|
return r.matchCondition(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoRuleFound, false
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) matchCondition(obj resource.Request) (status Status, matched bool) {
|
func (r *Rule) matchCondition(obj resource.Request) (status Status, matched bool, err error) {
|
||||||
if r.Any {
|
if r.Any {
|
||||||
return r.matchAny(obj)
|
return r.matchAny(obj)
|
||||||
}
|
}
|
||||||
return r.matchAll(obj)
|
return r.matchAll(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) matchAny(obj resource.Request) (status Status, matched bool) {
|
func (r *Rule) matchAny(obj resource.Request) (status Status, matched bool, err error) {
|
||||||
for i := range r.Condition {
|
for i := range r.Condition {
|
||||||
if r.Condition[i].Match(obj) {
|
matched, err = r.Condition[i].Match(obj)
|
||||||
return r.Status, true
|
if err != nil {
|
||||||
|
return NoRuleFound, false, err
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
return r.Status, true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoRuleFound, false
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) matchAll(obj resource.Request) (status Status, matched bool) {
|
func (r *Rule) matchAll(obj resource.Request) (status Status, matched bool, err error) {
|
||||||
for i := range r.Condition {
|
for i := range r.Condition {
|
||||||
if !r.Condition[i].Match(obj) {
|
matched, err = r.Condition[i].Match(obj)
|
||||||
return NoRuleFound, false
|
if err != nil {
|
||||||
|
return NoRuleFound, false, err
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r.Status, true
|
return r.Status, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chain) Match(req resource.Request) (status Status, matched bool) {
|
func (c *Chain) Match(req resource.Request) (status Status, matched bool, err error) {
|
||||||
switch c.MatchType {
|
switch c.MatchType {
|
||||||
case MatchTypeDenyPriority:
|
case MatchTypeDenyPriority:
|
||||||
return c.denyPriority(req)
|
return c.denyPriority(req)
|
||||||
|
@ -244,30 +285,36 @@ func (c *Chain) Match(req resource.Request) (status Status, matched bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chain) firstMatch(req resource.Request) (status Status, matched bool) {
|
func (c *Chain) firstMatch(req resource.Request) (status Status, matched bool, err error) {
|
||||||
for i := range c.Rules {
|
for i := range c.Rules {
|
||||||
status, matched := c.Rules[i].Match(req)
|
status, matched, err = c.Rules[i].Match(req)
|
||||||
|
if err != nil {
|
||||||
|
return NoRuleFound, false, err
|
||||||
|
}
|
||||||
if matched {
|
if matched {
|
||||||
return status, true
|
return status, true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoRuleFound, false
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Chain) denyPriority(req resource.Request) (status Status, matched bool) {
|
func (c *Chain) denyPriority(req resource.Request) (status Status, matched bool, err error) {
|
||||||
var allowFound bool
|
var allowFound bool
|
||||||
for i := range c.Rules {
|
for i := range c.Rules {
|
||||||
status, matched := c.Rules[i].Match(req)
|
status, matched, err = c.Rules[i].Match(req)
|
||||||
|
if err != nil {
|
||||||
|
return NoRuleFound, false, err
|
||||||
|
}
|
||||||
if !matched {
|
if !matched {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if status != Allow {
|
if status != Allow {
|
||||||
return status, true
|
return status, true, nil
|
||||||
}
|
}
|
||||||
allowFound = true
|
allowFound = true
|
||||||
}
|
}
|
||||||
if allowFound {
|
if allowFound {
|
||||||
return Allow, true
|
return Allow, true, nil
|
||||||
}
|
}
|
||||||
return NoRuleFound, false
|
return NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/s3"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,14 +76,16 @@ func TestReturnFirstMatch(t *testing.T) {
|
||||||
request := testutil.NewRequest(native.MethodPutObject, resource, nil)
|
request := testutil.NewRequest(native.MethodPutObject, resource, nil)
|
||||||
|
|
||||||
t.Run("default match", func(t *testing.T) {
|
t.Run("default match", func(t *testing.T) {
|
||||||
st, found := ch.Match(request)
|
st, found, err := ch.Match(request)
|
||||||
|
require.NoError(t, err)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, AccessDenied, st)
|
require.Equal(t, AccessDenied, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("return first match", func(t *testing.T) {
|
t.Run("return first match", func(t *testing.T) {
|
||||||
ch.MatchType = MatchTypeFirstMatch
|
ch.MatchType = MatchTypeFirstMatch
|
||||||
st, found := ch.Match(request)
|
st, found, err := ch.Match(request)
|
||||||
|
require.NoError(t, err)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, Allow, st)
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
@ -144,7 +147,85 @@ func TestCondSliceContainsMatch(t *testing.T) {
|
||||||
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: tc.value})
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: tc.value})
|
||||||
|
|
||||||
st, _ := ch.Match(request)
|
st, _, err := ch.Match(request)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, tc.status.String(), st.String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNumericConditionsMatch(t *testing.T) {
|
||||||
|
propKey := s3.PropertyKeyMaxKeys
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
conditions []Condition
|
||||||
|
value string
|
||||||
|
status Status
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "value from interval",
|
||||||
|
conditions: []Condition{
|
||||||
|
{
|
||||||
|
Op: CondNumericLessThan,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "100",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericGreaterThan,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericNotEquals,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "91",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: "90",
|
||||||
|
status: Allow,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "border value",
|
||||||
|
conditions: []Condition{
|
||||||
|
{
|
||||||
|
Op: CondNumericEquals,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "50",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericLessThanEquals,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "50",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericGreaterThanEquals,
|
||||||
|
Object: ObjectRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "50",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: "50",
|
||||||
|
status: Allow,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: tc.value})
|
||||||
|
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: tc.conditions,
|
||||||
|
}}}
|
||||||
|
st, _, err := ch.Match(request)
|
||||||
|
require.NoError(t, err)
|
||||||
require.Equal(t, tc.status.String(), st.String())
|
require.Equal(t, tc.status.String(), st.String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ func (dr *defaultChainRouter) matchLocalOverrides(name chain.Name, target Target
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
status, ruleFound = dr.getStatusFromChains(localOverrides, r)
|
status, ruleFound, err = dr.getStatusFromChains(localOverrides, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,22 +95,26 @@ func (dr *defaultChainRouter) matchMorphRuleChains(name chain.Name, target Targe
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return chain.NoRuleFound, false, err
|
return chain.NoRuleFound, false, err
|
||||||
}
|
}
|
||||||
status, ruleFound = dr.getStatusFromChains(namespaceChains, r)
|
status, ruleFound, err = dr.getStatusFromChains(namespaceChains, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dr *defaultChainRouter) getStatusFromChains(chains []*chain.Chain, r resource.Request) (chain.Status, bool) {
|
func (dr *defaultChainRouter) getStatusFromChains(chains []*chain.Chain, r resource.Request) (chain.Status, bool, error) {
|
||||||
var allow bool
|
var allow bool
|
||||||
for _, c := range chains {
|
for _, c := range chains {
|
||||||
if status, found := c.Match(r); found {
|
status, found, err := c.Match(r)
|
||||||
|
if err != nil {
|
||||||
|
return chain.NoRuleFound, false, err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
if status != chain.Allow {
|
if status != chain.Allow {
|
||||||
return status, true
|
return status, true, nil
|
||||||
}
|
}
|
||||||
allow = true
|
allow = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allow {
|
if allow {
|
||||||
return chain.Allow, true
|
return chain.Allow, true, nil
|
||||||
}
|
}
|
||||||
return chain.NoRuleFound, false
|
return chain.NoRuleFound, false, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const (
|
||||||
PropertyKeyDelimiter = "s3:delimiter"
|
PropertyKeyDelimiter = "s3:delimiter"
|
||||||
PropertyKeyPrefix = "s3:prefix"
|
PropertyKeyPrefix = "s3:prefix"
|
||||||
PropertyKeyVersionID = "s3:VersionId"
|
PropertyKeyVersionID = "s3:VersionId"
|
||||||
|
PropertyKeyMaxKeys = "s3:max-keys"
|
||||||
|
|
||||||
ResourceFormatS3All = "arn:aws:s3:::*"
|
ResourceFormatS3All = "arn:aws:s3:::*"
|
||||||
ResourceFormatS3Bucket = "arn:aws:s3:::%s"
|
ResourceFormatS3Bucket = "arn:aws:s3:::%s"
|
||||||
|
|
Loading…
Reference in New Issue