From bd6431323a5d567609925d3a78e7b1e82f33362f Mon Sep 17 00:00:00 2001 From: Taahir Ahmed Date: Fri, 7 Jul 2023 13:43:52 -0700 Subject: [PATCH] ClusterTrustBundle projection: e2e test --- test/e2e/auth/projected_clustertrustbundle.go | 169 ++++++++++++++++++ test/e2e/feature/feature.go | 2 + 2 files changed, 171 insertions(+) create mode 100644 test/e2e/auth/projected_clustertrustbundle.go diff --git a/test/e2e/auth/projected_clustertrustbundle.go b/test/e2e/auth/projected_clustertrustbundle.go new file mode 100644 index 00000000000..4213da9a4ed --- /dev/null +++ b/test/e2e/auth/projected_clustertrustbundle.go @@ -0,0 +1,169 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package auth + +import ( + "context" + "crypto/ed25519" + "crypto/rand" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "os" + "regexp" + + certificatesv1alpha1 "k8s.io/api/certificates/v1alpha1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" + "k8s.io/kubernetes/test/e2e/feature" + "k8s.io/kubernetes/test/e2e/framework" + e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output" + imageutils "k8s.io/kubernetes/test/utils/image" + admissionapi "k8s.io/pod-security-admission/api" + "k8s.io/utils/ptr" + + "github.com/onsi/ginkgo/v2" +) + +var _ = SIGDescribe(feature.ClusterTrustBundle, feature.ClusterTrustBundleProjection, func() { + f := framework.NewDefaultFramework("projected-clustertrustbundle") + f.NamespacePodSecurityLevel = admissionapi.LevelBaseline + + goodCert1 := mustMakeCertificate(&x509.Certificate{ + SerialNumber: big.NewInt(0), + Subject: pkix.Name{ + CommonName: "root1", + }, + IsCA: true, + BasicConstraintsValid: true, + }) + + goodCert1Block := string(mustMakePEMBlock("CERTIFICATE", nil, goodCert1)) + + ginkgo.It("should be able to mount a single ClusterTrustBundle by name", func(ctx context.Context) { + + ctb1 := &certificatesv1alpha1.ClusterTrustBundle{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ctb1", + }, + Spec: certificatesv1alpha1.ClusterTrustBundleSpec{ + TrustBundle: goodCert1Block, + }, + } + + if _, err := f.ClientSet.CertificatesV1alpha1().ClusterTrustBundles().Create(ctx, ctb1, metav1.CreateOptions{}); err != nil { + framework.Failf("Error while creating ClusterTrustBundle: %v", err) + } + + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod-projected-ctb-" + string(uuid.NewUUID()), + }, + Spec: v1.PodSpec{ + RestartPolicy: v1.RestartPolicyNever, + Containers: []v1.Container{ + { + Name: "projected-ctb-volume-test", + Image: imageutils.GetE2EImage(imageutils.Agnhost), + Args: []string{ + "mounttest", + "--file_content=/var/run/ctbtest/trust-anchors.pem", + "--file_mode=/var/run/ctbtest/trust-anchors.pem", + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "ctb-volume", + MountPath: "/var/run/ctbtest", + }, + }, + }, + }, + Volumes: []v1.Volume{ + { + Name: "ctb-volume", + VolumeSource: v1.VolumeSource{ + Projected: &v1.ProjectedVolumeSource{ + Sources: []v1.VolumeProjection{ + { + ClusterTrustBundle: &v1.ClusterTrustBundleProjection{ + Name: ptr.To("ctb1"), + Path: "trust-anchors.pem", + }, + }, + }, + }, + }, + }, + }, + }, + } + + fileModeRegexp := getFileModeRegex("/var/run/ctbtest/trust-anchors.pem", nil) + expectedOutput := []string{ + regexp.QuoteMeta(goodCert1Block), + fileModeRegexp, + } + + e2epodoutput.TestContainerOutputRegexp(ctx, f, "project cluster trust bundle", pod, 0, expectedOutput) + }) +}) + +func mustMakeCertificate(template *x509.Certificate) []byte { + pub, priv, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + framework.Failf("Error while generating key: %v", err) + } + + cert, err := x509.CreateCertificate(rand.Reader, template, template, pub, priv) + if err != nil { + framework.Failf("Error while making certificate: %v", err) + } + + return cert +} + +func mustMakePEMBlock(blockType string, headers map[string]string, data []byte) string { + return string(pem.EncodeToMemory(&pem.Block{ + Type: blockType, + Headers: headers, + Bytes: data, + })) +} + +// getFileModeRegex returns a file mode related regex which should be matched by the mounttest pods' output. +// If the given mask is nil, then the regex will contain the default OS file modes, which are 0644 for Linux and 0775 for Windows. +func getFileModeRegex(filePath string, mask *int32) string { + var ( + linuxMask int32 + windowsMask int32 + ) + if mask == nil { + linuxMask = int32(0644) + windowsMask = int32(0775) + } else { + linuxMask = *mask + windowsMask = *mask + } + + linuxOutput := fmt.Sprintf("mode of file \"%s\": %v", filePath, os.FileMode(linuxMask)) + windowsOutput := fmt.Sprintf("mode of Windows file \"%v\": %s", filePath, os.FileMode(windowsMask)) + + return fmt.Sprintf("(%s|%s)", linuxOutput, windowsOutput) +} diff --git a/test/e2e/feature/feature.go b/test/e2e/feature/feature.go index f4b9d87ce4b..4071cd0279e 100644 --- a/test/e2e/feature/feature.go +++ b/test/e2e/feature/feature.go @@ -38,6 +38,8 @@ var ( ClusterSizeAutoscalingGpu = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingGpu")) ClusterSizeAutoscalingScaleDown = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingScaleDown")) ClusterSizeAutoscalingScaleUp = framework.WithFeature(framework.ValidFeatures.Add("ClusterSizeAutoscalingScaleUp")) + ClusterTrustBundle = framework.WithFeature(framework.ValidFeatures.Add("ClusterTrustBundle")) + ClusterTrustBundleProjection = framework.WithFeature(framework.ValidFeatures.Add("ClusterTrustBundleProjection")) ClusterUpgrade = framework.WithFeature(framework.ValidFeatures.Add("ClusterUpgrade")) ComprehensiveNamespaceDraining = framework.WithFeature(framework.ValidFeatures.Add("ComprehensiveNamespaceDraining")) CPUManager = framework.WithFeature(framework.ValidFeatures.Add("CPUManager"))