我翻譯的一篇Docker的白皮書 - 容器安全簡介
容器安全簡介
Docker白皮書
譯者:李毅中國惠普大學資深培訓專家
摘要
最近幾年中軟件開發方式的演進已經根本性地改變了應用程序。這些改變影響了對于底層基礎架構、工具以及流程(管理整個生命周期)的需求。應用程序 從大型單體代碼庫轉變成了一種由很多小型服務松散耦合而成的集合,人們稱之為微架構。在一種渴望的驅使下-用一種在基礎架構間可以移植的新方式來更快地交 付更多軟件,我們看到身邊越來越多的敏捷組織從中收益,這些組織囊括了初創企業和大型企業。
這些新的應用程序不僅行為不同而且他們的架構從根本上改變了它們是如何隨著時間的推移進行構建、部署、管理及安全防護的。不再需要在虛擬機 (VM)或者裸機上以配置大型服務器來處理少量的大型負載,而代之以在一組普通硬件之上運行小型應用程序集。通過在應用程序之間共享同一個OS,容器升格 為這些新應用程序的打包模型。較少的OS實例在主機資源、成本和持續運維等方面為應用程序基礎架構帶來了明顯的優勢。
為了增強一個系統的彈性,關于應用程序安全的最佳實踐長久以來都建議分層的策略。在這篇論文中我們將介紹與Linux技術及Docker容器有關的安全概念。
要點包括:
·容器通過減少主機自身的暴露區域以及對應用程序與主機之間、應用程序之間進行隔離實現了更多一層的防護,而這種隔離并沒有使用更多的底層基礎架構資源。
·容器和虛擬機(VMs)可以部署在一起,從而為應用程序服務提供更多的隔離及安全層級
·容器的性質有利于快速、便捷的應用程序打補丁以及OS更新,應用程序及基礎架構的分層,有助于維持整體的安全合規性
Docker概述
Docker是一個用于構建、分發及運行分布式應用程序的開發平臺。組織應用Docker是為了簡化并加速他們的應用開發和部署。Docker可 以很容易地把分布式應用程序組合成輕量級的應用程序容器,它可以動態地調整而不會中斷應用程序并且可以順場地在開發、測試和生產環境中移植,而這些環境則 是運行在一個數據中心或者不同云服務提供者的物理機或虛擬機上。
該平臺的核心是Docker Engine,一個輕量級的應用程序運行環境,它也提供了強大的工具來構建、分發和運行Docker應用程序容器。Docker Engine可以安裝到任何一個運行LinuxOS的物理機、虛擬機及便攜電腦之上或者數據中心里、云服務提供者的服務器上。Docker的容器模型允許 多個隔離的應用程序容器運行在同一個服務器上,從而更好地使用硬件資源并且降低行為異常的應用程序對于其他應用程序及物理主機的影響。Docker容器是 基于應用程序的映像而創建的,而這些映像是由一個稱之為Docker Hub的注冊機(registry)負責存儲、管理與發布。在Docker Hub上有對Docker用戶開放且來自社區和生態系統的公共、私有及官方映像倉庫。

Docker Engine使用客戶端-服務器架構。一個Docker客戶端與Docker Engine的守護進程通信,該守護進程負責為一個特定的應用程序服務完成構建、分發和運行Docker容器的所有繁重工作。Docker客戶端可以是運 行的一個命令行工具或者通過DockerAPI集成到第三方應用程序中。客戶端和守護進程可以運行在相同的系統中,但是客戶端也可以遠程地訪問 DockerEngines。所有客戶端與守護進程之間的通訊可以使用TLS進行防護并且借助RESTfulAPI來實現。Docker是使用Go語言開 發的,守護進程使用多個庫和內核功能來實現它的設計目標。
Linux技術最佳實踐及Docker的缺省安全
容器技術以兩種方式提升了應用程序的安全性。首先通過使用應用程序之間和應用程序與主機之間的隔離層來實現。第二,它通過限制對主機的訪問來降低 主機的暴露區域來保護主機以及其上的容器。Docker容器構建在Linux的最佳實踐之上,從而提供了更強的缺省配置和未來能夠降低風險的可配置設置。
最佳實踐對于Linux系統管理員的建議包括應用最少權限原則。系統管理員長久以來都被要求使用chroot流程并且為部署的應用程序創建資源限 制。Docker容器模型通過在他們自己的根(root)文件系統中運行應用程序、允許使用獨立的用戶賬號、以及更進一步地使用Linux名字空間和 cgroups為程序提供沙盒來強制資源限制從而支持并強化了這些限制。這些強大的隔離機制在Linux內核中已經存在幾年了,Docker將其發揚光大 并且將分布式的應用程序視為獨立、隔離的單元從而極大地簡化了相關約束的創建和管理。
Docker利用一種叫做命名空間(namespace)的Linux技術來提供隔離的工作空間,我們稱之為容器(container)。當一個容器被部署時,Docker為該特定的容器創建一套命名空間,將它與所有其他正在運行的程序隔離開。
Docker也利用了Linux的控制組。控制組(Control group或者縮寫為cgroup)是內核級的功能,它允許Docker控制每一個容器訪問的資源從而保障容器的多租戶應用。控制組使得Docker能夠 共享可用的硬件資源,而且如果需要可能夠為容器設置限制和約束。一個典型的例子是對某個特定容器可用內存的總量進行限制,這樣它就不會消耗掉整個主機的資 源。
進程限制
限制訪問和能力將降低暴露區域在攻擊面前的潛在弱點。Docke的缺省設置被設計為限制Linux的capabilities(能力)。 Linux的傳統視角是以root權限對比用戶權限的方式考慮OS安全,而現在的Linux已經演進到支持一種更加細致的權限模 型:Capabilities。
Linux capabilities支持用戶capabilit及傳統方式的顆粒度規格,root用戶可以訪問每一個capability。通常非root用戶有一 個更加嚴格的capability集,但是一般通過使用sudo或執行文件的setuid權限為他們提供了提升至root級別訪問的選擇。這會構成一個安 全鳳風險。

