From 39207dada254f4db1376682ce3877b038b7cc419 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Thu, 13 Jul 2023 14:00:12 -0400 Subject: [PATCH] Add integration test for node authorizer claim references --- test/integration/auth/node_test.go | 76 ++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/test/integration/auth/node_test.go b/test/integration/auth/node_test.go index 7f613de6f72..9021d263181 100644 --- a/test/integration/auth/node_test.go +++ b/test/integration/auth/node_test.go @@ -27,14 +27,18 @@ import ( coordination "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1" + "k8s.io/api/resource/v1alpha2" storagev1 "k8s.io/api/storage/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" + featuregatetesting "k8s.io/component-base/featuregate/testing" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/test/integration/framework" "k8s.io/utils/pointer" ) @@ -61,7 +65,10 @@ func TestNodeAuthorizer(t *testing.T) { }, "\n")) tokenFile.Close() + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicResourceAllocation, true)() + server := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{ + "--runtime-config=api/all=true", "--authorization-mode", "Node,RBAC", "--token-auth-file", tokenFile.Name(), "--enable-admission-plugins", "NodeRestriction", @@ -100,6 +107,13 @@ func TestNodeAuthorizer(t *testing.T) { if _, err := superuserClient.CoreV1().ConfigMaps("ns").Create(context.TODO(), &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "myconfigmap"}}, metav1.CreateOptions{}); err != nil { t.Fatal(err) } + if _, err := superuserClient.ResourceV1alpha2().ResourceClaims("ns").Create(context.TODO(), &v1alpha2.ResourceClaim{ObjectMeta: metav1.ObjectMeta{Name: "mynamedresourceclaim"}, Spec: v1alpha2.ResourceClaimSpec{ResourceClassName: "example.com"}}, metav1.CreateOptions{}); err != nil { + t.Fatal(err) + } + if _, err := superuserClient.ResourceV1alpha2().ResourceClaims("ns").Create(context.TODO(), &v1alpha2.ResourceClaim{ObjectMeta: metav1.ObjectMeta{Name: "mytemplatizedresourceclaim"}, Spec: v1alpha2.ResourceClaimSpec{ResourceClassName: "example.com"}}, metav1.CreateOptions{}); err != nil { + t.Fatal(err) + } + pvName := "mypv" if _, err := superuserClientExternal.StorageV1().VolumeAttachments().Create(context.TODO(), &storagev1.VolumeAttachment{ ObjectMeta: metav1.ObjectMeta{Name: "myattachment"}, @@ -169,6 +183,34 @@ func TestNodeAuthorizer(t *testing.T) { return err } } + getResourceClaim := func(client clientset.Interface) func() error { + return func() error { + _, err := client.ResourceV1alpha2().ResourceClaims("ns").Get(context.TODO(), "mynamedresourceclaim", metav1.GetOptions{}) + return err + } + } + getResourceClaimTemplate := func(client clientset.Interface) func() error { + return func() error { + _, err := client.ResourceV1alpha2().ResourceClaims("ns").Get(context.TODO(), "mytemplatizedresourceclaim", metav1.GetOptions{}) + return err + } + } + addResourceClaimTemplateReference := func(client clientset.Interface) func() error { + return func() error { + _, err := client.CoreV1().Pods("ns").Patch(context.TODO(), "node2normalpod", types.MergePatchType, + []byte(`{"status":{"resourceClaimStatuses":[{"name":"templateclaim","resourceClaimName":"mytemplatizedresourceclaim"}]}}`), + metav1.PatchOptions{}, "status") + return err + } + } + removeResourceClaimReference := func(client clientset.Interface) func() error { + return func() error { + _, err := client.CoreV1().Pods("ns").Patch(context.TODO(), "node2normalpod", types.MergePatchType, + []byte(`{"status":{"resourceClaimStatuses":null}}`), + metav1.PatchOptions{}, "status") + return err + } + } createNode2NormalPod := func(client clientset.Interface) func() error { return func() error { @@ -182,6 +224,10 @@ func TestNodeAuthorizer(t *testing.T) { {Name: "cm", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "myconfigmap"}}}}, {Name: "pvc", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: "mypvc"}}}, }, + ResourceClaims: []corev1.PodResourceClaim{ + {Name: "namedclaim", Source: corev1.ClaimSource{ResourceClaimName: pointer.String("mynamedresourceclaim")}}, + {Name: "templateclaim", Source: corev1.ClaimSource{ResourceClaimTemplateName: pointer.String("myresourceclaimtemplate")}}, + }, }, }, metav1.CreateOptions{}) return err @@ -428,6 +474,8 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getConfigMap(nodeanonClient)) expectForbidden(t, getPVC(nodeanonClient)) expectForbidden(t, getPV(nodeanonClient)) + expectForbidden(t, getResourceClaim(nodeanonClient)) + expectForbidden(t, getResourceClaimTemplate(nodeanonClient)) expectForbidden(t, createNode2NormalPod(nodeanonClient)) expectForbidden(t, deleteNode2NormalPod(nodeanonClient)) expectForbidden(t, createNode2MirrorPodEviction(nodeanonClient)) @@ -440,6 +488,8 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getConfigMap(node1Client)) expectForbidden(t, getPVC(node1Client)) expectForbidden(t, getPV(node1Client)) + expectForbidden(t, getResourceClaim(node1Client)) + expectForbidden(t, getResourceClaimTemplate(node1Client)) expectForbidden(t, createNode2NormalPod(nodeanonClient)) expectNotFound(t, createNode2MirrorPodEviction(node1Client)) expectForbidden(t, createNode2(node1Client)) @@ -452,6 +502,8 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getConfigMap(node2Client)) expectForbidden(t, getPVC(node2Client)) expectForbidden(t, getPV(node2Client)) + expectForbidden(t, getResourceClaim(node2Client)) + expectForbidden(t, getResourceClaimTemplate(node2Client)) expectForbidden(t, createNode2NormalPod(nodeanonClient)) // mirror pod and self node lifecycle is allowed @@ -479,6 +531,8 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getConfigMap(nodeanonClient)) expectForbidden(t, getPVC(nodeanonClient)) expectForbidden(t, getPV(nodeanonClient)) + expectForbidden(t, getResourceClaim(nodeanonClient)) + expectForbidden(t, getResourceClaimTemplate(nodeanonClient)) expectForbidden(t, createNode2NormalPod(nodeanonClient)) expectForbidden(t, updateNode2NormalPodStatus(nodeanonClient)) expectForbidden(t, deleteNode2NormalPod(nodeanonClient)) @@ -492,6 +546,8 @@ func TestNodeAuthorizer(t *testing.T) { expectForbidden(t, getConfigMap(node1Client)) expectForbidden(t, getPVC(node1Client)) expectForbidden(t, getPV(node1Client)) + expectForbidden(t, getResourceClaim(node1Client)) + expectForbidden(t, getResourceClaimTemplate(node1Client)) expectForbidden(t, createNode2NormalPod(node1Client)) expectForbidden(t, updateNode2NormalPodStatus(node1Client)) expectForbidden(t, deleteNode2NormalPod(node1Client)) @@ -507,6 +563,26 @@ func TestNodeAuthorizer(t *testing.T) { expectAllowed(t, getPVC(node2Client)) expectAllowed(t, getPV(node2Client)) + // node2 can only get direct claim references + expectAllowed(t, getResourceClaim(node2Client)) + expectForbidden(t, getResourceClaimTemplate(node2Client)) + + // node cannot add a claim reference + expectForbidden(t, addResourceClaimTemplateReference(node2Client)) + // superuser can add a claim reference + expectAllowed(t, addResourceClaimTemplateReference(superuserClient)) + // node can get direct and template claim references + expectAllowed(t, getResourceClaim(node2Client)) + expectAllowed(t, getResourceClaimTemplate(node2Client)) + + // node cannot remove a claim reference + expectForbidden(t, removeResourceClaimReference(node2Client)) + // superuser can remove a claim reference + expectAllowed(t, removeResourceClaimReference(superuserClient)) + // node2 can only get direct claim references + expectAllowed(t, getResourceClaim(node2Client)) + expectForbidden(t, getResourceClaimTemplate(node2Client)) + expectForbidden(t, createNode2NormalPod(node2Client)) expectAllowed(t, updateNode2NormalPodStatus(node2Client)) expectAllowed(t, deleteNode2NormalPod(node2Client))