多雲環境下的DevSecOps實行
大多數會上雲的企業是看中了在雲端中開發自有的應用程式可以加速其過程。因為應用程式的功能是不斷變化的。既然在雲端上的一切使用都是"有規矩的",哪麼這些應用程式的變動就必須在其目標雲端平台中的基礎設施被測試、部署然後交給維運團隊。
為了加速上述說的過程,企業使用了DevOps這一持續優化IT運作的流程或說文化。但是,在這不斷變動的應用程式功能中有一件事最為重要,哪就是"一致性": 開發的代碼必需在一個嚴格的版本控制之下。故CI/CD Pipeline就是為此而產生的。在這整個運作之中,我們必須確保代碼、Pipeline、應用程式與基礎設施是安全的。所以我們從DevOps走向的DevSecOps。
本文中,我們將探討DevSecOps的原則,CI/CD pipeline是如何作業的,以及它如何設計成符合多雲的環境並且遵守組織的資安政策。以下是討論的主題:
- 理解為什麼需要DevSecOps
- 開始實行DevSecOps的文化
- 設立CI/CD
- 在多雲中運作CI/CD
- CI/CD的工具討論
- 遵循我們所設計的資安原則
- 使用自動化保護開發與維運
理解為什麼需要DevSecOps
在我們介紹DevSecOps各個面向之前,我們需要理解為什麼DevSecOps在多雲環境中如此重要。在雲端中,安全分為以下四個層級:
- Organizational Level(組織層級) — 總體的治理
- Enterprise Level(企業層級) — 確保安全涵蓋到accounts、透過監控與日誌進行的稽核與合規,與進行自動化
- Subscription Level(訂閱層級) — 使用RBAC、威脅偵測與縱深防禦
- Solution Level(解決方案層級) — 使用經過驗證的範本、藍圖與images的CI/CD
而這些層級都需要定義其安全防禦。以下圖示顯示在所有層級安全防禦。
在多雲環境中,企業通常使用容器與CI/CD pipeline。不過VM也行,如果團隊的能力、技能與工作是熟練與足夠的話。所以企業需要擁有在多雲環境中的以下能力:
- 在多個雲端平台的多個region中能夠管理與啟用工作負載(workload)
- 擴展工作負載到最佳效能,並且能運用不同雲端平台的不同專長能力
- 運用多雲平台的韌性來建立可高用度的解決方案
- 能同時在多個雲端中運行應用程式
根據上述的要求能力,運行容器應該是最佳的答案。不過每個雲端平台的container平台操作方式不盡相同,技術人員需要克服此一挑戰。
哪麼有人會說,我們不能將我們的應用程式放在VM中運作於多雲環境中嗎?當然可以,只是麻煩了一些。在公有雲中,運作VM與容器最大的不同點在於我們需要管理VM的OS(但老實說,容器也是一個OS,只是非常小跟簡化)。會麻煩一些,管理成本與雲端費用可能都會增加。
由於容器的"可移植性"。可以讓企業將他們應用程式隨意移動到不同的雲端平台使用,前提是技術人員要對不同平台的操作方式熟悉。目前容器的運作管理最普遍的應該就是Kubernets了,而這也是主流的雲端平台都有支援的,如GCP的GKE、AWS EKS、Azure AKS。
在我們使用了這些雲端平台的PaaS K8S管理平台,接下來就要聚焦在資安的議題上。雲端的shared responsibility讓我們與平台業者各自有需要負的資安責任存在。我們(也就是PaaS的使用者)第一件事就是要考量整個K8S Cluster的安全。在設計與實行cluster中,我們需要考量以下部分:
- 啟用RBAC
- 啟用驗證(Authentication)
- 啟用防火牆
- K8S node的隔離
- 監控網路流量與稽核日誌
為此,我們參考NIST SP 800-190 Application Container Security Guide來強化我們容器的安全。更多SP 800–190的介紹請參閱本部落格NIST SP 800–190 Part 1容器簡介一文及其系列文章。
在使用K8S時,我們必需考量強化 host的OS(但如果是公有雲的PaaS,這是平台業者的責任),同時最重要的則是使用容器的images。這個image是我們所有運作中容器(副本)的來源(正本)。
這些來源image會存在於一個受控的container registries。Container registries會如此重要的原因在於,一旦Image有問題,整個運作中的Container都會有問題。而CI/CD pipeline需要使用安全的image。至此我們開始了DevSecOps的流程了。
DevSecOps可以分為三個層面。第一個是在DevSecOps團隊中建立意識。這個意識是指團隊中的成員都需要認知到 — 他們的每一個決定產生安全與財務的後果。要達到這樣的成果,團隊成員都需要精通在雲端的開發、安全與維運。然而這樣的人才是需要付出代價的,不管是外聘或是培訓現有成員(會時間與費用成本)。
第二層面是應用安全設計原則,使安全性成為開發和維運在雲端中構建和管理的所有內容的整合部分。這裡需要的是自動化,因為這一類的作業非常多,但重複性也高,最重要的是防止人為錯誤。第三個層面就是自動化的安全。
開始實行DevSecOps的文化
NIST SP 800–190清楚說明了容器技術的安全原則與實踐。不過NIST給了第一個建議不是技術類的,而是一種心態:
客制組織的維運文化和技術流程,以支援容器的開發、運作和應用程序的新方法。
為什麼需要改變組織的文化?很簡單,做事的方法不同了。雲端、雲原生、容器等,這些新的軟體開發方式與傳統方法有了很大的差異。安全性不再是單點監看,而是需要融入整個IT環境。從軟體開發流程(CI/CD)到維運與其基礎設施。
下圖呈現了一個CI/CD pipeline的流程,其中紅色三角的圖示顯示我們需要在此遵循安全實踐:
根據上圖,我們介紹一個左移(shift-left)原則:
我們在應用程式開發的生命週期中儘早"轉移測試"的原則,實際上,就已經在pull或write 代碼的pipeline的最開始階段進行了轉移。 這是 DevSecOps 中的一個重要原則。另一個原則是開發與維運的緊密合作,包含安全的定義與管理。
DevOps這一個詞彙,不同的人可能有不同的觀點。本文使用的是DASA(DevOps Agile Skill Association)的定義與原則。DASA定義出基於6個原則的DevOps框架:
- 以客戶為中心的行動(這也是DDD-domain-driven design的目標)
- 以終為始的建立
- 負完全的責任(you build it, you run it, and you break it, you fix it,最後 you destroy it)
- 跨職能的自治團隊(能自主決定開發流程)
- 持續優化
- 盡可能的自動化
怎麼建立DevSecOps的文化呢?答案是: "教育與實驗"。企業需要建立一個能夠讓開發與維運人員不斷實驗並能從中學習到的隔離環境。不管是外訓或內訊,還是互相學習都可以加速DevSecOps思維的採用。
設立CI/CD
在我們開始討論之前,我們先來定義一下甚麼是CI?甚麼是CD?
CI(Continuous Integration)是基於shared Repo的原則構建,其中代碼經常更新並在雲端環境中作業的團隊之間共享。 CI 允許開發人員同時處理相同的代碼。 代碼中的變更直接整合並準備在不同的測試環境中進行全面測試。
CD(Continuous Delivery/Deployment)是專注於軟體到測試環境的自動傳輸。 CD 的最終目標是以完全自動化的方式將軟體投入生產環境。 自動執行各種測試。 部署後,開發人員能立即收到有關代碼功能的反饋。
CI/CD是整個DevOps循環的核心。因為CI/CD,團隊需要負責CI/CD從規劃到管理,並且客戶要求的變更能夠靠著自動化與強健的開發流程快速交付到客戶手上。下圖DevOps循環的CI/CD流程示意圖:
大多數的企業整天嘴巴喊要有DevOps與CI/CD,但很多人都失敗了。普遍的原因是因為缺乏一致性。CI流程讓開發人員可以經常變更代碼,之後再觸發CD流程。大型企業通常有多個開發團隊,也伴隨著使用多個雲端環境,這意味著企業的工作方式(唯一的一種)需要套用在這多個團隊與環境中。而全自動化的CI/CD pipeline流程才能達成這種一致性。所以DevOps與CI/CD不是先選甚麼工具,而是文化與嚴格遵守流程。
以下建議的步驟能夠企業要能夠成功實行DevOps文化:
- 實施有效的 CI/CD pipeline始於所有利害關係人是實施 DevOps 流程。一個主要原則是DevOps是一個能夠完全負責的自治團隊。因為DevOps是基於敏捷文化,如果DevOps有官僚文化,哪麼時間都會浪費在官僚之上。
- 選擇CI/CD系統。選擇哪個Repo存放代碼非常重要,因為這是CI/CD的第一步。再來才是選擇CI/CD系統,這一類的解決方案一大堆。選擇哪一種,基本上可能會有CTO決定,好一點的可能是Develpoment lead決定。不管是哪一解決方案,重點還是一致性。
- 需要PoC(proof of concept)。CI/CD重要的元素之一就是自動測試,所以第一步是建立一個自動化流程的pipeline。大型企業通常都會有一個品質與測試計畫,通常寫成GTA(Generic Test Agreement)。這是描述系統在進入生產環境之前,測試必須要怎麼樣的進行。不過在DevOps,企業使用的是DoD(Definition of Done)。DoD是描述系統在部署到生產環境之前必須滿足的條件和驗收標準。 DoD 是需要交付的最終產品、應用程序或 IT 系統的品質標準。
- DevOps另一個重要元素則是"盡可能的自動化"。這意味著企業必需捨棄硬體的一些概念,因為在雲端中每件事都是代碼。在 CI/CD 中,團隊在同一個Repo中作業,這意味著application code和IaC位於同一Repo中,以便所有團隊都可以在需要時存取它。
DevOps文化中,團隊是跟隨User story作業的。一個客戶案例是:
作為電商的企業主,我希望擁有多種付款方式,以便更多的客戶可以線上購買我們的產品。這就會對開發與維運團隊設下要求。當User story內的要求被滿足時,也滿足了 DoD,這意味著unit test已經完成,代碼已經過檢視,驗收標準已經簽署,並且所有功能和技術測試都已通過。
下圖為一個有著多個測試階段的build與release pipeline的流程概念圖。
在多雲中運作CI/CD
容器技術讓我們的應用程式具可移植性。所以我們的應用程式可以在不同的雲端平台運作,也就是多雲的環境。概念上這感覺很重要,但實際上針對多雲運作的開發也許不是哪麼簡單。
在多雲環境中,開發人員一樣使用一個Repo,但是進入到了佈署階段時,針對每個平台的部署設定與配置就變得不一樣。也許還要加上測試,因為就算是K8S,每家CSP的操作設定也搞得不一樣。
有幾個步驟是開發人員必須注意的。首先不管用我們的應用程式放在哪一個雲端平台,一致性依然很重要。不論哪一個平台application code在DevOps循環中還是要一樣的。每個雲端平台可能有自己的獨特功能,但大都是有關於configuration。
我們需要思考一下Layers這一個詞彙:
從Infra和Configuration layer的資源中抽像出Application Layer。 這是使用 CI/CD 實現一致性形式的應用程式開發的唯一方法。 開發人員在多雲環境中需要應對的另一個挑戰是各種雲端平台的高變動率。 DevOps 工具必須能夠適應在程式部署中的這些雲端平台的變動,但不必一直更改應用程式代碼本身。
但是開發人員需要對要使用的雲端平台有很好的理解,還有該平台的特別之處。研究這些平台的 DevOps 最佳實踐和推薦的工具也很有意義,這個會在下一節討論到。多數通用的DevOps工具是可以套用到多數的雲端平台,用的是跟API來跟雲端平台構通。
所以成功實行DevOps的基本原則如下:
- 一個Repo
- 一種框架或方式來作業
- 一種能夠適用多雲環境的通用工具集
說到框架,SAFe(Scaled Agile Framework)是許多企業實行DevOps的基礎。SAFe一個主要資產是Agile Release Train。
Agile Release Train是一種應用程式開發標準化和代碼發布管理的原則構建的。 這是通過將一切自動化來完成的。必要的步驟如下:
- 構建程式是使用自動化流程來編譯程式
- 自動化的單元、驗收、效能與負載測試
- 自動化的安全測試
- 通過運行整合測試和發布可部署到生產環境的單元來實現自動化來持續整整合(CI)
- 通過將版本控制代碼自動部署到不同環境來持續交付(CD)
- 針對配置、啟用、設計安全性、code review、稽核、日誌記錄和管理能夠有自動化工具
CI/CD的工具討論
如同我們之前講的,DevOps與CI/CD相關的解決方法或工具一大堆。用哪一種其實沒有對與錯,重要的是團隊有沒有得好很好的訓練以及用起來順不順手。這一節我們將討論三大公有雲(AWS/Azure/GCP)的原生CI/CD工具 — Aws CodePipeline/CloudFormation, Azure DevOps與GCP的Cloud Build。
我們將使用K8S的CI/CD為範例,因為如同我們之前講說,容器技術是讓我們可以使用多雲環境的主要原因。主要組件有:
- Container Management
- Cluster Operation
- 底層基礎設施的Configuration Management
- Version control system
- Container Image的registry
- Security testing and audits
- 持續監控與可觀測(observability)
為了建立一個良好的Pipeline,我們需要考量以下設計原則:
- 使用多雲環境時,我們要用的是一個通用的All-In-One的CI/CD工具。
- 託管或自行管理的CI/CD包含佈署,配置與基礎設施的管理
- 自動或手動的代碼測試與驗證
- 佈署方法: Rolling 或Blue/Green
AWS CodePipeline
此工具可以佈署應用程式與Infra資源於AWS中。CodePile提供以下功能:
- Workflow modeling:
我們可以把它視為規劃工具。此功能定義了發布代碼的不同階段(build/test/deploy)。我們可以建立在這些不同階段的作業(tasks) - Integration:
如同其他CI/CD工具,codepipeline也可以與存放source code的系統整合在一起,如GitHub、AWS的codecommit、AWS ECR與S3。而代碼的provisioningm與更新則是依靠AWS的CloudFormation。此功能還有更多的整合,詳情可參閱AWS的網站。 - Plugins:
這是讓我們能夠整合第三方的CI/CD工具,像是要佈署代碼在地端,我們可以透過與地端的Jenkis佈署程式
Azure DevOps
Azure DevOps提供以下功能:
- Boards:
這是規劃工具,支援Kanban與Scrum的scheduling。 - Repos:
這是Azure DevOps的Repo(基於Git或TFVC — Team Foundation Version control) - Pipeline:
CI/CD的功能 — 負責code build與release,它與Board整合 - Test Plans:
這可以配置test scripts,可以自動或手動 - Artifacts:
這可以讓我們share code packag給其他來源Repo並且能整合其他的CI/CD工具
使用 Azure DevOps 時,首先要做的就是定義project並加入project member。 接下來,PM或產品負責人定義開發方法。 根據該選擇,DevOps 提供了定義work items的可能性,例如功能、待辦事項清單項和作業(tasks),以及用於規劃這些項的執行的Board。 work item或產品可以是一段可以部署的代碼; 在 DevOps 中,這可以通過 Azure Pipelines 實現自動化,Azure Pipelines 在檢視後將代碼部署到雲端環境。
GCP Cloud Build
GCP在CI/CD的主要功能有:
- Cloud Source Repositories:
這是一個GCP託管的Git Repo。代碼的存取可以透過Cloud Build與Cloud Pub/Sub。在建立Repo之後,我們可以從gcloud console使用Git的相關命令: 如git add/ git commit/git push - Artifact Registry:
這與Azure Devops的Artifacts是一樣的功能。在Azure,它是保存Maven與NPM package,在GCP,這是保存Docker container images - Cloud Build:
這是 GCP 中 CI/CD 功能的引擎。 在 Cloud Build 中,我們定義pipeline。 它從 Cloud Source Repositories 導入source code,但也可以從其他來源(例如 GitHub)pull code。 Cloud Build 測試代碼並將其部署到GCP 。 Cloud Build 與許多不同的解決方案整合,例如,與 Jenkins 和開源工具 Spinnaker 整合,用於自動化測試和持續交付。 這些解決方案還可與 GKE 配合使用,在運行 Kubernetes 的容器平台上啟用 CI/CD。
適用於多雲環境的container orchestration與應用程式開發的工具
以上我們所談論的都是各家CSP自有的解決方案或工具。在多雲環境中,我們也許會使用K8S在不同的CSP中。大部分的CSP都將自己的K8S 管理平台往外面延伸出去,像是AWS的ECS Everywhere或GCP的Anthos。
不過也有其他第三方解決方案可以用於multi-cloud container orchestration,如Vmware的Tanzu Mission Control與Red hat Openshift。Tanzu 使用單一管理平台來管理多個雲中的 Kubernetes cluster。 Tanzu Mission Control 可以在 AWS、Azure、GCP、OCI,當然還有基於 vSphere 構建的雲端上部署、擴展和管理cluster。
Redhat OpenShift 也是一個沒有特定於軟硬體或雲端的環境,可使用Red Hat suite以及Red Hat Enterprise Linux 和 Ansible 來部署、擴展和管理 K8S Cluster。 OpenShift 有用在Azure、AWS 和 IBM Cloud 的版本。 完全託管的 RedHat OpenShift Dedicated 版本可用於 AWS 和 GCP。
遵循我們所設計的資安原則
我們之前所提及的都是屬於DevOps的部分。但是我們也提到,安全應該包含在每一個流程步驟中,甚至融入整個IT環境裡。我們需要通過設計來應用安全性。這是DevSecOps的第二個層次,並且包含以下的作業活動:
1.保護Piepline
最佳實踐應該是套用zero-trust原則。pipeline的存取須採用least privilege policies。同時持續測試應該也要整合在pipeline中,這包括SAST(Static Application Security Testing)與DAST(Dynamic Application Security Testing)。也要對pipeline做penetration testing。
2.無瑕代碼(clean code)的實踐
這個說法有多種解釋,但關鍵是KISS的原理:Keep it simple and stupid。最重要的是:保持一致性。
3.應用程式安全設計原則
此處,我們可以使用OWASP安全設計原則。這些原則是基於資安的C.I.A原則產生的。OWASP 列出了安全原則,其中包括:
- 盡可能縮小攻擊面
- 應用程序預設是受到保護,這意味著使用者必須“證明”他們有資格使用該應用程城市和相關資料
- Least privilege
- 使用Layered security control進行縱深防禦
- SOD(Separation of duties),確保使用者只能執行他們有權限執行的操作,而無法控制應用程序中整個transaction的生命週期。 意思是:發起請求的人不能自己授權該請求。
4.帶有container與sidecar的微服務
眾所週知,微服務是一種鬆散耦合(loosely coupled)的服務,它們共同構成整體應用程式的功能。它們的安全性通常比單體式程式還要高,因為各個功能是分離的。攻陷了一個要再攻陷另一個是比較困難的,不過前提是我們有做好資安實踐。關於微服務的安全實踐請參閱本部落格NIST SP 800–190 Part 1容器簡介一文及其系列文章。
系統的安全性取決於多個因素,而架構只是其中的一個面向。 具有容器和 sidecar 的微服務可以提供安全方面的優勢,例如強化的隔離性和模組化,這可以使管理各個組件中的安全漏洞變得更加容易。 但有一好沒有兩好,管理多個容器和服務的複雜性也會帶來新的安全挑戰,像是保護組件之間的網路溝通以及確保安全設定的正確配置。
而單體式架構的資安則與微服務相反,管理可能很容易,但是一旦被攻陷則衝擊就非常大。但是單體式的相關資安事故的處理就變得非常麻煩,因為要檢查的東西非常多。
然而,構建微服務架構很複雜,開發人員仍然希望能夠重複使用工件(Artifacts),而不是一遍又一遍地對每個微服務進行programing。 對於適用於每個應用程序的functions來說,情況很可能如此。 這些function可以使用 sidecar 進行耦合。 在 sidecar 中,應用程式的組件使用容器部署為單獨的Processes,提供隔離和封裝。 sidecar就像摩托車上真正的邊車一樣(二戰時德軍使用的哪種),附加到parent application並為應用程式提供支援性功能。 我們可以使用 sidecar 來部署監控、日誌記錄和configuration files。 下圖顯示了 sidecar 模式:
為了將 sidecar 與應用程序的其他組件整合,我們需要一個Service Mesh,它支援微服務之間的Service to Service的網路傳輸。 將Service Mesh與 sidecar 結合使用的最流行的是開源 Istio 。 所有使用 Kubernetes 作為Orchestrato平台的公有雲都有這一個功能。
5.進行威脅建模
企業應使用一種流程來識別潛在威脅,並根據安全政策以及應用程式和資料堆棧(Data stack)中實施的保護措施來評估這些威脅。 威脅建模將揭示漏洞並指示必須採取哪些緩解措施來防止這些漏洞被利用。 執行威脅建模的常見方法是使用TTP(Tactics, Techniques, and Procedure),以及 Mitre Att@ck 框架使用的其他方法。 Tactics描述了攻擊者的行為以及使用什麼技術以及如何破壞系統。
雲端的軟體開發週期中,測試應用程式與基礎設施。這包含用測試來驗證漏洞與可能的風險可以被解決。為了達成這個目的,以下是需要考量的整體堆棧:
- Code
- CI/CD pipeline
- 保存container images與service的Registries與Repo
- 在雲端中佈署資源的IaC
- 雲端中的VM
- Container runtime(主流通常是K8S)
- 容器
我們到現在還沒有談到的是serverless函數。這在雲端中,我們只需要注意應用程式及其serverless相關設置的安全部分就可以,因為其他的一切都是CSP在負責。而serverless在雲端中是高度自動化的服務。
使用自動化保護開發與維運
自動化在DevSecOps是必要的存在,我們應該在以下列流程清單中考量自動化的可能:
- version control
- CI
- Continuous Testing
- configuration Management and Deployment
- Continuous Monitoring
在本文中,我們已經討論過相關容器技術的效益與風險。而使用公有雲的PaaS K8S託管服務則會強化效益與減緩風險。不過,依據ITIL的思維,有一好沒有兩好,在強化效益(成本)與減緩風險的同時,我們也同時引入了新的成本與風險。
為此,在安全方面,我們需要更強力的執行測試。這些測試可以在很大的程度上是自動化的:
- Application and Application runtime security testing
- SCA(Software composition analysis)
- IaC validation and testing
- Container image scanning
- Dynamic threat analysis
- Network Scanning
- Vulnerability scanning and management
從DevSecOps的角度來看,有兩種部署方式是我們可以討論: Rolling與 blur/green。這兩種方式的選擇每家企業的每個團隊都有所不同,有時根據狀況可能兩種都會用到。
但是從安全的角度來看,blue/green可能更安全。因為在生產環境中不會有新舊程式共存的狀況發生。整個網路流量是從blue轉移到green中,但是這可能會有非常短暫的停機時間(可能幾十秒)。另外一個缺點是費用問題,因為如果企業K8S cluster非常龐大,意味著企業在做blue/green轉換時要準備另一個一模一樣架構的K8S cluster。