在一個Docker容器內部的缺省capability集不到一個Linux進程所被授予的capability集的一半(見 LinuxCapabilities圖)。這降低了通過應用程序漏洞提升為root用戶而擁有一切權利的的風險。Docker應用了一個額外的顆粒度等 級,它對傳統的root/非root二分法進行了極大的擴充。在多數情況下,應用程序容器不需要root用戶所擁有的全部能力,因為需要這些權限的大多數 任務都由容器之外的OS環境來處理。容器可以使用一套縮減的capability集運行,而這不會對應用程序帶來負面的影響反而提升了系統整體的安全級別 并且缺省使得運行的應用程序更安全。它使得在入侵過程中很難發起系統級別的破壞,即使入侵者想要提升到root權限也無能為力因為容器的能力從根本上被限 制住了。
設備及文件限制
Docker通過使用設備資源控制組(cgroup)機制來封裝應用程序并限制對主機上物理設備的訪問,進而進一步地降低暴露區域。容器沒有缺省的設備訪問,需要明確地授予對設備的訪問。這些對于正在運行程序的限制保護了容器主機的內核及其硬件,無論是物理的還是虛擬的。
Docker容器使用copy-on-write文件系統,它允許使用同一個文件系統映像作為多個容器的基礎層。即使想同一個文件系統映像進行寫操作時,容器察覺不到其他容器所作的變更,從而有效地隔離了運行在不同容器中的進程。

