Skip to content

Commit e1040a7

Browse files
committed
setup the testing interface between test cases and utils backend
1 parent 7ed7c87 commit e1040a7

File tree

2 files changed

+138
-21
lines changed

2 files changed

+138
-21
lines changed

test/e2e/authorization.go

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,88 @@
11
package e2e
22

33
import (
4+
"context"
5+
46
g "github.com/onsi/ginkgo/v2"
7+
gomega "github.com/onsi/gomega"
8+
"k8s.io/client-go/kubernetes"
9+
"k8s.io/kubernetes/test/e2e/framework"
10+
)
11+
12+
var (
13+
allGroups = [][]string{
14+
[]string{"FooBar"},
15+
[]string{"ReadOnly"},
16+
[]string{"PowerUser"},
17+
[]string{"Emergency"},
18+
[]string{"Manual"},
19+
[]string{"system:serviceaccounts:kube-system"},
20+
[]string{"CollaboratorEmergency"},
21+
[]string{"CollaboratorManual"},
22+
[]string{"Collaborator24x7"},
23+
[]string{"CollaboratorPowerUser"},
24+
[]string{"Administrator"},
25+
}
526
)
627

7-
var _ = g.Describe("Authorisation [RBAC] [Zalando]", func() {
28+
var _ = g.Describe("Authorization [RBAC] [Zalando]", func() {
29+
var cs kubernetes.Interface
30+
31+
f := framework.NewDefaultFramework("authorization")
832

33+
// Initialise the clientset before each test
34+
g.BeforeEach(func() {
35+
cs = f.ClientSet
36+
})
37+
38+
// Test cases for all groups of users
939
g.Context("For all groups", func() {
40+
var tc testCase
41+
g.BeforeEach(func() {
42+
tc.data.groups = allGroups
43+
tc.data.users = []string{"test-user"}
44+
})
1045
g.When("the verb is impersonate", func() {
11-
g.It("should deny access for users", func() {})
12-
g.It("should deny access for service accounts", func() {})
46+
g.BeforeEach(func() {
47+
tc.data.verbs = []string{"impersonate"}
48+
})
49+
50+
g.It("should deny access for users and groups", func() {
51+
// This is safe to do since the BeforeEach block
52+
// will clear these values for other specs.
53+
// https://onsi.github.io/ginkgo/#organizing-specs-with-container-nodes
54+
tc.data.resources = []string{"users", "groups"}
55+
tc.run(context.TODO(), cs)
56+
output := tc.output
57+
gomega.Expect(output.denied).To(gomega.BeTrue())
58+
59+
})
60+
g.It("should deny access for service accounts", func() {
61+
tc.data.resources = []string{"serviceaccounts"}
62+
tc.data.namespaces = []string{"", "teapot", "kube-system"}
63+
tc.run(context.TODO(), cs)
64+
output := tc.output
65+
gomega.Expect(output.denied).To(gomega.BeTrue())
66+
})
1367
})
1468
g.When("the verb is escalate", func() {
15-
g.It("should deny access for cluster roles", func() {})
16-
g.It("should deny access for roles in all namespaces", func() {})
69+
g.BeforeEach(func() {
70+
tc.data.verbs = []string{"escalate"}
71+
})
72+
73+
g.It("should deny access for cluster roles", func() {
74+
tc.data.resources = []string{"rbac.authorization.k8s.io/clusterrole"}
75+
tc.run(context.TODO(), cs)
76+
output := tc.output
77+
gomega.Expect(output.denied).To(gomega.BeTrue())
78+
})
79+
g.It("should deny access for roles in all namespaces", func() {
80+
tc.data.resources = []string{"rbac.authorization.k8s.io/role"}
81+
tc.data.namespaces = []string{"", "teapot", "kube-system"}
82+
tc.run(context.TODO(), cs)
83+
output := tc.output
84+
gomega.Expect(output.denied).To(gomega.BeTrue())
85+
})
1786
})
1887
})
1988

test/e2e/authorization_utils.go

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,85 @@ package e2e
22

33
import (
44
"context"
5-
"fmt"
65

76
authv1 "k8s.io/api/authorization/v1"
87
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
98
"k8s.io/client-go/kubernetes"
10-
"k8s.io/client-go/tools/clientcmd"
119
)
1210

13-
func createSubjectAccessReview(ctx context.Context, cs kubernetes.Interface, sar authv1.SubjectAccessReview) (*authv1.SubjectAccessReview, error) {
14-
return cs.AuthorizationV1().SubjectAccessReviews().Create(ctx, &sar, metav1.CreateOptions{})
11+
// testCase is a struct that represents a single testcase.
12+
type testCase struct {
13+
data testcaseData
14+
output testcaseOutput
15+
}
16+
17+
// testcaseData is a struct that makes it user-friendly to write testcases
18+
// more logically. This will be used to generate individual SubjectAccessReview
19+
// objects in order to test the authorization rules.
20+
type testcaseData struct {
21+
namespaces []string
22+
names []string
23+
verbs []string
24+
apiGroups []string
25+
resources []string
26+
subresources []string
27+
nonResourceVerbs []string
28+
nonResourcePaths []string
29+
users []string
30+
31+
// this is double slice since we need to check individually for
32+
// each group of users. A single slice would mean that the same user
33+
// is part of all the groups.
34+
groups [][]string
1535
}
1636

17-
func createLocalClient() (kubernetes.Interface, error) {
18-
kubeconfigPath := "/workdir/test/e2e/kubeconfig"
37+
// testcaseOutput is a struct that represents the expected result of a testcase.
38+
// This is based on the SubjectAccessReviewStatus type. It provides simplicity in testcase
39+
// writing since one testcase can have multiple SubjectAccessReview objects
40+
// and we need to determine the "final" result and expose that as the testcase output.
41+
type testcaseOutput struct {
42+
// the final result based on results of individual SubjectAccessReview objects
43+
allowed, denied bool
44+
// the set of reasons from individual SubjectAccessReview objects
45+
reason []string
46+
}
1947

20-
// use the current context in kubeconfig
21-
config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
48+
func (t *testCase) run(ctx context.Context, cs kubernetes.Interface) error {
49+
// Generate the list of SubjectAccessReview objects based on the testcase data
50+
sars, err := generateSubjectAccessReviews(t.data)
2251
if err != nil {
23-
return nil, err
52+
return err
2453
}
2554

26-
client, err := kubernetes.NewForConfig(config)
55+
// Create the SubjectAccessReview objects in the cluster
56+
err = createSubjectAccessReviews(ctx, cs, sars)
2757
if err != nil {
28-
return nil, fmt.Errorf("unable to create a client: %v", err)
58+
return err
2959
}
3060

31-
return client, nil
61+
// TODO: Implement the logic to determine the final result based on the results of individual SubjectAccessReview objects
62+
return nil
3263
}
3364

34-
type testCase struct {
35-
name string
36-
sar authv1.SubjectAccessReview
37-
expectedStatus authv1.SubjectAccessReviewStatus
65+
// accessReviewGenerator generates a list of SubjectAccessReview objects based on the
66+
// testcase data provided.
67+
func generateSubjectAccessReviews(data testcaseData) ([]authv1.SubjectAccessReview, error) {
68+
// TODO: Implement this function
69+
return nil, nil
70+
}
71+
72+
// createSubjectAccessReviews creates provided SubjectAccessReview objects in the cluster
73+
func createSubjectAccessReviews(ctx context.Context, cs kubernetes.Interface, sars []authv1.SubjectAccessReview) error {
74+
for _, sar := range sars {
75+
_, err := createSubjectAccessReview(ctx, cs, sar)
76+
if err != nil {
77+
return err
78+
}
79+
}
80+
return nil
81+
}
82+
83+
// createSubjectAccessReview creates a SubjectAccessReview object in the cluster
84+
func createSubjectAccessReview(ctx context.Context, cs kubernetes.Interface, sar authv1.SubjectAccessReview) (*authv1.SubjectAccessReview, error) {
85+
return cs.AuthorizationV1().SubjectAccessReviews().Create(ctx, &sar, metav1.CreateOptions{})
3886
}

0 commit comments

Comments
 (0)