mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #14705 from pmorie/pod-sc-inline
PodSecurityContext with inline fields
This commit is contained in:
commit
e3642f1b3f
@ -12625,7 +12625,7 @@
|
|||||||
},
|
},
|
||||||
"securityContext": {
|
"securityContext": {
|
||||||
"$ref": "v1.PodSecurityContext",
|
"$ref": "v1.PodSecurityContext",
|
||||||
"description": "SecurityContext holds pod-level security attributes and common container settings"
|
"description": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field."
|
||||||
},
|
},
|
||||||
"imagePullSecrets": {
|
"imagePullSecrets": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@ -13115,28 +13115,28 @@
|
|||||||
},
|
},
|
||||||
"v1.SecurityContext": {
|
"v1.SecurityContext": {
|
||||||
"id": "v1.SecurityContext",
|
"id": "v1.SecurityContext",
|
||||||
"description": "SecurityContext holds security configuration that will be applied to a container.",
|
"description": "SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"$ref": "v1.Capabilities",
|
"$ref": "v1.Capabilities",
|
||||||
"description": "The linux kernel capabilites that should be added or removed. Default to Container.Capabilities if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime."
|
||||||
},
|
},
|
||||||
"privileged": {
|
"privileged": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Run the container in privileged mode. Default to Container.Privileged if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false."
|
||||||
},
|
},
|
||||||
"seLinuxOptions": {
|
"seLinuxOptions": {
|
||||||
"$ref": "v1.SELinuxOptions",
|
"$ref": "v1.SELinuxOptions",
|
||||||
"description": "SELinuxOptions are the labels to be applied to the container and volumes. Options that control the SELinux labels applied. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
},
|
},
|
||||||
"runAsUser": {
|
"runAsUser": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"description": "RunAsUser is the UID to run the entrypoint of the container process. The user id that runs the first process in the container. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
},
|
},
|
||||||
"runAsNonRoot": {
|
"runAsNonRoot": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "RunAsNonRoot indicates that the container should be run as a non-root user. If the RunAsUser field is not explicitly set then the kubelet may check the image for a specified user or perform defaulting to specify a user."
|
"description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -13170,19 +13170,19 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"user": {
|
"user": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "User is a SELinux user label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "User is a SELinux user label that applies to the container."
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Role is a SELinux role label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Role is a SELinux role label that applies to the container."
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Type is a SELinux type label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Type is a SELinux type label that applies to the container."
|
||||||
},
|
},
|
||||||
"level": {
|
"level": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Level is SELinux level label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Level is SELinux level label that applies to the container."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -13196,6 +13196,19 @@
|
|||||||
"$ref": "integer"
|
"$ref": "integer"
|
||||||
},
|
},
|
||||||
"description": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container."
|
"description": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container."
|
||||||
|
},
|
||||||
|
"seLinuxOptions": {
|
||||||
|
"$ref": "v1.SELinuxOptions",
|
||||||
|
"description": "SELinuxOptions is the SELinux context to be applied to all containers If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container."
|
||||||
|
},
|
||||||
|
"runAsUser": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container."
|
||||||
|
},
|
||||||
|
"runAsNonRoot": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2959,7 +2959,7 @@
|
|||||||
},
|
},
|
||||||
"securityContext": {
|
"securityContext": {
|
||||||
"$ref": "v1.PodSecurityContext",
|
"$ref": "v1.PodSecurityContext",
|
||||||
"description": "SecurityContext holds pod-level security attributes and common container settings"
|
"description": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field."
|
||||||
},
|
},
|
||||||
"imagePullSecrets": {
|
"imagePullSecrets": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
@ -3763,28 +3763,28 @@
|
|||||||
},
|
},
|
||||||
"v1.SecurityContext": {
|
"v1.SecurityContext": {
|
||||||
"id": "v1.SecurityContext",
|
"id": "v1.SecurityContext",
|
||||||
"description": "SecurityContext holds security configuration that will be applied to a container.",
|
"description": "SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
"$ref": "v1.Capabilities",
|
"$ref": "v1.Capabilities",
|
||||||
"description": "The linux kernel capabilites that should be added or removed. Default to Container.Capabilities if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime."
|
||||||
},
|
},
|
||||||
"privileged": {
|
"privileged": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Run the container in privileged mode. Default to Container.Privileged if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false."
|
||||||
},
|
},
|
||||||
"seLinuxOptions": {
|
"seLinuxOptions": {
|
||||||
"$ref": "v1.SELinuxOptions",
|
"$ref": "v1.SELinuxOptions",
|
||||||
"description": "SELinuxOptions are the labels to be applied to the container and volumes. Options that control the SELinux labels applied. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
},
|
},
|
||||||
"runAsUser": {
|
"runAsUser": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int64",
|
"format": "int64",
|
||||||
"description": "RunAsUser is the UID to run the entrypoint of the container process. The user id that runs the first process in the container. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
|
"description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
},
|
},
|
||||||
"runAsNonRoot": {
|
"runAsNonRoot": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "RunAsNonRoot indicates that the container should be run as a non-root user. If the RunAsUser field is not explicitly set then the kubelet may check the image for a specified user or perform defaulting to specify a user."
|
"description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3818,19 +3818,19 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"user": {
|
"user": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "User is a SELinux user label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "User is a SELinux user label that applies to the container."
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Role is a SELinux role label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Role is a SELinux role label that applies to the container."
|
||||||
},
|
},
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Type is a SELinux type label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Type is a SELinux type label that applies to the container."
|
||||||
},
|
},
|
||||||
"level": {
|
"level": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Level is SELinux level label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md"
|
"description": "Level is SELinux level label that applies to the container."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -3844,6 +3844,19 @@
|
|||||||
"$ref": "integer"
|
"$ref": "integer"
|
||||||
},
|
},
|
||||||
"description": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container."
|
"description": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container."
|
||||||
|
},
|
||||||
|
"seLinuxOptions": {
|
||||||
|
"$ref": "v1.SELinuxOptions",
|
||||||
|
"description": "SELinuxOptions is the SELinux context to be applied to all containers If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container."
|
||||||
|
},
|
||||||
|
"runAsUser": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"description": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container."
|
||||||
|
},
|
||||||
|
"runAsNonRoot": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1494,6 +1494,26 @@ func deepCopy_api_PodSecurityContext(in PodSecurityContext, out *PodSecurityCont
|
|||||||
} else {
|
} else {
|
||||||
out.SupplementalGroups = nil
|
out.SupplementalGroups = nil
|
||||||
}
|
}
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(SELinuxOptions)
|
||||||
|
if err := deepCopy_api_SELinuxOptions(*in.SELinuxOptions, out.SELinuxOptions, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1966,7 +1986,12 @@ func deepCopy_api_SecurityContext(in SecurityContext, out *SecurityContext, c *c
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +101,10 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
|
|||||||
}
|
}
|
||||||
s.TerminationGracePeriodSeconds = &ttl
|
s.TerminationGracePeriodSeconds = &ttl
|
||||||
|
|
||||||
|
c.Fuzz(s.SecurityContext)
|
||||||
|
|
||||||
if s.SecurityContext == nil {
|
if s.SecurityContext == nil {
|
||||||
s.SecurityContext = &api.PodSecurityContext{}
|
s.SecurityContext = new(api.PodSecurityContext)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(j *api.PodPhase, c fuzz.Continue) {
|
func(j *api.PodPhase, c fuzz.Continue) {
|
||||||
@ -297,14 +299,19 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
|
|||||||
},
|
},
|
||||||
func(sc *api.SecurityContext, c fuzz.Continue) {
|
func(sc *api.SecurityContext, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(sc) // fuzz self without calling this function again
|
c.FuzzNoCustom(sc) // fuzz self without calling this function again
|
||||||
priv := c.RandBool()
|
if c.RandBool() {
|
||||||
sc.Privileged = &priv
|
priv := c.RandBool()
|
||||||
sc.Capabilities = &api.Capabilities{
|
sc.Privileged = &priv
|
||||||
Add: make([]api.Capability, 0),
|
}
|
||||||
Drop: make([]api.Capability, 0),
|
|
||||||
|
if c.RandBool() {
|
||||||
|
sc.Capabilities = &api.Capabilities{
|
||||||
|
Add: make([]api.Capability, 0),
|
||||||
|
Drop: make([]api.Capability, 0),
|
||||||
|
}
|
||||||
|
c.Fuzz(&sc.Capabilities.Add)
|
||||||
|
c.Fuzz(&sc.Capabilities.Drop)
|
||||||
}
|
}
|
||||||
c.Fuzz(&sc.Capabilities.Add)
|
|
||||||
c.Fuzz(&sc.Capabilities.Drop)
|
|
||||||
},
|
},
|
||||||
func(e *api.Event, c fuzz.Continue) {
|
func(e *api.Event, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(e) // fuzz self without calling this function again
|
c.FuzzNoCustom(e) // fuzz self without calling this function again
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -789,7 +789,8 @@ type Container struct {
|
|||||||
TerminationMessagePath string `json:"terminationMessagePath,omitempty"`
|
TerminationMessagePath string `json:"terminationMessagePath,omitempty"`
|
||||||
// Required: Policy for pulling images for this container
|
// Required: Policy for pulling images for this container
|
||||||
ImagePullPolicy PullPolicy `json:"imagePullPolicy"`
|
ImagePullPolicy PullPolicy `json:"imagePullPolicy"`
|
||||||
// Optional: SecurityContext defines the security options the pod should be run with
|
// Optional: SecurityContext defines the security options the container should be run with.
|
||||||
|
// If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext.
|
||||||
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
SecurityContext *SecurityContext `json:"securityContext,omitempty"`
|
||||||
|
|
||||||
// Variables for interactive containers, these have very specialized use-cases (e.g. debugging)
|
// Variables for interactive containers, these have very specialized use-cases (e.g. debugging)
|
||||||
@ -987,7 +988,8 @@ type PodSpec struct {
|
|||||||
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
|
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
|
||||||
// requirements.
|
// requirements.
|
||||||
NodeName string `json:"nodeName,omitempty"`
|
NodeName string `json:"nodeName,omitempty"`
|
||||||
// SecurityContext holds pod-level security attributes and common container settings
|
// SecurityContext holds pod-level security attributes and common container settings.
|
||||||
|
// Optional: Defaults to empty. See type description for default values of each field.
|
||||||
SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`
|
SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`
|
||||||
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
|
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
|
||||||
// If specified, these secrets will be passed to individual puller implementations for them to use. For example,
|
// If specified, these secrets will be passed to individual puller implementations for them to use. For example,
|
||||||
@ -996,12 +998,13 @@ type PodSpec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PodSecurityContext holds pod-level security attributes and common container settings.
|
// PodSecurityContext holds pod-level security attributes and common container settings.
|
||||||
|
// Some fields are also present in SecurityContext. Field values of SecurityContext take
|
||||||
|
// precedence over field values of PodSecurityContext.
|
||||||
type PodSecurityContext struct {
|
type PodSecurityContext struct {
|
||||||
// Use the host's network namespace. If this option is set, the ports that will be
|
// Use the host's network namespace. If this option is set, the ports that will be
|
||||||
// used must be specified.
|
// used must be specified.
|
||||||
// Optional: Default to false
|
// Optional: Default to false
|
||||||
HostNetwork bool `json:"hostNetwork,omitempty"`
|
HostNetwork bool `json:"hostNetwork,omitempty"`
|
||||||
|
|
||||||
// Use the host's pid namespace.
|
// Use the host's pid namespace.
|
||||||
// Optional: Default to false.
|
// Optional: Default to false.
|
||||||
HostPID bool `json:"hostPID,omitempty"`
|
HostPID bool `json:"hostPID,omitempty"`
|
||||||
@ -1014,6 +1017,25 @@ type PodSecurityContext struct {
|
|||||||
// as. This will be applied to all containers in the pod in
|
// as. This will be applied to all containers in the pod in
|
||||||
// addition to the primary group of the container.
|
// addition to the primary group of the container.
|
||||||
SupplementalGroups []int64 `json:"supplementalGroups,omitempty"`
|
SupplementalGroups []int64 `json:"supplementalGroups,omitempty"`
|
||||||
|
// The SELinux context to be applied to all containers.
|
||||||
|
// If unspecified, the container runtime will allocate a random SELinux context for each
|
||||||
|
// container. May also be set in SecurityContext. If set in
|
||||||
|
// both SecurityContext and PodSecurityContext, the value specified in SecurityContext
|
||||||
|
// takes precedence for that container.
|
||||||
|
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
||||||
|
// The UID to run the entrypoint of the container process.
|
||||||
|
// Defaults to user specified in image metadata if unspecified.
|
||||||
|
// May also be set in SecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence
|
||||||
|
// for that container.
|
||||||
|
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||||
|
// Indicates that the container must run as a non-root user.
|
||||||
|
// If true, the Kubelet will validate the image at runtime to ensure that it
|
||||||
|
// does not run as UID 0 (root) and fail to start the container if it does.
|
||||||
|
// If unset or false, no such validation will be performed.
|
||||||
|
// May also be set in SecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
|
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodStatus represents information about the status of a pod. Status may trail the actual
|
// PodStatus represents information about the status of a pod. Status may trail the actual
|
||||||
@ -2037,41 +2059,44 @@ type ComponentStatusList struct {
|
|||||||
Items []ComponentStatus `json:"items"`
|
Items []ComponentStatus `json:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecurityContext holds security configuration that will be applied to a container. SecurityContext
|
// SecurityContext holds security configuration that will be applied to a container.
|
||||||
// contains duplication of some existing fields from the Container resource. These duplicate fields
|
// Some fields are present in both SecurityContext and PodSecurityContext. When both
|
||||||
// will be populated based on the Container configuration if they are not set. Defining them on
|
// are set, the values in SecurityContext take precedence.
|
||||||
// both the Container AND the SecurityContext will result in an error.
|
|
||||||
type SecurityContext struct {
|
type SecurityContext struct {
|
||||||
// Capabilities are the capabilities to add/drop when running the container
|
// The capabilities to add/drop when running containers.
|
||||||
|
// Defaults to the default set of capabilities granted by the container runtime.
|
||||||
Capabilities *Capabilities `json:"capabilities,omitempty"`
|
Capabilities *Capabilities `json:"capabilities,omitempty"`
|
||||||
|
// Run container in privileged mode.
|
||||||
// Run the container in privileged mode
|
// Processes in privileged containers are essentially equivalent to root on the host.
|
||||||
|
// Defaults to false.
|
||||||
Privileged *bool `json:"privileged,omitempty"`
|
Privileged *bool `json:"privileged,omitempty"`
|
||||||
|
// The SELinux context to be applied to the container.
|
||||||
// SELinuxOptions are the labels to be applied to the container
|
// If unspecified, the container runtime will allocate a random SELinux context for each
|
||||||
// and volumes
|
// container. May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
||||||
|
// The UID to run the entrypoint of the container process.
|
||||||
// RunAsUser is the UID to run the entrypoint of the container process.
|
// Defaults to user specified in image metadata if unspecified.
|
||||||
|
// May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||||
|
// Indicates that the container must run as a non-root user.
|
||||||
// RunAsNonRoot indicates that the container should be run as a non-root user. If the RunAsUser
|
// If true, the Kubelet will validate the image at runtime to ensure that it
|
||||||
// field is not explicitly set then the kubelet may check the image for a specified user or
|
// does not run as UID 0 (root) and fail to start the container if it does.
|
||||||
// perform defaulting to specify a user.
|
// If unset or false, no such validation will be performed.
|
||||||
RunAsNonRoot bool
|
// May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
|
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SELinuxOptions are the labels to be applied to the container.
|
// SELinuxOptions are the labels to be applied to the container.
|
||||||
type SELinuxOptions struct {
|
type SELinuxOptions struct {
|
||||||
// SELinux user label
|
// SELinux user label
|
||||||
User string `json:"user,omitempty"`
|
User string `json:"user,omitempty"`
|
||||||
|
|
||||||
// SELinux role label
|
// SELinux role label
|
||||||
Role string `json:"role,omitempty"`
|
Role string `json:"role,omitempty"`
|
||||||
|
|
||||||
// SELinux type label
|
// SELinux type label
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
|
|
||||||
// SELinux level label.
|
// SELinux level label.
|
||||||
Level string `json:"level,omitempty"`
|
Level string `json:"level,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -289,6 +289,8 @@ func convert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conversi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the host namespace fields have to be handled here for backward compatibilty
|
||||||
|
// with v1.0.0
|
||||||
out.HostPID = in.SecurityContext.HostPID
|
out.HostPID = in.SecurityContext.HostPID
|
||||||
out.HostNetwork = in.SecurityContext.HostNetwork
|
out.HostNetwork = in.SecurityContext.HostNetwork
|
||||||
out.HostIPC = in.SecurityContext.HostIPC
|
out.HostIPC = in.SecurityContext.HostIPC
|
||||||
@ -365,6 +367,9 @@ func convert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conversi
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the host namespace fields have to be handled specially for backward compatibility
|
||||||
|
// with v1.0.0
|
||||||
if out.SecurityContext == nil {
|
if out.SecurityContext == nil {
|
||||||
out.SecurityContext = new(api.PodSecurityContext)
|
out.SecurityContext = new(api.PodSecurityContext)
|
||||||
}
|
}
|
||||||
@ -415,6 +420,26 @@ func convert_api_PodSecurityContext_To_v1_PodSecurityContext(in *api.PodSecurity
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.SupplementalGroups = in.SupplementalGroups
|
out.SupplementalGroups = in.SupplementalGroups
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(SELinuxOptions)
|
||||||
|
if err := convert_api_SELinuxOptions_To_v1_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,5 +449,25 @@ func convert_v1_PodSecurityContext_To_api_PodSecurityContext(in *PodSecurityCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.SupplementalGroups = in.SupplementalGroups
|
out.SupplementalGroups = in.SupplementalGroups
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(api.SELinuxOptions)
|
||||||
|
if err := convert_v1_SELinuxOptions_To_api_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -2650,7 +2650,12 @@ func autoconvert_api_SecurityContext_To_v1_SecurityContext(in *api.SecurityConte
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5666,7 +5671,12 @@ func autoconvert_v1_SecurityContext_To_api_SecurityContext(in *SecurityContext,
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1509,6 +1509,26 @@ func deepCopy_v1_PodSecurityContext(in PodSecurityContext, out *PodSecurityConte
|
|||||||
} else {
|
} else {
|
||||||
out.SupplementalGroups = nil
|
out.SupplementalGroups = nil
|
||||||
}
|
}
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(SELinuxOptions)
|
||||||
|
if err := deepCopy_v1_SELinuxOptions(*in.SELinuxOptions, out.SELinuxOptions, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1990,7 +2010,12 @@ func deepCopy_v1_SecurityContext(in SecurityContext, out *SecurityContext, c *co
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1247,7 +1247,8 @@ type PodSpec struct {
|
|||||||
// Use the host's ipc namespace.
|
// Use the host's ipc namespace.
|
||||||
// Optional: Default to false.
|
// Optional: Default to false.
|
||||||
HostIPC bool `json:"hostIPC,omitempty"`
|
HostIPC bool `json:"hostIPC,omitempty"`
|
||||||
// SecurityContext holds pod-level security attributes and common container settings
|
// SecurityContext holds pod-level security attributes and common container settings.
|
||||||
|
// Optional: Defaults to empty. See type description for default values of each field.
|
||||||
SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`
|
SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`
|
||||||
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
|
// ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec.
|
||||||
// If specified, these secrets will be passed to individual puller implementations for them to use. For example,
|
// If specified, these secrets will be passed to individual puller implementations for them to use. For example,
|
||||||
@ -1263,6 +1264,25 @@ type PodSecurityContext struct {
|
|||||||
// as. This will be applied to all containers in the pod in
|
// as. This will be applied to all containers in the pod in
|
||||||
// addition to the primary group of the container.
|
// addition to the primary group of the container.
|
||||||
SupplementalGroups []int64 `json:"supplementalGroups,omitempty"`
|
SupplementalGroups []int64 `json:"supplementalGroups,omitempty"`
|
||||||
|
// SELinuxOptions is the SELinux context to be applied to all containers
|
||||||
|
// If unspecified, the container runtime will allocate a random SELinux context for each
|
||||||
|
// container. May also be set in SecurityContext. If set in
|
||||||
|
// both SecurityContext and PodSecurityContext, the value specified in SecurityContext
|
||||||
|
// takes precedence for that container.
|
||||||
|
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
||||||
|
// The UID to run the entrypoint of the container process.
|
||||||
|
// Defaults to user specified in image metadata if unspecified.
|
||||||
|
// May also be set in SecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence
|
||||||
|
// for that container.
|
||||||
|
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||||
|
// Indicates that the container must run as a non-root user.
|
||||||
|
// If true, the Kubelet will validate the image at runtime to ensure that it
|
||||||
|
// does not run as UID 0 (root) and fail to start the container if it does.
|
||||||
|
// If unset or false, no such validation will be performed.
|
||||||
|
// May also be set in SecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
|
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodStatus represents information about the status of a pod. Status may trail the actual
|
// PodStatus represents information about the status of a pod. Status may trail the actual
|
||||||
@ -2474,50 +2494,44 @@ type DownwardAPIVolumeFile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SecurityContext holds security configuration that will be applied to a container.
|
// SecurityContext holds security configuration that will be applied to a container.
|
||||||
|
// Some fields are present in both SecurityContext and PodSecurityContext. When both
|
||||||
|
// are set, the values in SecurityContext take precedence.
|
||||||
type SecurityContext struct {
|
type SecurityContext struct {
|
||||||
// The linux kernel capabilites that should be added or removed.
|
// The capabilities to add/drop when running containers.
|
||||||
// Default to Container.Capabilities if left unset.
|
// Defaults to the default set of capabilities granted by the container runtime.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
|
|
||||||
Capabilities *Capabilities `json:"capabilities,omitempty"`
|
Capabilities *Capabilities `json:"capabilities,omitempty"`
|
||||||
|
// Run container in privileged mode.
|
||||||
// Run the container in privileged mode.
|
// Processes in privileged containers are essentially equivalent to root on the host.
|
||||||
// Default to Container.Privileged if left unset.
|
// Defaults to false.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
|
|
||||||
Privileged *bool `json:"privileged,omitempty"`
|
Privileged *bool `json:"privileged,omitempty"`
|
||||||
|
// The SELinux context to be applied to the container.
|
||||||
// SELinuxOptions are the labels to be applied to the container
|
// If unspecified, the container runtime will allocate a random SELinux context for each
|
||||||
// and volumes.
|
// container. May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
// Options that control the SELinux labels applied.
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
|
|
||||||
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
SELinuxOptions *SELinuxOptions `json:"seLinuxOptions,omitempty"`
|
||||||
|
// The UID to run the entrypoint of the container process.
|
||||||
// RunAsUser is the UID to run the entrypoint of the container process.
|
// Defaults to user specified in image metadata if unspecified.
|
||||||
// The user id that runs the first process in the container.
|
// May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
RunAsUser *int64 `json:"runAsUser,omitempty"`
|
||||||
|
// Indicates that the container must run as a non-root user.
|
||||||
// RunAsNonRoot indicates that the container should be run as a non-root user. If the RunAsUser
|
// If true, the Kubelet will validate the image at runtime to ensure that it
|
||||||
// field is not explicitly set then the kubelet may check the image for a specified user or
|
// does not run as UID 0 (root) and fail to start the container if it does.
|
||||||
// perform defaulting to specify a user.
|
// If unset or false, no such validation will be performed.
|
||||||
RunAsNonRoot bool `json:"runAsNonRoot,omitempty"`
|
// May also be set in PodSecurityContext. If set in both SecurityContext and
|
||||||
|
// PodSecurityContext, the value specified in SecurityContext takes precedence.
|
||||||
|
RunAsNonRoot *bool `json:"runAsNonRoot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// SELinuxOptions are the labels to be applied to the container
|
// SELinuxOptions are the labels to be applied to the container
|
||||||
type SELinuxOptions struct {
|
type SELinuxOptions struct {
|
||||||
// User is a SELinux user label that applies to the container.
|
// User is a SELinux user label that applies to the container.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md
|
|
||||||
User string `json:"user,omitempty"`
|
User string `json:"user,omitempty"`
|
||||||
|
|
||||||
// Role is a SELinux role label that applies to the container.
|
// Role is a SELinux role label that applies to the container.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md
|
|
||||||
Role string `json:"role,omitempty"`
|
Role string `json:"role,omitempty"`
|
||||||
|
|
||||||
// Type is a SELinux type label that applies to the container.
|
// Type is a SELinux type label that applies to the container.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md
|
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
|
|
||||||
// Level is SELinux level label that applies to the container.
|
// Level is SELinux level label that applies to the container.
|
||||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md
|
|
||||||
Level string `json:"level,omitempty"`
|
Level string `json:"level,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,6 +977,9 @@ func (PodProxyOptions) SwaggerDoc() map[string]string {
|
|||||||
var map_PodSecurityContext = map[string]string{
|
var map_PodSecurityContext = map[string]string{
|
||||||
"": "PodSecurityContext holds pod-level security attributes and common container settings.",
|
"": "PodSecurityContext holds pod-level security attributes and common container settings.",
|
||||||
"supplementalGroups": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container.",
|
"supplementalGroups": "SupplementalGroups can be used to specify a list of additional groups which the main container process will run as. This will be applied to all containers in the pod in addition to the primary group of the container.",
|
||||||
|
"seLinuxOptions": "SELinuxOptions is the SELinux context to be applied to all containers If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.",
|
||||||
|
"runAsUser": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.",
|
||||||
|
"runAsNonRoot": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PodSecurityContext) SwaggerDoc() map[string]string {
|
func (PodSecurityContext) SwaggerDoc() map[string]string {
|
||||||
@ -998,7 +1001,7 @@ var map_PodSpec = map[string]string{
|
|||||||
"hostNetwork": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.",
|
"hostNetwork": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.",
|
||||||
"hostPID": "Use the host's pid namespace. Optional: Default to false.",
|
"hostPID": "Use the host's pid namespace. Optional: Default to false.",
|
||||||
"hostIPC": "Use the host's ipc namespace. Optional: Default to false.",
|
"hostIPC": "Use the host's ipc namespace. Optional: Default to false.",
|
||||||
"securityContext": "SecurityContext holds pod-level security attributes and common container settings",
|
"securityContext": "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.",
|
||||||
"imagePullSecrets": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod",
|
"imagePullSecrets": "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://releases.k8s.io/HEAD/docs/user-guide/images.md#specifying-imagepullsecrets-on-a-pod",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,10 +1196,10 @@ func (ResourceRequirements) SwaggerDoc() map[string]string {
|
|||||||
|
|
||||||
var map_SELinuxOptions = map[string]string{
|
var map_SELinuxOptions = map[string]string{
|
||||||
"": "SELinuxOptions are the labels to be applied to the container",
|
"": "SELinuxOptions are the labels to be applied to the container",
|
||||||
"user": "User is a SELinux user label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md",
|
"user": "User is a SELinux user label that applies to the container.",
|
||||||
"role": "Role is a SELinux role label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md",
|
"role": "Role is a SELinux role label that applies to the container.",
|
||||||
"type": "Type is a SELinux type label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md",
|
"type": "Type is a SELinux type label that applies to the container.",
|
||||||
"level": "Level is SELinux level label that applies to the container. More info: http://releases.k8s.io/HEAD/docs/user-guide/labels.md",
|
"level": "Level is SELinux level label that applies to the container.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SELinuxOptions) SwaggerDoc() map[string]string {
|
func (SELinuxOptions) SwaggerDoc() map[string]string {
|
||||||
@ -1234,12 +1237,12 @@ func (SecretVolumeSource) SwaggerDoc() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var map_SecurityContext = map[string]string{
|
var map_SecurityContext = map[string]string{
|
||||||
"": "SecurityContext holds security configuration that will be applied to a container.",
|
"": "SecurityContext holds security configuration that will be applied to a container. Some fields are present in both SecurityContext and PodSecurityContext. When both are set, the values in SecurityContext take precedence.",
|
||||||
"capabilities": "The linux kernel capabilites that should be added or removed. Default to Container.Capabilities if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context",
|
"capabilities": "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.",
|
||||||
"privileged": "Run the container in privileged mode. Default to Container.Privileged if left unset. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context",
|
"privileged": "Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults to false.",
|
||||||
"seLinuxOptions": "SELinuxOptions are the labels to be applied to the container and volumes. Options that control the SELinux labels applied. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context",
|
"seLinuxOptions": "The SELinux context to be applied to the container. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.",
|
||||||
"runAsUser": "RunAsUser is the UID to run the entrypoint of the container process. The user id that runs the first process in the container. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context",
|
"runAsUser": "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.",
|
||||||
"runAsNonRoot": "RunAsNonRoot indicates that the container should be run as a non-root user. If the RunAsUser field is not explicitly set then the kubelet may check the image for a specified user or perform defaulting to specify a user.",
|
"runAsNonRoot": "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (SecurityContext) SwaggerDoc() map[string]string {
|
func (SecurityContext) SwaggerDoc() map[string]string {
|
||||||
|
@ -472,6 +472,26 @@ func deepCopy_api_PodSecurityContext(in api.PodSecurityContext, out *api.PodSecu
|
|||||||
} else {
|
} else {
|
||||||
out.SupplementalGroups = nil
|
out.SupplementalGroups = nil
|
||||||
}
|
}
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(api.SELinuxOptions)
|
||||||
|
if err := deepCopy_api_SELinuxOptions(*in.SELinuxOptions, out.SELinuxOptions, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,7 +676,12 @@ func deepCopy_api_SecurityContext(in api.SecurityContext, out *api.SecurityConte
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +333,26 @@ func convert_api_PodSecurityContext_To_v1_PodSecurityContext(in *api.PodSecurity
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.SupplementalGroups = in.SupplementalGroups
|
out.SupplementalGroups = in.SupplementalGroups
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(v1.SELinuxOptions)
|
||||||
|
if err := convert_api_SELinuxOptions_To_v1_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,5 +362,25 @@ func convert_v1_PodSecurityContext_To_api_PodSecurityContext(in *v1.PodSecurityC
|
|||||||
}
|
}
|
||||||
|
|
||||||
out.SupplementalGroups = in.SupplementalGroups
|
out.SupplementalGroups = in.SupplementalGroups
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(api.SELinuxOptions)
|
||||||
|
if err := convert_v1_SELinuxOptions_To_api_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -889,7 +889,12 @@ func autoconvert_api_SecurityContext_To_v1_SecurityContext(in *api.SecurityConte
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1944,7 +1949,12 @@ func autoconvert_v1_SecurityContext_To_api_SecurityContext(in *v1.SecurityContex
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,6 +505,26 @@ func deepCopy_v1_PodSecurityContext(in v1.PodSecurityContext, out *v1.PodSecurit
|
|||||||
} else {
|
} else {
|
||||||
out.SupplementalGroups = nil
|
out.SupplementalGroups = nil
|
||||||
}
|
}
|
||||||
|
if in.SELinuxOptions != nil {
|
||||||
|
out.SELinuxOptions = new(v1.SELinuxOptions)
|
||||||
|
if err := deepCopy_v1_SELinuxOptions(*in.SELinuxOptions, out.SELinuxOptions, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.SELinuxOptions = nil
|
||||||
|
}
|
||||||
|
if in.RunAsUser != nil {
|
||||||
|
out.RunAsUser = new(int64)
|
||||||
|
*out.RunAsUser = *in.RunAsUser
|
||||||
|
} else {
|
||||||
|
out.RunAsUser = nil
|
||||||
|
}
|
||||||
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,7 +713,12 @@ func deepCopy_v1_SecurityContext(in v1.SecurityContext, out *v1.SecurityContext,
|
|||||||
} else {
|
} else {
|
||||||
out.RunAsUser = nil
|
out.RunAsUser = nil
|
||||||
}
|
}
|
||||||
out.RunAsNonRoot = in.RunAsNonRoot
|
if in.RunAsNonRoot != nil {
|
||||||
|
out.RunAsNonRoot = new(bool)
|
||||||
|
*out.RunAsNonRoot = *in.RunAsNonRoot
|
||||||
|
} else {
|
||||||
|
out.RunAsNonRoot = nil
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1911,7 +1911,7 @@ func (dm *DockerManager) SyncPod(pod *api.Pod, runningPod kubecontainer.Pod, pod
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.SecurityContext != nil && container.SecurityContext.RunAsNonRoot {
|
if container.SecurityContext != nil && container.SecurityContext.RunAsNonRoot != nil && *container.SecurityContext.RunAsNonRoot {
|
||||||
err := dm.verifyNonRoot(container)
|
err := dm.verifyNonRoot(container)
|
||||||
dm.updateReasonCache(pod, container, "VerifyNonRootError", err)
|
dm.updateReasonCache(pod, container, "VerifyNonRootError", err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,11 +38,12 @@ type SimpleSecurityContextProvider struct{}
|
|||||||
// The security context provider can make changes to the Config with which
|
// The security context provider can make changes to the Config with which
|
||||||
// the container is created.
|
// the container is created.
|
||||||
func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *docker.Config) {
|
func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *api.Pod, container *api.Container, config *docker.Config) {
|
||||||
if container.SecurityContext == nil {
|
effectiveSC := determineEffectiveSecurityContext(pod, container)
|
||||||
|
if effectiveSC == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if container.SecurityContext.RunAsUser != nil {
|
if effectiveSC.RunAsUser != nil {
|
||||||
config.User = strconv.FormatInt(*container.SecurityContext.RunAsUser, 10)
|
config.User = strconv.Itoa(int(*effectiveSC.RunAsUser))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,30 +63,32 @@ func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *api.Pod, container
|
|||||||
if pod.Spec.SecurityContext.SupplementalGroups != nil && container.Name != leaky.PodInfraContainerName {
|
if pod.Spec.SecurityContext.SupplementalGroups != nil && container.Name != leaky.PodInfraContainerName {
|
||||||
hostConfig.GroupAdd = make([]string, len(pod.Spec.SecurityContext.SupplementalGroups))
|
hostConfig.GroupAdd = make([]string, len(pod.Spec.SecurityContext.SupplementalGroups))
|
||||||
for i, group := range pod.Spec.SecurityContext.SupplementalGroups {
|
for i, group := range pod.Spec.SecurityContext.SupplementalGroups {
|
||||||
hostConfig.GroupAdd[i] = strconv.FormatInt(group, 10)
|
hostConfig.GroupAdd[i] = strconv.Itoa(int(group))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply container security context
|
// Apply effective security context for container
|
||||||
if container.SecurityContext == nil {
|
effectiveSC := determineEffectiveSecurityContext(pod, container)
|
||||||
|
if effectiveSC == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if container.SecurityContext.Privileged != nil {
|
|
||||||
hostConfig.Privileged = *container.SecurityContext.Privileged
|
if effectiveSC.Privileged != nil {
|
||||||
|
hostConfig.Privileged = *effectiveSC.Privileged
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.SecurityContext.Capabilities != nil {
|
if effectiveSC.Capabilities != nil {
|
||||||
add, drop := makeCapabilites(container.SecurityContext.Capabilities.Add, container.SecurityContext.Capabilities.Drop)
|
add, drop := makeCapabilites(effectiveSC.Capabilities.Add, effectiveSC.Capabilities.Drop)
|
||||||
hostConfig.CapAdd = add
|
hostConfig.CapAdd = add
|
||||||
hostConfig.CapDrop = drop
|
hostConfig.CapDrop = drop
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.SecurityContext.SELinuxOptions != nil {
|
if effectiveSC.SELinuxOptions != nil {
|
||||||
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelUser, container.SecurityContext.SELinuxOptions.User)
|
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelUser, effectiveSC.SELinuxOptions.User)
|
||||||
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelRole, container.SecurityContext.SELinuxOptions.Role)
|
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelRole, effectiveSC.SELinuxOptions.Role)
|
||||||
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelType, container.SecurityContext.SELinuxOptions.Type)
|
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelType, effectiveSC.SELinuxOptions.Type)
|
||||||
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelLevel, container.SecurityContext.SELinuxOptions.Level)
|
hostConfig.SecurityOpt = modifySecurityOption(hostConfig.SecurityOpt, dockerLabelLevel, effectiveSC.SELinuxOptions.Level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,3 +115,69 @@ func makeCapabilites(capAdd []api.Capability, capDrop []api.Capability) ([]strin
|
|||||||
}
|
}
|
||||||
return addCaps, dropCaps
|
return addCaps, dropCaps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func determineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *api.SecurityContext {
|
||||||
|
effectiveSc := securityContextFromPodSecurityContext(pod)
|
||||||
|
containerSc := container.SecurityContext
|
||||||
|
|
||||||
|
if effectiveSc == nil && containerSc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if effectiveSc != nil && containerSc == nil {
|
||||||
|
return effectiveSc
|
||||||
|
}
|
||||||
|
if effectiveSc == nil && containerSc != nil {
|
||||||
|
return containerSc
|
||||||
|
}
|
||||||
|
|
||||||
|
if containerSc.SELinuxOptions != nil {
|
||||||
|
effectiveSc.SELinuxOptions = new(api.SELinuxOptions)
|
||||||
|
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
if containerSc.Capabilities != nil {
|
||||||
|
effectiveSc.Capabilities = new(api.Capabilities)
|
||||||
|
*effectiveSc.Capabilities = *containerSc.Capabilities
|
||||||
|
}
|
||||||
|
|
||||||
|
if containerSc.Privileged != nil {
|
||||||
|
effectiveSc.Privileged = new(bool)
|
||||||
|
*effectiveSc.Privileged = *containerSc.Privileged
|
||||||
|
}
|
||||||
|
|
||||||
|
if containerSc.RunAsUser != nil {
|
||||||
|
effectiveSc.RunAsUser = new(int64)
|
||||||
|
*effectiveSc.RunAsUser = *containerSc.RunAsUser
|
||||||
|
}
|
||||||
|
|
||||||
|
if containerSc.RunAsNonRoot != nil {
|
||||||
|
effectiveSc.RunAsNonRoot = new(bool)
|
||||||
|
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
return effectiveSc
|
||||||
|
}
|
||||||
|
|
||||||
|
func securityContextFromPodSecurityContext(pod *api.Pod) *api.SecurityContext {
|
||||||
|
if pod.Spec.SecurityContext == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
synthesized := &api.SecurityContext{}
|
||||||
|
|
||||||
|
if pod.Spec.SecurityContext.SELinuxOptions != nil {
|
||||||
|
synthesized.SELinuxOptions = &api.SELinuxOptions{}
|
||||||
|
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
|
||||||
|
}
|
||||||
|
if pod.Spec.SecurityContext.RunAsUser != nil {
|
||||||
|
synthesized.RunAsUser = new(int64)
|
||||||
|
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
|
||||||
|
}
|
||||||
|
|
||||||
|
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
|
||||||
|
synthesized.RunAsNonRoot = new(bool)
|
||||||
|
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
return synthesized
|
||||||
|
}
|
||||||
|
@ -28,94 +28,148 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestModifyContainerConfig(t *testing.T) {
|
func TestModifyContainerConfig(t *testing.T) {
|
||||||
var uid int64 = 1
|
var uid int64 = 123
|
||||||
testCases := map[string]struct {
|
var overrideUid int64 = 321
|
||||||
securityContext *api.SecurityContext
|
|
||||||
expected *docker.Config
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
podSc *api.PodSecurityContext
|
||||||
|
sc *api.SecurityContext
|
||||||
|
expected *docker.Config
|
||||||
}{
|
}{
|
||||||
"modify config, value set for user": {
|
{
|
||||||
securityContext: &api.SecurityContext{
|
name: "container.SecurityContext.RunAsUser set",
|
||||||
|
sc: &api.SecurityContext{
|
||||||
RunAsUser: &uid,
|
RunAsUser: &uid,
|
||||||
},
|
},
|
||||||
expected: &docker.Config{
|
expected: &docker.Config{
|
||||||
User: strconv.FormatInt(uid, 10),
|
User: strconv.FormatInt(uid, 10),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"modify config, nil user value": {
|
{
|
||||||
securityContext: &api.SecurityContext{},
|
name: "no RunAsUser value set",
|
||||||
expected: &docker.Config{},
|
sc: &api.SecurityContext{},
|
||||||
|
expected: &docker.Config{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod.Spec.SecurityContext.RunAsUser set",
|
||||||
|
podSc: &api.PodSecurityContext{
|
||||||
|
RunAsUser: &uid,
|
||||||
|
},
|
||||||
|
expected: &docker.Config{
|
||||||
|
User: strconv.FormatInt(uid, 10),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "container.SecurityContext.RunAsUser overrides pod.Spec.SecurityContext.RunAsUser",
|
||||||
|
podSc: &api.PodSecurityContext{
|
||||||
|
RunAsUser: &uid,
|
||||||
|
},
|
||||||
|
sc: &api.SecurityContext{
|
||||||
|
RunAsUser: &overrideUid,
|
||||||
|
},
|
||||||
|
expected: &docker.Config{
|
||||||
|
User: strconv.FormatInt(overrideUid, 10),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := NewSimpleSecurityContextProvider()
|
provider := NewSimpleSecurityContextProvider()
|
||||||
dummyContainer := &api.Container{}
|
dummyContainer := &api.Container{}
|
||||||
for k, v := range testCases {
|
for _, tc := range cases {
|
||||||
dummyContainer.SecurityContext = v.securityContext
|
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}}
|
||||||
|
dummyContainer.SecurityContext = tc.sc
|
||||||
dockerCfg := &docker.Config{}
|
dockerCfg := &docker.Config{}
|
||||||
provider.ModifyContainerConfig(nil, dummyContainer, dockerCfg)
|
|
||||||
if !reflect.DeepEqual(v.expected, dockerCfg) {
|
provider.ModifyContainerConfig(pod, dummyContainer, dockerCfg)
|
||||||
t.Errorf("unexpected modification of docker config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg)
|
|
||||||
|
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("%v: unexpected modification of docker config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestModifyHostConfig(t *testing.T) {
|
func TestModifyHostConfig(t *testing.T) {
|
||||||
nilPrivSC := fullValidSecurityContext()
|
priv := true
|
||||||
nilPrivSC.Privileged = nil
|
setPrivSC := &api.SecurityContext{}
|
||||||
nilPrivHC := fullValidHostConfig()
|
setPrivSC.Privileged = &priv
|
||||||
nilPrivHC.Privileged = false
|
setPrivHC := &docker.HostConfig{
|
||||||
|
Privileged: true,
|
||||||
|
}
|
||||||
|
|
||||||
nilCapsSC := fullValidSecurityContext()
|
setCapsHC := &docker.HostConfig{
|
||||||
nilCapsSC.Capabilities = nil
|
CapAdd: []string{"addCapA", "addCapB"},
|
||||||
nilCapsHC := fullValidHostConfig()
|
CapDrop: []string{"dropCapA", "dropCapB"},
|
||||||
nilCapsHC.CapAdd = *new([]string)
|
}
|
||||||
nilCapsHC.CapDrop = *new([]string)
|
|
||||||
|
|
||||||
nilSELinuxSC := fullValidSecurityContext()
|
setSELinuxHC := &docker.HostConfig{}
|
||||||
nilSELinuxSC.SELinuxOptions = nil
|
setSELinuxHC.SecurityOpt = []string{
|
||||||
nilSELinuxHC := fullValidHostConfig()
|
fmt.Sprintf("%s:%s", dockerLabelUser, "user"),
|
||||||
nilSELinuxHC.SecurityOpt = *new([]string)
|
fmt.Sprintf("%s:%s", dockerLabelRole, "role"),
|
||||||
|
fmt.Sprintf("%s:%s", dockerLabelType, "type"),
|
||||||
|
fmt.Sprintf("%s:%s", dockerLabelLevel, "level"),
|
||||||
|
}
|
||||||
|
|
||||||
seLinuxLabelsSC := fullValidSecurityContext()
|
// seLinuxLabelsSC := fullValidSecurityContext()
|
||||||
seLinuxLabelsHC := fullValidHostConfig()
|
// seLinuxLabelsHC := fullValidHostConfig()
|
||||||
|
|
||||||
testCases := map[string]struct {
|
cases := []struct {
|
||||||
securityContext *api.SecurityContext
|
name string
|
||||||
expected *docker.HostConfig
|
podSc *api.PodSecurityContext
|
||||||
|
sc *api.SecurityContext
|
||||||
|
expected *docker.HostConfig
|
||||||
}{
|
}{
|
||||||
"full settings": {
|
{
|
||||||
securityContext: fullValidSecurityContext(),
|
name: "fully set container.SecurityContext",
|
||||||
expected: fullValidHostConfig(),
|
sc: fullValidSecurityContext(),
|
||||||
|
expected: fullValidHostConfig(),
|
||||||
},
|
},
|
||||||
"nil privileged": {
|
{
|
||||||
securityContext: nilPrivSC,
|
name: "container.SecurityContext.Privileged",
|
||||||
expected: nilPrivHC,
|
sc: setPrivSC,
|
||||||
|
expected: setPrivHC,
|
||||||
},
|
},
|
||||||
"nil capabilities": {
|
{
|
||||||
securityContext: nilCapsSC,
|
name: "container.SecurityContext.Capabilities",
|
||||||
expected: nilCapsHC,
|
sc: &api.SecurityContext{
|
||||||
|
Capabilities: inputCapabilities(),
|
||||||
|
},
|
||||||
|
expected: setCapsHC,
|
||||||
},
|
},
|
||||||
"nil selinux options": {
|
{
|
||||||
securityContext: nilSELinuxSC,
|
name: "container.SecurityContext.SELinuxOptions",
|
||||||
expected: nilSELinuxHC,
|
sc: &api.SecurityContext{
|
||||||
|
SELinuxOptions: inputSELinuxOptions(),
|
||||||
|
},
|
||||||
|
expected: setSELinuxHC,
|
||||||
},
|
},
|
||||||
"selinux labels": {
|
{
|
||||||
securityContext: seLinuxLabelsSC,
|
name: "pod.Spec.SecurityContext.SELinuxOptions",
|
||||||
expected: seLinuxLabelsHC,
|
podSc: &api.PodSecurityContext{
|
||||||
|
SELinuxOptions: inputSELinuxOptions(),
|
||||||
|
},
|
||||||
|
expected: setSELinuxHC,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "container.SecurityContext overrides pod.Spec.SecurityContext",
|
||||||
|
podSc: overridePodSecurityContext(),
|
||||||
|
sc: fullValidSecurityContext(),
|
||||||
|
expected: fullValidHostConfig(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := NewSimpleSecurityContextProvider()
|
provider := NewSimpleSecurityContextProvider()
|
||||||
dummyContainer := &api.Container{}
|
dummyContainer := &api.Container{}
|
||||||
dummyPod := &api.Pod{
|
|
||||||
Spec: apitesting.DeepEqualSafePodSpec(),
|
for _, tc := range cases {
|
||||||
}
|
pod := &api.Pod{Spec: api.PodSpec{SecurityContext: tc.podSc}}
|
||||||
for k, v := range testCases {
|
dummyContainer.SecurityContext = tc.sc
|
||||||
dummyContainer.SecurityContext = v.securityContext
|
|
||||||
dockerCfg := &docker.HostConfig{}
|
dockerCfg := &docker.HostConfig{}
|
||||||
provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg)
|
|
||||||
if !reflect.DeepEqual(v.expected, dockerCfg) {
|
provider.ModifyHostConfig(pod, dummyContainer, dockerCfg)
|
||||||
t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg)
|
|
||||||
|
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
|
||||||
|
t.Errorf("%v: unexpected modification of host config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,20 +243,45 @@ func TestModifySecurityOption(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func overridePodSecurityContext() *api.PodSecurityContext {
|
||||||
|
return &api.PodSecurityContext{
|
||||||
|
SELinuxOptions: &api.SELinuxOptions{
|
||||||
|
User: "user2",
|
||||||
|
Role: "role2",
|
||||||
|
Type: "type2",
|
||||||
|
Level: "level2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fullValidPodSecurityContext() *api.PodSecurityContext {
|
||||||
|
return &api.PodSecurityContext{
|
||||||
|
SELinuxOptions: inputSELinuxOptions(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func fullValidSecurityContext() *api.SecurityContext {
|
func fullValidSecurityContext() *api.SecurityContext {
|
||||||
priv := true
|
priv := true
|
||||||
return &api.SecurityContext{
|
return &api.SecurityContext{
|
||||||
Privileged: &priv,
|
Privileged: &priv,
|
||||||
Capabilities: &api.Capabilities{
|
Capabilities: inputCapabilities(),
|
||||||
Add: []api.Capability{"addCapA", "addCapB"},
|
SELinuxOptions: inputSELinuxOptions(),
|
||||||
Drop: []api.Capability{"dropCapA", "dropCapB"},
|
}
|
||||||
},
|
}
|
||||||
SELinuxOptions: &api.SELinuxOptions{
|
|
||||||
User: "user",
|
func inputCapabilities() *api.Capabilities {
|
||||||
Role: "role",
|
return &api.Capabilities{
|
||||||
Type: "type",
|
Add: []api.Capability{"addCapA", "addCapB"},
|
||||||
Level: "level",
|
Drop: []api.Capability{"dropCapA", "dropCapB"},
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func inputSELinuxOptions() *api.SELinuxOptions {
|
||||||
|
return &api.SELinuxOptions{
|
||||||
|
User: "user",
|
||||||
|
Role: "role",
|
||||||
|
Type: "type",
|
||||||
|
Level: "level",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,7 @@ func NewSecurityContextDeny(client client.Interface) admission.Interface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admit will deny any SecurityContext that defines options that were not previously available in the api.Container
|
// Admit will deny any pod that defines SELinuxOptions or RunAsUser.
|
||||||
// struct (Capabilities and Privileged)
|
|
||||||
func (p *plugin) Admit(a admission.Attributes) (err error) {
|
func (p *plugin) Admit(a admission.Attributes) (err error) {
|
||||||
if a.GetResource() != string(api.ResourcePods) {
|
if a.GetResource() != string(api.ResourcePods) {
|
||||||
return nil
|
return nil
|
||||||
@ -61,6 +60,14 @@ func (p *plugin) Admit(a admission.Attributes) (err error) {
|
|||||||
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
|
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SupplementalGroups != nil {
|
||||||
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("SecurityContext.SupplementalGroups is forbidden"))
|
||||||
}
|
}
|
||||||
|
if pod.Spec.SecurityContext != nil {
|
||||||
|
if pod.Spec.SecurityContext.SELinuxOptions != nil {
|
||||||
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.SELinuxOptions is forbidden"))
|
||||||
|
}
|
||||||
|
if pod.Spec.SecurityContext.RunAsUser != nil {
|
||||||
|
return apierrors.NewForbidden(a.GetResource(), pod.Name, fmt.Errorf("pod.Spec.SecurityContext.RunAsUser is forbidden"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range pod.Spec.Containers {
|
for _, v := range pod.Spec.Containers {
|
||||||
if v.SecurityContext != nil {
|
if v.SecurityContext != nil {
|
||||||
|
@ -29,37 +29,64 @@ func TestAdmission(t *testing.T) {
|
|||||||
|
|
||||||
var runAsUser int64 = 1
|
var runAsUser int64 = 1
|
||||||
priv := true
|
priv := true
|
||||||
successCases := map[string]*api.SecurityContext{
|
|
||||||
"no sc": nil,
|
|
||||||
"empty sc": {},
|
|
||||||
"valid sc": {Privileged: &priv, Capabilities: &api.Capabilities{}},
|
|
||||||
}
|
|
||||||
|
|
||||||
pod := api.Pod{
|
cases := []struct {
|
||||||
Spec: api.PodSpec{
|
name string
|
||||||
Containers: []api.Container{
|
sc *api.SecurityContext
|
||||||
{},
|
podSc *api.PodSecurityContext
|
||||||
},
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "unset",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty container.SecurityContext",
|
||||||
|
sc: &api.SecurityContext{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty pod.Spec.SecurityContext",
|
||||||
|
podSc: &api.PodSecurityContext{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid container.SecurityContext",
|
||||||
|
sc: &api.SecurityContext{Privileged: &priv, Capabilities: &api.Capabilities{}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "valid pod.Spec.SecurityContext",
|
||||||
|
podSc: &api.PodSecurityContext{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "container.SecurityContext.RunAsUser",
|
||||||
|
sc: &api.SecurityContext{RunAsUser: &runAsUser},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "container.SecurityContext.SELinuxOptions",
|
||||||
|
sc: &api.SecurityContext{SELinuxOptions: &api.SELinuxOptions{}},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod.Spec.SecurityContext.RunAsUser",
|
||||||
|
podSc: &api.PodSecurityContext{RunAsUser: &runAsUser},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pod.Spec.SecurityContext.SELinuxOptions",
|
||||||
|
podSc: &api.PodSecurityContext{SELinuxOptions: &api.SELinuxOptions{}},
|
||||||
|
expectError: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for k, v := range successCases {
|
|
||||||
pod.Spec.Containers[0].SecurityContext = v
|
|
||||||
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", "foo", "name", string(api.ResourcePods), "", "ignored", nil))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Unexpected error returned from admission handler for case %s", k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errorCases := map[string]*api.SecurityContext{
|
for _, tc := range cases {
|
||||||
"run as user": {RunAsUser: &runAsUser},
|
pod := pod()
|
||||||
"se linux optons": {SELinuxOptions: &api.SELinuxOptions{}},
|
pod.Spec.SecurityContext = tc.podSc
|
||||||
"mixed settings": {Privileged: &priv, RunAsUser: &runAsUser, SELinuxOptions: &api.SELinuxOptions{}},
|
pod.Spec.Containers[0].SecurityContext = tc.sc
|
||||||
}
|
|
||||||
for k, v := range errorCases {
|
err := handler.Admit(admission.NewAttributesRecord(pod, "Pod", "foo", "name", string(api.ResourcePods), "", "ignored", nil))
|
||||||
pod.Spec.Containers[0].SecurityContext = v
|
if err != nil && !tc.expectError {
|
||||||
err := handler.Admit(admission.NewAttributesRecord(&pod, "Pod", "foo", "name", string(api.ResourcePods), "", "ignored", nil))
|
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||||
if err == nil {
|
} else if err == nil && tc.expectError {
|
||||||
t.Errorf("Expected error returned from admission handler for case %s", k)
|
t.Errorf("%v: expected error", tc.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,3 +145,13 @@ func TestHandles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pod() *api.Pod {
|
||||||
|
return &api.Pod{
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -23,13 +23,15 @@ limitations under the License.
|
|||||||
package e2e
|
package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/util"
|
"k8s.io/kubernetes/pkg/util"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getSecurityContextTestPod() *api.Pod {
|
func scTestPod() *api.Pod {
|
||||||
podName := "security-context-" + string(util.NewUUID())
|
podName := "security-context-" + string(util.NewUUID())
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
@ -55,11 +57,35 @@ var _ = Describe("[Skipped] Security Context", func() {
|
|||||||
framework := NewFramework("security-context")
|
framework := NewFramework("security-context")
|
||||||
|
|
||||||
It("should support pod.Spec.SecurityContext.SupplementalGroups", func() {
|
It("should support pod.Spec.SecurityContext.SupplementalGroups", func() {
|
||||||
pod := getSecurityContextTestPod()
|
pod := scTestPod()
|
||||||
pod.Spec.Containers[0].Command = []string{"id", "-G"}
|
pod.Spec.Containers[0].Command = []string{"id", "-G"}
|
||||||
pod.Spec.SecurityContext.SupplementalGroups = []int64{1234, 5678}
|
pod.Spec.SecurityContext.SupplementalGroups = []int64{1234, 5678}
|
||||||
groups := []string{"1234", "5678"}
|
groups := []string{"1234", "5678"}
|
||||||
framework.TestContainerOutput("pod.Spec.SecurityContext.SupplementalGroups", pod, 0, groups)
|
framework.TestContainerOutput("pod.Spec.SecurityContext.SupplementalGroups", pod, 0, groups)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should support pod.Spec.SecurityContext.RunAsUser", func() {
|
||||||
|
pod := scTestPod()
|
||||||
|
var uid int64 = 1001
|
||||||
|
pod.Spec.SecurityContext.RunAsUser = &uid
|
||||||
|
pod.Spec.Containers[0].Command = []string{"sh", "-c", "id -u"}
|
||||||
|
|
||||||
|
framework.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
|
||||||
|
fmt.Sprintf("%v", uid),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should support container.SecurityContext.RunAsUser", func() {
|
||||||
|
pod := scTestPod()
|
||||||
|
var uid int64 = 1001
|
||||||
|
var overrideUid int64 = 1002
|
||||||
|
pod.Spec.SecurityContext.RunAsUser = &uid
|
||||||
|
pod.Spec.Containers[0].SecurityContext = new(api.SecurityContext)
|
||||||
|
pod.Spec.Containers[0].SecurityContext.RunAsUser = &overrideUid
|
||||||
|
pod.Spec.Containers[0].Command = []string{"sh", "-c", "id -u"}
|
||||||
|
|
||||||
|
framework.TestContainerOutput("pod.Spec.SecurityContext.RunAsUser", pod, 0, []string{
|
||||||
|
fmt.Sprintf("%v", overrideUid),
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user