@@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- package e2enode
17
+ package node
18
18
19
19
import (
20
20
"context"
21
- "crypto/tls"
22
21
"fmt"
23
- "net/http"
24
22
25
23
"github.com/onsi/ginkgo/v2"
26
24
"github.com/onsi/gomega"
27
- authenticationv1 "k8s.io/api/authentication/v1"
28
25
authorizationv1 "k8s.io/api/authorization/v1"
29
26
v1 "k8s.io/api/core/v1"
30
27
rbacv1 "k8s.io/api/rbac/v1"
@@ -34,32 +31,40 @@ import (
34
31
"k8s.io/kubernetes/test/e2e/feature"
35
32
"k8s.io/kubernetes/test/e2e/framework"
36
33
e2eauth "k8s.io/kubernetes/test/e2e/framework/auth"
34
+ e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
35
+ e2eoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
36
+ admissionapi "k8s.io/pod-security-admission/api"
37
37
)
38
38
39
- var _ = SIGDescribe ("Kubelet Authz" , feature .KubeletFineGrainedAuthz , func () {
39
+ var _ = SIGDescribe (feature .KubeletFineGrainedAuthz , func () {
40
40
f := framework .NewDefaultFramework ("kubelet-authz-test" )
41
+ f .NamespacePodSecurityLevel = admissionapi .LevelBaseline
42
+
41
43
ginkgo .Context ("when calling kubelet API" , func () {
42
44
ginkgo .It ("check /healthz enpoint is accessible via nodes/healthz RBAC" , func (ctx context.Context ) {
43
45
sc := runKubeletAuthzTest (ctx , f , "healthz" , "healthz" )
44
- gomega .Expect (sc ).To (gomega .Equal (http . StatusOK ))
46
+ gomega .Expect (sc ).To (gomega .Equal ("200" ))
45
47
})
46
48
ginkgo .It ("check /healthz enpoint is accessible via nodes/proxy RBAC" , func (ctx context.Context ) {
47
49
sc := runKubeletAuthzTest (ctx , f , "healthz" , "proxy" )
48
- gomega .Expect (sc ).To (gomega .Equal (http . StatusOK ))
50
+ gomega .Expect (sc ).To (gomega .Equal ("200" ))
49
51
})
50
52
ginkgo .It ("check /healthz enpoint is not accessible via nodes/configz RBAC" , func (ctx context.Context ) {
51
53
sc := runKubeletAuthzTest (ctx , f , "healthz" , "configz" )
52
- gomega .Expect (sc ).To (gomega .Equal (http . StatusUnauthorized ))
54
+ gomega .Expect (sc ).To (gomega .Equal ("403" ))
53
55
})
54
56
})
55
57
})
56
58
57
- func runKubeletAuthzTest (ctx context.Context , f * framework.Framework , endpoint , authzSubresource string ) int {
59
+ func runKubeletAuthzTest (ctx context.Context , f * framework.Framework , endpoint , authzSubresource string ) string {
58
60
ns := f .Namespace .Name
59
61
saName := authzSubresource
60
62
crName := authzSubresource
61
63
verb := "get"
62
64
resource := "nodes"
65
+
66
+ ginkgo .By (fmt .Sprintf ("Creating Service Account %s/%s" , ns , saName ))
67
+
63
68
_ , err := f .ClientSet .CoreV1 ().ServiceAccounts (ns ).Create (ctx , & v1.ServiceAccount {
64
69
ObjectMeta : metav1.ObjectMeta {
65
70
Name : saName ,
@@ -68,12 +73,15 @@ func runKubeletAuthzTest(ctx context.Context, f *framework.Framework, endpoint,
68
73
}, metav1.CreateOptions {})
69
74
framework .ExpectNoError (err )
70
75
76
+ ginkgo .By (fmt .Sprintf ("Creating ClusterRole %s with for %s/%s" , crName , resource , authzSubresource ))
77
+
71
78
_ , err = f .ClientSet .RbacV1 ().ClusterRoles ().Create (ctx , & rbacv1.ClusterRole {
72
79
ObjectMeta : metav1.ObjectMeta {
73
80
Name : crName ,
74
81
},
75
82
Rules : []rbacv1.PolicyRule {
76
83
{
84
+ APIGroups : []string {"" },
77
85
Verbs : []string {verb },
78
86
Resources : []string {resource + "/" + authzSubresource },
79
87
},
@@ -87,9 +95,13 @@ func runKubeletAuthzTest(ctx context.Context, f *framework.Framework, endpoint,
87
95
Name : saName ,
88
96
}
89
97
98
+ ginkgo .By (fmt .Sprintf ("Creating ClusterRoleBinding with ClusterRole %s with subject %s/%s" , crName , ns , saName ))
99
+
90
100
err = e2eauth .BindClusterRole (ctx , f .ClientSet .RbacV1 (), crName , ns , subject )
91
101
framework .ExpectNoError (err )
92
102
103
+ ginkgo .By ("Waiting for Authorization Update." )
104
+
93
105
err = e2eauth .WaitForAuthzUpdate (ctx , f .ClientSet .AuthorizationV1 (),
94
106
serviceaccount .MakeUsername (ns , saName ),
95
107
& authorizationv1.ResourceAttributes {
@@ -102,25 +114,41 @@ func runKubeletAuthzTest(ctx context.Context, f *framework.Framework, endpoint,
102
114
)
103
115
framework .ExpectNoError (err )
104
116
105
- tr , err := f .ClientSet .CoreV1 ().ServiceAccounts (ns ).CreateToken (ctx , saName , & authenticationv1.TokenRequest {}, metav1.CreateOptions {})
106
- framework .ExpectNoError (err )
117
+ pod := e2epod .NewAgnhostPod (ns , fmt .Sprintf ("agnhost-pod-%s" , authzSubresource ), nil , nil , nil )
118
+ pod .Spec .ServiceAccountName = saName
119
+ pod .Spec .Containers [0 ].Env = []v1.EnvVar {
120
+ {
121
+ Name : "NODE_IP" ,
122
+ ValueFrom : & v1.EnvVarSource {
123
+ FieldRef : & v1.ObjectFieldSelector {
124
+ FieldPath : "status.hostIP" ,
125
+ },
126
+ },
127
+ },
128
+ }
107
129
108
- resp , err := healthCheck (fmt .Sprintf ("https://127.0.0.1:%d/%s" , ports .KubeletPort , endpoint ), tr .Status .Token )
109
- framework .ExpectNoError (err )
110
- return resp .StatusCode
111
- }
130
+ ginkgo .By (fmt .Sprintf ("Creating Pod %s in namespace %s with serviceaccount %s" , pod .Name , pod .Namespace , pod .Spec .ServiceAccountName ))
112
131
113
- func healthCheck (url , token string ) (* http.Response , error ) {
114
- insecureTransport := http .DefaultTransport .(* http.Transport ).Clone ()
115
- insecureTransport .TLSClientConfig = & tls.Config {InsecureSkipVerify : true }
116
- insecureHTTPClient := & http.Client {
117
- Transport : insecureTransport ,
118
- }
132
+ _ = e2epod .NewPodClient (f ).CreateSync (ctx , pod )
133
+
134
+ ginkgo .By ("Running command in Pod" )
119
135
120
- req , err := http .NewRequest (http .MethodGet , url , nil )
121
- if err != nil {
122
- return nil , err
136
+ var hostWarpStart , hostWarpEnd string
137
+ // IPv6 host must be wrapped within [] if you specify a port.
138
+ if framework .TestContext .ClusterIsIPv6 () {
139
+ hostWarpStart = "["
140
+ hostWarpEnd = "]"
123
141
}
124
- req .Header .Set ("Authorization" , fmt .Sprintf ("Bearer %s" , token ))
125
- return insecureHTTPClient .Do (req )
142
+
143
+ result := e2eoutput .RunHostCmdOrDie (ns ,
144
+ pod .Name ,
145
+ fmt .Sprintf ("curl -XGET -sIk -o /dev/null -w '%s' --header \" Authorization: Bearer `%s`\" https://%s$NODE_IP%s:%d/%s" ,
146
+ "%{http_code}" ,
147
+ "cat /var/run/secrets/kubernetes.io/serviceaccount/token" ,
148
+ hostWarpStart ,
149
+ hostWarpEnd ,
150
+ ports .KubeletPort ,
151
+ endpoint ))
152
+
153
+ return result
126
154
}
0 commit comments