7.6. 管理 SELinux 配置集
创建和管理 SELinux 配置集并将其绑定到工作负载。
7.6.1. 创建 SELinux 配置集
使用 SelinuxProfile
对象来创建配置集。
SelinuxProfile
对象有几个功能,允许改进安全强化和可读性:
-
限制配置集从继承到当前命名空间或系统范围的配置集。因为系统中通常会安装很多配置集,但集群工作负载只能使用子集,所以可继承的系统配置集列在
spec.selinuxOptions.allowedSystemProfiles
的spod
实例中。 - 执行权限、类和标签的基本验证。
-
添加新的关键字
@self
,用于描述使用该策略的进程。这允许在工作负载和命名空间间轻松使用策略,因为策略的使用取决于名称和命名空间。 - 与直接在 SELinux CIL 语言中写入配置文件相比,添加了更高的安全强化和易读功能。
流程
通过创建以下
SelinuxProfile
对象来创建可与非特权工作负载一起使用的策略:apiVersion: security-profiles-operator.x-k8s.io/v1alpha2 kind: SelinuxProfile metadata: name: nginx-secure namespace: nginx-deploy spec: allow: '@self': tcp_socket: - listen http_cache_port_t: tcp_socket: - name_bind node_t: tcp_socket: - node_bind inherit: - kind: System name: container
运行以下命令,等待
selinuxd
安装策略:$ oc wait --for=condition=ready -n nginx-deploy selinuxprofile nginx-secure
输出示例
selinuxprofile.security-profiles-operator.x-k8s.io/nginx-secure condition met
策略被放入由 Security Profiles Operator 拥有的容器中的
emptyDir
中。策略以通用中间语言 (CIL) 格式保存,格式为/etc/selinux.d/<name>_<namespace>.cil
。运行以下命令来访问 pod:
$ oc -n openshift-security-profiles rsh -c selinuxd ds/spod
验证
运行以下命令,使用
cat
查看文件内容:$ cat /etc/selinux.d/nginx-secure_nginx-deploy.cil
输出示例
(block nginx-secure_nginx-deploy (blockinherit container) (allow process nginx-secure_nginx-deploy.process ( tcp_socket ( listen ))) (allow process http_cache_port_t ( tcp_socket ( name_bind ))) (allow process node_t ( tcp_socket ( node_bind ))) )
运行以下命令验证策略是否已安装:
$ semodule -l | grep nginx-secure
输出示例
nginx-secure_nginx-deploy
7.6.2. 将 SELinux 配置集应用到 pod
创建 pod 以应用其中一个创建的配置集。
对于 SELinux 配置集,必须标记命名空间以允许 特权 工作负载。
流程
运行以下命令,将
scc.podSecurityLabelSync=false
标签应用到nginx-deploy
命名空间:$ oc label ns nginx-deploy security.openshift.io/scc.podSecurityLabelSync=false
运行以下命令,将
privileged
标签应用到nginx-deploy
命名空间:$ oc label ns nginx-deploy --overwrite=true pod-security.kubernetes.io/enforce=privileged
运行以下命令来获取 SELinux 配置集使用字符串:
$ oc get selinuxprofile.security-profiles-operator.x-k8s.io/nginx-secure -n nginx-deploy -ojsonpath='{.status.usage}'
输出示例
nginx-secure_nginx-deploy.process%
在
.spec.containers[].securityContext.seLinuxOptions
属性中应用工作负载清单中的输出字符串:apiVersion: v1 kind: Pod metadata: name: nginx-secure namespace: nginx-deploy spec: containers: - image: nginxinc/nginx-unprivileged:1.21 name: nginx securityContext: seLinuxOptions: # NOTE: This uses an appropriate SELinux type type: nginx-secure_nginx-deploy.process
重要在创建工作负载前,SELinux
type
必须存在。
7.6.2.1. 应用 SELinux 日志策略
要记录策略违反或 AVC 拒绝,请将 SElinuxProfile
配置集设置为 permissive
。
此流程定义日志策略。它没有设置强制策略。
流程
在
SElinuxProfile
中添加permissive: true
:apiVersion: security-profiles-operator.x-k8s.io/v1alpha2 kind: SelinuxProfile metadata: name: nginx-secure namespace: nginx-deploy spec: permissive: true
7.6.2.2. 使用 ProfileBindings 将工作负载绑定到配置集
您可以使用 ProfileBinding
资源将安全配置集绑定到容器的 SecurityContext
。
流程
要将使用
quay.io/security-profiles-operator/test-nginx-unprivileged:1.21
镜像的 pod 绑定到示例SelinuxProfile
配置集,请在与 pod 和SelinuxProfile
对象相同的命名空间中创建一个ProfileBinding
对象:apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileBinding metadata: namespace: my-namespace name: nginx-binding spec: profileRef: kind: SelinuxProfile 1 name: profile 2 image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21
运行以下命令,使用
enable-binding=true
标记命名空间:$ oc label ns my-namespace spo.x-k8s.io/enable-binding=true
删除并重新创建 pod 以使用
ProfileBinding
对象:$ oc delete pods test-pod && oc create -f pod01.yaml
验证
运行以下命令确认 pod 会继承
ProfileBinding
:$ oc get pod test-pod -o jsonpath='{.spec.containers[*].securityContext.seLinuxOptions.type}'
输出示例
profile_nginx-binding.process
7.6.2.3. 复制控制器和 SecurityContextConstraints
当部署用于复制控制器(如部署或守护进程集)的 SELinux 策略时,请注意控制器生成的 Pod
对象不会与创建工作负载的用户身份运行。除非选择了 ServiceAccount
,否则 Pod 可能会恢复到使用不允许使用自定义安全策略的受限 SecurityContextConstraints
(SCC)。
流程
创建以下
RoleBinding
对象,以允许在nginx-secure
命名空间中使用 SELinux 策略:kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: spo-use-seccomp-scc namespace: nginx-secure subjects: - kind: ServiceAccount name: spo-deploy-test roleRef: kind: Role name: spo-use-seccomp-scc apiGroup: rbac.authorization.k8s.io
创建
Role
对象:apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: creationTimestamp: null name: spo-use-seccomp-scc namespace: nginx-secure rules: - apiGroups: - security.openshift.io resources: - securitycontextconstraints resourceNames: - privileged verbs: - use
创建
ServiceAccount
对象:apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: null name: spo-deploy-test namespace: nginx-secure
创建
Deployment
对象:apiVersion: apps/v1 kind: Deployment metadata: name: selinux-test namespace: nginx-secure metadata: labels: app: selinux-test spec: replicas: 3 selector: matchLabels: app: selinux-test template: metadata: labels: app: selinux-test spec: serviceAccountName: spo-deploy-test securityContext: seLinuxOptions: type: nginx-secure_nginx-secure.process 1 containers: - name: nginx-unpriv image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080
- 1
- 在创建 Deployment 前,必须存在
.seLinuxOptions.type
。
注意SELinux 类型没有在工作负载中指定,并由 SCC 处理。当 Pod 由部署和
ReplicaSet
创建时,pod 将以适当的配置集运行。
确保您的 SCC 仅可供正确的服务帐户使用。如需更多信息,请参阅附加资源。
7.6.3. 从工作负载记录配置集
Security Profiles Operator 可以使用 ProfileRecording
对象记录系统调用,从而更轻松地为应用程序创建基准配置集。
当使用日志增强器来记录 SELinux 配置集时,请验证日志增强功能是否已启用。如需更多信息,请参阅附加资源。
具有 privileged: true
安全上下文保留的容器可防止基于日志的记录。特权容器不受到 SELinux 策略的影响,基于日志的记录利用特殊的 SELinux 配置集记录事件。
流程
运行以下命令,使用
enable-recording=true
标记命名空间:$ oc label ns my-namespace spo.x-k8s.io/enable-recording=true
创建包含
recorder: logs
变量的ProfileRecording
对象:apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileRecording metadata: name: test-recording spec: kind: SelinuxProfile recorder: logs podSelector: matchLabels: app: my-app
创建一个工作负载来记录:
apiVersion: v1 kind: Pod metadata: name: my-pod labels: app: my-app spec: containers: - name: nginx image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080 - name: redis image: quay.io/security-profiles-operator/redis:6.2.1
输入以下命令确认 pod 处于
Running
状态:$ oc -n openshift-security-profiles get pods
输出示例
NAME READY STATUS RESTARTS AGE my-pod 2/2 Running 0 18s
确认增强器表示它接收这些容器的审计日志:
$ oc -n openshift-security-profiles logs --since=1m --selector name=spod -c log-enricher
输出示例
I0517 13:55:36.383187 348295 enricher.go:376] log-enricher "msg"="audit" "container"="redis" "namespace"="my-namespace" "node"="ip-10-0-189-53.us-east-2.compute.internal" "perm"="name_bind" "pod"="my-pod" "profile"="test-recording_redis_6kmrb_1684331729" "scontext"="system_u:system_r:selinuxrecording.process:s0:c4,c27" "tclass"="tcp_socket" "tcontext"="system_u:object_r:redis_port_t:s0" "timestamp"="1684331735.105:273965" "type"="SELinux"
验证
删除 pod:
$ oc -n openshift-security-profiles delete pod my-pod
确认 Security Profiles Operator 协调两个 SELinux 配置集:
$ oc get selinuxprofiles -n my-namespace
输出示例
NAME USAGE STATE test-recording-nginx test-recording-nginx_my-namespace.process Installed test-recording-redis test-recording-redis_my-namespace.process Installed
7.6.3.1. 每个容器配置集实例合并
默认情况下,每个容器实例记录都记录到单独的配置文件中。Security Profiles Operator 可将每个容器配置集合并到一个配置集中。当使用 ReplicaSet
或 Deployment
对象部署应用程序时,合并配置集很有用。
流程
编辑
ProfileRecording
对象使其包含mergeStrategy: containers
变量:apiVersion: security-profiles-operator.x-k8s.io/v1alpha1 kind: ProfileRecording metadata: # The name of the Recording is the same as the resulting SelinuxProfile CRD # after reconciliation. name: test-recording spec: kind: SelinuxProfile recorder: logs mergeStrategy: containers podSelector: matchLabels: app: sp-record
创建工作负载:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deploy spec: replicas: 3 selector: matchLabels: app: sp-record template: metadata: labels: app: sp-record spec: serviceAccountName: spo-record-sa containers: - name: nginx-record image: quay.io/security-profiles-operator/test-nginx-unprivileged:1.21 ports: - containerPort: 8080
要记录单个配置集,请运行以下命令删除部署:
$ oc delete deployment nginx-deploy
要合并配置集,请运行以下命令删除配置集记录:
$ oc delete profilerecording test-recording
要启动合并操作并生成结果配置集,请运行以下命令:
$ oc get selinuxprofiles -lspo.x-k8s.io/recording-id=test-recording
输出示例
NAME USAGE STATE test-recording-nginx-record test-recording-nginx-record_mytest1.process Installed
要查看任何容器使用的权限,请运行以下命令:
$ oc get selinuxprofiles test-recording-nginx-record -o yaml
7.6.3.2. 关于 SELinuxContext: RunAsAny
SELinux 策略的记录是通过一个 webhook 来实现的,它将一个特殊的 SELinux 类型注入被记录的 pod。SELinux 类型使 pod 以 permissive
模式运行,将所有 AVC 拒绝记录到 audit.log
中。默认情况下,不允许使用自定义 SELinux 策略运行工作负载,而是使用自动生成的类型。
要记录工作负载,工作负载必须使用具有使用 SCC 权限的服务帐户,允许 Webhook 注入 permissive SELinux 类型。privileged
SCC 包含 seLinuxContext: RunAsAny
。
另外,如果集群启用了 Pod Security Admission,则命名空间必须使用 pod-security.kubernetes.io/enforce: privileged
标记,因为只有 privileged
Pod Security Standard 允许使用自定义 SELinux 策略。