package chain import ( "testing" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil" "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) func TestChainIDSerialization(t *testing.T) { chainIDBytes := []byte{93, 236, 80, 138, 168, 3, 144, 92, 173, 141, 16, 42, 249, 90, 97, 109, 211, 169, 54, 163} chain1 := &Chain{ID: ID(chainIDBytes)} data := chain1.Bytes() var chain2 Chain err := chain2.DecodeBytes(data) require.NoError(t, err) require.Equal(t, chain1.ID, chain2.ID) } func TestEncodeDecode(t *testing.T) { expected := Chain{ MatchType: MatchTypeFirstMatch, Rules: []Rule{ { Status: Allow, Actions: Actions{Names: []string{ "native::PutObject", }}, Resources: Resources{Names: []string{"*"}}, Condition: []Condition{ { Op: CondStringEquals, Key: "Name", Value: "NNS", }, }, }, }, } data := expected.Bytes() var actual Chain require.NoError(t, actual.DecodeBytes(data)) require.Equal(t, expected, actual) } func TestReturnFirstMatch(t *testing.T) { ch := Chain{ Rules: []Rule{ { Status: Allow, Actions: Actions{Names: []string{ native.MethodPutObject, }}, Resources: Resources{Names: []string{native.ResourceFormatRootContainers}}, Condition: []Condition{}, }, { Status: AccessDenied, Actions: Actions{Names: []string{ native.MethodPutObject, }}, Resources: Resources{Names: []string{native.ResourceFormatRootContainers}}, Condition: []Condition{}, }, }, } resource := testutil.NewResource(native.ResourceFormatRootContainers, nil) request := testutil.NewRequest(native.MethodPutObject, resource, nil) t.Run("default match", func(t *testing.T) { st, found := ch.Match(request) require.True(t, found) require.Equal(t, AccessDenied, st) }) t.Run("return first match", func(t *testing.T) { ch.MatchType = MatchTypeFirstMatch st, found := ch.Match(request) require.True(t, found) require.Equal(t, Allow, st) }) } func TestCondSliceContainsMatch(t *testing.T) { propKey := common.PropertyKeyFrostFSIDGroupID groupID := "1" ch := Chain{Rules: []Rule{{ Status: Allow, Actions: Actions{Names: []string{native.MethodPutObject}}, Resources: Resources{Names: []string{native.ResourceFormatRootContainers}}, Condition: []Condition{{ Op: CondSliceContains, Object: ObjectRequest, Key: propKey, Value: groupID, }}, }}} for _, tc := range []struct { name string value string status Status }{ { name: "simple value", value: groupID, status: Allow, }, { name: "simple value by func", value: FormCondSliceContainsValue([]string{groupID}), status: Allow, }, { name: "multiple values by func", value: FormCondSliceContainsValue([]string{groupID, "2", "3"}), status: Allow, }, { name: "simple mismatched", value: "3", status: NoRuleFound, }, { name: "multiple mismatched", value: FormCondSliceContainsValue([]string{"11", "12"}), status: NoRuleFound, }, { name: "comma correct handling mismatched", value: "1,11", status: NoRuleFound, }, } { 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}) st, _ := ch.Match(request) require.Equal(t, tc.status.String(), st.String()) }) } }