...

Source file src/k8s.io/kubernetes/test/e2e/windows/gmsa_kubelet.go

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

     1  /*
     2  Copyright 2018 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  // This test only makes sure that the kubelet correctly passes down GMSA cred specs
    18  // down to the runtime.
    19  // It's a much lighter test than gmsa_full, that tests the whole GMSA process, but
    20  // also requires a heavy weight setup to run.
    21  
    22  package windows
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"strings"
    28  	"time"
    29  
    30  	v1 "k8s.io/api/core/v1"
    31  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    32  	"k8s.io/kubernetes/test/e2e/feature"
    33  	"k8s.io/kubernetes/test/e2e/framework"
    34  	e2ekubectl "k8s.io/kubernetes/test/e2e/framework/kubectl"
    35  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    36  	imageutils "k8s.io/kubernetes/test/utils/image"
    37  	admissionapi "k8s.io/pod-security-admission/api"
    38  
    39  	"github.com/onsi/ginkgo/v2"
    40  	"github.com/onsi/gomega"
    41  )
    42  
    43  var _ = sigDescribe(feature.Windows, "GMSA Kubelet", framework.WithSlow(), skipUnlessWindows(func() {
    44  	f := framework.NewDefaultFramework("gmsa-kubelet-test-windows")
    45  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    46  
    47  	ginkgo.Describe("kubelet GMSA support", func() {
    48  		ginkgo.Context("when creating a pod with correct GMSA credential specs", func() {
    49  			ginkgo.It("passes the credential specs down to the Pod's containers", func(ctx context.Context) {
    50  				defer ginkgo.GinkgoRecover()
    51  
    52  				podName := "with-correct-gmsa-specs"
    53  
    54  				container1Name := "container1"
    55  				podDomain := "acme.com"
    56  
    57  				container2Name := "container2"
    58  				container2Domain := "contoso.org"
    59  
    60  				pod := &v1.Pod{
    61  					ObjectMeta: metav1.ObjectMeta{
    62  						Name: podName,
    63  					},
    64  					Spec: v1.PodSpec{
    65  						Containers: []v1.Container{
    66  							{
    67  								Name:  container1Name,
    68  								Image: imageutils.GetE2EImage(imageutils.BusyBox),
    69  								Command: []string{
    70  									"powershell.exe",
    71  									"-Command",
    72  									"sleep -Seconds 600",
    73  								},
    74  							},
    75  							{
    76  								Name:  container2Name,
    77  								Image: imageutils.GetE2EImage(imageutils.BusyBox),
    78  								Command: []string{
    79  									"powershell.exe",
    80  									"-Command",
    81  									"sleep -Seconds 600",
    82  								},
    83  								SecurityContext: &v1.SecurityContext{
    84  									WindowsOptions: &v1.WindowsSecurityContextOptions{
    85  										GMSACredentialSpec: generateDummyCredSpecs(container2Domain),
    86  									},
    87  								},
    88  							},
    89  						},
    90  						SecurityContext: &v1.PodSecurityContext{
    91  							WindowsOptions: &v1.WindowsSecurityContextOptions{
    92  								GMSACredentialSpec: generateDummyCredSpecs(podDomain),
    93  							},
    94  						},
    95  					},
    96  				}
    97  
    98  				ginkgo.By("creating a pod with correct GMSA specs")
    99  				e2epod.NewPodClient(f).CreateSync(ctx, pod)
   100  
   101  				ginkgo.By("checking the domain reported by nltest in the containers")
   102  				namespaceOption := fmt.Sprintf("--namespace=%s", f.Namespace.Name)
   103  				for containerName, domain := range map[string]string{
   104  					container1Name: podDomain,
   105  					container2Name: container2Domain,
   106  				} {
   107  					var (
   108  						output string
   109  						err    error
   110  					)
   111  
   112  					containerOption := fmt.Sprintf("--container=%s", containerName)
   113  					// even for bogus creds, `nltest /PARENTDOMAIN` simply returns the AD domain, which is enough for our purpose here.
   114  					// note that the "eventually" part seems to be needed to account for the fact that powershell containers
   115  					// are a bit slow to become responsive, even when docker reports them as running.
   116  					gomega.Eventually(ctx, func() bool {
   117  						output, err = e2ekubectl.RunKubectl(f.Namespace.Name, "exec", namespaceOption, podName, containerOption, "--", "nltest", "/PARENTDOMAIN")
   118  						return err == nil
   119  					}, 1*time.Minute, 1*time.Second).Should(gomega.BeTrue())
   120  
   121  					if !strings.HasPrefix(output, domain) {
   122  						framework.Failf("Expected %q to start with %q", output, domain)
   123  					}
   124  
   125  					expectedSubstr := "The command completed successfully"
   126  					if !strings.Contains(output, expectedSubstr) {
   127  						framework.Failf("Expected %q to contain %q", output, expectedSubstr)
   128  					}
   129  				}
   130  
   131  				// If this was an e2e_node test, we could also check that the registry keys used to pass down the cred specs to Docker
   132  				// have been properly cleaned up - but as of right now, e2e_node tests don't support Windows. We should migrate this
   133  				// test to an e2e_node test when they start supporting Windows.
   134  			})
   135  		})
   136  	})
   137  }))
   138  
   139  func generateDummyCredSpecs(domain string) *string {
   140  	shortName := strings.ToUpper(strings.Split(domain, ".")[0])
   141  
   142  	credSpecs := fmt.Sprintf(`{
   143         "ActiveDirectoryConfig":{
   144            "GroupManagedServiceAccounts":[
   145               {
   146                  "Name":"WebApplication",
   147                  "Scope":"%s"
   148               },
   149               {
   150                  "Name":"WebApplication",
   151                  "Scope":"%s"
   152               }
   153            ]
   154         },
   155         "CmsPlugins":[
   156            "ActiveDirectory"
   157         ],
   158         "DomainJoinConfig":{
   159            "DnsName":"%s",
   160            "DnsTreeName":"%s",
   161            "Guid":"244818ae-87ca-4fcd-92ec-e79e5252348a",
   162            "MachineAccountName":"WebApplication",
   163            "NetBiosName":"%s",
   164            "Sid":"S-1-5-21-2126729477-2524175714-3194792973"
   165         }
   166      }`, shortName, domain, domain, domain, shortName)
   167  
   168  	return &credSpecs
   169  }
   170  

View as plain text