generated from TrueCloudLab/basic
[#XX] chain: Introduce new condition operations
Some checks failed
DCO action / DCO (pull_request) Failing after 31s
Tests and linters / Staticcheck (pull_request) Successful in 1m2s
Tests and linters / Tests (pull_request) Successful in 1m27s
Tests and linters / Tests with -race (pull_request) Successful in 1m44s
Tests and linters / Lint (pull_request) Successful in 2m28s
Some checks failed
DCO action / DCO (pull_request) Failing after 31s
Tests and linters / Staticcheck (pull_request) Successful in 1m2s
Tests and linters / Tests (pull_request) Successful in 1m27s
Tests and linters / Tests with -race (pull_request) Successful in 1m44s
Tests and linters / Lint (pull_request) Successful in 2m28s
* Introduce new operation with suffix "IfExists" for all string and numeric condition operations; * An operation with "IfExists" suffix specifies the following: if the condition key is present in the context of the request, process the key as specified in the policy. If the key is not present, evaluate the condition element as true; * Change the signature for interface method `Property()`: since it returns two values - the second indicates whether the property exists; * This also means that original condition operations for string and number comparison is slightly changed: if property doesn't exist, then the condition is not evaluated. Signed-off-by: Airat Arifullin <aarifullin@yadro.com>
This commit is contained in:
parent
a3bc3099bd
commit
fc750ccedd
4 changed files with 534 additions and 25 deletions
|
@ -111,6 +111,24 @@ const (
|
||||||
|
|
||||||
CondIPAddress
|
CondIPAddress
|
||||||
CondNotIPAddress
|
CondNotIPAddress
|
||||||
|
|
||||||
|
CondStringEqualsIfExists
|
||||||
|
CondStringNotEqualsIfExists
|
||||||
|
CondStringEqualsIgnoreCaseIfExists
|
||||||
|
CondStringNotEqualsIgnoreCaseIfExists
|
||||||
|
CondStringLikeIfExists
|
||||||
|
CondStringNotLikeIfExists
|
||||||
|
CondStringLessThanIfExists
|
||||||
|
CondStringLessThanEqualsIfExists
|
||||||
|
CondStringGreaterThanIfExists
|
||||||
|
CondStringGreaterThanEqualsIfExists
|
||||||
|
|
||||||
|
CondNumericEqualsIfExists
|
||||||
|
CondNumericNotEqualsIfExists
|
||||||
|
CondNumericLessThanIfExists
|
||||||
|
CondNumericLessThanEqualsIfExists
|
||||||
|
CondNumericGreaterThanIfExists
|
||||||
|
CondNumericGreaterThanEqualsIfExists
|
||||||
)
|
)
|
||||||
|
|
||||||
var condToStr = []struct {
|
var condToStr = []struct {
|
||||||
|
@ -127,12 +145,28 @@ var condToStr = []struct {
|
||||||
{CondStringLessThanEquals, "StringLessThanEquals"},
|
{CondStringLessThanEquals, "StringLessThanEquals"},
|
||||||
{CondStringGreaterThan, "StringGreaterThan"},
|
{CondStringGreaterThan, "StringGreaterThan"},
|
||||||
{CondStringGreaterThanEquals, "StringGreaterThanEquals"},
|
{CondStringGreaterThanEquals, "StringGreaterThanEquals"},
|
||||||
|
{CondStringEqualsIfExists, "StringEqualsIfExists"},
|
||||||
|
{CondStringNotEqualsIfExists, "StringNotEqualsIfExists"},
|
||||||
|
{CondStringEqualsIgnoreCaseIfExists, "StringEqualsIgnoreCaseIfExists"},
|
||||||
|
{CondStringNotEqualsIgnoreCaseIfExists, "StringNotEqualsIgnoreCaseIfExists"},
|
||||||
|
{CondStringLikeIfExists, "StringLikeIfExists"},
|
||||||
|
{CondStringNotLikeIfExists, "StringNotLikeIfExists"},
|
||||||
|
{CondStringLessThanIfExists, "StringLessThanIfExists"},
|
||||||
|
{CondStringLessThanEqualsIfExists, "StringLessThanEqualsIfExists"},
|
||||||
|
{CondStringGreaterThanIfExists, "StringGreaterThanIfExists"},
|
||||||
|
{CondStringGreaterThanEqualsIfExists, "StringGreaterThanEqualsIfExists"},
|
||||||
{CondNumericEquals, "NumericEquals"},
|
{CondNumericEquals, "NumericEquals"},
|
||||||
{CondNumericNotEquals, "NumericNotEquals"},
|
{CondNumericNotEquals, "NumericNotEquals"},
|
||||||
{CondNumericLessThan, "NumericLessThan"},
|
{CondNumericLessThan, "NumericLessThan"},
|
||||||
{CondNumericLessThanEquals, "NumericLessThanEquals"},
|
{CondNumericLessThanEquals, "NumericLessThanEquals"},
|
||||||
{CondNumericGreaterThan, "NumericGreaterThan"},
|
{CondNumericGreaterThan, "NumericGreaterThan"},
|
||||||
{CondNumericGreaterThanEquals, "NumericGreaterThanEquals"},
|
{CondNumericGreaterThanEquals, "NumericGreaterThanEquals"},
|
||||||
|
{CondNumericEqualsIfExists, "NumericEqualsIfExists"},
|
||||||
|
{CondNumericNotEqualsIfExists, "NumericNotEqualsIfExists"},
|
||||||
|
{CondNumericLessThanIfExists, "NumericLessThanIfExists"},
|
||||||
|
{CondNumericLessThanEqualsIfExists, "NumericLessThanEqualsIfExists"},
|
||||||
|
{CondNumericGreaterThanIfExists, "NumericGreaterThanIfExists"},
|
||||||
|
{CondNumericGreaterThanEqualsIfExists, "NumericGreaterThanEqualsIfExists"},
|
||||||
{CondSliceContains, "SliceContains"},
|
{CondSliceContains, "SliceContains"},
|
||||||
{CondIPAddress, "IPAddress"},
|
{CondIPAddress, "IPAddress"},
|
||||||
{CondNotIPAddress, "NotIPAddress"},
|
{CondNotIPAddress, "NotIPAddress"},
|
||||||
|
@ -157,11 +191,12 @@ func FormCondSliceContainsValue(values []string) string {
|
||||||
|
|
||||||
func (c *Condition) Match(req resource.Request) bool {
|
func (c *Condition) Match(req resource.Request) bool {
|
||||||
var val string
|
var val string
|
||||||
|
var exists bool
|
||||||
switch c.Kind {
|
switch c.Kind {
|
||||||
case KindResource:
|
case KindResource:
|
||||||
val = req.Resource().Property(c.Key)
|
val, exists = req.Resource().Property(c.Key)
|
||||||
case KindRequest:
|
case KindRequest:
|
||||||
val = req.Property(c.Key)
|
val, exists = req.Property(c.Key)
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unknown condition type: %d", c.Kind))
|
panic(fmt.Sprintf("unknown condition type: %d", c.Kind))
|
||||||
}
|
}
|
||||||
|
@ -170,30 +205,53 @@ 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 exists && val == c.Value
|
||||||
|
case CondStringEqualsIfExists:
|
||||||
|
return !exists || val == c.Value
|
||||||
case CondStringNotEquals:
|
case CondStringNotEquals:
|
||||||
return val != c.Value
|
return exists && val != c.Value
|
||||||
|
case CondStringNotEqualsIfExists:
|
||||||
|
return !exists || val != c.Value
|
||||||
case CondStringEqualsIgnoreCase:
|
case CondStringEqualsIgnoreCase:
|
||||||
return strings.EqualFold(val, c.Value)
|
return exists && strings.EqualFold(val, c.Value)
|
||||||
|
case CondStringEqualsIgnoreCaseIfExists:
|
||||||
|
return !exists || strings.EqualFold(val, c.Value)
|
||||||
case CondStringNotEqualsIgnoreCase:
|
case CondStringNotEqualsIgnoreCase:
|
||||||
return !strings.EqualFold(val, c.Value)
|
return exists && !strings.EqualFold(val, c.Value)
|
||||||
|
case CondStringNotEqualsIgnoreCaseIfExists:
|
||||||
|
return !exists || !strings.EqualFold(val, c.Value)
|
||||||
case CondStringLike:
|
case CondStringLike:
|
||||||
return util.GlobMatch(val, c.Value)
|
return exists && util.GlobMatch(val, c.Value)
|
||||||
|
case CondStringLikeIfExists:
|
||||||
|
return !exists || util.GlobMatch(val, c.Value)
|
||||||
case CondStringNotLike:
|
case CondStringNotLike:
|
||||||
return !util.GlobMatch(val, c.Value)
|
return exists && !util.GlobMatch(val, c.Value)
|
||||||
|
case CondStringNotLikeIfExists:
|
||||||
|
return !exists || !util.GlobMatch(val, c.Value)
|
||||||
case CondStringLessThan:
|
case CondStringLessThan:
|
||||||
return val < c.Value
|
return exists && val < c.Value
|
||||||
|
case CondStringLessThanIfExists:
|
||||||
|
return !exists || val < c.Value
|
||||||
case CondStringLessThanEquals:
|
case CondStringLessThanEquals:
|
||||||
return val <= c.Value
|
return exists && val <= c.Value
|
||||||
|
case CondStringLessThanEqualsIfExists:
|
||||||
|
return !exists || val <= c.Value
|
||||||
case CondStringGreaterThan:
|
case CondStringGreaterThan:
|
||||||
return val > c.Value
|
return exists && val > c.Value
|
||||||
|
case CondStringGreaterThanIfExists:
|
||||||
|
return !exists || val > c.Value
|
||||||
case CondStringGreaterThanEquals:
|
case CondStringGreaterThanEquals:
|
||||||
return val >= c.Value
|
return exists && val >= c.Value
|
||||||
|
case CondStringGreaterThanEqualsIfExists:
|
||||||
|
return !exists || val >= c.Value
|
||||||
case CondSliceContains:
|
case CondSliceContains:
|
||||||
return slices.Contains(strings.Split(val, condSliceContainsDelimiter), c.Value)
|
return slices.Contains(strings.Split(val, condSliceContainsDelimiter), c.Value)
|
||||||
case CondNumericEquals, CondNumericNotEquals, CondNumericLessThan, CondNumericLessThanEquals, CondNumericGreaterThan,
|
case CondNumericEquals, CondNumericNotEquals, CondNumericLessThan, CondNumericLessThanEquals, CondNumericGreaterThan,
|
||||||
CondNumericGreaterThanEquals:
|
CondNumericGreaterThanEquals:
|
||||||
return c.matchNumeric(val)
|
return exists && c.matchNumeric(val)
|
||||||
|
case CondNumericEqualsIfExists, CondNumericNotEqualsIfExists, CondNumericLessThanIfExists, CondNumericLessThanEqualsIfExists, CondNumericGreaterThanIfExists,
|
||||||
|
CondNumericGreaterThanEqualsIfExists:
|
||||||
|
return !exists || c.matchNumeric(val)
|
||||||
case CondIPAddress, CondNotIPAddress:
|
case CondIPAddress, CondNotIPAddress:
|
||||||
return c.matchIP(val)
|
return c.matchIP(val)
|
||||||
}
|
}
|
||||||
|
@ -213,17 +271,17 @@ func (c *Condition) matchNumeric(val string) bool {
|
||||||
switch c.Op {
|
switch c.Op {
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("unimplemented: %d", c.Op))
|
panic(fmt.Sprintf("unimplemented: %d", c.Op))
|
||||||
case CondNumericEquals:
|
case CondNumericEquals, CondNumericEqualsIfExists:
|
||||||
return valDecimal.Equal(condVal)
|
return valDecimal.Equal(condVal)
|
||||||
case CondNumericNotEquals:
|
case CondNumericNotEquals, CondNumericNotEqualsIfExists:
|
||||||
return !valDecimal.Equal(condVal)
|
return !valDecimal.Equal(condVal)
|
||||||
case CondNumericLessThan:
|
case CondNumericLessThan, CondNumericLessThanIfExists:
|
||||||
return valDecimal.LessThan(condVal)
|
return valDecimal.LessThan(condVal)
|
||||||
case CondNumericLessThanEquals:
|
case CondNumericLessThanEquals, CondNumericLessThanEqualsIfExists:
|
||||||
return valDecimal.LessThan(condVal) || valDecimal.Equal(condVal)
|
return valDecimal.LessThan(condVal) || valDecimal.Equal(condVal)
|
||||||
case CondNumericGreaterThan:
|
case CondNumericGreaterThan, CondNumericGreaterThanIfExists:
|
||||||
return valDecimal.GreaterThan(condVal)
|
return valDecimal.GreaterThan(condVal)
|
||||||
case CondNumericGreaterThanEquals:
|
case CondNumericGreaterThanEquals, CondNumericGreaterThanEqualsIfExists:
|
||||||
return valDecimal.GreaterThan(condVal) || valDecimal.Equal(condVal)
|
return valDecimal.GreaterThan(condVal) || valDecimal.Equal(condVal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -398,6 +398,31 @@ func testNumericConditionsMatch(t *testing.T) {
|
||||||
value: "50",
|
value: "50",
|
||||||
status: Allow,
|
status: Allow,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "value if exists from interval",
|
||||||
|
conditions: []Condition{
|
||||||
|
{
|
||||||
|
Op: CondNumericLessThanIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "100",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericGreaterThanIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "80",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondNumericNotEqualsIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "91",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
value: "90",
|
||||||
|
status: Allow,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
@ -411,6 +436,16 @@ func testNumericConditionsMatch(t *testing.T) {
|
||||||
}}}
|
}}}
|
||||||
st, _ := ch.Match(request)
|
st, _ := ch.Match(request)
|
||||||
require.Equal(t, tc.status.String(), st.String())
|
require.Equal(t, tc.status.String(), st.String())
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found := ch.Match(emptyPropsRequest)
|
||||||
|
if strings.HasSuffix(tc.conditions[0].Op.String(), "IfExists") {
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, tc.status.String(), st.String())
|
||||||
|
} else {
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, st, NoRuleFound)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -448,6 +483,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
_, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringEqualsIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringEqualsIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val,
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val,
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: "distort_tag_value" + val,
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringNotEquals.String(), func(t *testing.T) {
|
t.Run(CondStringNotEquals.String(), func(t *testing.T) {
|
||||||
|
@ -479,6 +555,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
_, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotEqualsIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringNotEqualsIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val,
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: "distort_tag_value" + val,
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val,
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringEqualsIgnoreCase.String(), func(t *testing.T) {
|
t.Run(CondStringEqualsIgnoreCase.String(), func(t *testing.T) {
|
||||||
|
@ -510,6 +627,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
_, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringEqualsIgnoreCaseIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringEqualsIgnoreCaseIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val,
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: strings.ToUpper(val),
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: strings.ToUpper("distort_tag_value" + val),
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringNotEqualsIgnoreCase.String(), func(t *testing.T) {
|
t.Run(CondStringNotEqualsIgnoreCase.String(), func(t *testing.T) {
|
||||||
|
@ -541,6 +699,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotEqualsIgnoreCaseIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringNotEqualsIgnoreCaseIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val,
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: strings.ToUpper("distort_tag_value" + val),
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: strings.ToUpper(val),
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringLike.String(), func(t *testing.T) {
|
t.Run(CondStringLike.String(), func(t *testing.T) {
|
||||||
|
@ -572,6 +771,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLikeIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringLikeIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val + "*",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "suffix",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: string([]byte(val)[:len(val)-1]), //cut last letter
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringNotLike.String(), func(t *testing.T) {
|
t.Run(CondStringNotLike.String(), func(t *testing.T) {
|
||||||
|
@ -603,6 +843,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotLikeIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringNotLikeIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "prefix" + val + "*",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "suffix",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: "prefix" + val,
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringLessThan.String(), func(t *testing.T) {
|
t.Run(CondStringLessThan.String(), func(t *testing.T) {
|
||||||
|
@ -634,6 +915,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLessThanIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringLessThanIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val + "b",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "a",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "c",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringLessThanEquals.String(), func(t *testing.T) {
|
t.Run(CondStringLessThanEquals.String(), func(t *testing.T) {
|
||||||
|
@ -665,6 +987,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, Allow, st)
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLessThanEqualsIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringLessThanEqualsIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val + "b",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "a",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "b",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringGreaterThan.String(), func(t *testing.T) {
|
t.Run(CondStringGreaterThan.String(), func(t *testing.T) {
|
||||||
|
@ -696,6 +1059,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
require.Equal(t, NoRuleFound, st)
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringGreaterThanIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringGreaterThanIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val + "b",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "c",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "b",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run(CondStringGreaterThanEquals.String(), func(t *testing.T) {
|
t.Run(CondStringGreaterThanEquals.String(), func(t *testing.T) {
|
||||||
|
@ -727,6 +1131,47 @@ func testStringConiditionsMatch(t *testing.T) {
|
||||||
st, found = ch.Match(request)
|
st, found = ch.Match(request)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, Allow, st)
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringGreaterThanEqualsIfExists.String(), func(t *testing.T) {
|
||||||
|
ch := Chain{Rules: []Rule{{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondStringGreaterThanEqualsIfExists,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: val + "b",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "c",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val + "b",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
emptyPropsRequest := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{})
|
||||||
|
st, found = ch.Match(emptyPropsRequest)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,17 @@ type Request interface {
|
||||||
// Name is the operation name, such as Object.Put. Must not include wildcards.
|
// Name is the operation name, such as Object.Put. Must not include wildcards.
|
||||||
Operation() string
|
Operation() string
|
||||||
// Property returns request properties, such as IP address of the origin.
|
// Property returns request properties, such as IP address of the origin.
|
||||||
Property(string) string
|
// The second return boolean value determines if the specified value exists within the properties.
|
||||||
|
Property(string) (string, bool)
|
||||||
// Resource returns resource the operation is applied to.
|
// Resource returns resource the operation is applied to.
|
||||||
Resource() Resource
|
Resource() Resource
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resource represents the resource operation is applied to.
|
// Resource represents the resource operation is applied to.
|
||||||
type Resource interface {
|
type Resource interface {
|
||||||
|
// Name is the resource name.
|
||||||
Name() string
|
Name() string
|
||||||
Property(string) string
|
// Property returns resource properties, such as object type etc.
|
||||||
|
// The second return boolean value determines if the specified value exists within the properties.
|
||||||
|
Property(string) (string, bool)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,9 @@ func (r *Resource) Name() string {
|
||||||
return r.name
|
return r.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) Property(name string) string {
|
func (r *Resource) Property(name string) (val string, exists bool) {
|
||||||
return r.properties[name]
|
val, exists = r.properties[name]
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewResource(name string, properties map[string]string) *Resource {
|
func NewResource(name string, properties map[string]string) *Resource {
|
||||||
|
@ -40,8 +41,9 @@ func (r *Request) Resource() resourcepkg.Resource {
|
||||||
return r.resource
|
return r.resource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Request) Property(name string) string {
|
func (r *Request) Property(name string) (val string, exists bool) {
|
||||||
return r.properties[name]
|
val, exists = r.properties[name]
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRequest(op string, r *Resource, properties map[string]string) *Request {
|
func NewRequest(op string, r *Resource, properties map[string]string) *Request {
|
||||||
|
|
Loading…
Reference in a new issue