API changes for Windows GMSA support

This patch comprises the API changes outlined in the Windows GMSA KEP
(https://github.com/kubernetes/enhancements/blob/master/keps/sig-windows/20181221-windows-group-managed-service-accounts-for-container-identity.md)
to add GMSA support to Windows workloads.

It includes validation, as well as dropping fields if the `WindowsGMSA` feature
flag is not set, both with unit tests.

Signed-off-by: Jean Rouge <rougej+github@gmail.com>
This commit is contained in:
Jean Rouge
2019-05-16 15:32:59 -07:00
parent 8ae998ceb6
commit a3e914528a
6 changed files with 410 additions and 3 deletions

View File

@@ -368,6 +368,8 @@ func dropDisabledFields(
dropDisabledRunAsGroupField(podSpec, oldPodSpec)
dropDisabledGMSAFields(podSpec, oldPodSpec)
if !utilfeature.DefaultFeatureGate.Enabled(features.RuntimeClass) && !runtimeClassInUse(oldPodSpec) {
// Set RuntimeClassName to nil only if feature is disabled and it is not used
podSpec.RuntimeClassName = nil
@@ -399,6 +401,39 @@ func dropDisabledRunAsGroupField(podSpec, oldPodSpec *api.PodSpec) {
}
}
// dropDisabledGMSAFields removes disabled fields related to Windows GMSA
// from the given PodSpec.
func dropDisabledGMSAFields(podSpec, oldPodSpec *api.PodSpec) {
if utilfeature.DefaultFeatureGate.Enabled(features.WindowsGMSA) ||
gMSAFieldsInUse(oldPodSpec) {
return
}
if podSpec.SecurityContext != nil {
dropDisabledGMSAFieldsFromWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions)
}
dropDisabledGMSAFieldsFromContainers(podSpec.Containers)
dropDisabledGMSAFieldsFromContainers(podSpec.InitContainers)
}
// dropDisabledGMSAFieldsFromWindowsSecurityOptions removes disabled fields
// related to Windows GMSA from the given WindowsSecurityContextOptions.
func dropDisabledGMSAFieldsFromWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) {
if windowsOptions != nil {
windowsOptions.GMSACredentialSpecName = nil
windowsOptions.GMSACredentialSpec = nil
}
}
// dropDisabledGMSAFieldsFromContainers removes disabled fields
func dropDisabledGMSAFieldsFromContainers(containers []api.Container) {
for i := range containers {
if containers[i].SecurityContext != nil {
dropDisabledGMSAFieldsFromWindowsSecurityOptions(containers[i].SecurityContext.WindowsOptions)
}
}
}
// dropDisabledProcMountField removes disabled fields from PodSpec related
// to ProcMount only if it is not already used by the old spec
func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
@@ -612,6 +647,44 @@ func runAsGroupInUse(podSpec *api.PodSpec) bool {
return false
}
// gMSAFieldsInUse returns true if the pod spec is non-nil and has one of any
// SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
func gMSAFieldsInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {
return false
}
if podSpec.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(podSpec.SecurityContext.WindowsOptions) {
return true
}
return gMSAFieldsInUseInAnyContainer(podSpec.Containers) ||
gMSAFieldsInUseInAnyContainer(podSpec.InitContainers)
}
// gMSAFieldsInUseInWindowsSecurityOptions returns true if the given WindowsSecurityContextOptions is
// non-nil and one of its GMSACredentialSpecName or GMSACredentialSpec fields is set.
func gMSAFieldsInUseInWindowsSecurityOptions(windowsOptions *api.WindowsSecurityContextOptions) bool {
if windowsOptions == nil {
return false
}
return windowsOptions.GMSACredentialSpecName != nil ||
windowsOptions.GMSACredentialSpec != nil
}
// gMSAFieldsInUseInAnyContainer returns true if any of the given Containers has its
// SecurityContext's GMSACredentialSpecName or GMSACredentialSpec fields set.
func gMSAFieldsInUseInAnyContainer(containers []api.Container) bool {
for _, container := range containers {
if container.SecurityContext != nil && gMSAFieldsInUseInWindowsSecurityOptions(container.SecurityContext.WindowsOptions) {
return true
}
}
return false
}
// subpathExprInUse returns true if the pod spec is non-nil and has a volume mount that makes use of the subPathExpr feature
func subpathExprInUse(podSpec *api.PodSpec) bool {
if podSpec == nil {