srujantata/container-image-hardening
GitHub: srujantata/container-image-hardening
这是一个集成多种安全工具的容器镜像加固工具集,用于自动化CI/CD中的安全扫描、合规检查和镜像签名。
Stars: 0 | Forks: 0
# 容器镜像加固
[](https://github.com/srujantata/container-image-hardening/actions)
一套用于构建和审计安全容器镜像的实用工具集:
**Hadolint** 代码检查、**多阶段无发行版**构建、**Trivy** CVE 扫描、
**kube-bench** CIS 基准测试,以及 **Cosign** 无密钥签名——全部集成到 CI 流程中。
## 涵盖内容
| 技术 | 工具 | 结果 |
|------|------|------|
| Dockerfile 最佳实践强制执行 | Hadolint | 在编写时捕获误用 |
| 最小化攻击面 | 多阶段 + 无发行版基础镜像 | 最终镜像中无 shell,无包管理器 |
| 已知 CVE 拦截 | Trivy | 在 CI 中阻止 CRITICAL/HIGH 级别漏洞 |
| CIS Kubernetes 基准测试 | kube-bench | 节点和控制平面状态报告 |
| 防篡改镜像来源 | Cosign (无密钥) | 签名存储在注册表中,可在任何地方验证 |
## 架构
```
Developer writes Dockerfile
│
▼
Hadolint (lint) ──► violations? ──► PR blocked
│ clean
▼
docker build (multi-stage)
└── Stage 1: golang:1.22 (build)
└── Stage 2: gcr.io/distroless/base (final — no shell)
│
▼
Trivy image scan ──► CRITICAL CVE? ──► PR blocked
│ clean
▼
Push to GHCR
│
▼
Cosign sign (keyless OIDC — no stored key)
│
▼
Deploy to cluster
│
▼
kube-bench Job ──► CIS compliance report in CI output
```
## Hadolint
Hadolint 解析您的 Dockerfile 并标记违反 Docker 最佳规范的行为。
在提交前于 CI 和本地环境中运行它。
```
# 安装
brew install hadolint # macOS
choco install hadolint # Windows
# 运行
hadolint Dockerfile
```
示例违规:
```
Dockerfile:3 DL3008 Pin versions in apt-get install: apt-get install -y curl
Dockerfile:7 DL3006 Always tag the version of the image you're using
Dockerfile:11 SC2086 Double quote to prevent globbing: COPY $SRC /app
```
配置 (`.hadolint.yaml`):
```
ignore:
- DL3018 # accept unpinned apk in build stage only
failure-threshold: error
```
## 多阶段无发行版构建
第一阶段在完整的 SDK 镜像中完成所有编译工作。
第二阶段仅将二进制文件复制到无发行版镜像中——无 shell,无 apt,无额外的 libc 库。
```
# Dockerfile
# ── 阶段 1: 构建 ────────────────────────────────────────────────────────────
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /app/server ./cmd/server
# ── 阶段 2: 运行时 (distroless — 无 shell,无包管理器) ──────────────
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
USER nonroot:nonroot
ENTRYPOINT ["/server"]
```
改造前 vs 改造后:
```
Base image: golang:1.22 → 819 MB
Base image: distroless/static → 2.5 MB (-99.7%)
CVEs (Trivy):
golang:1.22 → 23 MEDIUM, 6 HIGH, 2 CRITICAL
distroless/static → 0 CVEs
```
## CI 中的 Trivy 扫描
```
# .github/workflows/scan.yml (节选)
- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/srujantata/my-app:${{ github.sha }}
format: table
exit-code: 1 # fail CI if vulnerabilities found
severity: CRITICAL,HIGH
ignore-unfixed: true # skip CVEs with no upstream fix yet
```
Trivy 输出示例:
```
ghcr.io/srujantata/my-app:abc1234 (debian 12.5)
OS/Arch: linux/amd64
Total: 0 (CRITICAL: 0, HIGH: 0)
```
如果发现漏洞:
```
Total: 2 (CRITICAL: 1, HIGH: 1)
┌──────────────────┬────────────────┬──────────┬──────────┬──────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed│ Fixed Version │
├──────────────────┼────────────────┼──────────┼──────────┼──────────────────────┤
│ libssl3 │ CVE-2024-5535 │ CRITICAL │ 3.0.13-1 │ 3.0.14-1~deb12u1 │
│ curl │ CVE-2024-2398 │ HIGH │ 7.88.1-1 │ 7.88.1-10+deb12u6 │
└──────────────────┴────────────────┴──────────┴──────────┴──────────────────────┘
```
## kube-bench CIS 基准测试
kube-bench 对控制平面和工作节点运行 CIS Kubernetes 基准测试检查。
```
# k8s/kube-bench-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench
namespace: kube-system
spec:
template:
spec:
hostPID: true
containers:
- name: kube-bench
image: aquasec/kube-bench:v0.7.3
command: ["kube-bench", "run", "--targets", "node"]
volumeMounts:
- name: var-lib-kubelet
mountPath: /var/lib/kubelet
readOnly: true
- name: etc-systemd
mountPath: /etc/systemd
readOnly: true
restartPolicy: Never
volumes:
- name: var-lib-kubelet
hostPath:
path: /var/lib/kubelet
- name: etc-systemd
hostPath:
path: /etc/systemd
```
输出示例:
```
[INFO] 4 Worker Node Security Configuration
[INFO] 4.1 Worker Node Configuration Files
[PASS] 4.1.1 Ensure that the kubelet service file permissions are set to 644
[PASS] 4.1.2 Ensure that the kubelet service file ownership is set to root:root
[WARN] 4.2.6 Ensure that the --protect-kernel-defaults argument is set to true
[FAIL] 4.2.11 Ensure that the RotateKubeletServerCertificate argument is set to true
== Summary node ==
16 checks PASS
1 checks FAIL
3 checks WARN
```
## Cosign 无密钥签名
```
# .github/workflows/sign.yml (节选)
- name: Sign image with Cosign
env:
COSIGN_EXPERIMENTAL: "true"
run: |
cosign sign --yes \
ghcr.io/srujantata/my-app@${{ steps.build.outputs.digest }}
```
```
# 随时随地验证
cosign verify \
--certificate-identity-regexp="https://github.com/srujantata/container-image-hardening" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
ghcr.io/srujantata/my-app:latest
```
## 展示的技能
- 使用 Hadolint 进行 Dockerfile 代码检查及最佳实践强制执行
- 多阶段构建将镜像大小和 CVE 攻击面减少 99% 以上
- 无发行版基础镜像(无 shell,无包管理器,默认非 root)
- Trivy 漏洞扫描与基于严重级别的 CI 拦截
- kube-bench CIS Kubernetes 基准节点审计
- 使用 GitHub Actions OIDC 进行 Cosign 无密钥镜像签名
标签:Chrome Headless, CI/CD安全集成, Claude, Cosign签名, CVE检测, DevSecOps, Distroless镜像, Docker安全, GitHub Advanced Security, Hadolint最佳实践, kube-bench CIS基准, Kubernetes安全, Trivy漏洞扫描, 上游代理, 多阶段构建, 子域名突变, 安全加固, 安全基准检查, 容器安全工具, 容器镜像安全, 无shell镜像, 请求拦截, 镜像安全扫描, 镜像扫描工具, 镜像签名验证