generated from TrueCloudLab/basic
[#76] chain: Increase unit-test coverage for chain related types
All checks were successful
DCO action / DCO (pull_request) Successful in 1m8s
Tests and linters / Tests (1.20) (pull_request) Successful in 1m22s
Tests and linters / Tests (1.21) (pull_request) Successful in 1m17s
Tests and linters / Staticcheck (pull_request) Successful in 1m31s
Tests and linters / Tests with -race (pull_request) Successful in 1m43s
Tests and linters / Lint (pull_request) Successful in 2m17s
All checks were successful
DCO action / DCO (pull_request) Successful in 1m8s
Tests and linters / Tests (1.20) (pull_request) Successful in 1m22s
Tests and linters / Tests (1.21) (pull_request) Successful in 1m17s
Tests and linters / Staticcheck (pull_request) Successful in 1m31s
Tests and linters / Tests with -race (pull_request) Successful in 1m43s
Tests and linters / Lint (pull_request) Successful in 2m17s
* Add more unit-test cases. Signed-off-by: Airat Arifullin <aarifullin@yadro.com>
This commit is contained in:
parent
1f6f4163d4
commit
d7ed188f68
1 changed files with 795 additions and 54 deletions
|
@ -1,6 +1,8 @@
|
||||||
package chain
|
package chain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil"
|
||||||
|
@ -50,7 +52,7 @@ func TestEncodeDecode(t *testing.T) {
|
||||||
require.Equal(t, expected, actual)
|
require.Equal(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReturnFirstMatch(t *testing.T) {
|
func TestChainMatch(t *testing.T) {
|
||||||
ch := Chain{
|
ch := Chain{
|
||||||
Rules: []Rule{
|
Rules: []Rule{
|
||||||
{
|
{
|
||||||
|
@ -87,9 +89,195 @@ func TestReturnFirstMatch(t *testing.T) {
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, Allow, st)
|
require.Equal(t, Allow, st)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("unknown match", func(t *testing.T) {
|
||||||
|
ch.MatchType = MatchType(255)
|
||||||
|
request := testutil.NewRequest(native.MethodGetObject, resource, nil)
|
||||||
|
require.PanicsWithValue(t, "unknown MatchType 255", func() {
|
||||||
|
ch.Match(request)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("no rule found", func(t *testing.T) {
|
||||||
|
ch.MatchType = MatchTypeFirstMatch
|
||||||
|
request := testutil.NewRequest(native.MethodGetObject, resource, nil)
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCondSliceContainsMatch(t *testing.T) {
|
func TestAnyAllConditionMatch(t *testing.T) {
|
||||||
|
ch := Chain{
|
||||||
|
Rules: []Rule{
|
||||||
|
{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{
|
||||||
|
{
|
||||||
|
Op: CondIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/20",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondStringEquals,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: native.PropertyKeyActorRole,
|
||||||
|
Value: "owner",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Op: CondStringEquals,
|
||||||
|
Kind: KindResource,
|
||||||
|
Key: native.PropertyKeyObjectID,
|
||||||
|
Value: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
|
t.Run("match by all conditions", func(t *testing.T) {
|
||||||
|
ch.Rules[0].Any = false
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, map[string]string{
|
||||||
|
native.PropertyKeyObjectID: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
})
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
native.PropertyKeyActorRole: "owner",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.93.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("match by any condition", func(t *testing.T) {
|
||||||
|
ch.Rules[0].Any = true
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, map[string]string{
|
||||||
|
native.PropertyKeyObjectID: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
})
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, nil)
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
native.PropertyKeyActorRole: "owner",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
resource = testutil.NewResource(native.ResourceFormatRootContainers, map[string]string{})
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.93.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConditionMatch(t *testing.T) {
|
||||||
|
t.Run("condition types", func(t *testing.T) {
|
||||||
|
t.Run("slice condition type", testCondSliceContainsMatch)
|
||||||
|
t.Run("numeric condition types", testNumericConditionsMatch)
|
||||||
|
t.Run("string condition types", testStringConiditionsMatch)
|
||||||
|
t.Run("ip conidition types", testIPConditionMatch)
|
||||||
|
t.Run("unknown condition type", 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: ConditionType(255),
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/20",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, map[string]string{
|
||||||
|
native.PropertyKeyObjectID: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
})
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
native.PropertyKeyActorRole: "owner",
|
||||||
|
})
|
||||||
|
require.PanicsWithValue(t, "unimplemented: 255", func() {
|
||||||
|
ch.Match(request)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("kind", func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, map[string]string{
|
||||||
|
native.PropertyKeyObjectID: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
})
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
native.PropertyKeyActorRole: "owner",
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("resource", func(t *testing.T) {
|
||||||
|
cond := Condition{
|
||||||
|
Op: CondStringEquals,
|
||||||
|
Kind: KindResource,
|
||||||
|
Key: native.PropertyKeyObjectID,
|
||||||
|
Value: "79xGoKYwhyJQhrDNb7bHhY1WCvN6trHJPTjKkw24c6W9",
|
||||||
|
}
|
||||||
|
|
||||||
|
found := cond.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
})
|
||||||
|
t.Run("request", func(t *testing.T) {
|
||||||
|
cond := Condition{
|
||||||
|
Op: CondStringEquals,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: native.PropertyKeyActorRole,
|
||||||
|
Value: "owner",
|
||||||
|
}
|
||||||
|
|
||||||
|
found := cond.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
})
|
||||||
|
t.Run("unknown", func(t *testing.T) {
|
||||||
|
cond := Condition{
|
||||||
|
Op: CondStringEquals,
|
||||||
|
Kind: ConditionKindType(255),
|
||||||
|
Key: native.PropertyKeyActorRole,
|
||||||
|
Value: "owner",
|
||||||
|
}
|
||||||
|
|
||||||
|
require.PanicsWithValue(t, "unknown condition type: 255", func() {
|
||||||
|
cond.Match(request)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCondSliceContainsMatch(t *testing.T) {
|
||||||
propKey := common.PropertyKeyFrostFSIDGroupID
|
propKey := common.PropertyKeyFrostFSIDGroupID
|
||||||
groupID := "1"
|
groupID := "1"
|
||||||
|
|
||||||
|
@ -151,7 +339,7 @@ func TestCondSliceContainsMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNumericConditionsMatch(t *testing.T) {
|
func testNumericConditionsMatch(t *testing.T) {
|
||||||
propKey := s3.PropertyKeyMaxKeys
|
propKey := s3.PropertyKeyMaxKeys
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
|
@ -227,61 +415,614 @@ func TestNumericConditionsMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidNumericValues(t *testing.T) {
|
func testStringConiditionsMatch(t *testing.T) {
|
||||||
propKey := s3.PropertyKeyMaxKeys
|
propKey := fmt.Sprintf(common.PropertyKeyFormatFrostFSIDUserClaim, "some-tag")
|
||||||
propValues := []string{"", "invalid"}
|
val := "tag-value"
|
||||||
|
|
||||||
for _, tc := range []struct {
|
t.Run(CondStringEquals.String(), func(t *testing.T) {
|
||||||
name string
|
ch := Chain{Rules: []Rule{{
|
||||||
conditionType ConditionType
|
Status: Allow,
|
||||||
match bool
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
}{
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
{
|
Condition: []Condition{{
|
||||||
name: "NumericEquals condition",
|
Op: CondStringEquals,
|
||||||
conditionType: CondNumericEquals,
|
|
||||||
match: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "NumericNotEquals condition",
|
|
||||||
conditionType: CondNumericNotEquals,
|
|
||||||
match: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "NumericLessThan condition",
|
|
||||||
conditionType: CondNumericLessThan,
|
|
||||||
match: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "NumericLessThanEquals condition",
|
|
||||||
conditionType: CondNumericLessThanEquals,
|
|
||||||
match: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "NumericGreaterThan condition",
|
|
||||||
conditionType: CondNumericGreaterThan,
|
|
||||||
match: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "NumericGreaterThanEquals condition",
|
|
||||||
conditionType: CondNumericGreaterThanEquals,
|
|
||||||
match: false,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
|
||||||
condition := Condition{
|
|
||||||
Op: tc.conditionType,
|
|
||||||
Kind: KindRequest,
|
Kind: KindRequest,
|
||||||
Key: propKey,
|
Key: propKey,
|
||||||
Value: "50",
|
Value: val,
|
||||||
}
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
for _, propValue := range propValues {
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: propValue})
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
propKey: val,
|
||||||
match := condition.Match(request)
|
|
||||||
require.Equal(t, tc.match, match)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotEquals.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: CondStringNotEquals,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringEqualsIgnoreCase.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: CondStringEqualsIgnoreCase,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotEqualsIgnoreCase.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: CondStringNotEqualsIgnoreCase,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLike.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: CondStringLike,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringNotLike.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: CondStringNotLike,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLessThan.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: CondStringLessThan,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringLessThanEquals.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: CondStringLessThanEquals,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringGreaterThan.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: CondStringGreaterThan,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondStringGreaterThanEquals.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: CondStringGreaterThanEquals,
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testIPConditionMatch(t *testing.T) {
|
||||||
|
t.Run(CondIPAddress.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: CondIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/20",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.93.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(CondNotIPAddress.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: CondNotIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/20",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.93.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
|
||||||
|
request = testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found = ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid ip address condition value", 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: CondIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1:33333",
|
||||||
|
}},
|
||||||
|
}}}
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
|
||||||
|
st, found := ch.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("match ip", func(t *testing.T) {
|
||||||
|
cond := Condition{
|
||||||
|
Op: CondIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/10",
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
cond.matchIP("192.92.1.91")
|
||||||
|
})
|
||||||
|
|
||||||
|
require.PanicsWithValue(t, "unimplemented: 10", func() {
|
||||||
|
cond.Op = CondNumericEquals
|
||||||
|
cond.matchIP("192.92.1.91")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInvalidNumericValues(t *testing.T) {
|
||||||
|
t.Run("invalid request property", func(t *testing.T) {
|
||||||
|
propKey := s3.PropertyKeyMaxKeys
|
||||||
|
propValues := []string{"", "invalid"}
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
conditionType ConditionType
|
||||||
|
match bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "NumericEquals condition",
|
||||||
|
conditionType: CondNumericEquals,
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumericNotEquals condition",
|
||||||
|
conditionType: CondNumericNotEquals,
|
||||||
|
match: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumericLessThan condition",
|
||||||
|
conditionType: CondNumericLessThan,
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumericLessThanEquals condition",
|
||||||
|
conditionType: CondNumericLessThanEquals,
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumericGreaterThan condition",
|
||||||
|
conditionType: CondNumericGreaterThan,
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NumericGreaterThanEquals condition",
|
||||||
|
conditionType: CondNumericGreaterThanEquals,
|
||||||
|
match: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
condition := Condition{
|
||||||
|
Op: tc.conditionType,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "50",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, propValue := range propValues {
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: propValue})
|
||||||
|
|
||||||
|
match := condition.Match(request)
|
||||||
|
require.Equal(t, tc.match, match)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
t.Run("invalid condition numeric value", func(t *testing.T) {
|
||||||
|
propKey := s3.PropertyKeyMaxKeys
|
||||||
|
|
||||||
|
condition := Condition{
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: propKey,
|
||||||
|
Value: "invalid",
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("match on CondNumericNotEquals", func(t *testing.T) {
|
||||||
|
condition.Op = CondNumericNotEquals
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: "50"})
|
||||||
|
|
||||||
|
match := condition.Match(request)
|
||||||
|
require.Equal(t, true, match)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("non-match on non-CondNumericNotEquals", func(t *testing.T) {
|
||||||
|
condition.Op = CondNumericEquals
|
||||||
|
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{propKey: "50"})
|
||||||
|
|
||||||
|
match := condition.Match(request)
|
||||||
|
require.Equal(t, false, match)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("match numeric", func(t *testing.T) {
|
||||||
|
cond := Condition{
|
||||||
|
Op: CondNumericLessThan,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: s3.PropertyKeyMaxKeys,
|
||||||
|
Value: "5",
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
cond.matchNumeric("6")
|
||||||
|
})
|
||||||
|
|
||||||
|
require.PanicsWithValue(t, "unimplemented: 0", func() {
|
||||||
|
cond.Op = CondStringEquals
|
||||||
|
cond.matchNumeric("10")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCondTypeStringification(t *testing.T) {
|
||||||
|
for _, pair := range []struct {
|
||||||
|
cond ConditionType
|
||||||
|
expectedString string
|
||||||
|
}{
|
||||||
|
{CondStringEquals, "StringEquals"},
|
||||||
|
{CondStringNotEquals, "StringNotEquals"},
|
||||||
|
{CondStringEqualsIgnoreCase, "StringEqualsIgnoreCase"},
|
||||||
|
{CondStringNotEqualsIgnoreCase, "StringNotEqualsIgnoreCase"},
|
||||||
|
{CondStringLike, "StringLike"},
|
||||||
|
{CondStringNotLike, "StringNotLike"},
|
||||||
|
{CondStringLessThan, "StringLessThan"},
|
||||||
|
{CondStringLessThanEquals, "StringLessThanEquals"},
|
||||||
|
{CondStringGreaterThan, "StringGreaterThan"},
|
||||||
|
{CondStringGreaterThanEquals, "StringGreaterThanEquals"},
|
||||||
|
{CondNumericEquals, "NumericEquals"},
|
||||||
|
{CondNumericNotEquals, "NumericNotEquals"},
|
||||||
|
{CondNumericLessThan, "NumericLessThan"},
|
||||||
|
{CondNumericLessThanEquals, "NumericLessThanEquals"},
|
||||||
|
{CondNumericGreaterThan, "NumericGreaterThan"},
|
||||||
|
{CondNumericGreaterThanEquals, "NumericGreaterThanEquals"},
|
||||||
|
{CondSliceContains, "SliceContains"},
|
||||||
|
{CondIPAddress, "IPAddress"},
|
||||||
|
{CondNotIPAddress, "NotIPAddress"},
|
||||||
|
{ConditionType(255), "unknown condition type"},
|
||||||
|
} {
|
||||||
|
require.Equal(t, pair.expectedString, pair.cond.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRuleMatch(t *testing.T) {
|
||||||
|
rule := Rule{
|
||||||
|
Status: Allow,
|
||||||
|
Actions: Actions{Names: []string{native.MethodPutObject}},
|
||||||
|
Resources: Resources{Names: []string{native.ResourceFormatRootContainers}},
|
||||||
|
Condition: []Condition{{
|
||||||
|
Op: CondIPAddress,
|
||||||
|
Kind: KindRequest,
|
||||||
|
Key: common.PropertyKeyFrostFSSourceIP,
|
||||||
|
Value: "192.92.1.1/20",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("match", func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
st, found := rule.Match(request)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, Allow, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not matching resource name", func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(fmt.Sprintf(native.ResourceFormatNamespaceContainers, "namespicy"), nil)
|
||||||
|
request := testutil.NewRequest(native.MethodPutObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
st, found := rule.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not matching action", func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodGetObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.92.1.91",
|
||||||
|
})
|
||||||
|
st, found := rule.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("not matching condition", func(t *testing.T) {
|
||||||
|
resource := testutil.NewResource(native.ResourceFormatRootContainers, nil)
|
||||||
|
request := testutil.NewRequest(native.MethodGetObject, resource, map[string]string{
|
||||||
|
common.PropertyKeyFrostFSSourceIP: "192.93.1.91",
|
||||||
|
})
|
||||||
|
st, found := rule.Match(request)
|
||||||
|
require.False(t, found)
|
||||||
|
require.Equal(t, NoRuleFound, st)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue