

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# Amazon ECS 任務與容器安全最佳實務
<a name="security-tasks-containers"></a>

您應該將容器映像視為對抗攻擊的第一道防線。不安全、構造不良的映像可允許攻擊者逸出容器的邊界並取得主機的存取。您應該執行以下操作以減輕發生這種情況的風險。

建議您在設定任務和容器時進行下列操作。

## 建立最小或使用 distroless 映像
<a name="security-tasks-containers-recommendations-images"></a>

首先從容器映像中刪除所有無關的二進位檔案。如果您使用 Amazon ECR Public Gallery 中不熟悉的映像，請檢查映像以參考每個容器層的內容。您可以使用 [Dive](https://github.com/wagoodman/dive) 之類的應用程式來執行此操作。

或者，您可以使用僅包含應用程式及其執行期相依項的 **distroless** 映像。此映像不包含套件管理工具或 Shell。Distroless 映像可改善「掃描器的訊號雜訊，並減少您所需要確定來源的負擔」。如需詳細資訊，請參閱 distroless 上的 [GitHub](https://github.com/GoogleContainerTools/distroless) 文件。

Docker 具有一種機制，用於從稱為 **scratch** 的保留最小映像建立映像。如需詳細資訊，請參閱 Docker 文件中的[使用 **scratch** 建立簡單的父映像](https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch)。使用 Go 等語言，您可以建立一個靜態連結的二進位檔案並在 Dockerfile 中作為參考。以下範例展示如何完成這項操作。

```
############################
# STEP 1 build executable binary
############################
FROM golang:alpine AS builder
# Install git.
# Git is required for fetching the dependencies.
RUN apk update && apk add --no-cache git
WORKDIR $GOPATH/src/mypackage/myapp/
COPY . .
# Fetch dependencies.
# Using go get.
RUN go get -d -v
# Build the binary.
RUN go build -o /go/bin/hello
############################
# STEP 2 build a small image
############################
FROM scratch
# Copy our static executable.
COPY --from=builder /go/bin/hello /go/bin/hello
# Run the hello binary.
ENTRYPOINT ["/go/bin/hello"]
This creates a container image that consists of your application and nothing else, making it extremely secure.
```

上一個範例也是多階段建置的範例。從安全的角度來看，這些類型的建置很有吸引力，因為您可以使用這些建置來最小化推送至容器登錄檔的最終映像大小。沒有構建工具和其他無關二進位檔案的容器映像透過減少映像的受攻擊面來改善您的安全狀態。如需有關多階段建置的詳細資訊，請參閱 Docker 文件中的 [Multi-stage builds](https://docs.docker.com/build/building/multi-stage/)。

## 掃描您的映像是否有漏洞
<a name="security-tasks-containers-recommendations-vulnerability-scanning"></a>

容器映像檔與虛擬機器對應部分類似，容器映像檔可以包含具有漏洞的二進位檔案和應用程式程式庫，或隨著時間的推移而產生漏洞。防止漏洞攻擊的最佳方法是使用映像掃描器定期掃描映像。

Amazon ECR 提供兩種使用通用漏洞披露 (CVE) 資料庫的基本掃描版本：
+ **AWS 原生基本掃描** – AWS 使用原生技術，現在為 GA 且建議使用。這項改進的基本掃描機制旨在為客戶提供更精準的掃描結果，跨多種主流作業系統強化漏洞偵測能力。這有助於客戶進一步提升容器映像的安全性。依預設，所有新客戶登錄檔都會選擇加入此改進版本。
+ **Clair 基本掃描** – 舊版基本掃描採用開放原始碼 Clair 專案技術，現已棄用。如需 Clair 的詳細資訊，請參閱 GitHub 上的 [Clair](https://github.com/quay/clair)。

[AWS 依](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services/)區域列出的所有區域都支援 AWS 原生和 Clair 基本掃描，但 2024 年 9 月之後新增的區域除外。由於 Clair 支援已被棄用，新增區域將不再支援 Clair，且自 2025 年 10 月 1 日起，所有區域都將停止支援 Clair。

若有，Amazon ECR 會使用上游分發來源提供的 CVE 嚴重性程度。若無，則會使用通用漏洞評分系統 (CVSS) 分數。CVSS 分數可用於取得 NVD 漏洞嚴重性等級。如需詳細資訊，請參閱 [NVD 漏洞嚴重性等級](https://nvd.nist.gov/vuln-metrics/cvss)。

您也可以從 Amazon ECR 主控台內或呼叫 [DescribeImageScanFindings](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeImageScanFindings.html) API 來查看掃描的結果。應刪除或重建具有 `HIGH` 或 `CRITICAL` 漏洞的映像。如果已部署的映像出現漏洞，則應盡快更換。

[Docker Desktop Edge](https://www.docker.com/products/docker-desktop/) 2.3.6.0 以上版本可以[掃描](https://docs.docker.com/engine/scan/)本機映像。掃描由 [Snyk](https://snyk.io/) 提供支援，其為一種應用程式安全服務。當發現漏洞時，Snyk 會識別 Dockerfile 中具漏洞的圖層和相依項。也建議使用安全的替代方法，例如使用具有較少漏洞的更細微基礎映像，或將特定套件升級至較新版本。透過使用 Docker 掃描，開發人員可以在將映像推送至登錄檔之前解決潛在的安全問題。
+ [使用 Amazon ECR 自動化映像合規，並 AWS Security Hub CSPM](https://aws.amazon.com/blogs/containers/automating-image-compliance-for-amazon-eks-using-amazon-elastic-container-registry-and-aws-security-hub/)說明如何從 AWS Security Hub CSPM Amazon ECR 中顯示漏洞資訊，以及透過封鎖易受攻擊映像的存取來自動修補。

## 從映像移除特殊權限
<a name="security-tasks-containers-recommendations-defang-images"></a>

存取權標記 `setuid` 並 `setgid` 允許執行具有擁有者許可或可執行檔群組的可執行檔。從映像中移除具有這些存取權的所有二進位檔案，因為這些二進位檔案可用來提升權限。考慮刪除所有可用於惡意目的的 Shell 和共用程序，如 `nc` 和 `curl` 。您可以使用以下命令找到具有 `setuid` 和 `setgid` 存取權的檔案。

```
find / -perm /6000 -type f -exec ls -ld {} \;
```

若要從這些檔案中刪除這些特殊權限，請將以下指令新增至容器映像中。

```
RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} \; || true
```

## 建立一組精選映像
<a name="security-tasks-containers-recommendations-curated-images"></a>

為組織中的不同應用程式堆疊建立一組經過審查的映像，而不是允許開發人員建立自己的映像。透過執行此動作，開發人員可以放棄學習如何編寫 Dockerfile 並專注於編寫程式碼。當變更合併至您的程式碼庫中時，CI/CD 管道可以自動編譯資產，然後將其儲存在成品儲存庫中。最後，將成品複製到適當的映像中，然後再將其推送至 Docker 登錄檔 (例如 Amazon ECR)。至少您應該建立一組基礎映像，開發人員可以從中建立自己的 Dockerfile。您應避免從 Docker Hub 推送映像。您不一定知道影像中的內容，而且影像可能會有漏洞。

## 掃描應用程式套件和程式庫是否有漏洞
<a name="security-tasks-containers-recommendations-vulnerability-scanning"></a>

現在，使用開放原始碼程式庫很普遍。如同使用作業系統和 OS 套件，這些程式庫可能存在漏洞。作為開發生命週期的一部分，這些程式庫應在發現嚴重漏洞時進行掃描和更新。

Docker Desktop 使用 Snyk 執行本機掃描。也可以用來尋找開放原始碼程式庫中的漏洞和潛在的授權問題。可以直接整合至開發人員工作流程中，讓您能夠減輕開放原始碼程式庫所帶來的風險。如需詳細資訊，請參閱下列主題：
+ [開放原始碼應用程式安全工具](https://owasp.org/www-community/Free_for_Open_Source_Application_Security_Tools)包括用於偵測應用程式漏洞的工具清單。

## 執行靜態程式碼分析
<a name="security-tasks-containers-recommendations-static-code-analysis"></a>

建置容器映像之前，您應該先執行靜態程式碼分析。此分析會針對您的原始程式碼執行，並用來識別惡意行為 (例如故障注入) 可能利用的編碼錯誤和程式碼。您可以使用 Amazon Inspector。如需詳細資訊，請參閱 *Amazon Inspector User Guide* 中的 [Scanning Amazon ECR container images with Amazon Inspector](https://docs.aws.amazon.com/inspector/latest/user/scanning-ecr.html)。

## 以非根使用者身分執行容器
<a name="security-tasks-containers-recommendations-run-non-root-users"></a>

您應以非根使用者身分執行容器。在預設情況下，容器以 `root` 使用者身份執行，除非在 Dockerfile 中包含該 `USER` 指令。Docker 指派的預設 Linux 功能會限制可做為 `root` 執行的動作，但僅限於稍微限制。例如，做為 `root` 執行的容器仍不允許存取裝置。

作為 CI/CD 管道的一部分，您應該檢查 Docerfile 來查找 `USER` 指令，如果缺少該指令，則建置失敗。如需詳細資訊，請參閱下列主題：
+ [Dockerfile-lint](https://github.com/projectatomic/dockerfile_lint) 是來自 RedHat 的開放原始碼工具，可用於檢查檔案是否符合最佳實務。
+ [Hadolint](https://github.com/hadolint/hadolint) 是建置符合最佳實務 Docker 映像檔的另一種工具。

## 使用唯讀的根檔案系統
<a name="security-tasks-containers-recommendations-read-only-file-system"></a>

您應該使用唯讀的根檔案系統。容器的根檔案系統預設為可寫入。當您使用 `RO` (唯讀) 根檔案系統設定容器時，會強制您明確定義資料可以保存的位置。這會減少您的受攻擊面，因為除非特別授予許可，否則無法寫入容器的檔案系統。

**注意**  
擁有唯讀根檔案系統可能會導致某些作業系統套件發生問題，這些套件預期能夠寫入檔案系統。如果您打算使用唯讀的根檔案系統，請事先徹底測試。

## 使用 CPU 和記憶體限制來設定任務 (Amazon EC2)
<a name="security-tasks-containers-recommendations-configure-limits"></a>

您應該使用 CPU 和記憶體限制來設定任務，以將下列風險降至最低。任務的資源限制會設定任務內所有容器可保留的 CPU 和記憶體數量上限。如果未設定限制，則任務可以存取主機的 CPU 和記憶體。這可能會導致部署在共用主機上的任務會剝奪其他任務系統資源的問題。

**注意**  
 AWS Fargate 任務上的 Amazon ECS 需要您指定 CPU 和記憶體限制，因為它會將這些值用於計費目的。對於 Amazon ECS Fargate 而言，一項佔用所有系統資源的任務並不是問題，因為每個任務都在自己的專用預留執行個體上執行。如果您未指定記憶體限制，Amazon ECS 會為每個容器配置至少 4MB。同樣，如果沒有為任務設定 CPU 限制，Amazon ECS 容器代理程式至少會為其指派 2 個 CPU。

## 不可變標籤與 Amazon ECR 一起使用
<a name="security-tasks-containers-recommendations-immutable-ecr-tags"></a>

使用 Amazon ECR，您可以且應使用具有不可變標籤的設定映像。這樣可以防止將已更改或更新版本的映像推送至具相同標籤的映像儲存庫。這樣可以防止攻擊者將破解版本的映像推送至具相同標籤的映像。透過使用不可變標籤，您可以有效地強制自己為每次變更推送具有不同標籤的新映像。

## 避免以特權方式執行容器 (Amazon EC2)
<a name="security-tasks-containers-recommendations-avoid-privileged-containers"></a>

您應該避免以特權方式執行容器。對於背景，在主機上使用擴展權限執行作為 `privileged` 執行的容器。這表示容器會繼承在主機上指派給 `root` 的所有 Linux 功能。應嚴格限制或禁止其使用。我們建議將 Amazon ECS 容器代理程式環境變數 `ECS_DISABLE_PRIVILEGED` 設定為 `true`，如不需要 `privileged` 時，以防止容器在特定主機上作為 `privileged` 執行。或者，您可以使用 AWS Lambda 掃描任務定義，以使用 `privileged` 參數。

**注意**  
 AWS Fargate上的Amazon ECS 不支援作為 `privileged` 執行的容器。

## 從容器中移除不必要的 Linux 功能
<a name="security-tasks-containers-recommendations-remove-linux-capabilities"></a>

以下是指派給 Docker 容器的預設 Linux 功能清單。如需有關每項功能的詳細資訊，請參閱 [Linux 功能概觀](https://man7.org/linux/man-pages/man7/capabilities.7.html)。

```
CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_FOWNER, CAP_FSETID, CAP_KILL,
CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_NET_BIND_SERVICE, 
CAP_NET_RAW, CAP_SYS_CHROOT, CAP_MKNOD, CAP_AUDIT_WRITE, 
CAP_SETFCAP
```

如果容器不需要上面列出的所有 Docker 核心功能，請考慮將其從容器中刪除。如需有關每個 Docker 核心功能的詳細資訊，請參閱 [KernelCapabilities](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_KernelCapabilities.html)。透過執行以下操作，您可以了解正在使用哪些功能：
+ 安裝作業系統套件 [libcap-ng](https://people.redhat.com/sgrubb/libcap-ng) 並執行 `pscap` 公用程式，以列出每個程序正在使用的功能。
+ 您也可以使用 [capsh](https://www.man7.org/linux/man-pages/man1/capsh.1.html) 來解讀程序正在使用哪些功能。

## 使用客戶自管金鑰 (CMK) 來加密推送至 Amazon ECR 的映像
<a name="security-tasks-containers-recommendations-cmk-encryption"></a>

您應該使用客戶自管金鑰 (CMK) 來加密推送至 Amazon ECR 的映像。推送至 Amazon ECR 的影像會使用 a AWS Key Management Service (AWS KMS) 受管金鑰自動進行靜態加密。如果您寧願使用自己的金鑰，Amazon ECR 現在支援使用客戶受管金鑰 (CMK) AWS KMS 加密。使用 CMK 啟用伺服器端加密之前，請檢閱[靜態加密](https://docs.aws.amazon.com/AmazonECR/latest/userguide/encryption-at-rest.html)文件中列出的注意事項。