Skip to content
This repository was archived by the owner on Aug 26, 2022. It is now read-only.

Commit 14cbd5a

Browse files
authored
Add accesscontrol tests (#602)
* Add accesscontrol tests * Put constants back
1 parent e6d20f7 commit 14cbd5a

File tree

5 files changed

+205
-80
lines changed

5 files changed

+205
-80
lines changed

pkg/config/config.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func (env *TestEnvironment) labelNodes() {
296296

297297
// create Nodes data from podset
298298
func (env *TestEnvironment) createNodes(nodes map[string]configsections.Node) map[string]*NodeConfig {
299-
log.Debug("autodiscovery: create nodes start")
299+
log.Debug("autodiscovery: create nodes start")
300300
defer log.Debug("autodiscovery: create nodes done")
301301
nodesConfig := make(map[string]*NodeConfig)
302302
for _, n := range nodes {

test-network-function/accesscontrol/suite.go

+41-58
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ var _ = ginkgo.Describe(common.AccessControlTestKey, func() {
8686
renderedTestCase, err := testConfigure.RenderTestCaseSpec(testcases.Cnf, testType)
8787
gomega.Expect(err).To(gomega.BeNil())
8888
gomega.Expect(renderedTestCase).ToNot(gomega.BeNil())
89-
for _, testCase := range renderedTestCase.TestCase {
90-
if !testCase.SkipTest {
91-
runTestOnPods(env, testCase, testType)
89+
90+
// Loop through test cases
91+
for i := range renderedTestCase.TestCase {
92+
if !renderedTestCase.TestCase[i].SkipTest {
93+
runTestOnPods(env, &renderedTestCase.TestCase[i], testType)
9294
}
9395
}
9496
}
@@ -111,23 +113,19 @@ func addFailedTcInfo(failedTcs map[string][]failedTcInfo, tc, pod, ns string, co
111113
}
112114
}
113115

114-
//nolint:gocritic,funlen // ignore hugeParam error. Pointers to loop iterator vars are bad and `testCmd` is likely to be such.
115-
func runTestOnPods(env *config.TestEnvironment, testCmd testcases.BaseTestCase, testType string) {
116+
//nolint:funlen // ignore hugeParam error. Pointers to loop iterator vars are bad and `testCmd` is likely to be such.
117+
func runTestOnPods(env *config.TestEnvironment, testCmd *testcases.BaseTestCase, testType string) {
116118
const noContainerIdx = -1
117119
testID := identifiers.XformToGinkgoItIdentifierExtended(identifiers.TestHostResourceIdentifier, testCmd.Name)
118120
ginkgo.It(testID, ginkgo.Label(testID), func() {
119121
context := env.GetLocalShellContext()
120122
failedTcs := map[string][]failedTcInfo{} // maps a pod name to a slice of failed TCs
121123
for _, podUnderTest := range env.PodsUnderTest {
122-
podName := podUnderTest.Name
123-
podNamespace := podUnderTest.Namespace
124124
if testCmd.ExpectedType == testcases.Function {
125125
for _, val := range testCmd.ExpectedStatus {
126-
testCmd.ExpectedStatusFn(podName, testcases.StatusFunctionType(val))
126+
testCmd.ExpectedStatusFn(podUnderTest.Name, testcases.StatusFunctionType(val))
127127
}
128128
}
129-
testType := testType
130-
testCmd := testCmd
131129
var args []interface{}
132130
if testType == testcases.PrivilegedRoles {
133131
args = []interface{}{podUnderTest.Namespace, podUnderTest.Namespace, podUnderTest.ServiceAccount}
@@ -144,8 +142,8 @@ func runTestOnPods(env *config.TestEnvironment, testCmd testcases.BaseTestCase,
144142
if count > 0 {
145143
count := 0
146144
for count < podUnderTest.ContainerCount {
147-
ginkgo.By(fmt.Sprintf("Executing TC %s on pod %s (ns %s), container index %d", testCmd.Name, podNamespace, podName, count))
148-
argsCount := append(args, count)
145+
ginkgo.By(fmt.Sprintf("Executing TC %s on pod %s (ns %s), container index %d", testCmd.Name, podUnderTest.Namespace, podUnderTest.Name, count))
146+
argsCount := append(args, count) //nolint:gocritic
149147
cmd := fmt.Sprintf(testCmd.Command, argsCount...)
150148
cmdArgs := strings.Split(cmd, " ")
151149
cnfInTest := containerpkg.NewPod(cmdArgs, podUnderTest.Name, podUnderTest.Namespace, testCmd.ExpectedStatus, testCmd.ResultType, testCmd.Action, common.DefaultTimeout)
@@ -155,15 +153,15 @@ func runTestOnPods(env *config.TestEnvironment, testCmd testcases.BaseTestCase,
155153
gomega.Expect(test).ToNot(gomega.BeNil())
156154
test.RunWithCallbacks(nil, func() {
157155
tnf.ClaimFilePrintf("FAILURE: Command sent: %s, Expectations: %v", cmd, testCmd.ExpectedStatus)
158-
addFailedTcInfo(failedTcs, testCmd.Name, podName, podNamespace, count)
156+
addFailedTcInfo(failedTcs, testCmd.Name, podUnderTest.Name, podUnderTest.Namespace, count)
159157
}, func(e error) {
160158
tnf.ClaimFilePrintf("ERROR: Command sent: %s, Expectations: %v, Error: %v", cmd, testCmd.ExpectedStatus, e)
161-
addFailedTcInfo(failedTcs, testCmd.Name, podName, podNamespace, count)
159+
addFailedTcInfo(failedTcs, testCmd.Name, podUnderTest.Name, podUnderTest.Namespace, count)
162160
})
163161
count++
164162
}
165163
} else {
166-
ginkgo.By(fmt.Sprintf("Executing TC %s on pod %s (ns %s)", testCmd.Name, podNamespace, podName))
164+
ginkgo.By(fmt.Sprintf("Executing TC %s on pod %s (ns %s)", testCmd.Name, podUnderTest.Namespace, podUnderTest.Name))
167165
cmd := fmt.Sprintf(testCmd.Command, args...)
168166
cmdArgs := strings.Split(cmd, " ")
169167
podTest := containerpkg.NewPod(cmdArgs, podUnderTest.Name, podUnderTest.Namespace, testCmd.ExpectedStatus, testCmd.ResultType, testCmd.Action, common.DefaultTimeout)
@@ -173,10 +171,10 @@ func runTestOnPods(env *config.TestEnvironment, testCmd testcases.BaseTestCase,
173171
gomega.Expect(test).ToNot(gomega.BeNil())
174172
test.RunWithCallbacks(nil, func() {
175173
tnf.ClaimFilePrintf("FAILURE: Command sent: %s, Expectations: %v", cmd, testCmd.ExpectedStatus)
176-
addFailedTcInfo(failedTcs, testCmd.Name, podName, podNamespace, noContainerIdx)
174+
addFailedTcInfo(failedTcs, testCmd.Name, podUnderTest.Name, podUnderTest.Namespace, noContainerIdx)
177175
}, func(e error) {
178176
tnf.ClaimFilePrintf("ERROR: Command sent: %s, Expectations: %v, Error: %v", cmd, testCmd.ExpectedStatus, e)
179-
addFailedTcInfo(failedTcs, testCmd.Name, podName, podNamespace, noContainerIdx)
177+
addFailedTcInfo(failedTcs, testCmd.Name, podUnderTest.Name, podUnderTest.Namespace, noContainerIdx)
180178
})
181179
}
182180
}
@@ -189,24 +187,26 @@ func runTestOnPods(env *config.TestEnvironment, testCmd testcases.BaseTestCase,
189187
}
190188

191189
func getCrsNamespaces(crdName, crdKind string, context *interactive.Context) (map[string]string, error) {
192-
const expectedNumFields = 2
193-
const crNameFieldIdx = 0
194-
const namespaceFieldIdx = 0
195-
196190
gomega.Expect(crdKind).NotTo(gomega.BeEmpty())
197191
getCrNamespaceCommand := fmt.Sprintf(ocGetCrNamespaceFormat, crdKind)
198192
cmdOut := utils.ExecuteCommandAndValidate(getCrNamespaceCommand, common.DefaultTimeout, context, func() {
199193
common.TcClaimLogPrintf("CRD %s: Failed to get CRs (kind=%s)", crdName, crdKind)
200194
})
201195

202-
crNamespaces := map[string]string{}
196+
return parseCrOutput(cmdOut)
197+
}
203198

204-
if cmdOut == "" {
199+
func parseCrOutput(rawOutput string) (map[string]string, error) {
200+
const crNameFieldIdx = 0
201+
const namespaceFieldIdx = 1
202+
const expectedNumFields = 2
203+
crNamespaces := map[string]string{}
204+
if rawOutput == "" {
205205
// Filter out empty (0 CRs) output.
206206
return crNamespaces, nil
207207
}
208208

209-
lines := strings.Split(cmdOut, "\n")
209+
lines := strings.Split(rawOutput, "\n")
210210
for _, line := range lines {
211211
lineFields := strings.Split(line, ",")
212212
if len(lineFields) != expectedNumFields {
@@ -234,15 +234,7 @@ func testCrsNamespaces(crNames, configNamespaces []string, context *interactive.
234234
ginkgo.By(fmt.Sprintf("CRD %s has %d CRs (plural name: %s).", crdName, len(crNamespaces), crdPluralName))
235235
for crName, namespace := range crNamespaces {
236236
ginkgo.By(fmt.Sprintf("Checking CR %s - Namespace %s", crName, namespace))
237-
found := false
238-
for _, configNamespace := range configNamespaces {
239-
if namespace == configNamespace {
240-
found = true
241-
break
242-
}
243-
}
244-
245-
if !found {
237+
if !utils.StringInSlice(configNamespaces, namespace) {
246238
common.TcClaimLogPrintf("CRD: %s (kind:%s) - CR %s has an invalid namespace (%s)", crdName, crdPluralName, crName, namespace)
247239
if crNames, exists := invalidCrs[crdName]; exists {
248240
invalidCrs[crdName] = append(crNames, crName)
@@ -334,17 +326,14 @@ func testAutomountService(env *config.TestEnvironment) {
334326
msg := []string{}
335327
for _, podUnderTest := range env.PodsUnderTest {
336328
ginkgo.By(fmt.Sprintf("check the existence of pod service account %s (ns= %s )", podUnderTest.Namespace, podUnderTest.Name))
337-
podName := podUnderTest.Name
338-
podNamespace := podUnderTest.Namespace
339-
serviceAccountName := podUnderTest.ServiceAccount
340-
gomega.Expect(serviceAccountName).ToNot(gomega.BeEmpty())
329+
gomega.Expect(podUnderTest.ServiceAccount).ToNot(gomega.BeEmpty())
341330
context := env.GetLocalShellContext()
342-
tester := automountservice.NewAutomountService(automountservice.WithNamespace(podNamespace), automountservice.WithServiceAccount(serviceAccountName))
331+
tester := automountservice.NewAutomountService(automountservice.WithNamespace(podUnderTest.Namespace), automountservice.WithServiceAccount(podUnderTest.ServiceAccount))
343332
test, err := tnf.NewTest(context.GetExpecter(), tester, []reel.Handler{tester}, context.GetErrorChannel())
344333
gomega.Expect(err).To(gomega.BeNil())
345334
test.RunAndValidate()
346335
serviceAccountToken := tester.Token()
347-
tester = automountservice.NewAutomountService(automountservice.WithNamespace(podNamespace), automountservice.WithPodname(podName))
336+
tester = automountservice.NewAutomountService(automountservice.WithNamespace(podUnderTest.Namespace), automountservice.WithPodname(podUnderTest.Name))
348337
test, err = tnf.NewTest(context.GetExpecter(), tester, []reel.Handler{tester}, context.GetErrorChannel())
349338
gomega.Expect(err).To(gomega.BeNil())
350339
test.RunAndValidate()
@@ -357,7 +346,7 @@ func testAutomountService(env *config.TestEnvironment) {
357346
// the test would pass iif token is explicitly set to false
358347
// if the token is set to true in the pod, the test would fail right away
359348
if podToken == automountservice.TokenIsTrue {
360-
msg = append(msg, fmt.Sprintf("Pod %s:%s is configured with automountServiceAccountToken set to true ", podNamespace, podName))
349+
msg = append(msg, fmt.Sprintf("Pod %s:%s is configured with automountServiceAccountToken set to true ", podUnderTest.Namespace, podUnderTest.Name))
361350
continue
362351
}
363352
// The pod token is false means the pod is configured properly
@@ -370,12 +359,12 @@ func testAutomountService(env *config.TestEnvironment) {
370359
// using this service account are not configured properly, register the error
371360
// message and fail
372361
if serviceAccountToken == automountservice.TokenIsTrue {
373-
msg = append(msg, fmt.Sprintf("serviceaccount %s:%s is configured with automountServiceAccountToken set to true, impacting pod %s ", podNamespace, serviceAccountName, podName))
362+
msg = append(msg, fmt.Sprintf("serviceaccount %s:%s is configured with automountServiceAccountToken set to true, impacting pod %s ", podUnderTest.Namespace, podUnderTest.ServiceAccount, podUnderTest.Name))
374363
}
375364
// the token should be set explicitly to false, otherwise, it's a failure
376365
// register the error message and check the next pod
377366
if serviceAccountToken == automountservice.TokenNotSet {
378-
msg = append(msg, fmt.Sprintf("serviceaccount %s:%s is not configured with automountServiceAccountToken set to false, impacting pod %s ", podNamespace, serviceAccountName, podName))
367+
msg = append(msg, fmt.Sprintf("serviceaccount %s:%s is not configured with automountServiceAccountToken set to false, impacting pod %s ", podUnderTest.Namespace, podUnderTest.ServiceAccount, podUnderTest.Name))
379368
}
380369
}
381370
if len(msg) > 0 {
@@ -391,22 +380,19 @@ func testRoleBindings(env *config.TestEnvironment) {
391380
failedPods := []*configsections.Pod{}
392381
ginkgo.By("Should not have RoleBinding in other namespaces")
393382
for _, podUnderTest := range env.PodsUnderTest {
394-
podName := podUnderTest.Name
395-
podNamespace := podUnderTest.Namespace
396-
serviceAccountName := podUnderTest.ServiceAccount
397383
context := env.GetLocalShellContext()
398-
ginkgo.By(fmt.Sprintf("Testing role binding %s %s", podNamespace, podName))
399-
if serviceAccountName == "" {
384+
ginkgo.By(fmt.Sprintf("Testing role binding %s %s", podUnderTest.Namespace, podUnderTest.Name))
385+
if podUnderTest.ServiceAccount == "" {
400386
ginkgo.Skip("Can not test when serviceAccountName is empty. Please check previous tests for failures")
401387
}
402-
rbTester := rolebinding.NewRoleBinding(common.DefaultTimeout, serviceAccountName, podNamespace)
388+
rbTester := rolebinding.NewRoleBinding(common.DefaultTimeout, podUnderTest.ServiceAccount, podUnderTest.Namespace)
403389
test, err := tnf.NewTest(context.GetExpecter(), rbTester, []reel.Handler{rbTester}, context.GetErrorChannel())
404390
gomega.Expect(err).To(gomega.BeNil())
405391
test.RunWithCallbacks(nil, func() {
406-
tnf.ClaimFilePrintf("FAILURE: Pod %s (ns: %s) roleBindings: %v", podName, podNamespace, rbTester.GetRoleBindings())
392+
tnf.ClaimFilePrintf("FAILURE: Pod %s (ns: %s) roleBindings: %v", podUnderTest.Name, podUnderTest.Namespace, rbTester.GetRoleBindings())
407393
failedPods = append(failedPods, podUnderTest)
408394
}, func(err error) {
409-
tnf.ClaimFilePrintf("ERROR: Pod %s (ns: %s) roleBindings: %v, error: %v", podName, podNamespace, rbTester.GetRoleBindings(), err)
395+
tnf.ClaimFilePrintf("ERROR: Pod %s (ns: %s) roleBindings: %v, error: %v", podUnderTest.Name, podUnderTest.Namespace, rbTester.GetRoleBindings(), err)
410396
failedPods = append(failedPods, podUnderTest)
411397
})
412398
}
@@ -423,22 +409,19 @@ func testClusterRoleBindings(env *config.TestEnvironment) {
423409
ginkgo.By("Should not have ClusterRoleBindings")
424410
failedPods := []*configsections.Pod{}
425411
for _, podUnderTest := range env.PodsUnderTest {
426-
podName := podUnderTest.Name
427-
podNamespace := podUnderTest.Namespace
428-
serviceAccountName := podUnderTest.ServiceAccount
429412
context := env.GetLocalShellContext()
430-
ginkgo.By(fmt.Sprintf("Testing cluster role binding %s %s", podNamespace, podName))
431-
if serviceAccountName == "" {
413+
ginkgo.By(fmt.Sprintf("Testing cluster role binding %s %s", podUnderTest.Namespace, podUnderTest.Name))
414+
if podUnderTest.ServiceAccount == "" {
432415
ginkgo.Skip("Can not test when serviceAccountName is empty. Please check previous tests for failures")
433416
}
434-
crbTester := clusterrolebinding.NewClusterRoleBinding(common.DefaultTimeout, serviceAccountName, podNamespace)
417+
crbTester := clusterrolebinding.NewClusterRoleBinding(common.DefaultTimeout, podUnderTest.ServiceAccount, podUnderTest.Namespace)
435418
test, err := tnf.NewTest(context.GetExpecter(), crbTester, []reel.Handler{crbTester}, context.GetErrorChannel())
436419
gomega.Expect(err).To(gomega.BeNil())
437420
test.RunWithCallbacks(nil, func() {
438-
tnf.ClaimFilePrintf("FAILURE: Pod: %s (ns: %s) SA: %s clusterRoleBindings: %v", podName, podNamespace, serviceAccountName, crbTester.GetClusterRoleBindings())
421+
tnf.ClaimFilePrintf("FAILURE: Pod: %s (ns: %s) SA: %s clusterRoleBindings: %v", podUnderTest.Name, podUnderTest.Namespace, podUnderTest.ServiceAccount, crbTester.GetClusterRoleBindings())
439422
failedPods = append(failedPods, podUnderTest)
440423
}, func(err error) {
441-
tnf.ClaimFilePrintf("ERROR: Pod: %s (ns: %s) SA: %s clusterRoleBindings: %v, error: %v", podName, podNamespace, serviceAccountName, crbTester.GetClusterRoleBindings(), err)
424+
tnf.ClaimFilePrintf("ERROR: Pod: %s (ns: %s) SA: %s clusterRoleBindings: %v, error: %v", podUnderTest.Name, podUnderTest.Namespace, podUnderTest.ServiceAccount, crbTester.GetClusterRoleBindings(), err)
442425
failedPods = append(failedPods, podUnderTest)
443426
})
444427
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// Copyright (C) 2022 Red Hat, Inc.
2+
//
3+
// This program is free software; you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation; either version 2 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License along
14+
// with this program; if not, write to the Free Software Foundation, Inc.,
15+
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16+
17+
package accesscontrol
18+
19+
import (
20+
"errors"
21+
"testing"
22+
"time"
23+
24+
"github.com/onsi/ginkgo/v2"
25+
"github.com/onsi/gomega"
26+
"github.com/stretchr/testify/assert"
27+
"github.com/test-network-function/test-network-function/pkg/tnf/interactive"
28+
"github.com/test-network-function/test-network-function/pkg/utils"
29+
)
30+
31+
func TestParseCrOutput(t *testing.T) {
32+
testCases := []struct {
33+
rawOutput string
34+
expectedOutput map[string]string
35+
expectedErr error
36+
}{
37+
{
38+
rawOutput: "aws-ebs-csi-driver-operator,openshift-cloud-credential-operator",
39+
expectedOutput: map[string]string{
40+
"aws-ebs-csi-driver-operator": "openshift-cloud-credential-operator",
41+
},
42+
expectedErr: nil,
43+
},
44+
{
45+
rawOutput: "abcd1234,openshift-cloud-credential-operator",
46+
expectedOutput: map[string]string{
47+
"abcd1234": "openshift-cloud-credential-operator",
48+
},
49+
expectedErr: nil,
50+
},
51+
{
52+
rawOutput: "openshift-cloud-credential-operator",
53+
expectedOutput: map[string]string{},
54+
expectedErr: errors.New("failed to parse output line openshift-cloud-credential-operator"),
55+
},
56+
{
57+
rawOutput: "",
58+
expectedOutput: map[string]string{},
59+
expectedErr: nil,
60+
},
61+
}
62+
63+
for _, tc := range testCases {
64+
crMap, err := parseCrOutput(tc.rawOutput)
65+
assert.Equal(t, tc.expectedErr, err)
66+
if err == nil {
67+
assert.Equal(t, tc.expectedOutput, crMap)
68+
}
69+
}
70+
}
71+
72+
func TestGetCrsNamespaces(t *testing.T) {
73+
gomega.RegisterFailHandler(ginkgo.Fail)
74+
origFunc := utils.ExecuteCommandAndValidate
75+
defer func() {
76+
utils.ExecuteCommandAndValidate = origFunc
77+
}()
78+
79+
utils.ExecuteCommandAndValidate = func(command string, timeout time.Duration, context *interactive.Context, failureCallbackFun func()) string {
80+
return "aws-ebs-csi-driver-operator,openshift-cloud-credential-operator"
81+
}
82+
83+
crsNamespaces, err := getCrsNamespaces("test123", "testCRD", nil)
84+
assert.Nil(t, err)
85+
assert.Equal(t, map[string]string{
86+
"aws-ebs-csi-driver-operator": "openshift-cloud-credential-operator",
87+
}, crsNamespaces)
88+
}
89+
90+
//nolint:funlen
91+
func TestAddFailedTcInfo(t *testing.T) {
92+
testCases := []struct {
93+
tc string
94+
pod string
95+
namespace string
96+
contID int
97+
existingMap map[string][]failedTcInfo
98+
expectedMap map[string][]failedTcInfo
99+
}{
100+
{
101+
tc: "tc1",
102+
pod: "pod1",
103+
namespace: "ns1",
104+
contID: 1,
105+
existingMap: map[string][]failedTcInfo{},
106+
expectedMap: map[string][]failedTcInfo{
107+
"pod1": {
108+
{
109+
tc: "tc1",
110+
containerIdx: 1,
111+
ns: "ns1",
112+
},
113+
},
114+
},
115+
},
116+
{
117+
tc: "tc1",
118+
pod: "pod1",
119+
namespace: "ns1",
120+
contID: 1,
121+
existingMap: map[string][]failedTcInfo{
122+
"pod1": {
123+
{
124+
tc: "tc1",
125+
containerIdx: 1,
126+
ns: "ns1",
127+
},
128+
},
129+
},
130+
expectedMap: map[string][]failedTcInfo{
131+
"pod1": {
132+
{
133+
tc: "tc1",
134+
containerIdx: 1,
135+
ns: "ns1",
136+
},
137+
{
138+
tc: "tc1",
139+
containerIdx: 1,
140+
ns: "ns1",
141+
},
142+
},
143+
},
144+
},
145+
}
146+
147+
for _, tc := range testCases {
148+
addFailedTcInfo(tc.existingMap, tc.tc, tc.pod, tc.namespace, tc.contID)
149+
assert.Equal(t, tc.expectedMap, tc.existingMap)
150+
}
151+
}

0 commit comments

Comments
 (0)