本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

使用 OCI 製品分發 seccomp、SELinux 和 AppArmor 的安全配置檔案

安全配置檔案運算元(SPO)使得在 Kubernetes 中管理 seccomp、SELinux 和 AppArmor 配置檔案比以往任何時候都更容易。它允許叢集管理員在預定義的自定義資源 YAML 中定義配置檔案,然後由 SPO 將其分發到整個叢集。安全配置檔案的修改和刪除也由該運算元以相同的方式管理,但這只是其能力的一小部分。

SPO 的另一個核心功能是能夠堆疊 seccomp 配置檔案。這意味著使用者可以在 YAML 規範中定義一個 `baseProfileName`,然後運算元會自動解析併合並系統呼叫規則。如果基礎配置檔案還有另一個 `baseProfileName`,那麼運算元將遞迴解析配置檔案,直至達到一定深度。一個常見的用例是為低階容器執行時(如 runccrun)定義基礎配置檔案,其中包含執行容器所必需的系統呼叫。另外,應用程式開發人員可以為其標準分發容器定義 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 製品

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)郵件列表直接與我們聯絡。