Skip to content

Commit 497a998

Browse files
authored
Merge pull request kubernetes#88654 from ddebroy/gmsa-disable1
Promote GMSA support for Windows to GA
2 parents 4d19c6f + 16d221e commit 497a998

File tree

10 files changed

+7
-288
lines changed

10 files changed

+7
-288
lines changed

api/openapi-spec/swagger.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/pod/util.go

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,6 @@ func dropDisabledFields(
387387

388388
dropDisabledRunAsGroupField(podSpec, oldPodSpec)
389389

390-
dropDisabledGMSAFields(podSpec, oldPodSpec)
391-
392390
if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && !runtimeClassInUse(oldPodSpec) {
393391
// Set RuntimeClassName to nil only if feature is disabled and it is not used
394392
podSpec.RuntimeClassName = nil
@@ -432,39 +430,6 @@ func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) {
432430
}
433431
}
434432

435-
// dropDisabledGMSAFields removes disabled fields related to Windows GMSA
436-
// from the given PodSpec.
437-
func dropDisabledGMSAFields(podSpec, oldPodSpec *api.PodSpec) {
438-
if utilfeature.DefaultFeatureGate.Enabled(features.WindowsGMSA) ||
439-
gMSAFieldsInUse(oldPodSpec) {
440-
return
441-
}
442-
443-
if podSpec.SecurityContext != nil {
444-
dropDisabledGMSAFieldsFromWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions)
445-
}
446-
dropDisabledGMSAFieldsFromContainers(podSpec.Containers)
447-
dropDisabledGMSAFieldsFromContainers(podSpec.InitContainers)
448-
}
449-
450-
// dropDisabledGMSAFieldsFromWindowsSecurityOptions removes disabled fields
451-
// related to Windows GMSA from the given WindowsSecurityContextOptions.
452-
func dropDisabledGMSAFieldsFromWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) {
453-
if windowsOptions != nil {
454-
windowsOptions.GMSACredentialSpecName = nil
455-
windowsOptions.GMSACredentialSpec = nil
456-
}
457-
}
458-
459-
// dropDisabledGMSAFieldsFromContainers removes disabled fields
460-
func dropDisabledGMSAFieldsFromContainers(containers []api.Container) {
461-
for i := range containers {
462-
if containers[i].SecurityContext != nil {
463-
dropDisabledGMSAFieldsFromWindowsSecurityOptions(containers[i].SecurityContext.WindowsOptions)
464-
}
465-
}
466-
}
467-
468433
// dropDisabledProcMountField removes disabled fields from PodSpec related
469434
// to ProcMount only if it is not already used by the old spec
470435
func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
@@ -655,44 +620,6 @@ func runAsGroupInUse(podSpec *api.PodSpec) bool {
655620
return inUse
656621
}
657622

658-
// gMSAFieldsInUse returns true if the pod spec is non-nil and has one of any
659-
// SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
660-
func gMSAFieldsInUse(podSpec *api.PodSpec) bool {
661-
if podSpec == nil {
662-
return false
663-
}
664-
665-
if podSpec.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions) {
666-
return true
667-
}
668-
669-
return gMSAFieldsInUseInAnyContainer(podSpec.Containers) ||
670-
gMSAFieldsInUseInAnyContainer(podSpec.InitContainers)
671-
}
672-
673-
// gMSAFieldsInUseInWindowsSecurityOptions returns true if the given WindowsSecurityContextOptions is
674-
// non-nil and one of its GMSACredentialSpecName or GMSACredentialSpec fields is set.
675-
func gMSAFieldsInUseInWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) bool {
676-
if windowsOptions == nil {
677-
return false
678-
}
679-
680-
return windowsOptions.GMSACredentialSpecName != nil ||
681-
windowsOptions.GMSACredentialSpec != nil
682-
}
683-
684-
// gMSAFieldsInUseInAnyContainer returns true if any of the given Containers has its
685-
// SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
686-
func gMSAFieldsInUseInAnyContainer(containers []api.Container) bool {
687-
for _, container := range containers {
688-
if container.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(container.SecurityContext.WindowsOptions) {
689-
return true
690-
}
691-
}
692-
693-
return false
694-
}
695-
696623
// subpathExprInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPathExpr feature
697624
func subpathExprInUse(podSpec *api.PodSpec) bool {
698625
if podSpec == nil {

pkg/api/pod/util_test.go

Lines changed: 0 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,208 +1171,6 @@ func TestDropRunAsGroup(t *testing.T) {
11711171
}
11721172
}
11731173

1174-
func TestDropGMSAFields(t *testing.T) {
1175-
defaultContainerSecurityContextFactory := func() *api.SecurityContext {
1176-
defaultProcMount := api.DefaultProcMount
1177-
return &api.SecurityContext{ProcMount: &defaultProcMount}
1178-
}
1179-
podWithoutWindowsOptionsFactory := func() *api.Pod {
1180-
return &api.Pod{
1181-
Spec: api.PodSpec{
1182-
RestartPolicy: api.RestartPolicyNever,
1183-
SecurityContext: &api.PodSecurityContext{},
1184-
Containers: []api.Container{{Name: "container1", Image: "testimage", SecurityContext: defaultContainerSecurityContextFactory()}},
1185-
InitContainers: []api.Container{{Name: "initContainer1", Image: "testimage", SecurityContext: defaultContainerSecurityContextFactory()}},
1186-
},
1187-
}
1188-
}
1189-
1190-
type podFactoryInfo struct {
1191-
description string
1192-
hasGMSAField bool
1193-
// this factory should generate the input pod whose spec will be fed to dropDisabledFields
1194-
podFactory func() *api.Pod
1195-
// this factory should generate the expected pod after the GMSA fields have been dropped
1196-
// we can't just use podWithoutWindowsOptionsFactory as is for this, since in some cases
1197-
// we'll be left with a WindowsSecurityContextOptions struct with no GMSA field set, as opposed
1198-
// to a nil pointer in the pod generated by podWithoutWindowsOptionsFactory
1199-
// if this field is not set, it will default to the podFactory
1200-
strippedPodFactory func() *api.Pod
1201-
}
1202-
podFactoryInfos := []podFactoryInfo{
1203-
{
1204-
description: "does not have any GMSA field set",
1205-
hasGMSAField: false,
1206-
podFactory: podWithoutWindowsOptionsFactory,
1207-
},
1208-
{
1209-
description: "has a pod-level WindowsSecurityContextOptions struct with no GMSA field set",
1210-
hasGMSAField: false,
1211-
podFactory: func() *api.Pod {
1212-
pod := podWithoutWindowsOptionsFactory()
1213-
pod.Spec.SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1214-
return pod
1215-
},
1216-
},
1217-
{
1218-
description: "has a WindowsSecurityContextOptions struct with no GMSA field set on a container",
1219-
hasGMSAField: false,
1220-
podFactory: func() *api.Pod {
1221-
pod := podWithoutWindowsOptionsFactory()
1222-
pod.Spec.Containers[0].SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1223-
return pod
1224-
},
1225-
},
1226-
{
1227-
description: "has a WindowsSecurityContextOptions struct with no GMSA field set on an init container",
1228-
hasGMSAField: false,
1229-
podFactory: func() *api.Pod {
1230-
pod := podWithoutWindowsOptionsFactory()
1231-
pod.Spec.InitContainers[0].SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1232-
return pod
1233-
},
1234-
},
1235-
{
1236-
description: "is nil",
1237-
hasGMSAField: false,
1238-
podFactory: func() *api.Pod { return nil },
1239-
},
1240-
}
1241-
1242-
toPtr := func(s string) *string {
1243-
return &s
1244-
}
1245-
addGMSACredentialSpecName := func(windowsOptions *api.WindowsSecurityContextOptions) {
1246-
windowsOptions.GMSACredentialSpecName = toPtr("dummy-gmsa-cred-spec-name")
1247-
}
1248-
addGMSACredentialSpec := func(windowsOptions *api.WindowsSecurityContextOptions) {
1249-
windowsOptions.GMSACredentialSpec = toPtr("dummy-gmsa-cred-spec-contents")
1250-
}
1251-
addBothGMSAFields := func(windowsOptions *api.WindowsSecurityContextOptions) {
1252-
addGMSACredentialSpecName(windowsOptions)
1253-
addGMSACredentialSpec(windowsOptions)
1254-
}
1255-
1256-
for fieldName, windowsOptionsTransformingFunc := range map[string]func(*api.WindowsSecurityContextOptions){
1257-
"GMSACredentialSpecName field": addGMSACredentialSpecName,
1258-
"GMSACredentialSpec field": addGMSACredentialSpec,
1259-
"both GMSA fields": addBothGMSAFields,
1260-
} {
1261-
// yes, these variables are indeed needed for the closure to work
1262-
// properly, please do NOT remove them
1263-
name := fieldName
1264-
transformingFunc := windowsOptionsTransformingFunc
1265-
1266-
windowsOptionsWithGMSAFieldFactory := func() *api.WindowsSecurityContextOptions {
1267-
windowsOptions := &api.WindowsSecurityContextOptions{}
1268-
transformingFunc(windowsOptions)
1269-
return windowsOptions
1270-
}
1271-
1272-
podFactoryInfos = append(podFactoryInfos,
1273-
podFactoryInfo{
1274-
description: fmt.Sprintf("has %s in Pod", name),
1275-
hasGMSAField: true,
1276-
podFactory: func() *api.Pod {
1277-
pod := podWithoutWindowsOptionsFactory()
1278-
pod.Spec.SecurityContext.WindowsOptions = windowsOptionsWithGMSAFieldFactory()
1279-
return pod
1280-
},
1281-
strippedPodFactory: func() *api.Pod {
1282-
pod := podWithoutWindowsOptionsFactory()
1283-
pod.Spec.SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1284-
return pod
1285-
},
1286-
},
1287-
podFactoryInfo{
1288-
description: fmt.Sprintf("has %s in Container", name),
1289-
hasGMSAField: true,
1290-
podFactory: func() *api.Pod {
1291-
pod := podWithoutWindowsOptionsFactory()
1292-
pod.Spec.Containers[0].SecurityContext.WindowsOptions = windowsOptionsWithGMSAFieldFactory()
1293-
return pod
1294-
},
1295-
strippedPodFactory: func() *api.Pod {
1296-
pod := podWithoutWindowsOptionsFactory()
1297-
pod.Spec.Containers[0].SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1298-
return pod
1299-
},
1300-
},
1301-
podFactoryInfo{
1302-
description: fmt.Sprintf("has %s in InitContainer", name),
1303-
hasGMSAField: true,
1304-
podFactory: func() *api.Pod {
1305-
pod := podWithoutWindowsOptionsFactory()
1306-
pod.Spec.InitContainers[0].SecurityContext.WindowsOptions = windowsOptionsWithGMSAFieldFactory()
1307-
return pod
1308-
},
1309-
strippedPodFactory: func() *api.Pod {
1310-
pod := podWithoutWindowsOptionsFactory()
1311-
pod.Spec.InitContainers[0].SecurityContext.WindowsOptions = &api.WindowsSecurityContextOptions{}
1312-
return pod
1313-
},
1314-
})
1315-
}
1316-
1317-
for _, enabled := range []bool{true, false} {
1318-
for _, oldPodFactoryInfo := range podFactoryInfos {
1319-
for _, newPodFactoryInfo := range podFactoryInfos {
1320-
newPodHasGMSAField, newPod := newPodFactoryInfo.hasGMSAField, newPodFactoryInfo.podFactory()
1321-
if newPod == nil {
1322-
continue
1323-
}
1324-
oldPodHasGMSAField, oldPod := oldPodFactoryInfo.hasGMSAField, oldPodFactoryInfo.podFactory()
1325-
1326-
t.Run(fmt.Sprintf("feature enabled=%v, old pod %s, new pod %s", enabled, oldPodFactoryInfo.description, newPodFactoryInfo.description), func(t *testing.T) {
1327-
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WindowsGMSA, enabled)()
1328-
1329-
var oldPodSpec *api.PodSpec
1330-
if oldPod != nil {
1331-
oldPodSpec = &oldPod.Spec
1332-
}
1333-
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
1334-
1335-
// old pod should never be changed
1336-
if !reflect.DeepEqual(oldPod, oldPodFactoryInfo.podFactory()) {
1337-
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodFactoryInfo.podFactory()))
1338-
}
1339-
1340-
switch {
1341-
case enabled || oldPodHasGMSAField:
1342-
// new pod should not be changed if the feature is enabled, or if the old pod had any GMSA field set
1343-
if !reflect.DeepEqual(newPod, newPodFactoryInfo.podFactory()) {
1344-
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodFactoryInfo.podFactory()))
1345-
}
1346-
case newPodHasGMSAField:
1347-
// new pod should be changed
1348-
if reflect.DeepEqual(newPod, newPodFactoryInfo.podFactory()) {
1349-
t.Errorf("%v", oldPod)
1350-
t.Errorf("%v", newPod)
1351-
t.Errorf("new pod was not changed")
1352-
}
1353-
// new pod should not have any GMSA field set
1354-
var expectedStrippedPod *api.Pod
1355-
if newPodFactoryInfo.strippedPodFactory == nil {
1356-
expectedStrippedPod = newPodFactoryInfo.podFactory()
1357-
} else {
1358-
expectedStrippedPod = newPodFactoryInfo.strippedPodFactory()
1359-
}
1360-
1361-
if !reflect.DeepEqual(newPod, expectedStrippedPod) {
1362-
t.Errorf("new pod had some GMSA field set: %v", diff.ObjectReflectDiff(newPod, expectedStrippedPod))
1363-
}
1364-
default:
1365-
// new pod should not need to be changed
1366-
if !reflect.DeepEqual(newPod, newPodFactoryInfo.podFactory()) {
1367-
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodFactoryInfo.podFactory()))
1368-
}
1369-
}
1370-
})
1371-
}
1372-
}
1373-
}
1374-
}
1375-
13761174
func TestDropPodSysctls(t *testing.T) {
13771175
podWithSysctls := func() *api.Pod {
13781176
return &api.Pod{

pkg/apis/core/types.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5092,14 +5092,12 @@ type SELinuxOptions struct {
50925092
// WindowsSecurityContextOptions contain Windows-specific options and credentials.
50935093
type WindowsSecurityContextOptions struct {
50945094
// GMSACredentialSpecName is the name of the GMSA credential spec to use.
5095-
// This field is alpha-level and is only honored by servers that enable the WindowsGMSA feature flag.
50965095
// +optional
50975096
GMSACredentialSpecName *string
50985097

50995098
// GMSACredentialSpec is where the GMSA admission webhook
51005099
// (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the
51015100
// GMSA credential spec named by the GMSACredentialSpecName field.
5102-
// This field is alpha-level and is only honored by servers that enable the WindowsGMSA feature flag.
51035101
// +optional
51045102
GMSACredentialSpec *string
51055103

pkg/features/kube_features.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
632632
ProcMountType: {Default: false, PreRelease: featuregate.Alpha},
633633
TTLAfterFinished: {Default: false, PreRelease: featuregate.Alpha},
634634
KubeletPodResources: {Default: true, PreRelease: featuregate.Beta},
635-
WindowsGMSA: {Default: true, PreRelease: featuregate.Beta},
635+
WindowsGMSA: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
636636
WindowsRunAsUserName: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
637637
ServiceLoadBalancerFinalizer: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
638638
LocalStorageCapacityIsolationFSQuotaMonitoring: {Default: false, PreRelease: featuregate.Alpha},

staging/src/k8s.io/api/core/v1/generated.proto

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

staging/src/k8s.io/api/core/v1/types.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5839,14 +5839,12 @@ type SELinuxOptions struct {
58395839
// WindowsSecurityContextOptions contain Windows-specific options and credentials.
58405840
type WindowsSecurityContextOptions struct {
58415841
// GMSACredentialSpecName is the name of the GMSA credential spec to use.
5842-
// This field is alpha-level and is only honored by servers that enable the WindowsGMSA feature flag.
58435842
// +optional
58445843
GMSACredentialSpecName *string `json:"gmsaCredentialSpecName,omitempty" protobuf:"bytes,1,opt,name=gmsaCredentialSpecName"`
58455844

58465845
// GMSACredentialSpec is where the GMSA admission webhook
58475846
// (https://github.com/kubernetes-sigs/windows-gmsa) inlines the contents of the
58485847
// GMSA credential spec named by the GMSACredentialSpecName field.
5849-
// This field is alpha-level and is only honored by servers that enable the WindowsGMSA feature flag.
58505848
// +optional
58515849
GMSACredentialSpec *string `json:"gmsaCredentialSpec,omitempty" protobuf:"bytes,2,opt,name=gmsaCredentialSpec"`
58525850

staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/e2e/windows/gmsa_full.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const (
7979
gmsaWebhookDeployScriptURL = "https://raw.githubusercontent.com/kubernetes-sigs/windows-gmsa/master/admission-webhook/deploy/deploy-gmsa-webhook.sh"
8080
)
8181

82-
var _ = SIGDescribe("[Feature:Windows] [Feature:WindowsGMSA] GMSA Full [Slow]", func() {
82+
var _ = SIGDescribe("[Feature:Windows] GMSA Full [Slow]", func() {
8383
f := framework.NewDefaultFramework("gmsa-full-test-windows")
8484

8585
ginkgo.Describe("GMSA support", func() {

test/e2e/windows/gmsa_kubelet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
"github.com/onsi/gomega"
3636
)
3737

38-
var _ = SIGDescribe("[Feature:Windows] [Feature:WindowsGMSA] GMSA Kubelet [Slow]", func() {
38+
var _ = SIGDescribe("[Feature:Windows] GMSA Kubelet [Slow]", func() {
3939
f := framework.NewDefaultFramework("gmsa-kubelet-test-windows")
4040

4141
ginkgo.Describe("kubelet GMSA support", func() {

0 commit comments

Comments
 (0)