Skip to content

Commit 58e9954

Browse files
authored
operator: add scc permissions unit tests (#2751)
1 parent dce1c28 commit 58e9954

File tree

3 files changed

+100
-33
lines changed

3 files changed

+100
-33
lines changed

tests/operator/access/access.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package access
2+
3+
import (
4+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
5+
)
6+
7+
func PermissionsHaveBadRule(clusterPermissions []v1alpha1.StrategyDeploymentPermissions) bool {
8+
badRuleFound := false
9+
for permissionIndex := range clusterPermissions {
10+
permission := &clusterPermissions[permissionIndex]
11+
for ruleIndex := range permission.Rules {
12+
rule := &permission.Rules[ruleIndex]
13+
14+
// Check whether the rule is for the security api group.
15+
securityGroupFound := false
16+
for _, group := range rule.APIGroups {
17+
if group == "*" || group == "security.openshift.io" {
18+
securityGroupFound = true
19+
break
20+
}
21+
}
22+
23+
if !securityGroupFound {
24+
continue
25+
}
26+
27+
// Now check whether it grants some access to securitycontextconstraint resources.
28+
for _, resource := range rule.Resources {
29+
if resource == "*" || resource == "securitycontextconstraints" {
30+
// Keep reviewing other permissions' rules so we can log all the failing ones in the claim file.
31+
badRuleFound = true
32+
break
33+
}
34+
}
35+
}
36+
}
37+
38+
return badRuleFound
39+
}

tests/operator/access/access_test.go

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package access
2+
3+
import (
4+
"testing"
5+
6+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
7+
"github.com/stretchr/testify/assert"
8+
rbacv1 "k8s.io/api/rbac/v1"
9+
)
10+
11+
func TestPermissionsHaveBadRule(t *testing.T) {
12+
generateSDP := func(apiGroups []string, resources []string) v1alpha1.StrategyDeploymentPermissions {
13+
return v1alpha1.StrategyDeploymentPermissions{
14+
Rules: []rbacv1.PolicyRule{
15+
{
16+
APIGroups: apiGroups,
17+
Resources: resources,
18+
},
19+
},
20+
}
21+
}
22+
23+
testCases := []struct {
24+
testClusterPermissions []v1alpha1.StrategyDeploymentPermissions
25+
expectedResult bool
26+
}{
27+
{ // SCC granted - this is a bad rule
28+
testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{
29+
generateSDP([]string{"security.openshift.io"}, []string{"*"}),
30+
},
31+
expectedResult: true,
32+
},
33+
{ // SCC granted - this is a bad rule
34+
testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{
35+
generateSDP([]string{"security.openshift.io"}, []string{"securitycontextconstraints"}),
36+
},
37+
expectedResult: true,
38+
},
39+
{ // SCC granted - this is a bad rule
40+
testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{
41+
generateSDP([]string{"security.openshift.io"}, []string{"*"}),
42+
generateSDP([]string{"security.openshift.io"}, []string{"securitycontextconstraints"}),
43+
},
44+
expectedResult: true,
45+
},
46+
{ // No bad rule
47+
testClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{
48+
generateSDP([]string{"security.heathytest.io"}, []string{"*"}),
49+
},
50+
expectedResult: false,
51+
},
52+
}
53+
54+
for _, tc := range testCases {
55+
assert.Equal(t, tc.expectedResult, PermissionsHaveBadRule(tc.testClusterPermissions))
56+
}
57+
}

tests/operator/suite.go

+4-33
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/Masterminds/semver"
2424
"github.com/redhat-best-practices-for-k8s/certsuite/tests/common"
2525
"github.com/redhat-best-practices-for-k8s/certsuite/tests/identifiers"
26+
"github.com/redhat-best-practices-for-k8s/certsuite/tests/operator/access"
2627
"github.com/redhat-best-practices-for-k8s/certsuite/tests/operator/catalogsource"
2728
"github.com/redhat-best-practices-for-k8s/certsuite/tests/operator/openapi"
2829
"github.com/redhat-best-practices-for-k8s/certsuite/tests/operator/phasecheck"
@@ -243,39 +244,9 @@ func testOperatorInstallationAccessToSCC(check *checksdb.Check, env *provider.Te
243244
}
244245

245246
// Fails in case any cluster permission has a rule that refers to securitycontextconstraints.
246-
badRuleFound := false
247-
for permissionIndex := range clusterPermissions {
248-
permission := &clusterPermissions[permissionIndex]
249-
for ruleIndex := range permission.Rules {
250-
rule := &permission.Rules[ruleIndex]
251-
252-
// Check whether the rule is for the security api group.
253-
securityGroupFound := false
254-
for _, group := range rule.APIGroups {
255-
if group == "*" || group == "security.openshift.io" {
256-
securityGroupFound = true
257-
break
258-
}
259-
}
260-
261-
if !securityGroupFound {
262-
continue
263-
}
264-
265-
// Now check whether it grants some access to securitycontextconstraint resources.
266-
for _, resource := range rule.Resources {
267-
if resource == "*" || resource == "securitycontextconstraints" {
268-
check.LogInfo("Operator %s has a rule (index %d) for service account %s to access cluster SCCs",
269-
operator, ruleIndex, permission.ServiceAccountName)
270-
// Keep reviewing other permissions' rules so we can log all the failing ones in the claim file.
271-
badRuleFound = true
272-
break
273-
}
274-
}
275-
}
276-
}
277-
278-
if badRuleFound {
247+
if access.PermissionsHaveBadRule(clusterPermissions) {
248+
check.LogInfo("Operator %s has a rule for a service account to access cluster SCCs",
249+
operator)
279250
nonCompliantObjects = append(nonCompliantObjects, testhelper.NewOperatorReportObject(operator.Namespace, operator.Name, "One or more RBAC rules for Security Context Constraints found in CSV", false))
280251
} else {
281252
compliantObjects = append(compliantObjects, testhelper.NewOperatorReportObject(operator.Namespace, operator.Name, "No RBAC rules for Security Context Constraints found in CSV", true))

0 commit comments

Comments
 (0)