In addition to authorization policies that control what a user
can do, OpenShift Container Platform provides security context constraints (SCC) that control the
actions that a pod can
perform and what it has the ability to access. Administrators can
manage SCCs using the CLI.
SCCs are objects that define a set of conditions that a pod must run with in
order to be accepted into the system. They allow an administrator to control the
following:
-
Running of
privileged
containers.
-
Capabilities a container can request to be added.
-
Use of host directories as volumes.
-
The SELinux context of the container.
-
The user ID.
-
The use of host namespaces and networking.
-
Allocating an FSGroup
that owns the pod’s volumes
-
Configuring allowable supplemental groups
-
Requiring the use of a read only root file system
-
Controlling the usage of volume types
-
Configuring allowable seccomp profiles
Seven SCCs are added to the cluster by default, and are viewable by cluster
administrators using the CLI:
$ oc get scc
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP PRIORITY READONLYROOTFS VOLUMES
anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny 10 false [configMap downwardAPI emptyDir persistentVolumeClaim secret]
hostaccess false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir hostPath persistentVolumeClaim secret]
hostmount-anyuid false [] MustRunAs RunAsAny RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir hostPath persistentVolumeClaim secret]
hostnetwork false [] MustRunAs MustRunAsRange MustRunAs MustRunAs <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret]
nonroot false [] MustRunAs MustRunAsNonRoot RunAsAny RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret]
privileged true [] RunAsAny RunAsAny RunAsAny RunAsAny <none> false [*]
restricted false [] MustRunAs MustRunAsRange MustRunAs RunAsAny <none> false [configMap downwardAPI emptyDir persistentVolumeClaim secret]
|
Do not modify the default SCCs. Customizing the default SCCs can lead to issues
when OpenShift Container Platform is upgraded. Instead,
create
new SCCs.
|
The definition for each SCC is also viewable by cluster administrators using the
CLI. For example, for the privileged SCC:
# oc export scc/privileged
allowHostDirVolumePlugin: true
allowHostIPC: true
allowHostNetwork: true
allowHostPID: true
allowHostPorts: true
allowPrivilegedContainer: true
allowedCapabilities: null
apiVersion: v1
defaultAddCapabilities: null
fsGroup: (1)
type: RunAsAny
groups: (2)
- system:cluster-admins
- system:nodes
kind: SecurityContextConstraints
metadata:
annotations:
kubernetes.io/description: 'privileged allows access to all privileged and host
features and the ability to run as any user, any group, any fsGroup, and with
any SELinux context. WARNING: this is the most relaxed SCC and should be used
only for cluster administration. Grant with caution.'
creationTimestamp: null
name: privileged
priority: null
readOnlyRootFilesystem: false
requiredDropCapabilities: null
runAsUser: (3)
type: RunAsAny
seLinuxContext: (4)
type: RunAsAny
supplementalGroups: (5)
type: RunAsAny
users: (6)
- system:serviceaccount:default:registry
- system:serviceaccount:default:router
- system:serviceaccount:openshift-infra:build-controller
volumes:
- '*'
1 |
The FSGroup strategy which dictates the allowable values for the
Security Context |
2 |
The groups that have access to this SCC |
3 |
The run as user strategy type which dictates the allowable values for the
Security Context |
4 |
The SELinux context strategy type which dictates the allowable values for
the Security Context |
5 |
The supplemental groups strategy which dictates the allowable supplemental
groups for the Security Context |
6 |
The users who have access to this SCC |
The users
and groups
fields on the SCC control which SCCs can be used.
By default, cluster administrators, nodes, and the build controller are granted
access to the privileged SCC. All authenticated users are granted access to the
restricted SCC.
-
allows privileged pods.
-
allows host directories to be mounted as volumes.
-
allows a pod to run as any user.
-
allows a pod to run with any MCS label.
-
allows a pod to use the host’s IPC namespace.
-
allows a pod to use the host’s PID namespace.
-
allows a pod to use any FSGroup.
-
allows a pod to use any supplemental group.
-
ensures pods cannot run as privileged.
-
ensures pods cannot use host directory volumes.
-
requires that a pod run as a user in a pre-allocated range of UIDs.
-
requires that a pod run with a pre-allocated MCS label.
-
allows a pod to use any FSGroup.
-
allows a pod to use any supplemental group.
|
For more information about each SCC, see the kubernetes.io/description
annotation available on the SCC.
|
SCCs are comprised of settings and strategies that control the security features
a pod has access to. These settings fall into three categories:
Controlled by a boolean |
Fields of this type default to the most restrictive value. For example,
AllowPrivilegedContainer is always set to false if unspecified. |
Controlled by an allowable set |
Fields of this type are checked against the set to ensure their value is
allowed. |
Controlled by a strategy |
Items that have a strategy to generate a value provide:
-
A mechanism to generate the value, and
-
A mechanism to ensure that a specified value falls into the set of allowable
values.
|
SCC Strategies
RunAsUser
-
MustRunAs - Requires a runAsUser
to be configured. Uses the configured
runAsUser
as the default. Validates against the configured runAsUser
.
-
MustRunAsRange - Requires minimum and maximum values to be defined if not
using pre-allocated values. Uses the minimum as the default. Validates against
the entire allowable range.
-
MustRunAsNonRoot - Requires that the pod be submitted with a non-zero
runAsUser
or have the USER
directive defined in the image. No default
provided.
-
RunAsAny - No default provided. Allows any runAsUser
to be specified.
SELinuxContext
-
MustRunAs - Requires seLinuxOptions
to be configured if not using
pre-allocated values. Uses seLinuxOptions
as the default. Validates against
seLinuxOptions
.
-
RunAsAny - No default provided. Allows any seLinuxOptions
to be
specified.
SupplementalGroups
-
MustRunAs - Requires at least one range to be specified if not using
pre-allocated values. Uses the minimum value of the first range as the default.
Validates against all ranges.
-
RunAsAny - No default provided. Allows any supplementalGroups
to be
specified.
FSGroup
-
MustRunAs - Requires at least one range to be specified if not using
pre-allocated values. Uses the minimum value of the first range as the default.
Validates against the first ID in the first range.
-
RunAsAny - No default provided. Allows any fsGroup
ID to be specified.
Controlling Volumes
The usage of specific volume types can be controlled by setting the volumes
field of the SCC. The allowable values of this field correspond to the volume
sources that are defined when creating a volume:
-
azureFile
-
flocker
-
flexVolume
-
hostPath
-
emptyDir
-
gcePersistentDisk
-
awsElasticBlockStore
-
gitRepo
-
secret
-
nfs
-
iscsi
-
glusterfs
-
persistentVolumeClaim
-
rbd
-
cinder
-
cephFS
-
downwardAPI
-
fc
-
configMap
-
*
The recommended minimum set of allowed volumes for new SCCs are configMap,
downwardAPI, emptyDir, persistentVolumeClaim, and secret.
|
* is a special value to allow the use of all volume types.
|
|
For backwards compatibility, the usage of allowHostDirVolumePlugin overrides
settings in the volumes field. For example, if allowHostDirVolumePlugin
is set to false but allowed in the volumes field, then the hostPath
value will be removed from volumes .
|
Seccomp
SeccompProfiles lists the allowed profiles that can be set for the pod or
container’s seccomp annotations. An unset (nil) or empty value means that no
profiles are specified by the pod or container. Use the wildcard *
to allow
all profiles. When used to generate a value for a pod, the first non-wildcard
profile is used as the default.
Admission
Admission control with SCCs allows for control over the creation of resources
based on the capabilities granted to a user.
In terms of the SCCs, this means that an admission controller can inspect the
user information made available in the context to retrieve an appropriate set of
SCCs. Doing so ensures the pod is authorized to make requests about its
operating environment or to generate a set of constraints to apply to the pod.
The set of SCCs that admission uses to authorize a pod are determined by the
user identity and groups that the user belongs to. Additionally, if the pod
specifies a service account, the set of allowable SCCs includes any constraints
accessible to the service account.
Admission uses the following approach to create the final security context for
the pod:
-
Retrieve all SCCs available for use.
-
Generate field values for security context settings that were not specified
on the request.
-
Validate the final settings against the available constraints.
If a matching set of constraints is found, then the pod is accepted. If the
request cannot be matched to an SCC, the pod is rejected.
A pod must validate every field against the SCC. The following are examples for
just two of the fields that must be validated:
|
These examples are in the context of a strategy using the preallocated values.
|
A FSGroup SCC Strategy of MustRunAs
If the pod defines a fsGroup
ID, then that ID must equal the default
fsGroup
ID. Otherwise, the pod is not validated by that SCC and the next SCC
is evaluated.
If the SecurityContextConstraints.fsGroup
field has value RunAsAny
and the pod specification omits the Pod.spec.securityContext.fsGroup
,
then this field is considered valid. Note that it is possible that during
validation, other SCC settings will reject other pod fields and thus cause the
pod to fail.
A SupplementalGroups SCC Strategy of MustRunAs
If the pod specification defines one or more supplementalGroups
IDs, then
the pod’s IDs must equal one of the IDs in the namespace’s
openshift.io/sa.scc.supplemental-groups annotation. Otherwise, the pod is not
validated by that SCC and the next SCC is evaluated.
If the SecurityContextConstraints.supplementalGroups
field has value RunAsAny
and the pod specification omits the Pod.spec.securityContext.supplementalGroups
,
then this field is considered valid. Note that it is possible that during
validation, other SCC settings will reject other pod fields and thus cause the
pod to fail.
SCC Prioritization
SCCs have a priority field that affects the ordering when attempting to
validate a request by the admission controller. A higher priority
SCC is moved to the front of the set when sorting. When the complete set
of available SCCs are determined they are ordered by:
-
Highest priority first, nil is considered a 0 priority
-
If priorities are equal, the SCCs will be sorted from most restrictive to least restrictive
-
If both priorities and restrictions are equal the SCCs will be sorted by name
By default, the anyuid SCC granted to cluster administrators is given priority
in their SCC set. This allows cluster administrators to run pods as any
user by without specifying a RunAsUser
on the pod’s SecurityContext
. The
administrator may still specify a RunAsUser
if they wish.
Understanding Pre-allocated Values and Security Context Constraints
The admission controller is aware of certain conditions in the security context
constraints that trigger it to look up pre-allocated values from a namespace and
populate the security context constraint before processing the pod. Each SCC
strategy is evaluated independently of other strategies, with the pre-allocated
values (where allowed) for each policy aggregated with pod specification values
to make the final values for the various IDs defined in the running pod.
The following SCCs cause the admission controller to look for pre-allocated
values when no ranges are defined in the pod specification:
-
A RunAsUser
strategy of MustRunAsRange with no minimum or maximum set.
Admission looks for the openshift.io/sa.scc.uid-range annotation to populate
range fields.
-
An SELinuxContext
strategy of MustRunAs with no level set. Admission
looks for the openshift.io/sa.scc.mcs annotation to populate the level.
-
A FSGroup
strategy of MustRunAs. Admission looks for the
openshift.io/sa.scc.supplemental-groups annotation.
-
A SupplementalGroups
strategy of MustRunAs. Admission looks for the
openshift.io/sa.scc.supplemental-groups annotation.
During the generation phase, the security context provider will default any
values that are not specifically set in the pod. Defaulting is based on the
strategy being used:
-
RunAsAny
and MustRunAsNonRoot
strategies do not provide default
values. Thus, if the pod needs a field defined (for example, a group ID), this
field must be defined inside the pod specification.
-
MustRunAs
(single value) strategies provide a default value which is
always used. As an example, for group IDs: even if the pod specification defines
its own ID value, the namespace’s default field will also appear in the pod’s
groups.
-
MustRunAsRange
and MustRunAs
(range-based) strategies provide the
minimum value of the range. As with a single value MustRunAs
strategy, the
namespace’s default value will appear in the running pod. If a range-based
strategy is configurable with multiple ranges, it will provide the minimum value
of the first configured range.
|
FSGroup and SupplementalGroups strategies fall back to the
openshift.io/sa.scc.uid-range annotation if the
openshift.io/sa.scc.supplemental-groups annotation does not exist on the
namespace. If neither exist, the SCC will fail to create.
|
|
By default, the annotation-based FSGroup strategy configures itself with a
single range based on the minimum value for the annotation. For example, if your
annotation reads 1/3, the FSGroup strategy will configure itself with a
minimum and maximum of 1. If you want to allow more groups to be accepted for
the FSGroup field, you can configure a custom SCC that does not use the
annotation.
|
|
The openshift.io/sa.scc.supplemental-groups annotation accepts a comma
delimited list of blocks in the format of <start>/<length or <start>-<end> .
The openshift.io/sa.scc.uid-range annotation accepts only a single block.
|