如果你銷毀了一個容器,所有對容器的變更也會丟失,除非你提交了你的變更。提交變更作為一個新的層將追蹤并審計對基礎映像的變更,它可以作為在 DockerHub中存儲的一個新映像進行發布而且可以在一個容器中運行。這個審計線索對于提供信息來于保持合規而言是很重要的。當一個容器被破解或者發 現漏洞,它也能夠快速且方便地回滾到以前的版本。為了程序的運行,只有很少的幾個核心Linux內核文件系統不得不用在容器環境中。大多數這些強制性的文 件,諸如/sys和其他/proc下的文件,是以只讀的方式進行掛載。這進一步限制了可能對它們進行寫操作的訪問能力,即使是有權限的容器進程也是如此。
應用程序映像(Image)安全
Docker允許容器映像來源于硬盤或者來自一個遠程的注冊機。DockerHub是一個SaaS注冊機,它包含公共映像和大量Docker用戶 可以公開搜索和下載的官方映像倉庫。官方倉庫是由獨立軟件開發商(ISV)和Canonical、Oracle、RedHat等眾多Docker貢獻者認 證的倉庫。這些映像由這些上游伙伴維護和支持以確保映像是最近的。Docker并不知道當前使用的是哪一個遠程的注冊機,這允許企業使用任何本地注冊機、 基于公有云的這冊及或者DockerHub的組合方案。
對于健全的安全措施而言合適的應用程序映像工具是非常關鍵的。無論計劃內還是計劃外,IT管理員需要快速且方便地執行應用程序更新并且讓這些變更 也部署到相關的應用程序上。Docker容器的易于組合的特性和動態性使其能夠適應持續的變更而幾乎不會中斷應用程序的其余組成部分。
由于容器映像是持續變更的而且需要通過你的基礎架構推送和拉取,安全通信對于構架和發布應用程序而言就非常重要。所有與注冊機的通信都使用 TLS,只為保證雙方的私密性及內容的完整性。缺省情況下是強制使用公共PKI基礎架構信任的憑證,但是Docker允許額外地把一個公司內部的CA根證 書加入信任庫。
缺省之外:Docker增強的控制
Docker用戶可以在缺省配置的基礎進行擴展,進一步嚴格地對應用程序使用Linux能力或修改文件等訪問進行限制。操作人員可以使用只讀文件系統來部署容器,從而顯著地限制在容器生成過程中通過隱性設備訪問來欺詐系統的潛在風險。
通過“cap_drop”功能,也可以超越缺省值來限制Docker容器的capabilities。Docker也兼容于seccomp(安全 計算模式- Secure computing mode),Docker Engine源代碼樹的‘contrib“目錄中的一個例子就展示了這種集成性。使用seccomp,甚至可以使得所選擇的系統調用(syscalls) 對于容器進程完全禁用。
以上描述的配置控制是作為運行環境功能提供的,它專注于隔離、構建、調度和應用程序管理機制。這允許用戶根據使用者的操作和組織需求為他們的容器調整和配置策略。
開源安全
Docker Engine是Docker項目中的一個開源項目,可以從這里獲取: https://github.com/docker/docker 。作為一個開源項目,我們與社區密切配合來進行創新并解決他們提出的問題。發布的貢獻指南中嚴格要求使用代碼審查來確保在高質量代碼的基礎上進行工作。 Docker Inc.也以合同的方式把外部安全公司引入季度審計及(或)針對對我們的代碼和基礎架構進行的滲透測試。
Docker支持安全漏洞的責任披露并且允許安全研究人員提交潛在漏洞便于在線修復: https://www.docker.com/resources/security/
其他Linux內核安全功能
現代的Linux內核除了之前提到的capability、命名空間和cgroups等概念外,還有很多其他安全構件。Docker能夠利用諸如 TOMOYO、AppArmor、SELinux和GRSEC等的現有系統,其中有些為Docker容器提供了安全模型模板。你可以使用這些訪問控制機制 的任何一種來進一步定義定制化的策略。
Linux主機可以用很多其他方式進行加固而且部署Docker在增強了主機安全的同時卻不會影響其他安全工具的使用。我們建議你在運行的 Linux內核中使用GRSEC和PAX。這些補丁集加入了很多內核級安全檢查,使得在編譯和運行環境中嘗試破壞或者一些常見披露技術變得更加困難。這并 不是Docker專有的配置,但是可以在系統范圍內應用并從中獲益。
在基礎架構中部署Docker
將容器與虛擬機結合
容器和虛擬機都能在一個共享主機上為運行的應用程序提供隔離環境,只是來自不同的技術視角而且可以基于應用程序環境的需要很好地獨立使用或者結合在一起。
虛擬機使用一個完整的OS,包括它自己的內存管理和虛擬設備驅動程序。隔離是在虛擬機層面提供的,因為資源是為客戶OS(guestOS)仿真而 來的,因此允許在單一主機上運行一個或多個并行(而且甚至是不同的)OS。虛擬機提供了應用程序進程和邏輯系統之間的邊界。Hypervisor會拒絕虛 擬機執行可能會危害主機平臺完整性的指令。對主機的保護有賴于提供一個安全的虛擬硬件環境來運行一個OS。這個架構對于主機資源利用率有不同的影響,但是 允許在單一主機上通過不同的OS運行應用程序。
Docker容器在相同主機上運行的所有應用程序容器之間共享一個單獨的主機OS。隔離是由Docker Engine在每一個應用程序層面上提供的。使用容器降低了每個應用程序的開銷因為避免了多個OS實例。這使得容器更加輕量、快速且易于擴展和收縮,并且 可以實現比完整的虛擬機更高的密度等級。這種方式只能對共享一個通用OS的應用程序有效,就像Linux用于分布式應用程序一樣。
虛擬機的常規方式不允許他們能真正縮小到只運行一個單獨應用程序服務的級別。一個虛擬機可以支持一個相對豐富的應用程序集,但是在單一虛擬機內運 行多個微服務而不使用容器則會帶來問題因為對于有些組織而言每個虛擬機只運行一個微服務在經濟上是不可行的。與虛擬機相結合地部署Docker容器能夠實 現整個服務組中的服務彼此隔離而且運行在一個虛擬機中。這種方式通過引入兩個層級:容器與虛擬機,而提升了分布式應用程序的安全。另外這種方式達成了更有 效的資源使用并且可以為所定義的隔離和安全目標在減少虛擬機數量的同時增加容器的密度。

