CI/CD 流水線是 DevOps 團隊軟體交付過程的基本組成部分。該流水線利用自動化和持續監控來實現軟體的無縫交付。通過持續自動化,確保 CI/CD 流水線每一步的安全性非常重要。在流水線的各個階段,通常需要存取憑據等敏感資訊。保護這些資訊對於保持強大的安全態勢至關重要。本文將帶你瞭解如何在 Jenkins CI/CD 流水線中保護金鑰(Secrets)。
轉自 SEAL安全
如前所述,CI/CD 流水線通常需要存取敏感資訊,如密碼和 API 金鑰。以明文對它們進行寫死會產生嚴重的安全風險,並且違反了大多數合規框架中的審計準則。使用這些憑證而不在非必要的情況下公開它們的機制,對於自動化軟體交付很重要。
用於安全儲存、管理和存取上述憑證的工具和技術的集合稱為機密管理(Secrets Management)。Secrets 廣泛用於 IT、DevOps 和雲環境。
Secrets 包括:
CI/CD 流水線整合了多個設定管理平臺,需要 secrets 來啟用服務到服務的通訊。這些平臺還需要 secrets 來驗證請求存取 SSH 伺服器、資料庫、HTTP 服務和其他資源的實體。
Secrets 用於管理 CI/CD 流水線中的存取許可權。一些用例包括原始碼控制管理、基礎設施連線、共同作業提供者和驗證。讓我們更詳細地討論這些用例中的每一個。
版本控制系統,如 Git,便於多人團隊之間的共同作業。這些系統通過管理和儲存來自多個開發人員的程式碼貢獻,來幫助維護應用程式的開發。由於原始碼可能包含一些組織最有價值的資產,因此正確驗證和管理 Git 儲存庫的存取許可權至關重要。
金鑰管理系統對保護用於將貢獻者的主機連線到儲存庫的憑據非常重要。為了避免惡意攻擊者利用 secrets 發起安全攻擊,因此 secrets 並不儲存在版本控制,而是儲存在特殊的敏感檔案中(當然這些敏感檔案會被排除在儲存庫和紀錄檔之外)。
CI/CD 流水線通常由在多個主機上的不同服務組成,這些主機分佈在不同的基礎設施上。隨著這些主機不斷地相互通訊,通過 API 呼叫與服務通訊,從而實現所需的應用程式功能。API 金鑰和系統到系統(system-to-system)密碼等 secrets 能夠支援在基礎設施之間建立安全的連線,從而連線多租戶和多雲 CI/CD 流水線。
CI/CD 流水線包含跨多個開發、運營和質量保證環境的共同作業活動。這些團隊依靠多種工具和框架來共同作業和共用資訊。使用 secrets 進行共同作業有助於團隊確保安全通訊並在雙方之間提供一層信任和安全保障。
身份驗證是 CI/CD 和應用程式安全的關鍵要素。通過將應用程式連線到身份和存取管理 (IAM)解決方案,secrets 用於確保 CI/CD 流水線的安全性和隱私性。這些解決方案提供了使用者角色和許可權的外部資料庫,讓使用者無需在 CI/CD 流水線中暴露其憑據即可登入應用程式。
要為改進金鑰管理奠定基礎,瞭解一些簡單的用例會很有幫助。
作為領先的雲 SaaS 平臺之一,AWS 是大多數基於雲的基礎設施的常見選擇。與 AWS API 互動以預置和查詢資源通常需要使用金鑰/存取金鑰憑證。保護這些憑證對於維護 AWS 賬戶的安全至關重要。
現代應用程式架構通常依賴於基礎架構即程式碼 (IaC) 來部署執行工作負載的底層系統。對這種設定進行編碼能夠更輕鬆地對可重複、可延伸和安全的基礎架構進行維護。在設定此基礎架構的過程中,通常需要將敏感資訊(例如 SSH 金鑰和 API 憑證)部署到節點。通過 IaC 和 CI/CD 自動設定基礎設施是一種常見模式,管理機密是該工作流程的重要組成部分。
環境變數在大多數 CI/CD 流水線中都有一致的用法。在處理 CI/CD 工作流時,需要動態設定值並保留這些資料,以供其他程序和指令碼使用。在許多情況下,敏感值需要通過環境變數傳遞,這也再次強調了有效機密管理的必要性。
Jenkins 需要存取大量憑據才能與構成完整 CI/CD 流水線的所有平臺和應用程式互動。Jenkins 附帶了一個預設的憑證外掛,其提供一個內建的金鑰儲存。還帶有憑據繫結外掛,可以將憑據繫結到環境變數。
將金鑰儲存在 Jenkins controller 中使流水線中的應用程式,即使這些機密僅被建立一次仍然能夠被多次參照。雖然 Jenkins 憑據外掛提供了一種儲存和管理機密的簡單方法,但任何 Jenkins 管理員和流水線作者都可以存取它們。因此,DevOps 團隊應確保正確設定存取許可權,以確保 CI/CD 流水線的安全。
Jenkins 機密外掛支援的憑證包括:Secret text、使用者名稱/密碼對、secrets file、SSH 使用者名稱和證書。對於數量有限的金鑰,可以單獨儲存,而大量金鑰通常最好使用憑證檔案進行管理。
接下來我們將討論在 Jenkins 中保護 secret 的一些可用選項。一起來看看將 secrets 安全地注入 Jenkins 流水線的一些最佳實踐。
一次性密碼通過確保使用者名稱/密碼組合不能多次使用來幫助防止使用者帳戶被盜用。雖然該帳戶始終保留使用者名稱,但使用者每次登入時都會收到一個 OTP。這可以保證 Jenkins 管理員和使用者帳戶的安全,防止金鑰資訊洩露。
刪除已寫死到 CI/CD 設定和 Jenkinsfiles 中的金鑰。這樣能夠讓敏感憑證資訊不出現在流水線中,避免惡意行為者存取和利用。
將金鑰儲存在多個檔案中有助於實施憑據最少暴露原則。這樣可以讓憑據用於儘可能少的應用程式和使用者。
開發團隊應設定安全檢查,以確保請求資源存取的應用程式具有有效應用程式的屬性。這些應用程式需要根據 RBAC (Role-based Access Control)策略中分配的許可權存取各種資源。
僅將許可權授予需要存取流水線內金鑰的應用程式。團隊應始終如一地稽核許可權,確保在流水線的整個生命週期中最小許可權原則得以實施和維護。
這一節我們將會介紹3個實際使用金鑰的Jenkins和Akeyless金鑰管理平臺的基本例子:
首先,我們將會在Jenkins中建立一個「freestyle」專案,並將其連線到GitHub Repo:
無論我們選擇如何管理程式碼中的金鑰,使用Jenkins內建的憑證機制來存取GitHub倉庫是有用的。
我們的實際程式碼將是一個非常基本的Python應用程式,它進行API呼叫。該API需要一個簡單的API金鑰,以文字字串的形式進行認證:
#!/usr/bin/env python
import os
import requests
api_key = os.environ[‘API_KEY’]response = requests.get(「https://thedogapi.com/v1/breeds?api_key={}」.format(api_key))
print(response)
Jenkins提供了設定環境變數的功能,然而,如果沒有額外的外掛,它們只能對Jenkins的環境或範例進行全域性設定。
程式碼將從剛才設定的環境變數中讀取API金鑰。下面是構建步驟的設定:
構建步驟執行一些簡單的提示,然後實際執行程式碼。下面是一個成功構建的紀錄檔的一部分:
API金鑰顯然已經在一個構建步驟中的一個簡單指令中以明文紀錄檔的形式暴露出來。一個小小的錯誤設定就有可能導致洩露或危險。
現在我們可以嘗試通過使用內建的證書處理程式來提高我們構建環境的安全性:
在本例中,我們將使用簡單的「Secret Text」憑據繫結來儲存API金鑰:
接下來,我們設定我們的構建job來使用新的憑證變數:
現在,在執行另一個構建job後,我們再次檢查構建紀錄檔:
儘管我們已經將構建步驟設定為將變數內容列印到紀錄檔中,但Jenkins憑證處理程式知道該值是敏感的,並在任何紀錄檔或輸出中混淆了實際值。
這固然極大地提高了構建的安全性,但並不是十全十美的。這對一個使用者量較少的Jenkins部署已經足夠用,但在一個大型的、分散式的Jenkins架構中,需要管理多個使用者和團隊的存取許可權,這十分複雜,難以有效管理。此外,儲存在憑證變數中的金鑰值仍然可以被叢集中的每個Jenkins範例以及具有適當許可權的任何使用者存取。
如果任意節點被破壞,跨越多個部署和上下文的金鑰可能處於危險之中。使用者仍然需要手動保護和設定Jenkins的基礎設施,在本例中指金鑰儲存。如果有一種方法可以使用敏感的憑證,而不需要將他們儲存在Jenkins內部,會怎麼樣呢?
讓我們試試使用Akeyless來管理金鑰。既然我們已經和Jenkins部署整合,我們可以按照檔案來進行操作。Akeyless與公開可用的Hashicorp Vault外掛整合,因此Jenkins的設定很簡單。
接下來,我們將建立一個免費的Akeyless並設定金鑰:
下一步是建立一個存取角色,並且該角色有許可權存取剛剛建立的金鑰:
現在我們需要給我們的存取角色以正確的許可權來檢視金鑰:
在Akeyless側我們需要建立的最後一個東西是一種認證方式。這就是我們如何讓外部實體,如我們的Jenkins部署,能夠對Akeyless進行API呼叫並檢索金鑰。
認證方式建立完畢後,請確保通過下載CSV檔案來儲存存取ID和金鑰,否則這些值將不會再次顯示。最後,我們需要將我們新建立的角色與這個存取方式聯絡起來。
下一步是根據Akeyless檔案設定Jenkins構建環境:
現在,我們將執行另一個構建,這次設定的是利用此前設定過的Akeyless vault
在紀錄檔中,現在有一個步驟展示了Jenkins從Akeyless Vault中檢索金鑰。但構建紀錄檔中的憑證值也依舊是模糊的。現在,我們有了一個與Jenkins範例整合的第三方金鑰管理平臺。
這看起來有些畫蛇添足,但是一個完全專注於金鑰管理的外部工具是一個強大的抽象。Jenkins首先是一個CI/CD工具,金鑰管理是一個附加功能。在這種情況下,它永遠無法提供一流的功能、管理能力和安全保障,而專門的金鑰管理平臺則可以提供:
像Akeyless這樣的工具還可以避免管理複雜的、自我託管的基礎設施。我們只需點選幾下,就能擁有一個執行中的金鑰終端。
由於安全性是 CI/CD 流水線的首要考慮因素,因此在 Jenkins 中使用金鑰時遵循最佳實踐非常重要。Jenkins 流水線依賴金鑰進行身份驗證、共同作業和基礎設施管理。CI/CD 金鑰管理對大多數團隊來說都是一個挑戰,因為在細節上實施存取控制非常困難和複雜。
而通過金鑰管理工具,Jenkins 使用者可以獲得更加集中且安全的資源來管理執行 CI/CD 流水線所需的包含敏感資訊的憑據,加速 DevOps 工作流程。同時,安全團隊也能夠全面瞭解金鑰的位置和使用方式。藉助自動化流程和集中存取策略,金鑰管理平臺還可以幫助安全團隊應對安全相關的法律和合規問題。