本指南演示如何配置 Kyverno 以强制执行容器的安全上下文,确保容器以适当的安全设置和限制运行。
安全上下文强制执行涉及通过设置与安全相关的参数来控制容器的运行方式。正确配置安全上下文可以防止:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-run-as-nonroot
annotations:
policies.kyverno.io/title: Require Run As Non-Root User
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Containers must run as a non-root user. This policy ensures runAsNonRoot is set to true.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: run-as-non-root
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Running as root is not allowed. Either the field spec.securityContext.runAsNonRoot
must be set to true, or the field spec.containers[*].securityContext.runAsNonRoot
must be set to true.
anyPattern:
- spec:
securityContext:
runAsNonRoot: "true"
- spec:
containers:
- securityContext:
runAsNonRoot: "true"# 应用策略
kubectl apply -f require-run-as-nonroot.yaml
# 尝试创建明确以 root 身份运行的容器(应失败)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-root
spec:
containers:
- name: nginx
image: nginx
securityContext:
runAsUser: 0
runAsNonRoot: false
EOF
# 尝试创建以非 root 用户运行的容器(应成功)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-nonroot
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
containers:
- name: nginx
image: nginx
EOF
# 清理
kubectl delete pod test-root test-nonroot --ignore-not-found防止容器提升权限:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privilege-escalation
annotations:
policies.kyverno.io/title: Disallow Privilege Escalation
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Privilege escalation, such as via set-user-ID or set-group-ID file mode, should not be allowed.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: privilege-escalation
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Privilege escalation is disallowed. The fields
spec.containers[*].securityContext.allowPrivilegeEscalation,
spec.initContainers[*].securityContext.allowPrivilegeEscalation,
and spec.ephemeralContainers[*].securityContext.allowPrivilegeEscalation
must be set to false.
pattern:
spec:
=(ephemeralContainers):
- securityContext:
allowPrivilegeEscalation: "false"
=(initContainers):
- securityContext:
allowPrivilegeEscalation: "false"
containers:
- securityContext:
allowPrivilegeEscalation: "false"确保容器以特定用户 ID 范围运行:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-user-id-range
annotations:
policies.kyverno.io/title: Require User ID Range
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Containers must run with a specific user ID range to prevent privilege escalation.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: user-id-range
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Containers must run with user ID between 1000 and 65535.
deny:
conditions:
any:
# 检查 Pod 级别的安全上下文
- key: "{{ request.object.spec.securityContext.runAsUser || 0 }}"
operator: LessThan
value: 1000
- key: "{{ request.object.spec.securityContext.runAsUser || 0 }}"
operator: GreaterThan
value: 65535
# 检查容器级别的安全上下文
- key: "{{ request.object.spec.containers[?securityContext.runAsUser && (securityContext.runAsUser < `1000` || securityContext.runAsUser > `65535`)] | length(@) }}"
operator: GreaterThan
value: 0确保容器以非 root 组 ID 运行:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-non-root-groups
annotations:
policies.kyverno.io/title: Require Non-Root Groups
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Containers should be required to run with a non-root group ID or supplemental groups.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: non-root-groups
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Containers must run with non-root group ID. Either spec.securityContext.runAsGroup
or spec.containers[*].securityContext.runAsGroup must be set and not be 0.
deny:
conditions:
any:
# 检查 Pod 级别的 runAsGroup 是否为 0
- key: "{{ request.object.spec.securityContext.runAsGroup || 0 }}"
operator: Equals
value: 0
# 检查是否有容器的 runAsGroup 设置为 0
- key: "{{ request.object.spec.containers[?securityContext.runAsGroup == `0`] | length(@) }}"
operator: GreaterThan
value: 0强制使用安全的 seccomp 配置:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-seccomp-strict
annotations:
policies.kyverno.io/title: Restrict Seccomp (Strict)
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Seccomp profile must be explicitly set to one of the allowed values.
Both the Unconfined profile and the absence of a profile are prohibited.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: seccomp-strict
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Use of custom Seccomp profiles is disallowed. The field
spec.securityContext.seccompProfile.type must be set to RuntimeDefault or Localhost.
anyPattern:
- spec:
securityContext:
seccompProfile:
type: RuntimeDefault
- spec:
securityContext:
seccompProfile:
type: Localhost
- spec:
containers:
- securityContext:
seccompProfile:
type: RuntimeDefault
- spec:
containers:
- securityContext:
seccompProfile:
type: Localhost确保容器丢弃所有能力:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-drop-all-capabilities
annotations:
policies.kyverno.io/title: Require Drop ALL Capabilities
policies.kyverno.io/category: Pod Security Standards (Restricted)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
Containers must drop all capabilities and only add back those that are specifically needed.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-drop-all
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
Containers must drop ALL capabilities.
foreach:
- list: request.object.spec.[ephemeralContainers, initContainers, containers][]
deny:
conditions:
all:
- key: ALL
operator: AnyNotIn
value: "{{ element.securityContext.capabilities.drop || `[]` }}"控制 AppArmor 配置的使用:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-apparmor-profiles
annotations:
policies.kyverno.io/title: Restrict AppArmor Profiles
policies.kyverno.io/category: Pod Security Standards (Baseline)
policies.kyverno.io/severity: medium
policies.kyverno.io/subject: Pod
policies.kyverno.io/description: >-
On supported hosts, the runtime/default AppArmor profile is applied by default.
The baseline policy should prevent overriding or disabling the default AppArmor profile.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: apparmor-profiles
match:
any:
- resources:
kinds:
- Pod
validate:
message: >-
AppArmor profile must be set to runtime/default or a custom profile.
Unconfined profiles are not allowed.
pattern:
metadata:
=(annotations):
=(container.apparmor.security.beta.kubernetes.io/*): "!unconfined"不同环境的安全需求不同:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: environment-security-contexts
spec:
validationFailureAction: Enforce
background: true
rules:
# 生产环境:严格的安全上下文
- name: production-strict-security
match:
any:
- resources:
kinds:
- Pod
namespaces:
- production
- prod-*
validate:
message: "Production environments require strict security contexts"
pattern:
spec:
securityContext:
runAsNonRoot: "true"
runAsUser: "1000-65535"
runAsGroup: "1000-65535"
seccompProfile:
type: RuntimeDefault
containers:
- securityContext:
allowPrivilegeEscalation: "false"
readOnlyRootFilesystem: "true"
runAsNonRoot: "true"
capabilities:
drop:
- ALL
# 开发环境:基本安全要求
- name: development-basic-security
match:
any:
- resources:
kinds:
- Pod
namespaces:
- development
- dev-*
- staging
validate:
message: "Development environments require basic security contexts"
pattern:
spec:
containers:
- securityContext:
allowPrivilegeEscalation: "false"
runAsNonRoot: "true"不同应用类型的安全上下文不同:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: application-security-contexts
spec:
validationFailureAction: Enforce
background: true
rules:
# 数据库应用:特定用户/组 ID
- name: database-security-context
match:
any:
- resources:
kinds:
- Pod
selector:
matchLabels:
app.type: database
validate:
message: "Database applications must use specific security contexts"
pattern:
spec:
securityContext:
runAsUser: "999"
runAsGroup: "999"
fsGroup: "999"
containers:
- securityContext:
runAsNonRoot: "true"
readOnlyRootFilesystem: "true"
# Web 应用:标准安全上下文
- name: web-app-security-context
match:
any:
- resources:
kinds:
- Pod
selector:
matchLabels:
app.type: web
validate:
message: "Web applications must use standard security contexts"
pattern:
spec:
containers:
- securityContext:
runAsNonRoot: "true"
allowPrivilegeEscalation: "false"
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE实现渐进式的安全上下文要求:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: graduated-security-contexts
spec:
validationFailureAction: Enforce
background: true
rules:
# 级别 1:基础安全(所有命名空间)
- name: basic-security-level
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- resources:
namespaces:
- kube-system
- kyverno
validate:
message: "All containers must have basic security contexts"
pattern:
spec:
containers:
- securityContext:
allowPrivilegeEscalation: "false"
# 级别 2:增强安全(敏感命名空间)
- name: enhanced-security-level
match:
any:
- resources:
kinds:
- Pod
namespaces:
- finance-*
- hr-*
- security-*
validate:
message: "Sensitive namespaces require enhanced security contexts"
pattern:
spec:
securityContext:
runAsNonRoot: "true"
containers:
- securityContext:
readOnlyRootFilesystem: "true"
capabilities:
drop:
- ALL
# 级别 3:最高安全(关键命名空间)
- name: maximum-security-level
match:
any:
- resources:
kinds:
- Pod
namespaces:
- critical-*
- payment-*
validate:
message: "Critical namespaces require maximum security contexts"
pattern:
spec:
securityContext:
runAsNonRoot: "true"
runAsUser: "1000-1999"
runAsGroup: "1000-1999"
seccompProfile:
type: RuntimeDefault
containers:
- securityContext:
allowPrivilegeEscalation: "false"
readOnlyRootFilesystem: "true"
runAsNonRoot: "true"
capabilities:
drop:
- ALLcat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-root-user
spec:
containers:
- name: test
image: nginx
securityContext:
runAsUser: 0
EOFcat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-privilege-escalation
spec:
containers:
- name: test
image: nginx
securityContext:
allowPrivilegeEscalation: true
EOFcat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-missing-drop-all
spec:
containers:
- name: test
image: nginx
securityContext:
capabilities:
add:
- NET_ADMIN
EOFcat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-secure-context
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: test
image: nginx
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
EOF