因此可以通過把虛擬化和容器相結合所提供的隔離比單獨使用虛擬化在成本和資源效率上更好。Docker容器與可以保護虛擬機自身的虛擬化技術能夠完備搭配,并且為主機提供深度防御。
在裸機上運行Docker
容器在主機及其應用程序之間提供了一層保護,在應用程序和主機之間提供了隔離。相比于不使用任何虛擬化或者容器技術,這使得它在邏輯上部署應用程序會更加安全。借助容器,很多應用程序服務可以部署在單一主機上從而使得組織能夠實現對其基礎架構更好的利用率。
然而,裸機部署不能提供最底層的硬件隔離,故而它不能充分發揮Intel的VT-d和VT-x技術的優勢。在這個情境下,對于主機隔離的等級而言容器不能完全替代虛擬化。

容器為運行在裸機之上的應用程序提供了隔離,它保護了主機去應對大量的威脅而且能夠滿足非常廣泛的使用場景需求。在以下的場景中虛擬機可能不是最 好的選擇而容器則可以取而代之;性能至上的應用程序運行在一個單租戶的私有云中,跨租戶或跨應用程序的攻擊并不是一個值得關注的問題;或者他們正在使用不 能直接映射給虛擬機的專用硬件,或者該硬件提供直接內存訪問而使得虛擬化的優勢無法發揮。很多GPU運算的用戶就面對著這個問題。
運行在裸機之上的Docker容器與他們運行在虛擬機上時擁有相同的高級別限制。無論那種場景,一個容器通常都被允許修改物理的或虛擬的設備。
生命周期管理
軟件開發只是應用程序生命周期的一個階段。測試、運行及管理階段的安全需求是非常關鍵的,并且涉及了不同的團隊、工具和流程。無論計劃內或者計劃 外的持續運維和更新都需要保持操作運行的安全和平穩。更新應用程序部件的過程往往不是小事兒甚至更嚴重,即使有補丁自動發布工具也會很繁瑣。此時的問題是 安裝的補丁是否影響了其他的東西?安裝這個補丁有多難?如果更新失敗要如何完全地回滾?構建映像的便利性應該延展到對這些映像的更新并且安裝安全更新。運 維工程師可以利用映像標簽來以一種自動的方式來安全地、容易地安裝計劃內的安全更新并為之前的版本安裝更新。計劃外的補丁和修復程序也可以通過提交、更新 和重新發布容器映像的方式安裝。更新的映像可以推送到Docker Hub或任何其他的注冊機以便于同其他團隊進行分享和發布。
Docker容器的這些特點使得系統管理員在更新系統工具、軟件包甚至是主機的內核都很容易。OS的升級周期被明顯地縮短而且也容易實現,顯著地 降低了基礎架構在攻擊面前的總體暴露面。相比于虛擬化模型中每個主機有多個OS需要維護,Docker環境中每個主機只有一個OS需要維護。需要打補丁和 更新的OS實例數量減少將降低與安全合規相關的開銷。
確保安全合規性等同于應用最新的更新并保持對系統包含什么及其變更歷史進行跟蹤。對生產環境中容器的變更歷史能夠進行審計可以驗證對生產系統沒有 進行有危害的變更,而且當問題出現時也有能力把容器回滾到一個已知的正常狀態下。總之,使用分層手段使得參照公開常見風險和漏洞列表(CVE)來檢查OS 包和應用程序依賴性變得更加容易。
總結
基于微服務的架構為應用程序在整個生命周期內如何開發、部署及管理提出了不同的需求而且打包工具的變化及安全模型也要能夠支持它。安全需求可以采取分層的方式來滿足,它以應用程序棧來對待整個基礎架構而且通常會綜合多種技術來保證滿足每一層的安全需求等級。
Docker在組織使得深度防御概念的部署簡單化了。使用Docker可以立即帶來有益,不僅僅是在應用程序開發和部署的速度和便利性方面,也表 現在安全方面。通過隔離、約束及隱形地應用了大量的最佳實踐–否則需要在組織內的每個OS上進行明確的配置,直接部署Docker自然就會提升系統的整體 安全等級。
總而言之,企業使用了Docker容器可以在不增加應用程序基礎架構開銷的前提下增強安全:
·容器通過在應用程序與主機之間以及在應用程序之間進行隔離而不需要使用更多的底層基礎架構資源和降低主機的暴露區域來提供了更多一層的保護。
·容器和虛擬機可以部署在一起來為所選擇的服務提供更多的隔離和安全層級
·容器的性質有利于快速、便捷的應用程序打補丁以及OS更新,應用程序及基礎架構的分層,有助于維持整體的安全合規性