Files
tk-factory-services/scripts/check-webroot-security.sh
Hyungi Ahn 9d2179e47a security: 웹루트 분리 — COPY . → COPY public/ + nginx deny 3중 방어
3개 서비스(system1/system2/system3 web)에서 Dockerfile, nginx.conf,
docker-compose.yml이 외부 노출되는 취약점 수정.

[구조 수정]
- Dockerfile: COPY . → COPY public/ (정적 파일만 웹루트에 복사)
- system3 uploads: plain prefix → ^~ (regex deny 우선순위 충돌 방지)

[nginx deny (defense in depth)]
- exact match: /Dockerfile, /docker-compose.yml, /nginx.conf, /.env, /.gitignore
- prefix: ^~ /.git/ 디렉토리 전체 차단
- regex: 하위 경로 + 변형 대비

[CI 보안 게이트]
- scripts/check-webroot-security.sh: 화이트리스트 방식, find + exact match

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 09:52:53 +09:00

95 lines
2.1 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# =============================================================================
# 웹루트 보안 검증 스크립트
# 배포 후 실행: docker 이미지 내 /usr/share/nginx/html에 허용된 파일만 있는지 확인
# 화이트리스트 방식 — 허용되지 않은 파일이 있으면 FAIL
# =============================================================================
SERVICES=("system1-web" "system2-web" "system3-web")
# 허용 목록 (줄바꿈 구분 — 공백 파일명 안전)
ALLOWED_system1_web="index.html
manifest.json
sw.js
logo.png
components
css
img
js
pages
static"
ALLOWED_system2_web="push-sw.js
css
img
js
pages"
ALLOWED_system3_web="ai-assistant.html
app.html
favicon.ico
issue-view.html
issues-archive.html
issues-dashboard.html
issues-inbox.html
issues-management.html
m
push-sw.js
reports-daily.html
reports-monthly.html
reports-weekly.html
reports.html
static
sw.js
uploads"
FAIL=0
for service in "${SERVICES[@]}"; do
varname="ALLOWED_${service//-/_}"
allowed="${!varname}"
echo "Checking $service..."
# 컨테이너 생성만 (실행 안 함) → exec으로 검사 → 제거
docker compose create --no-deps "$service" >/dev/null 2>&1
container=$(docker compose ps -q "$service" | head -n1)
if [ -z "$container" ]; then
echo " FAIL: container not found for $service"
FAIL=1; continue
fi
entries=$(docker exec "$container" \
find /usr/share/nginx/html -maxdepth 1 -mindepth 1 -printf '%f\n' 2>/dev/null || true)
docker compose rm -f "$service" >/dev/null 2>&1
# 빈 webroot 체크 (COPY public/ 실패 감지)
if [ -z "$entries" ]; then
echo " FAIL: $service webroot is empty"
FAIL=1; continue
fi
while IFS= read -r f; do
[ -z "$f" ] && continue
# -xF: 정확히 일치하는 줄만 (substring 매칭 방지)
if ! echo "$allowed" | grep -qxF "$f"; then
echo " FAIL: unexpected file in webroot → $f"
FAIL=1
fi
done <<< "$entries"
if [ $FAIL -eq 0 ]; then
echo " OK"
fi
done
echo ""
if [ $FAIL -eq 0 ]; then
echo "✓ All web roots clean"
else
echo "✗ Security check FAILED — fix before deploying"
fi
exit $FAIL