在軟體開發的過程中,從原始碼的開發編輯、套件的使用直到完成後,上線的日常維運,各個環節中,都會經歷一些安全性的議題,可能一個不小心,就會造成資安疑慮,那麼,使用 Pipeline 的過程中,有哪些特別需要注意的安全性議題呢?
關於使用 Pipeline期間的安全性議題,GitLab 官方提供了一篇Pipeline security 的專文給使用者們參考,今天的內容也會依據這篇內容為主軸並且補充自己的經驗。
機密管理是開發人員用來在環境中安全地存放敏感資料與存取控制的管理系統。通常這邊的機敏資料包括:帳號密碼、SSH Keys、Access Tokens 及其他憑證或暴露會造成危害的資料。
市面上關於機敏儲存管理也有許多的解決方案,如 HashiCorp’s Vault、Azure Key Vault和 Google Cloud Secret Manager等公司,在 GitLab 的服務中,也有直接整合這些服務,可以參考:Use external secrets in CI/CD | GitLab Docs
CI/CD 變數是在 CI/CD 管道中儲存和重複使用資料的便捷方法,但變數的安全性不如機敏管理的各種解決方案。不安全的點如:
這些變數,儲存在 GitLab 專案、Group 或 Instance 的設定中,有權限存取這些設定的使用者,就可以儲存這些未隱藏的變數數值。
因為變數在 Pipeline 的使用過程中,是可能在過程中被覆蓋的,因此不容易確定最終使用的數值。
這些數值,容易因為 Pipeline 的配置錯誤而造成暴露。
所以儲存在設定中的變數,應該要是非機敏或沒有被利用的風險的資料。如果沒有使用機敏資料的管理方案,至少在設定 CI/CD 變數的時候,要可以做到:
Mask 變數
隱藏變數
讓變數只在特定的分支使用
細節內文可以參考:GitLab CI/CD variables - CI/CD variable security | GitLab Docs
建議開始使用 CI/CD inputs 而不是直接使用 Pipeline Variables,因為:
一個完整的 Pipeline 安全除了 Pipeline 運行的過程外,還包含:
需要特別注意安全性的環境,在使用 Docker Image 時,可以透過鎖定 Image 的 SHA來確保使用的 Image 就是預期想使用的。例如:
image: node@sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
而不是直接使用:
image: python:3.9
在使用 image 的過程中,為了避免使用的 Image 來自惡意的 mirror,建議明確的指定來源,盡量不要在image 來源上使用變數,例如:
image: my-registry.example.com/node:18.17.1
而不是使用:
image: ${CUSTOM_REGISTRY}/node:latest
image: node:${VERSION}
使用 Package 在特別需要注意安全的環節上,應該鎖定檔案的確切版本,例如 JavaScript 的相依 Package 安裝,應該使用 npm ci
而不是 npm install
,兩者的差異在於 npm ci
會從 package-lock.json
指定安裝的版本,且 package-lock.json
必須存在。
同樣的,在 yarn 上,也有類似的方法,yarn 上是:yarn install --frozen-lockfile
,而不是使用 yarn install
。
在 Python 上是:
pip install -r requirements.txt --require-hashes
pip install -r requirements.lock
而不是:
pip install -r requirements.txt
在 Go 語言上是:
go mod verify
go mod download
而不是:
go get ./...
使用外部的 Shell Command 及 Scripts,在作業系統安裝工具時,要注意驗證安裝的版本是否如預期,例如透過 nvm
來指定安裝預期的 node 版本。
在 GitLab CI/CD YAML 的使用上也要特別注意,如 include 到外部的 CI/CD Components 時:
include:
- project: 'my-group/my-project'
ref: 8b0c8b318857c8211c15c6643b0894345a238c4e # Pin to a specific commit
file: '/templates/build.yml'
- project: 'my-group/security'
ref: v2.1.0 # Pin to a protected tag
file: '/templates/scan.yml'
- component: 'my-group/security-scans' # Pin to a specific version
version: '1.2.3'
而不是直接使用,不指定版本:
include:
- project: 'my-group/my-project' # Unsafe
file: '/templates/build.yml'
- component: 'my-group/security-scans' # Unsafe
- remote: 'https://example.com/security-scan.yml' # Unsafe
如果可以,減少外部相依,也是一個好方法,甚至是直接將相關內容下載到本地直接使用。
今天的這篇,主要在講述當 GitLab CI/CD Pipeline 使用的過程中特別需要注意安全性時,可以實作的方案,例如在正式環境的部署、正式版本的打包等,我認為,並不是所有的 CI/CD Pipeline 都應該同等的實作,有些純粹的開發環境,使用變動較大的版本,反而可以起到提早發現問題、提早治療的效果。因此在實作 Pipeline 安全性議題時,也要特別思考,目前執行的環境,是否需要到這個程度的安全,這樣的安全性,注意到這樣的安全性之後,會不會帶來其他的問題。我是墨嗓(陳佑竹),期待這次的內容能帶給你實用的啟發與幫助。