...

Source file src/k8s.io/kubernetes/test/e2e/auth/projected_clustertrustbundle.go

Documentation: k8s.io/kubernetes/test/e2e/auth

     1  /*
     2  Copyright 2023 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  	"crypto/ed25519"
    22  	"crypto/rand"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/pem"
    26  	"fmt"
    27  	"math/big"
    28  	"os"
    29  	"regexp"
    30  
    31  	certificatesv1alpha1 "k8s.io/api/certificates/v1alpha1"
    32  	v1 "k8s.io/api/core/v1"
    33  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    34  	"k8s.io/apimachinery/pkg/util/uuid"
    35  	"k8s.io/kubernetes/test/e2e/feature"
    36  	"k8s.io/kubernetes/test/e2e/framework"
    37  	e2epodoutput "k8s.io/kubernetes/test/e2e/framework/pod/output"
    38  	imageutils "k8s.io/kubernetes/test/utils/image"
    39  	admissionapi "k8s.io/pod-security-admission/api"
    40  	"k8s.io/utils/ptr"
    41  
    42  	"github.com/onsi/ginkgo/v2"
    43  )
    44  
    45  var _ = SIGDescribe(feature.ClusterTrustBundle, feature.ClusterTrustBundleProjection, func() {
    46  	f := framework.NewDefaultFramework("projected-clustertrustbundle")
    47  	f.NamespacePodSecurityLevel = admissionapi.LevelBaseline
    48  
    49  	goodCert1 := mustMakeCertificate(&x509.Certificate{
    50  		SerialNumber: big.NewInt(0),
    51  		Subject: pkix.Name{
    52  			CommonName: "root1",
    53  		},
    54  		IsCA:                  true,
    55  		BasicConstraintsValid: true,
    56  	})
    57  
    58  	goodCert1Block := string(mustMakePEMBlock("CERTIFICATE", nil, goodCert1))
    59  
    60  	ginkgo.It("should be able to mount a single ClusterTrustBundle by name", func(ctx context.Context) {
    61  
    62  		ctb1 := &certificatesv1alpha1.ClusterTrustBundle{
    63  			ObjectMeta: metav1.ObjectMeta{
    64  				Name: "ctb1",
    65  			},
    66  			Spec: certificatesv1alpha1.ClusterTrustBundleSpec{
    67  				TrustBundle: goodCert1Block,
    68  			},
    69  		}
    70  
    71  		if _, err := f.ClientSet.CertificatesV1alpha1().ClusterTrustBundles().Create(ctx, ctb1, metav1.CreateOptions{}); err != nil {
    72  			framework.Failf("Error while creating ClusterTrustBundle: %v", err)
    73  		}
    74  
    75  		pod := &v1.Pod{
    76  			ObjectMeta: metav1.ObjectMeta{
    77  				Name: "pod-projected-ctb-" + string(uuid.NewUUID()),
    78  			},
    79  			Spec: v1.PodSpec{
    80  				RestartPolicy: v1.RestartPolicyNever,
    81  				Containers: []v1.Container{
    82  					{
    83  						Name:  "projected-ctb-volume-test",
    84  						Image: imageutils.GetE2EImage(imageutils.Agnhost),
    85  						Args: []string{
    86  							"mounttest",
    87  							"--file_content=/var/run/ctbtest/trust-anchors.pem",
    88  							"--file_mode=/var/run/ctbtest/trust-anchors.pem",
    89  						},
    90  						VolumeMounts: []v1.VolumeMount{
    91  							{
    92  								Name:      "ctb-volume",
    93  								MountPath: "/var/run/ctbtest",
    94  							},
    95  						},
    96  					},
    97  				},
    98  				Volumes: []v1.Volume{
    99  					{
   100  						Name: "ctb-volume",
   101  						VolumeSource: v1.VolumeSource{
   102  							Projected: &v1.ProjectedVolumeSource{
   103  								Sources: []v1.VolumeProjection{
   104  									{
   105  										ClusterTrustBundle: &v1.ClusterTrustBundleProjection{
   106  											Name: ptr.To("ctb1"),
   107  											Path: "trust-anchors.pem",
   108  										},
   109  									},
   110  								},
   111  							},
   112  						},
   113  					},
   114  				},
   115  			},
   116  		}
   117  
   118  		fileModeRegexp := getFileModeRegex("/var/run/ctbtest/trust-anchors.pem", nil)
   119  		expectedOutput := []string{
   120  			regexp.QuoteMeta(goodCert1Block),
   121  			fileModeRegexp,
   122  		}
   123  
   124  		e2epodoutput.TestContainerOutputRegexp(ctx, f, "project cluster trust bundle", pod, 0, expectedOutput)
   125  	})
   126  })
   127  
   128  func mustMakeCertificate(template *x509.Certificate) []byte {
   129  	pub, priv, err := ed25519.GenerateKey(rand.Reader)
   130  	if err != nil {
   131  		framework.Failf("Error while generating key: %v", err)
   132  	}
   133  
   134  	cert, err := x509.CreateCertificate(rand.Reader, template, template, pub, priv)
   135  	if err != nil {
   136  		framework.Failf("Error while making certificate: %v", err)
   137  	}
   138  
   139  	return cert
   140  }
   141  
   142  func mustMakePEMBlock(blockType string, headers map[string]string, data []byte) string {
   143  	return string(pem.EncodeToMemory(&pem.Block{
   144  		Type:    blockType,
   145  		Headers: headers,
   146  		Bytes:   data,
   147  	}))
   148  }
   149  
   150  // getFileModeRegex returns a file mode related regex which should be matched by the mounttest pods' output.
   151  // 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.
   152  func getFileModeRegex(filePath string, mask *int32) string {
   153  	var (
   154  		linuxMask   int32
   155  		windowsMask int32
   156  	)
   157  	if mask == nil {
   158  		linuxMask = int32(0644)
   159  		windowsMask = int32(0775)
   160  	} else {
   161  		linuxMask = *mask
   162  		windowsMask = *mask
   163  	}
   164  
   165  	linuxOutput := fmt.Sprintf("mode of file \"%s\": %v", filePath, os.FileMode(linuxMask))
   166  	windowsOutput := fmt.Sprintf("mode of Windows file \"%v\": %s", filePath, os.FileMode(windowsMask))
   167  
   168  	return fmt.Sprintf("(%s|%s)", linuxOutput, windowsOutput)
   169  }
   170  

View as plain text