1
16
17
18
19
20
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
114
115
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
132
133
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