Docker 和 Kubernetes:root 與特權


隨意使用 root 和特權可能會帶來不必要的風險。本文展示了特權與 root 運行方式的不同之處以及特權的實際意義。

 

作者:Bryant Hagadorn

 

翻譯:Bach (K8sMeetup)

 

校對:星空下的文仔(才雲)

 

很多熟悉 Unix 系統的人(例如 macOS、Linux)都習慣於通過使用 sudo 隨意提升我們的特權給 root 用戶。在調試開發工具或嘗試編輯受保護目錄中的文件時,經常會發生這種情況,許多人在第一次嘗試之后,執行命令不成功,都會默認使用 sudo。

圖片

 

了解 Docker 安全性的基礎是了解實際的容器

Docker 提供了一個類似 --privileged flag,實際上這與我們隨意使用的 sudo 有很大不同,它可能會使應用程序面臨不必要的風險。本文將展示這與 root 運行方式有何不同(以及如何避免以 root 用戶身份運行),並介紹特權(privileged)的實際含義。

K8sMeetup

作為 root 運行

Docker 允許其在主機操作系統上隔離進程、功能和文件系統,並且實際上,大多數容器默認以 root 身份運行。為了示例,本文將使用 DockerHub 上的三個最受歡迎鏡像。

Postgres:

$ docker run -it postgres 

#whoami 

root 

#id -u 

0

Couchbase:

$ docker run -it couchbase sh 

#whoami 

root 

#id -u 

0

Alpine:

$ docker run -it alpine sh 

#whoami 

root 

#id -u 

0

我們可以看到,默認情況下,大多數鏡像都以 root 用戶身份運行。通常這可以簡化調試過程,尤其是在我們要 exec 到容器時。盡管 root 用戶的 Linux 功能非常有限,但最好還是避免以 root 用戶身份運行。

K8sMeetup

避免以 root 身份運行

盡管在容器內部以 root 身份運行是非常正常的事,但是如果我們想要強化容器,仍然需要避免這種情況。首先,違反了最小特權原則,其次,更嚴格地說,容器將成為運行 Docker 命令的同一用戶命名空間的一部分,並且如果容器能夠轉義,它將可以訪問 volume、socket 等資源。

有兩種避免以 root 用戶身份運行的方法。

通過調整 Dockerfile 以使用特定用戶:

// Dockerfile 

 

FROM microsoft/windowsservercore

# Create Windows user in the container

RUN net user /add patrick

# Set it for subsequent commands

USER patrick

在運行時重寫 User ID:

$ docker run -it --user 4000 postgres sh

# whoami

whoami: cannot find name for user ID 4000

# id -u

4000

K8sMeetup

關於特權

--privileged flag 將我們之前看到的用戶 ID 直接映射到主機的用戶 ID,並使其不受限制地訪問其選擇的任何系統調用。即使 root 在容器內部,在正常操作中,Docker 也會限制容器的 Linux 功能,例如限制 CAP_AUDIT_WRITE,它允許覆蓋內核的審計日志,這是容器化工作負載不太需要的功能。

實際上,特權應該只在我們真正需要的特定設置中使用,它可以使容器訪問主機(作為 root)幾乎可以執行所有操作。從本質上講,這是一個通行證,可以逃避容器包含的文件系統、進程、套接字和其他包含的項目。它有特定的用例,例如 Docker-in-Docker,其他 CI/CD 工具要求(從 Docker 容器內部需要 Docker 守護程序)以及需要極端網絡的地方。

下面看一個使用 Ubuntu 鏡像的示例(在 VM 內測試,這樣就不會破壞任何東西):

沒有特權:

# whoami

root # Notice here, we are still root!

# id -u

0

# hostname

382f1c400bd

# sysctl kernel.hostname=Attacker

sysctl: setting key "kernel.hostname": Read-only file system # Yet we can't do this

有特權:

$ docker run -it --privileged ubuntu sh

# whoami

root. # Root again

# id -u

0

# hostname

86c62e9bba5e

# sysctl kernel.hostname=Attacker

kernel.hostname = Attacker # Except now we are privileged

# hostname

Attacker 

Kubernetes 通過安全上下文提供相同的功能:

apiVersion: v1

kind: Pod

metadata:

  name: nginx

spec:

  containers:

  - name: nginx

    image: nginx

    securityContext:

      privileged: true

此外,Kubernetes 有一個稱為 PodSecurityPolicy 的強制機制,它是一個准入控制器(Kubernetes 在允許容器進入集群之前會對其進行檢查),這里強烈建議不允許使用特權 Pod:

apiVersion: policy/v1beta1

kind: PodSecurityPolicy

metadata:

  name: example

spec:

  privileged: false # Don't allow privileged pods!

K8sMeetup

總結

到此為止,我們了解了一些有關 root 和 --privileged flag 的信息,以及它們與“主機”操作系統的關系。無論我們是否想限制容器的安全性或調試問題,都需要確保應用程序安全。防御安全性需要深度防御(像洋蔥一層一層的保護)並減少攻擊面,通過不以 root 身份運行,不以特權身份運行以及添加 SecurityContext 和 PodSecurityPolicies 是實現更高容器安全性的四個主要方面。

原文鏈接:https://itnext.io/docker-and-kubernetes-root-vs-privileged-9d2a37453dec


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM