本文已發布超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
在邊緣環境使用 Seccomp 設定檔的樂趣
Security Profiles Operator (SPO) 是一個功能豐富的 Kubernetes operator,旨在讓管理 seccomp、SELinux 和 AppArmor 設定檔比以往更輕鬆。從頭開始記錄這些設定檔是此 operator 的主要功能之一,通常涉及整合到大型 CI/CD 系統中。能夠在邊緣案例中測試 operator 的記錄功能是 SPO 最近的開發重點之一,並且讓嘗試使用 seccomp 設定檔變得非常容易。
使用 spoc record
記錄 seccomp 設定檔
Security Profiles Operator 的 v0.8.0 版本發布了一個名為 spoc
的新命令列介面,這是一個用於記錄和重播 seccomp 設定檔的小型輔助工具,以及本文範圍之外的各種其他功能。
記錄 seccomp 設定檔需要執行二進制檔案,這可以是一個簡單的 golang 應用程式,它只調用 uname(2)
package main
import (
"syscall"
)
func main() {
utsname := syscall.Utsname{}
if err := syscall.Uname(&utsname); err != nil {
panic(err)
}
}
從該程式碼建置二進制檔案可以透過以下方式完成
> go build -o main main.go
> ldd ./main
not a dynamic executable
現在可以從 GitHub 下載 spoc
的最新二進制檔案,並在 Linux 上使用它運行應用程式
> sudo ./spoc record ./main
10:08:25.591945 Loading bpf module
10:08:25.591958 Using system btf file
libbpf: loading object 'recorder.bpf.o' from buffer
…
libbpf: prog 'sys_enter': relo #3: patched insn #22 (ALU/ALU64) imm 16 -> 16
10:08:25.610767 Getting bpf program sys_enter
10:08:25.610778 Attaching bpf tracepoint
10:08:25.611574 Getting syscalls map
10:08:25.611582 Getting pid_mntns map
10:08:25.613097 Module successfully loaded
10:08:25.613311 Processing events
10:08:25.613693 Running command with PID: 336007
10:08:25.613835 Received event: pid: 336007, mntns: 4026531841
10:08:25.613951 No container ID found for PID (pid=336007, mntns=4026531841, err=unable to find container ID in cgroup path)
10:08:25.614856 Processing recorded data
10:08:25.614975 Found process mntns 4026531841 in bpf map
10:08:25.615110 Got syscalls: read, close, mmap, rt_sigaction, rt_sigprocmask, madvise, nanosleep, clone, uname, sigaltstack, arch_prctl, gettid, futex, sched_getaffinity, exit_group, openat
10:08:25.615195 Adding base syscalls: access, brk, capget, capset, chdir, chmod, chown, close_range, dup2, dup3, epoll_create1, epoll_ctl, epoll_pwait, execve, faccessat2, fchdir, fchmodat, fchown, fchownat, fcntl, fstat, fstatfs, getdents64, getegid, geteuid, getgid, getpid, getppid, getuid, ioctl, keyctl, lseek, mkdirat, mknodat, mount, mprotect, munmap, newfstatat, openat2, pipe2, pivot_root, prctl, pread64, pselect6, readlink, readlinkat, rt_sigreturn, sched_yield, seccomp, set_robust_list, set_tid_address, setgid, setgroups, sethostname, setns, setresgid, setresuid, setsid, setuid, statfs, statx, symlinkat, tgkill, umask, umount2, unlinkat, unshare, write
10:08:25.616293 Wrote seccomp profile to: /tmp/profile.yaml
10:08:25.616298 Unloading bpf module
我必須以 root 身份執行 spoc
,因為它將透過重用 Security Profiles Operator 本身相同的程式碼部分,在內部運行 ebpf 程式。我可以看到 bpf 模組已成功載入,並且 spoc
已將所需的追蹤點附加到它。然後,它將透過使用其 mount namespace 來追蹤主要應用程式,並處理記錄的系統調用數據。ebpf 程式的本質是它們可以看到 Kernel 的整個上下文,這意味著 spoc
會追蹤系統的所有系統調用,但不會干擾它們的執行。
日誌表明 spoc
找到了系統調用 read
、close
、mmap
等,包括 uname
。除了 uname
之外的所有其他系統調用都來自 golang 運行時及其垃圾回收,這已經為像我們演示中的基本應用程式增加了開銷。我也從日誌行 Adding base syscalls: …
中看到 spoc
向結果設定檔添加了一堆基本系統調用。OCI 運行時(例如 runc 或 crun)使用它們以便能夠運行容器。這意味著 spoc
可用於記錄 seccomp 設定檔,然後可以直接容器化。可以在 spoc
中使用 --no-base-syscalls
/-n
禁用此行為,或透過 --base-syscalls
/-b
命令列標誌進行自訂。這在使用了 crun 和 runc 以外的不同 OCI 運行時,或者我只想記錄應用程式的 seccomp 設定檔並將其與另一個 基本設定檔 堆疊時很有用。
結果設定檔現在可在 /tmp/profile.yaml
中找到,但可以使用 --output-file value
/-o
標誌更改預設位置
> cat /tmp/profile.yaml
apiVersion: security-profiles-operator.x-k8s.io/v1beta1
kind: SeccompProfile
metadata:
creationTimestamp: null
name: main
spec:
architectures:
- SCMP_ARCH_X86_64
defaultAction: SCMP_ACT_ERRNO
syscalls:
- action: SCMP_ACT_ALLOW
names:
- access
- arch_prctl
- brk
- …
- uname
- …
status: {}
seccomp 設定檔自訂資源定義 (CRD) 可以直接與 Security Profiles Operator 一起使用,以便在 Kubernetes 中進行管理。spoc
也能夠透過使用 --type
/-t
raw-seccomp
標誌來產生原始 seccomp 設定檔(作為 JSON)。
> sudo ./spoc record --type raw-seccomp ./main
…
52.628827 Wrote seccomp profile to: /tmp/profile.json
> jq . /tmp/profile.json
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": ["access", "…", "write"],
"action": "SCMP_ACT_ALLOW"
}
]
}
實用程式 spoc record
允許我們直接從任何能夠在 Kernel 中運行 ebpf 程式碼的 Linux 系統中的二進制調用記錄複雜的 seccomp 設定檔。但它可以做更多的事情:修改 seccomp 設定檔,然後使用 spoc run
進行測試如何?
使用 spoc run
運行 seccomp 設定檔
spoc
也能夠運行應用了 seccomp 設定檔的二進制檔案,從而可以輕鬆測試對其進行的任何修改。為此,只需運行
> sudo ./spoc run ./main
10:29:58.153263 Reading file /tmp/profile.yaml
10:29:58.153311 Assuming YAML profile
10:29:58.154138 Setting up seccomp
10:29:58.154178 Load seccomp profile
10:29:58.154189 Starting audit log enricher
10:29:58.154224 Enricher reading from file /var/log/audit/audit.log
10:29:58.155356 Running command with PID: 437880
>
看起來應用程式已成功退出,這是預期的,因為我尚未修改先前記錄的設定檔。我也可以使用 --profile
/-p
標誌為設定檔指定自訂位置,但這不是必需的,因為我沒有修改記錄中的預設輸出位置。spoc
將自動確定它是原始 (JSON) 還是基於 CRD (YAML) 的 seccomp 設定檔,然後將其應用於進程。
Security Profiles Operator 支援 日誌豐富器功能,該功能透過解析稽核日誌來提供額外的 seccomp 相關資訊。在調試 seccomp 設定檔時,spoc run
以相同的方式使用豐富器,為最終用戶提供更多數據。
現在我必須修改設定檔才能在輸出中看到任何有價值的東西。例如,我可以刪除允許的 uname
系統調用
> jq 'del(.syscalls[0].names[] | select(. == "uname"))' /tmp/profile.json > /tmp/no-uname-profile.json
然後嘗試使用新設定檔 /tmp/no-uname-profile.json
再次運行它
> sudo ./spoc run -p /tmp/no-uname-profile.json ./main
10:39:12.707798 Reading file /tmp/no-uname-profile.json
10:39:12.707892 Setting up seccomp
10:39:12.707920 Load seccomp profile
10:39:12.707982 Starting audit log enricher
10:39:12.707998 Enricher reading from file /var/log/audit/audit.log
10:39:12.709164 Running command with PID: 480512
panic: operation not permitted
goroutine 1 [running]:
main.main()
/path/to/main.go:10 +0x85
10:39:12.713035 Unable to run: launch runner: wait for command: exit status 2
好的,這是預期的!應用的 seccomp 設定檔阻止了 uname
系統調用,這導致了「operation not permitted」錯誤。此錯誤非常通用,並且沒有提供任何關於 seccomp 阻止了什麼的提示。通常很難預測如果 seccomp 禁止單個系統調用,應用程式的行為方式。應用程式可能會像我們簡單的演示中那樣終止,但也可能導致奇怪的錯誤行為,並且應用程式根本不會停止。
如果我現在像這樣將設定檔的預設 seccomp 操作從 SCMP_ACT_ERRNO
更改為 SCMP_ACT_LOG
> jq '.defaultAction = "SCMP_ACT_LOG"' /tmp/no-uname-profile.json > /tmp/no-uname-profile-log.json
然後,日誌豐富器將提示我們,在使用 spoc run
時,uname
系統調用被阻止了
> sudo ./spoc run -p /tmp/no-uname-profile-log.json ./main
10:48:07.470126 Reading file /tmp/no-uname-profile-log.json
10:48:07.470234 Setting up seccomp
10:48:07.470245 Load seccomp profile
10:48:07.470302 Starting audit log enricher
10:48:07.470339 Enricher reading from file /var/log/audit/audit.log
10:48:07.470889 Running command with PID: 522268
10:48:07.472007 Seccomp: uname (63)
此應用程式將不再終止,但 seccomp 將把此行為記錄到 /var/log/audit/audit.log
,而 spoc
將解析這些資料,以將其直接關聯到我們的程式。將日誌訊息產生到稽核子系統會帶來大量的效能開銷,在生產系統中應謹慎處理。在生產環境中以稽核模式運行不受信任的應用程式時,也存在安全風險。
此示範應讓您瞭解如何使用我們由 Security Profiles Operator 功能驅動的閃亮新助手工具來除錯 seccomp 設定檔問題。spoc
是一個彈性且可攜式的二進制檔案,適用於資源受限的邊緣情況,甚至 Kubernetes 本身可能無法以其完整功能使用的情況。
感謝您閱讀這篇部落格文章!如果您對更多內容感興趣、提供意見回饋或尋求協助,請隨時透過 Slack (#security-profiles-operator) 或 郵寄清單 直接與我們聯繫。