k8s.io/kubernetes@v1.29.3/test/e2e/auth/selfsubjectreviews.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package auth 18 19 import ( 20 "context" 21 "fmt" 22 23 "github.com/onsi/ginkgo/v2" 24 "github.com/onsi/gomega" 25 authenticationv1 "k8s.io/api/authentication/v1" 26 authenticationv1alpha1 "k8s.io/api/authentication/v1alpha1" 27 authenticationv1beta1 "k8s.io/api/authentication/v1beta1" 28 apierrors "k8s.io/apimachinery/pkg/api/errors" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/client-go/kubernetes" 31 "k8s.io/client-go/rest" 32 "k8s.io/kubernetes/test/e2e/framework" 33 admissionapi "k8s.io/pod-security-admission/api" 34 ) 35 36 var _ = SIGDescribe("SelfSubjectReview", func() { 37 f := framework.NewDefaultFramework("selfsubjectreviews") 38 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged 39 40 /* 41 Release: v1.28 42 Testname: SelfSubjectReview API 43 Description: 44 The authentication.k8s.io API group MUST exist in the /apis discovery document. 45 The authentication.k8s.io/v1alpha1 API group/version MUST exist in the /apis/mode.k8s.io discovery document. 46 The authentication.k8s.io/v1beta1 API group/version MUST exist in the /apis/mode.k8s.io discovery document. 47 The authentication.k8s.io/v1 API group/version MUST exist in the /apis/mode.k8s.io discovery document. 48 The selfsubjectreviews resource MUST exist in the /apis/authentication.k8s.io/v1alpha1 discovery document. 49 The selfsubjectreviews resource MUST exist in the /apis/authentication.k8s.io/v1beta1 discovery document. 50 The selfsubjectreviews resource MUST exist in the /apis/authentication.k8s.io/v1 discovery document. 51 The selfsubjectreviews resource MUST support create. 52 */ 53 ginkgo.DescribeTable( 54 "testing SSR in different API groups", 55 func(ctx context.Context, apiVersion, gv string) { 56 // Discovery 57 ginkgo.By("getting /apis") 58 { 59 discoveryGroups, err := f.ClientSet.Discovery().ServerGroups() 60 framework.ExpectNoError(err) 61 found := false 62 for _, group := range discoveryGroups.Groups { 63 if group.Name == authenticationv1alpha1.GroupName { 64 for _, version := range group.Versions { 65 if version.Version == apiVersion { 66 found = true 67 break 68 } 69 } 70 } 71 } 72 if !found { 73 ginkgo.Skip(fmt.Sprintf("expected SelfSubjectReview API group/version, got %#v", discoveryGroups.Groups)) 74 } 75 } 76 77 ginkgo.By("getting /apis/authentication.k8s.io") 78 { 79 group := &metav1.APIGroup{} 80 err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/authentication.k8s.io").Do(ctx).Into(group) 81 framework.ExpectNoError(err) 82 found := false 83 for _, version := range group.Versions { 84 if version.Version == apiVersion { 85 found = true 86 break 87 } 88 } 89 if !found { 90 ginkgo.Skip(fmt.Sprintf("expected SelfSubjectReview API version, got %#v", group.Versions)) 91 } 92 } 93 94 ginkgo.By("getting /apis/authentication.k8s.io/" + apiVersion) 95 { 96 resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(gv) 97 framework.ExpectNoError(err) 98 found := false 99 for _, resource := range resources.APIResources { 100 switch resource.Name { 101 case "selfsubjectreviews": 102 found = true 103 } 104 } 105 if !found { 106 ginkgo.Skip(fmt.Sprintf("expected selfsubjectreviews, got %#v", resources.APIResources)) 107 } 108 } 109 }, 110 ginkgo.Entry("authentication/v1alpha1", "v1alpha1", authenticationv1alpha1.SchemeGroupVersion.String()), 111 ginkgo.Entry("authentication/v1beta1", "v1beta1", authenticationv1beta1.SchemeGroupVersion.String()), 112 ginkgo.Entry("authentication/v1", "v1", authenticationv1.SchemeGroupVersion.String()), 113 ) 114 115 ginkgo.It("should support SelfSubjectReview API operations", func(ctx context.Context) { 116 // Check creating 117 ginkgo.By("creating SSR authentication/v1alpha1") 118 { 119 // Use impersonate to make user attributes predictable 120 config := restConfig(f) 121 122 ssrClient := kubernetes.NewForConfigOrDie(config).AuthenticationV1alpha1().SelfSubjectReviews() 123 res, err := ssrClient.Create(ctx, &authenticationv1alpha1.SelfSubjectReview{}, metav1.CreateOptions{}) 124 if apierrors.IsNotFound(err) { 125 return // Alpha API is disabled 126 } 127 128 framework.ExpectNoError(err) 129 gomega.Expect(config.Impersonate.UserName).To(gomega.Equal(res.Status.UserInfo.Username)) 130 gomega.Expect(config.Impersonate.UID).To(gomega.Equal(res.Status.UserInfo.UID)) 131 gomega.Expect(config.Impersonate.Groups).To(gomega.Equal(res.Status.UserInfo.Groups)) 132 133 extra := make(map[string][]string, len(res.Status.UserInfo.Extra)) 134 for k, v := range res.Status.UserInfo.Extra { 135 extra[k] = v 136 } 137 138 gomega.Expect(config.Impersonate.Extra).To(gomega.Equal(extra)) 139 } 140 141 ginkgo.By("creating SSR authentication/v1beta1") 142 { 143 config := restConfig(f) 144 145 ssrClient := kubernetes.NewForConfigOrDie(config).AuthenticationV1beta1().SelfSubjectReviews() 146 res, err := ssrClient.Create(ctx, &authenticationv1beta1.SelfSubjectReview{}, metav1.CreateOptions{}) 147 if apierrors.IsNotFound(err) { 148 return // Beta API is disabled 149 } 150 151 framework.ExpectNoError(err) 152 gomega.Expect(config.Impersonate.UserName).To(gomega.Equal(res.Status.UserInfo.Username)) 153 gomega.Expect(config.Impersonate.UID).To(gomega.Equal(res.Status.UserInfo.UID)) 154 gomega.Expect(config.Impersonate.Groups).To(gomega.Equal(res.Status.UserInfo.Groups)) 155 156 extra := make(map[string][]string, len(res.Status.UserInfo.Extra)) 157 for k, v := range res.Status.UserInfo.Extra { 158 extra[k] = v 159 } 160 161 gomega.Expect(config.Impersonate.Extra).To(gomega.Equal(extra)) 162 } 163 164 ginkgo.By("creating SSR authentication/v1") 165 { 166 config := restConfig(f) 167 168 ssrClient := kubernetes.NewForConfigOrDie(config).AuthenticationV1().SelfSubjectReviews() 169 res, err := ssrClient.Create(ctx, &authenticationv1.SelfSubjectReview{}, metav1.CreateOptions{}) 170 framework.ExpectNoError(err) 171 172 gomega.Expect(config.Impersonate.UserName).To(gomega.Equal(res.Status.UserInfo.Username)) 173 gomega.Expect(config.Impersonate.UID).To(gomega.Equal(res.Status.UserInfo.UID)) 174 gomega.Expect(config.Impersonate.Groups).To(gomega.Equal(res.Status.UserInfo.Groups)) 175 176 extra := make(map[string][]string, len(res.Status.UserInfo.Extra)) 177 for k, v := range res.Status.UserInfo.Extra { 178 extra[k] = v 179 } 180 181 gomega.Expect(config.Impersonate.Extra).To(gomega.Equal(extra)) 182 } 183 }) 184 }) 185 186 func restConfig(f *framework.Framework) *rest.Config { 187 // Use impersonate to make user attributes predictable 188 config := f.ClientConfig() 189 config.Impersonate.UserName = "jane-doe" 190 config.Impersonate.UID = "uniq-id" 191 config.Impersonate.Groups = []string{"system:authenticated", "developers"} 192 config.Impersonate.Extra = map[string][]string{ 193 "known-languages": {"python", "javascript"}, 194 } 195 196 return config 197 }