本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
使用 OCI 制品分发 seccomp、SELinux 和 AppArmor 的安全配置文件
安全配置文件算子(SPO)使得在 Kubernetes 中管理 seccomp、SELinux 和 AppArmor 配置文件比以往任何时候都更容易。它允许集群管理员在预定义的自定义资源 YAML 中定义配置文件,然后由 SPO 将其分发到整个集群。安全配置文件的修改和删除也由该算子以相同的方式管理,但这只是其能力的一小部分。
SPO 的另一个核心功能是能够堆叠 seccomp 配置文件。这意味着用户可以在 YAML 规范中定义一个 `baseProfileName`,然后算子会自动解析并合并系统调用规则。如果基础配置文件还有另一个 `baseProfileName`,那么算子将递归解析配置文件,直至达到一定深度。一个常见的用例是为低级容器运行时(如 runc 或 crun)定义基础配置文件,其中包含运行容器所必需的系统调用。另外,应用程序开发人员可以为其标准分发容器定义 seccomp 基础配置文件,并在其上堆叠专门用于应用程序逻辑的配置文件。这样,开发人员可以专注于维护更简单且仅限于应用程序逻辑的 seccomp 配置文件,而无需考虑整个基础架构设置。
但是如何维护这些基础配置文件呢?例如,一个运行时所需的系统调用数量在其发布周期内可能会发生变化,就像主应用程序一样。基础配置文件必须在同一个集群中可用,否则主 seccomp 配置文件将无法部署。这意味着它们与主应用程序配置文件紧密耦合,这与基础配置文件的初衷相悖。将它们作为普通文件分发和管理感觉像是一个额外的负担。
OCI 制品来拯救
Security Profiles Operator 的 v0.8.0 版本支持将基础配置文件作为 OCI 制品进行管理!可以将 OCI 制品想象成轻量级的容器镜像,它们以与镜像相同的方式将文件存储在层中,但没有要执行的进程。这些制品可用于在兼容的镜像仓库中存储安全配置文件,就像常规容器镜像一样。这意味着它们可以像常规容器镜像一样进行版本控制、命名空间划分和注解。
要了解其实际工作原理,可以在 seccomp 配置文件 CRD 中指定一个以 `oci://` 为前缀的 `baseProfileName`,例如
apiVersion: security-profiles-operator.x-k8s.io/v1beta1
kind: SeccompProfile
metadata:
name: test
spec:
defaultAction: SCMP_ACT_ERRNO
baseProfileName: oci://ghcr.io/security-profiles/runc:v1.1.5
syscalls:
- action: SCMP_ACT_ALLOW
names:
- uname
算子将负责使用 oras 拉取内容,并验证制品的 sigstore (cosign) 签名。如果制品未签名,SPO 将拒绝它们。最终生成的配置文件 `test` 将包含来自远程 `runc` 文件的所有基础系统调用,以及额外允许的 `uname` 系统调用。也可以通过其摘要(SHA256)引用基础配置文件,使要拉取的制品更加具体,例如通过引用 `oci://ghcr.io/security-profiles/runc@sha256:380…`。
算子内部会缓存拉取的制品长达 24 小时,最多可缓存 1000 个配置文件,这意味着如果缓存已满或算子守护进程重新启动,它们将在此时间段后刷新。
由于最终生成的系统调用对用户是隐藏的(我只在 SeccompProfile 中列出了 `baseProfileName`,而不是系统调用本身),我将额外用最终的 `syscalls` 来注解该 SeccompProfile。
这是我注解后的 SeccompProfile 的样子
> kubectl describe seccompprofile test
Name: test
Namespace: security-profiles-operator
Labels: spo.x-k8s.io/profile-id=SeccompProfile-test
Annotations: syscalls:
[{"names":["arch_prctl","brk","capget","capset","chdir","clone","close",...
API Version: security-profiles-operator.x-k8s.io/v1beta1
SPO 维护者在 “Security Profiles” GitHub 组织中提供了所有公开的基础配置文件。
管理 OCI 安全配置文件
好了,现在官方的 SPO 提供了一堆基础配置文件,但是我该如何定义自己的呢?嗯,首先我们必须选择一个可用的镜像仓库。有很多镜像仓库已经支持 OCI 制品
- CNCF 发行版
- Azure 容器注册表
- Amazon Elastic Container Registry
- Google 制品库
- GitHub Packages 容器注册表
- Docker Hub
- Zot 注册表
Security Profiles Operator 提供了一个名为 `spoc` 的新命令行界面,它是一个用于管理 OCI 配置文件以及执行本博文范围之外的各种其他操作的小工具。但是,`spoc push` 命令可用于将安全配置文件推送到镜像仓库
> export USERNAME=my-user
> export PASSWORD=my-pass
> spoc push -f ./examples/baseprofile-crun.yaml ghcr.io/security-profiles/crun:v1.8.3
16:35:43.899886 Pushing profile ./examples/baseprofile-crun.yaml to: ghcr.io/security-profiles/crun:v1.8.3
16:35:43.899939 Creating file store in: /tmp/push-3618165827
16:35:43.899947 Adding profile to store: ./examples/baseprofile-crun.yaml
16:35:43.900061 Packing files
16:35:43.900282 Verifying reference: ghcr.io/security-profiles/crun:v1.8.3
16:35:43.900310 Using tag: v1.8.3
16:35:43.900313 Creating repository for ghcr.io/security-profiles/crun
16:35:43.900319 Using username and password
16:35:43.900321 Copying profile to repository
16:35:46.976108 Signing container image
Generating ephemeral keys...
Retrieving signed certificate...
Note that there may be personally identifiable information associated with this signed artifact.
This may include the email address associated with the account with which you authenticate.
This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
By typing 'y', you attest that you grant (or have permission to grant) and agree to have this information stored permanently in transparency logs.
Your browser will now be opened to:
https://oauth2.sigstore.dev/auth/auth?access_type=…
Successfully verified SCT...
tlog entry created with index: 16520520
Pushing signature to: ghcr.io/security-profiles/crun
你可以看到该工具自动对制品进行签名,并将 `./examples/baseprofile-crun.yaml` 推送到镜像仓库,然后就可以直接在 SPO 中使用了。如果需要用户名和密码认证,可以使用 `--username`、`-u` 标志,或者导出 `USERNAME` 环境变量。要设置密码,请导出 `PASSWORD` 环境变量。
可以使用 `--annotations` / `-a` 标志多次以 `KEY:VALUE` 格式为安全配置文件添加自定义注解。这些注解目前没有效果,但未来算子的其他功能可能会依赖它们。
`spoc` 客户端也能够从兼容 OCI 制品的镜像仓库中拉取安全配置文件。为此,只需运行 `spoc pull`
> spoc pull ghcr.io/security-profiles/runc:v1.1.5
16:32:29.795597 Pulling profile from: ghcr.io/security-profiles/runc:v1.1.5
16:32:29.795610 Verifying signature
Verification for ghcr.io/security-profiles/runc:v1.1.5 --
The following checks were performed on each of these signatures:
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates
[{"critical":{"identity":{"docker-reference":"ghcr.io/security-profiles/runc"},…}}]
16:32:33.208695 Creating file store in: /tmp/pull-3199397214
16:32:33.208713 Verifying reference: ghcr.io/security-profiles/runc:v1.1.5
16:32:33.208718 Creating repository for ghcr.io/security-profiles/runc
16:32:33.208742 Using tag: v1.1.5
16:32:33.208743 Copying profile from repository
16:32:34.119652 Reading profile
16:32:34.119677 Trying to unmarshal seccomp profile
16:32:34.120114 Got SeccompProfile: runc-v1.1.5
16:32:34.120119 Saving profile in: /tmp/profile.yaml
现在可以在 `/tmp/profile.yaml` 或指定的输出文件 `--output-file` / `-o` 中找到该配置文件。我们可以像 `spoc push` 一样指定用户名和密码。
`spoc` 使得将安全配置文件作为 OCI 制品进行管理变得容易,然后这些制品可以直接被算子本身使用。
这就是我们关于 Security Profiles Operator 最新功能的简短旅程!如果您对更多内容感兴趣、想提供反馈或寻求帮助,请随时通过 Slack (#security-profiles-operator) 或邮件列表直接与我们联系。