@@ -18,6 +18,11 @@ package noderestriction
18
18
19
19
import (
20
20
"context"
21
+ "crypto/rand"
22
+ "crypto/rsa"
23
+ "crypto/x509"
24
+ "crypto/x509/pkix"
25
+ "encoding/pem"
21
26
"reflect"
22
27
"strings"
23
28
"testing"
@@ -41,6 +46,7 @@ import (
41
46
"k8s.io/component-base/featuregate"
42
47
kubeletapis "k8s.io/kubelet/pkg/apis"
43
48
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
49
+ certificatesapi "k8s.io/kubernetes/pkg/apis/certificates"
44
50
"k8s.io/kubernetes/pkg/apis/coordination"
45
51
api "k8s.io/kubernetes/pkg/apis/core"
46
52
"k8s.io/kubernetes/pkg/apis/policy"
@@ -213,11 +219,15 @@ type admitTestCase struct {
213
219
nodesGetter corev1lister.NodeLister
214
220
attributes admission.Attributes
215
221
features featuregate.FeatureGate
222
+ setupFunc func (t * testing.T )
216
223
err string
217
224
}
218
225
219
226
func (a * admitTestCase ) run (t * testing.T ) {
220
227
t .Run (a .name , func (t * testing.T ) {
228
+ if a .setupFunc != nil {
229
+ a .setupFunc (t )
230
+ }
221
231
c := NewPlugin (nodeidentifier .NewDefaultNodeIdentifier ())
222
232
if a .features != nil {
223
233
c .InspectFeatureGates (a .features )
@@ -375,6 +385,8 @@ func Test_nodePlugin_Admit(t *testing.T) {
375
385
}
376
386
aLabeledPod = withLabels (coremypod , labelsA )
377
387
abLabeledPod = withLabels (coremypod , labelsAB )
388
+
389
+ privKey , _ = rsa .GenerateKey (rand .Reader , 2048 )
378
390
)
379
391
380
392
existingPodsIndex .Add (v1mymirrorpod )
@@ -1238,6 +1250,42 @@ func Test_nodePlugin_Admit(t *testing.T) {
1238
1250
attributes : admission .NewAttributesRecord (nil , nil , csiNodeKind , nodeInfo .Namespace , nodeInfo .Name , csiNodeResource , "" , admission .Delete , & metav1.UpdateOptions {}, false , mynode ),
1239
1251
err : "" ,
1240
1252
},
1253
+ // CSR
1254
+ {
1255
+ name : "allowed CSR create correct node serving" ,
1256
+ attributes : createCSRAttributes ("system:node:mynode" , certificatesapi .KubeletServingSignerName , true , privKey , mynode ),
1257
+ err : "" ,
1258
+ },
1259
+ {
1260
+ name : "allowed CSR create correct node client" ,
1261
+ attributes : createCSRAttributes ("system:node:mynode" , certificatesapi .KubeAPIServerClientKubeletSignerName , true , privKey , mynode ),
1262
+ err : "" ,
1263
+ },
1264
+ {
1265
+ name : "allowed CSR create non-node CSR" ,
1266
+ attributes : createCSRAttributes ("some-other-identity" , certificatesapi .KubeAPIServerClientSignerName , true , privKey , mynode ),
1267
+ err : "" ,
1268
+ },
1269
+ {
1270
+ name : "deny CSR create incorrect node" ,
1271
+ attributes : createCSRAttributes ("system:node:othernode" , certificatesapi .KubeletServingSignerName , true , privKey , mynode ),
1272
+ err : "forbidden: can only create a node CSR with CN=system:node:mynode" ,
1273
+ },
1274
+ {
1275
+ name : "allow CSR create incorrect node with feature gate disabled" ,
1276
+ attributes : createCSRAttributes ("system:node:othernode" , certificatesapi .KubeletServingSignerName , true , privKey , mynode ),
1277
+ err : "" ,
1278
+ features : feature .DefaultFeatureGate ,
1279
+ setupFunc : func (t * testing.T ) {
1280
+ t .Helper ()
1281
+ featuregatetesting .SetFeatureGateDuringTest (t , feature .DefaultFeatureGate , features .DisableKubeletCSRAdmissionValidation , true )
1282
+ },
1283
+ },
1284
+ {
1285
+ name : "deny CSR create invalid" ,
1286
+ attributes : createCSRAttributes ("system:node:mynode" , certificatesapi .KubeletServingSignerName , false , privKey , mynode ),
1287
+ err : "unable to parse csr: asn1: syntax error: sequence truncated" ,
1288
+ },
1241
1289
}
1242
1290
for _ , tt := range tests {
1243
1291
tt .nodesGetter = existingNodes
@@ -1603,6 +1651,31 @@ func createPodAttributes(pod *api.Pod, user user.Info) admission.Attributes {
1603
1651
return admission .NewAttributesRecord (pod , nil , podKind , pod .Namespace , pod .Name , podResource , "" , admission .Create , & metav1.CreateOptions {}, false , user )
1604
1652
}
1605
1653
1654
+ func createCSRAttributes (cn , signer string , validCsr bool , key any , user user.Info ) admission.Attributes {
1655
+ csrResource := certificatesapi .Resource ("certificatesigningrequests" ).WithVersion ("v1" )
1656
+ csrKind := certificatesapi .Kind ("CertificateSigningRequest" ).WithVersion ("v1" )
1657
+
1658
+ csrPem := []byte ("-----BEGIN CERTIFICATE REQUEST-----\n -----END CERTIFICATE REQUEST-----" )
1659
+ if validCsr {
1660
+ structuredCsr := x509.CertificateRequest {
1661
+ Subject : pkix.Name {
1662
+ CommonName : cn ,
1663
+ },
1664
+ }
1665
+ csrDer , _ := x509 .CreateCertificateRequest (rand .Reader , & structuredCsr , key )
1666
+ csrPem = pem .EncodeToMemory (& pem.Block {Type : "CERTIFICATE REQUEST" , Bytes : csrDer })
1667
+ }
1668
+
1669
+ csreq := & certificatesapi.CertificateSigningRequest {
1670
+ Spec : certificatesapi.CertificateSigningRequestSpec {
1671
+ Request : csrPem ,
1672
+ SignerName : signer ,
1673
+ },
1674
+ }
1675
+ return admission .NewAttributesRecord (csreq , nil , csrKind , "" , "" , csrResource , "" , admission .Create , & metav1.CreateOptions {}, false , user )
1676
+
1677
+ }
1678
+
1606
1679
func TestAdmitResourceSlice (t * testing.T ) {
1607
1680
apiResource := resourceapi .SchemeGroupVersion .WithResource ("resourceslices" )
1608
1681
nodename := "mynode"
0 commit comments