現代軟體開發已經進入了安全左移的時代,開發團隊不再將安全性視為上線前的最後一道關卡,而是將其深度整合到整個開發生命週期中。這種轉變源自於一個簡單但深刻的認知:越早發現安全問題,修復的成本就越低,對產品品質的影響也越小。GitLab 作為完整的 DevOps 平台,提供了從程式碼提交到生產佈署的一站式解決方案,讓安全檢測與開發流程無縫結合。
在傳統的開發模式中,安全測試往往是獨立的階段,由專門的安全團隊在應用程式開發完成後才開始進行。這種做法不僅拉長了交付週期,更可能在接近上線時才發現重大漏洞,導致大量返工甚至延期發布。GitLab 的 DevSecOps 理念徹底改變了這個流程,透過將各種安全掃描工具整合到 CI/CD Pipeline 中,讓每次程式碼提交都自動經過多層次的安全檢測。從靜態程式碼分析到動態應用測試,從第三方套件掃描到容器映像檢查,每個環節都有對應的防護機制。
程式碼的封裝與佈署同樣是軟體交付過程中的關鍵環節。GitLab 透過套件註冊表與容器註冊表的設計,提供了統一的程式碼產物管理機制。開發團隊可以將經過測試與驗證的程式碼編譯成可重複使用的套件或容器映像,透過版本控制與權限管理,確保只有經過審核的版本才能進入生產環境。這種集中管理的方式不僅提升了佈署的可靠性,也為問題追蹤與版本回溯提供了完整的基礎。
建立安全為先的開發文化
安全掃描工具的價值不僅在於技術層面的漏洞檢測,更重要的是推動組織文化的轉變。當開發者在提交程式碼的當下就能收到安全問題的即時回饋時,安全意識自然會深植於日常的開發活動中。GitLab 的安全掃描架構建立在開源工具的基礎上,這個設計選擇帶來了多重優勢。開源工具的運作邏輯完全透明,任何人都可以檢視其檢測規則與判斷標準,這種透明度對於建立信任感至關重要。
這些掃描工具支援跨語言的程式碼檢測能力,無論團隊使用的是 Java、Python、JavaScript、Go 或是其他程式語言,都能獲得一致的安全防護。工具的維護與更新由活躍的開源社群推動,當新的攻擊手法或漏洞模式被發現時,檢測規則能夠快速更新,確保防護能力始終與時俱進。所有的安全掃描器都透過 Docker 容器進行封裝,這個技術選擇大幅簡化了整合流程,開發團隊不需要在每個執行環境中手動安裝各種掃描工具,只需在 CI/CD 設定檔中宣告所需的掃描工作即可。
整個安全掃描流程與 GitLab 的合併請求機制深度整合。當開發者建立合併請求時,系統會自動觸發完整的安全檢測流程,並在合併請求的介面上直接呈現掃描結果。這種即時回饋機制讓程式碼審查者能夠同時評估功能實作與安全風險,在程式碼進入主分支之前就完成安全驗證。更進一步的是,團隊可以設定安全門檻,當發現高危漏洞時自動阻擋合併請求,從根本上防止不安全的程式碼進入生產環境。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
package "GitLab DevSecOps 架構" {
component "程式碼儲存庫" as repo {
[原始碼管理]
[版本控制]
[合併請求]
}
component "CI/CD Pipeline" as pipeline {
[建構階段]
[測試階段]
[安全掃描]
[佈署階段]
}
component "安全掃描工具" as security {
[SAST 靜態分析]
[DAST 動態測試]
[依賴掃描]
[容器掃描]
[秘密檢測]
[IaC 掃描]
}
component "產物管理" as artifacts {
[套件註冊表]
[容器註冊表]
[版本控制]
}
component "佈署目標" as targets {
[開發環境]
[測試環境]
[預生產環境]
[生產環境]
}
}
actor "開發者" as dev
actor "安全團隊" as sec_team
cloud "外部服務" as external
dev -> repo: 提交程式碼
repo -> pipeline: 觸發建構
pipeline -> security: 執行掃描
security -> security: 分析與檢測
security -> pipeline: 回報結果
pipeline -> artifacts: 儲存產物
artifacts -> targets: 佈署應用
security -> sec_team: 安全報告
pipeline -> dev: 即時回饋
note right of security
多層次安全防護
- 靜態程式碼分析
- 動態應用測試
- 第三方套件檢查
- 容器映像掃描
- 敏感資訊偵測
- 基礎設施檢查
end note
@enduml靜態程式碼分析的深度應用
靜態應用程式安全測試是安全左移策略的基石,這種檢測方式在程式碼編譯或執行之前就進行安全分析。透過分析原始碼的語法結構、資料流向與控制流程,SAST 工具能夠識別出可能導致安全漏洞的程式模式。這種檢測方式的最大優勢在於其執行速度與準確性,不需要實際運行應用程式就能發現大量的潛在問題。
當開發者撰寫資料庫查詢邏輯時,如果直接將使用者輸入拼接到 SQL 語句中,SAST 工具會立即標記這個風險點。SQL 注入攻擊是 Web 應用程式最常見且危害最嚴重的漏洞之一,攻擊者可以透過精心構造的輸入字串來操縱 SQL 查詢的邏輯,進而竊取或破壞資料庫內容。SAST 工具不僅能指出問題所在的程式碼行數,還會提供修正建議,例如使用參數化查詢或預備語句來取代字串拼接。
跨站腳本攻擊同樣是 SAST 工具關注的重點。當程式碼將使用者提供的資料直接輸出到網頁內容中而沒有進行適當的編碼處理時,攻擊者就可能注入惡意的 JavaScript 程式碼。這些惡意程式碼能夠竊取使用者的 Cookie、會話權杖,甚至完全控制使用者的瀏覽器會話。透過靜態分析,開發團隊能夠在程式碼審查階段就發現這些風險,避免將漏洞帶入生產環境。
include:
- template: Security/SAST.gitlab-ci.yml
variables:
SAST_EXCLUDED_PATHS: "tests/,migrations/"
SAST_EXCLUDED_ANALYZERS: "bandit,eslint"
stages:
- build
- test
- security
- deploy
compile_application:
stage: build
image: maven:3.8-openjdk-17
script:
- echo "開始編譯 Java 應用程式..."
- mvn clean compile -DskipTests
- echo "產生建構產物..."
- mvn package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 1 week
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository
unit_tests:
stage: test
image: maven:3.8-openjdk-17
script:
- echo "執行單元測試套件..."
- mvn test
- echo "產生測試覆蓋率報告..."
- mvn jacoco:report
artifacts:
reports:
junit: target/surefire-reports/TEST-*.xml
coverage_report:
coverage_format: cobertura
path: target/site/jacoco/jacoco.xml
coverage: '/Total.*?([0-9]{1,3})%/'
dependencies:
- compile_application
sast_security_scan:
stage: security
needs:
- compile_application
allow_failure: false
before_script:
- echo "準備靜態安全掃描環境..."
- echo "掃描範圍: 排除測試與遷移檔案"
script:
- echo "開始深度程式碼安全分析..."
- /analyzer run
artifacts:
reports:
sast: gl-sast-report.json
paths:
- gl-sast-report.json
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
這個 SAST 設定展現了實務上的細緻考量。透過排除測試程式碼與資料庫遷移腳本,掃描焦點能夠集中在實際的業務邏輯程式碼上,減少誤報並提升掃描效率。設定 allow_failure 為 false 表明團隊對安全的嚴格要求,任何被 SAST 發現的問題都必須先行修正才能繼續後續流程。掃描結果以標準化的 JSON 格式儲存,方便後續的自動化處理與報告產生。
敏感資訊洩漏的防護機制
秘密檢測專注於防止敏感資訊意外洩漏到版本控制系統中,這是資訊安全防護中極為關鍵但經常被忽視的一環。在開發過程中,工程師為了方便測試或除錯,可能會在設定檔或程式碼中直接寫入 API 金鑰、資料庫密碼、雲端服務憑證等敏感資訊。這些資訊一旦被提交到 Git 儲存庫,就會永久保留在版本歷史中,即使後續刪除也無法完全消除洩漏風險。
Secret Detection 工具使用先進的模式比對演算法與機器學習技術,能夠識別各種常見的敏感資訊格式。不僅是明顯的密碼或金鑰,連結串中包含的憑證、環境變數設定、甚至是 Base64 編碼後的敏感資料都在檢測範圍內。工具維護了一個龐大的規則庫,涵蓋了主流雲端服務提供者、第三方 API 服務、資料庫系統的憑證格式。當偵測到疑似的敏感資訊時,系統會在合併請求中顯示明確的警告訊息,阻止這些內容進入程式碼庫。
# 錯誤示範:敏感資訊直接寫在程式碼中
class DatabaseConnection:
def __init__(self):
self.config = {
'host': 'prod-db.example.com',
'port': 5432,
'username': 'admin',
'password': 'Sup3rS3cr3tP@ssw0rd', # Secret Detection 會標記
'database': 'production',
'ssl_mode': 'require'
}
def connect(self):
# 建立資料庫連線的邏輯
pass
# 正確做法:從環境變數讀取敏感資訊
import os
from typing import Optional
class SecureDatabaseConnection:
def __init__(self):
self.config = {
'host': os.getenv('DB_HOST', 'localhost'),
'port': int(os.getenv('DB_PORT', '5432')),
'username': os.getenv('DB_USER'),
'password': os.getenv('DB_PASSWORD'),
'database': os.getenv('DB_NAME'),
'ssl_mode': os.getenv('DB_SSL_MODE', 'require')
}
self._validate_config()
def _validate_config(self):
"""驗證必要的環境變數是否已設定"""
required_vars = ['DB_USER', 'DB_PASSWORD', 'DB_NAME']
missing_vars = [var for var in required_vars if not os.getenv(var)]
if missing_vars:
raise ValueError(
f"缺少必要的環境變數: {', '.join(missing_vars)}"
)
def connect(self):
"""建立安全的資料庫連線"""
try:
# 實際的連線邏輯
connection = self._create_connection()
return connection
except Exception as e:
# 記錄錯誤但不洩漏敏感資訊
print(f"資料庫連線失敗: {type(e).__name__}")
raise
這個範例清楚展示了處理敏感資訊的正確與錯誤方式。當密碼直接寫在程式碼中時,不僅 Secret Detection 工具會發出警告,更嚴重的是任何能夠存取儲存庫的人員都能看到這個密碼。使用環境變數的方式則完全不同,所有敏感資訊都在執行時期動態讀取,程式碼本身不包含任何機密內容。GitLab 的 CI/CD 變數功能提供了安全的儲存機制,支援變數加密、存取權限控制、以及審計日誌記錄。
secret_detection:
stage: security
image:
name: registry.gitlab.com/gitlab-org/security-products/analyzers/secrets:latest
script:
- echo "開始掃描程式碼中的敏感資訊..."
- /analyzer run
artifacts:
reports:
secret_detection: gl-secret-detection-report.json
paths:
- gl-secret-detection-report.json
allow_failure: false
rules:
- if: $CI_MERGE_REQUEST_IID
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_COMMIT_TAG
variables:
SECRET_DETECTION_EXCLUDED_PATHS: "tests/fixtures/,docs/"
SECRET_DETECTION_HISTORIC_SCAN: "false"
這個秘密檢測設定涵蓋了多種觸發情境,包括合併請求、主分支提交以及版本標籤建立。設定排除了測試固件與文件目錄,因為這些位置可能包含範例資料或文件說明,不應觸發誤報。歷史掃描功能被設定為關閉狀態,這是因為掃描整個 Git 歷史會消耗大量時間與資源,通常只在初次啟用工具時執行一次完整的歷史掃描。
動態應用測試的實戰技巧
動態應用程式安全測試採用了截然不同的檢測策略,這種方式針對正在運作中的應用程式進行測試,更接近真實世界的攻擊情境。DAST 工具會模擬惡意使用者的行為,嘗試對應用程式發送各種精心構造的惡意請求,透過觀察應用程式的回應方式來判斷是否存在安全漏洞。這種動態測試能夠發現許多在靜態分析階段難以察覺的問題,特別是那些只有在執行時期才會顯現的漏洞。
跨站請求偽造攻擊就是一個典型的例子,這類攻擊涉及瀏覽器的同源政策、Cookie 的自動傳遞機制等執行時期的特性,靜態分析工具很難準確判斷。DAST 工具會從不同的來源發送請求,檢查應用程式是否正確驗證請求的來源,是否實作了 CSRF Token 機制,以及 Token 的驗證邏輯是否嚴謹。透過這種實際的攻擊模擬,能夠全面評估應用程式的防護能力。
OWASP ZAP 是業界廣泛使用的開源 DAST 工具,GitLab 預設整合了這個強大的安全測試平台。當執行 DAST 掃描時,ZAP 會啟動一個攔截代理伺服器,分析所有進出應用程式的 HTTP 流量。它會自動探索應用程式的所有頁面與 API 端點,建立完整的網站架構圖。接著針對每個端點執行一系列的安全測試,包括注入攻擊、認證繞過、授權檢查、敏感資料洩漏等多達數百種測試案例。
variables:
DAST_WEBSITE: "https://staging.example.com"
DAST_AUTH_URL: "https://staging.example.com/login"
DAST_USERNAME: "test_user"
DAST_PASSWORD: ${DAST_TEST_PASSWORD}
DAST_FULL_SCAN_ENABLED: "true"
DAST_BROWSER_SCAN: "true"
deploy_staging:
stage: deploy
image: alpine:latest
script:
- echo "佈署應用程式到測試環境..."
- apk add --no-cache curl
- ./deploy_to_staging.sh
- echo "等待應用程式啟動完成..."
- sleep 30
- |
for i in {1..10}; do
if curl -f ${DAST_WEBSITE}/health; then
echo "應用程式已就緒"
break
fi
echo "等待應用程式啟動 (嘗試 $i/10)..."
sleep 10
done
environment:
name: staging
url: ${DAST_WEBSITE}
on_stop: stop_staging
dast_full_scan:
stage: security
image:
name: owasp/zap2docker-stable:latest
variables:
GIT_STRATEGY: none
script:
- mkdir -p /zap/wrk
- echo "開始完整的動態安全掃描..."
- echo "目標網站: ${DAST_WEBSITE}"
- |
zap-full-scan.py \
-t ${DAST_WEBSITE} \
-r dast-report.html \
-J gl-dast-report.json \
-a \
--hook=/zap/auth_hook.py
- echo "掃描完成,分析結果..."
artifacts:
paths:
- dast-report.html
reports:
dast: gl-dast-report.json
expire_in: 30 days
dependencies:
- deploy_staging
allow_failure: true
only:
- merge_requests
- schedules
這個 DAST 設定展現了完整的動態測試流程。應用程式首先被佈署到獨立的測試環境,確保掃描活動不會影響到生產服務。佈署腳本包含了健康檢查邏輯,確認應用程式完全啟動後才開始掃描。DAST 工具設定為完整掃描模式,這意味著會執行所有可用的測試案例,雖然耗時較長但能提供最全面的安全評估。掃描結果以 HTML 和 JSON 兩種格式儲存,前者便於人工審查,後者則用於自動化處理與趨勢分析。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
participant "GitLab Runner" as runner
participant "測試環境" as staging
participant "OWASP ZAP" as zap
participant "Web 應用程式" as app
database "掃描報告" as report
runner -> staging: 佈署應用程式
activate staging
staging -> app: 啟動服務
activate app
runner -> runner: 等待應用程式就緒
runner -> app: 健康檢查
app --> runner: 服務正常
runner -> zap: 啟動 DAST 掃描
activate zap
zap -> app: Spider 爬取\n發現所有端點
app --> zap: 網站架構圖
zap -> zap: 分析攻擊面\n規劃測試案例
loop 對每個端點進行測試
zap -> app: SQL 注入測試
app --> zap: 回應分析
zap -> app: XSS 攻擊測試
app --> zap: 回應分析
zap -> app: CSRF 測試
app --> zap: 回應分析
zap -> app: 認證繞過測試
app --> zap: 回應分析
zap -> app: 敏感資料洩漏檢查
app --> zap: 回應分析
end
zap -> zap: 彙整掃描結果\n評估風險等級
zap -> report: 產生詳細報告
deactivate zap
runner -> report: 上傳到 GitLab
report --> runner: 報告連結
deactivate app
deactivate staging
note right of zap
DAST 測試項目
- 注入攻擊測試
- 跨站腳本攻擊
- 跨站請求偽造
- 認證與授權缺陷
- 敏感資料洩漏
- 安全設定錯誤
- XML 外部實體注入
- 反序列化漏洞
end note
@enduml這個時序圖完整描繪了 DAST 掃描的執行流程。從應用程式佈署到測試環境開始,經過健康檢查確認服務正常後,DAST 工具才啟動掃描流程。Spider 階段會系統性地爬取整個網站,建立完整的 URL 地圖與參數清單。接著針對每個發現的端點執行多種攻擊測試,觀察應用程式的回應並判斷是否存在漏洞。整個過程完全自動化,無需人工介入。
依賴套件的安全治理
現代軟體開發高度仰賴第三方開源套件,這些依賴套件極大地提升了開發效率,但同時也引入了新的安全風險。一個典型的 Web 應用程式可能直接或間接依賴數百個外部程式庫,這些程式庫如果存在已知漏洞,就會成為整個應用程式的安全弱點。依賴套件掃描專門用於檢測這類風險,透過與公開漏洞資料庫的比對,識別出專案中使用的有漏洞版本。
掃描工具會深入分析專案的依賴宣告檔案,不僅檢查直接依賴的套件,還會遞迴分析間接依賴的整個依賴樹。這種深度掃描能夠發現隱藏在依賴鏈深處的漏洞,這些漏洞往往是開發者不易察覺的。系統會將提取出的套件資訊與 CVE 漏洞資料庫、NVD 國家漏洞資料庫、以及各個程式語言生態系統的安全公告進行比對。
當發現依賴套件存在已知漏洞時,掃描報告會提供豐富的資訊協助團隊評估與處理。報告不僅列出受影響的套件名稱與版本,還包含漏洞的詳細說明、CVSS 評分、影響範圍、以及建議的修補方式。對於高危漏洞,系統會明確指出可升級的安全版本,讓開發團隊能夠快速採取行動。對於無法直接升級的情況,報告也會提供替代方案或臨時緩解措施的建議。
dependency_scanning:
stage: security
image:
name: registry.gitlab.com/gitlab-org/security-products/analyzers/gemnasium:latest
script:
- echo "分析專案依賴套件安全性..."
- /analyzer run
artifacts:
reports:
dependency_scanning: gl-dependency-scanning-report.json
paths:
- gl-dependency-scanning-report.json
allow_failure: false
rules:
- if: $CI_MERGE_REQUEST_IID
changes:
- package.json
- package-lock.json
- requirements.txt
- Pipfile
- Pipfile.lock
- pom.xml
- build.gradle
- go.mod
- go.sum
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
license_scanning:
stage: security
image:
name: registry.gitlab.com/gitlab-org/security-products/analyzers/license-finder:latest
script:
- echo "掃描套件授權條款..."
- /analyzer run
artifacts:
reports:
license_scanning: gl-license-scanning-report.json
allow_failure: true
only:
- merge_requests
這個依賴掃描設定包含了智慧化的觸發邏輯。當合併請求修改了依賴宣告檔案時,掃描會自動執行以評估新引入的套件是否安全。這種針對性的掃描策略既確保了安全性,又避免了不必要的資源消耗。授權條款掃描是依賴管理的另一個重要面向,它檢查專案使用的套件授權是否與專案本身的授權相容,避免潛在的法律風險。
容器映像的多層防護
容器化技術徹底改變了應用程式的封裝與佈署方式,但也帶來了新的安全挑戰。Docker 容器映像由多個層次疊加而成,每一層都可能包含作業系統套件、系統程式庫、執行時期環境或應用程式元件。這些元件如果存在已知漏洞,就會讓整個容器環境暴露在風險之中。容器安全掃描針對這個問題提供了全面的檢測能力。
掃描工具會深入分析容器映像的每一層,識別出其中包含的所有軟體套件與檔案。這個過程不僅檢查應用程式本身的依賴,也會檢查基礎映像中包含的作業系統元件。許多安全問題其實源自於過時的基礎映像,例如使用了舊版本的 Ubuntu 或 Alpine Linux,其中包含的系統套件可能存在已被修補的漏洞。定期重建容器映像並使用最新的基礎映像版本是降低風險的重要實務作法。
# 不良實務:使用過時的基礎映像
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y python3 python3-pip
COPY requirements.txt .
RUN pip3 install -r requirements.txt
COPY app.py .
CMD ["python3", "app.py"]
# 良好實務:使用最新的安全基礎映像
FROM ubuntu:22.04-slim AS base
# 建立非特權使用者
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 更新系統套件並安裝必要元件
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
python3.10 \
python3-pip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 建構階段:安裝依賴
FROM base AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip3 install --user --no-cache-dir -r requirements.txt
# 執行階段:最小化映像
FROM base AS runtime
WORKDIR /app
# 從建構階段複製安裝的套件
COPY --from=builder /root/.local /root/.local
COPY --chown=appuser:appuser app.py .
# 使用非特權使用者執行
USER appuser
# 暴露應用程式埠
EXPOSE 8080
# 健康檢查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python3 -c "import requests; requests.get('http://localhost:8080/health')"
CMD ["python3", "app.py"]
這個 Dockerfile 範例展示了容器安全的最佳實踐。使用多階段建構可以顯著減小最終映像的大小,因為建構工具與中間檔案都不會包含在執行階段映像中。建立專用的非特權使用者並以此身份執行應用程式,即使容器被攻破,攻擊者也無法取得 root 權限。定期更新基礎映像與系統套件確保所有元件都是最新的安全版本。
build_container:
stage: build
image: docker:24-dind
services:
- docker:24-dind
variables:
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_DRIVER: overlay2
before_script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
script:
- echo "建構 Docker 容器映像..."
- docker build
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
--build-arg VCS_REF=$CI_COMMIT_SHORT_SHA
--build-arg VERSION=$CI_COMMIT_TAG
--tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
--tag $CI_REGISTRY_IMAGE:latest
.
- echo "推送映像到容器註冊表..."
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY_IMAGE:latest
- echo "產生映像清單..."
- docker inspect $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA > image-manifest.json
artifacts:
paths:
- image-manifest.json
expire_in: 7 days
after_script:
- docker logout $CI_REGISTRY
container_scanning:
stage: security
image:
name: registry.gitlab.com/gitlab-org/security-products/analyzers/container-scanning:latest
variables:
GIT_STRATEGY: none
CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
CS_SEVERITY_THRESHOLD: "high"
script:
- echo "開始掃描容器映像: ${CS_IMAGE}"
- gtcs scan
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
paths:
- gl-container-scanning-report.json
dependencies:
- build_container
allow_failure: false
容器掃描工作在映像建構完成後立即執行,確保只有通過安全檢查的映像才會被用於後續的佈署流程。嚴重程度閾值設定為 high 表示只要發現高危或嚴重等級的漏洞,掃描就會失敗,這種嚴格的標準能夠有效阻止不安全的映像進入生產環境。
基礎設施即程式碼的安全審查
當團隊採用基礎設施即程式碼的實務時,所有的雲端資源、網路設定、安全群組規則都以宣告式的程式碼形式定義。這種做法帶來了版本控制、可重複性與自動化等諸多優勢,但同時也需要確保這些基礎設施定義本身是安全的。IaC 掃描工具專門用於檢查 Terraform、CloudFormation、Kubernetes YAML 等基礎設施定義檔案中的安全問題。
掃描工具會根據雲端安全最佳實務規則檢查每個資源的設定。常見的問題包括資料庫實例沒有啟用加密、儲存貯體設定為公開存取、網路安全群組開放了過於寬鬆的存取規則、或是沒有啟用日誌記錄機制。這些設定錯誤可能導致嚴重的安全後果,例如敏感資料洩漏、未經授權的存取、或是合規性違規。
iac_security_scan:
stage: security
image:
name: bridgecrew/checkov:latest
entrypoint: [""]
script:
- echo "掃描 Terraform 基礎設施定義..."
- checkov -d terraform/
--framework terraform
--output json
--output-file gl-iac-report.json
--soft-fail
- echo "掃描 Kubernetes 設定檔..."
- checkov -d k8s/
--framework kubernetes
--output json
--output-file gl-k8s-report.json
--soft-fail
artifacts:
reports:
sast: gl-iac-report.json
paths:
- gl-iac-report.json
- gl-k8s-report.json
allow_failure: true
only:
changes:
- terraform/**/*
- k8s/**/*
IaC 掃描的觸發邏輯設定為只在基礎設施定義檔案發生變更時執行,這種最佳化策略能夠顯著縮短 Pipeline 的整體執行時間。軟失敗模式讓團隊能夠在初期階段逐步改善基礎設施的安全性,而不是一開始就因為大量的警告而阻礙整個流程。
@startuml
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
start
:開發者提交程式碼;
fork
:編譯與建構;
:單元測試;
fork again
:秘密檢測;
fork again
:SAST 靜態分析;
fork again
:依賴套件掃描;
fork again
:IaC 安全掃描;
end fork
if (所有靜態檢查通過?) then (是)
:建構容器映像;
:容器安全掃描;
if (容器掃描通過?) then (是)
:推送到容器註冊表;
:佈署到測試環境;
:DAST 動態測試;
if (發現嚴重漏洞?) then (是)
:產生安全報告;
:通知開發團隊;
:阻止佈署;
stop
else (否)
:產生完整報告;
if (人工審查?) then (需要)
:等待審查;
:安全團隊確認;
endif
:佈署到生產環境;
:監控與驗證;
stop
endif
else (否)
:標記容器不安全;
stop
endif
else (否)
:標記建構失敗;
stop
endif
@enduml這個完整的安全掃描流程圖展現了多層次防護的實作方式。所有的靜態掃描工具在測試階段完成後同時啟動,充分利用 GitLab Runner 的平行執行能力。只有當所有靜態掃描都通過後,才會進入容器建構與動態測試階段。這種分層檢查的設計既確保了全面的安全防護,又最佳化了執行效率。
GitLab 的 DevSecOps 實踐將安全檢測深度整合到整個開發生命週期中,從程式碼提交的第一刻就開始進行多層次的防護。透過 SAST、DAST、依賴掃描、容器掃描等多種工具的協同運作,開發團隊能夠在早期階段發現並修正安全問題。搭配套件註冊表與容器註冊表的版本管理機制,以及精心設計的 CI/CD Pipeline,應用程式能夠安全且可靠地佈署到各種目標環境。這套完整的實務方法不僅提升了開發效率,更建立了堅實的安全防護機制,讓團隊能夠持續交付高品質且安全的軟體產品,在快速迭代與安全防護之間取得最佳平衡。