Skip to content

[HotFix] 보안 취약점 스캐닝, 크롤링 방지 임시 조치 PROD 서버 적용#198

Merged
lvalentine6 merged 11 commits intomainfrom
develop
Sep 19, 2025
Merged

[HotFix] 보안 취약점 스캐닝, 크롤링 방지 임시 조치 PROD 서버 적용#198
lvalentine6 merged 11 commits intomainfrom
develop

Conversation

@lvalentine6
Copy link
Member

@lvalentine6 lvalentine6 commented Sep 19, 2025

✨ 개요

#197 에서 적용된 Hotfix 사항을 Prod 서버에 적용합니다.

🧾 관련 이슈

#196
#197

🔍 참고 사항 (선택)

Summary by CodeRabbit

  • 신기능

    • S3 CORS에 PUT 허용 추가로 브라우저 기반 업로드 지원.
    • HTTPS 리스너가 유효하지 않은 호스트 요청에 403과 명확한 메시지 반환.
  • 작업(Chores)

    • 더 이상 사용되지 않는 DB 이미지 컬럼 제거.
    • 인프라 지역 ARN 표기 정비.
    • 개발 환경: 인스턴스/컨테이너 리소스 축소 및 스왑 파일 추가로 안정성 개선.
  • 테스트

    • 데이터베이스 스키마 관련 테스트 일시 비활성화.

@coderabbitai
Copy link

coderabbitai bot commented Sep 19, 2025

Walkthrough

데이터베이스 마이그레이션으로 사용 중단된 컬럼을 조건부 삭제하고, 테스트 클래스 전체를 비활성화했다. ALB HTTPS 리스너의 기본 동작을 타깃 그룹 포워딩에서 403 고정 응답으로 변경했다. Terraform에서 ARN의 리전 표기를 id로 정정하고, dev 리소스 스펙/유저데이터/컨테이너 파라미터를 축소했으며, prod S3 CORS에 PUT을 추가했다.

Changes

Cohort / File(s) Summary of changes
DB migration
src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql
cheer, story 테이블의 _deprecated_image_key 존재 여부를 확인한 뒤, 존재 시 동적 SQL로 DROP. 미존재 시 스킵 메시지 SELECT.
Tests
src/test/java/eatda/repository/DatabaseSchemaTest.java
@Disabled 추가로 클래스 전체 테스트 비활성화.
ALB HTTPS listener
terraform/common/alb/https-listener/main.tf
기본 액션을 타깃 그룹 포워딩에서 fixed-response 403(텍스트 메시지)로 변경.
Terraform locals (common)
terraform/common/locals.tf
IAM/KMS ARN의 리전 참조를 data.aws_region.current.name...id로 교체.
Terraform dev
terraform/dev/locals.tf, terraform/dev/scripts/user-data.sh, terraform/dev/terraform.tfvars
EC2 인스턴스 타입 t3a.smallt2.micro. 컨테이너 JVM 옵션 일부 제거. 유저데이터에 2G 스왑 구성 추가. api-dev CPU 1500→500, 메모리 1024→256; mysql-dev 메모리 512→256.
Prod S3 CORS
terraform/prod/s3/main.tf
CORS allowed_methodsPUT 추가(기존 GET 유지).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Mig as Migration Script
  participant DB as DB Server
  participant ISC as INFORMATION_SCHEMA

  Note over Mig,DB: V9__drop_cheer_story_deprecated_image.sql

  Mig->>ISC: Check column exists (cheer._deprecated_image_key)
  alt exists
    Mig->>DB: EXECUTE ALTER TABLE cheer DROP COLUMN _deprecated_image_key
    DB-->>Mig: OK
  else not exists
    Mig-->>Mig: SELECT 'skip cheer'
  end

  Mig->>ISC: Check column exists (story._deprecated_image_key)
  alt exists
    Mig->>DB: EXECUTE ALTER TABLE story DROP COLUMN _deprecated_image_key
    DB-->>Mig: OK
  else not exists
    Mig-->>Mig: SELECT 'skip story'
  end
Loading
sequenceDiagram
  autonumber
  participant C as Client
  participant ALB as ALB HTTPS Listener
  participant TG as Target Group (이전)
  participant S as Service (이전)

  rect rgba(200,230,255,0.3)
  Note over C,ALB: 이전(Old)
  C->>ALB: HTTPS Request
  ALB->>TG: Forward default action
  TG->>S: Route
  S-->>C: Response
  end

  rect rgba(200,255,200,0.3)
  Note over C,ALB: 변경(New)
  C->>ALB: HTTPS Request (invalid host)
  ALB-->>C: Fixed response 403 "Access Denied: Invalid Host"
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

귀 쫑긋 토끼가 깡총깡총 뛰며 말하길:
낡은 이미지 키, 휙—정리 완료!
리스너는 단호히 403, “호스트가 달라요!”
dev는 가볍게, 스왑은 포근하게.
ARN엔 올바른 id, S3엔 PUT도 환영!
오늘도 깔끔 배포—(=^‥^=)ノ 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목은 "PROD 서버에 보안 취약점 스캐닝·크롤링 방지 임시 조치 적용"이라는 의도를 명확히 전달하며, 변경사항 중 ALB 리스너를 403 고정 응답으로 바꾸는 수정은 해당 목적과 직접적으로 일치합니다. 다만 PR에는 dev 환경 설정 변경, DB 마이그레이션, 테스트 비활성화 등 제목과 직접 관련이 적은 변경도 포함되어 있어 범위가 혼재되어 있습니다. 종합하면 제목은 주요 목적을 반영하지만 PR을 검토하는 동료가 일부 변경의 관련성을 혼동할 가능성이 있습니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

📌 최신 ERD가 자동 생성되었습니다.

👉 ERD 보러가기

@sonarqubecloud
Copy link

@github-actions
Copy link

📄 Terraform Plan Summary

🛡️ Common Infrastructure


No plan summary

Status: ✅ No Changes


🚀 Production Environment


No plan summary

Status: ✅ No Changes


📋 Full Results: View in Actions

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/test/java/eatda/repository/DatabaseSchemaTest.java (1)

5-16: @disabled 전체 비활성화 금지 — 임시 비활성화 시 사유 명시 & V9 마이그레이션은 DB별 분기/조건부로 수정

검증 요약: V9 마이그레이션이 MySQL의 SQL-level PREPARE/EXECUTE를 사용해 H2(MODE=MySQL)에서 실패함( H2는 해당 SQL 구문 미지원 ). 또한 MySQL 8.0은 "ALTER TABLE ... DROP COLUMN IF EXISTS" 문법을 지원하지 않음.

조치(필수):

  • 위치: src/test/java/eatda/repository/DatabaseSchemaTest.java (Lines 5-16) — 클래스 전체 @disabled 제거. 임시 유지 시에는 @disabled에 명확한 사유·티켓·해제 조건을 표기.
  • V9 마이그레이션 수정: SQL-level PREPARE/EXECUTE 제거(또는 JDBC PreparedStatement 사용)하거나 마이그레이션을 db별(mysql/h2)로 분리. DROP COLUMN 처리는 IF EXISTS 대신 INFORMATION_SCHEMA 조회 또는 DB별 스크립트로 처리.
  • 수정 완료 후 즉시 테스트 재활성화.

원하면 V9용 mysql/h2 분리 스크립트 템플릿 제공.

🧹 Nitpick comments (7)
terraform/dev/terraform.tfvars (2)

23-24: API 컨테이너 메모리 256MiB 축소 — OOM/성능 리스크. soft limit 병행 또는 힙 상한 고정 권장

Java(+dd-java-agent) 오버헤드 고려 시 256MiB hard limit은 불안정합니다. 최소 soft limit 추가 또는 hard limit 상향을 권장합니다.

아래처럼 soft/hard 병행을 제안합니다(로컬스에 memoryReservation 전달 추가 코멘트 별도):

-    cpu                      = 500
-    memory                   = 256
+    cpu                      = 500
+    memory                   = 384
+    memoryReservation        = 256

47-51: MySQL 8 컨테이너 256MiB hard limit — CrashLoop/OOM 우려

Dev라도 DB는 OOM 시 데이터 손상/트랜잭션 실패 위험이 큽니다. 최소 512MiB+ 또는 soft limit 사용을 권장합니다.

-    memory                   = 256
+    memory                   = 512

운영 방식에 따라 innodb_buffer_pool_size 축소 등도 병행 검토 바랍니다.

terraform/prod/s3/main.tf (1)

42-47: CORS에 PUT 추가는 타당. HEAD도 허용 권장(+멀티파트 사용 시 POST/DELETE 검토).

HEAD 미허용 시 일부 SDK/프록시에서 문제될 수 있습니다. 필요 시 POST/DELETE도 포함하세요.

-    allowed_methods = ["GET", "PUT"]
+    allowed_methods = ["GET", "HEAD", "PUT"]

참고: 현재 CloudFront는 GET/HEAD/OPTIONS만 허용 중이며, 버킷 정책은 GetObject@CloudFront만 Allow입니다. 브라우저 직업로드(사전서명 PUT)를 쓰려면 PutObject 관련 IAM/버킷 정책 정합성도 함께 확인하세요.

terraform/dev/scripts/user-data.sh (1)

4-8: swapfile 생성 로직 비멱등. 재실행 시 오류/중복 위험 — 존재 체크로 감싸기

멱등화 및 fallocate 실패 대비 dd fallback 권장.

-fallocate -l 2G /swapfile
-chmod 600 /swapfile
-mkswap /swapfile
-swapon /swapfile
-echo '/swapfile none swap sw 0 0' >> /etc/fstab
+if [ ! -f /swapfile ]; then
+  fallocate -l 2G /swapfile || dd if=/dev/zero of=/swapfile bs=1M count=2048
+  chmod 600 /swapfile
+  mkswap /swapfile
+  swapon /swapfile
+  echo '/swapfile none swap sw 0 0' >> /etc/fstab
+fi
terraform/dev/locals.tf (3)

43-52: t2.micro로 다운사이징 — 현재 태스크(자바+MySQL+Datadog) 적재 가능 용량 점검

메모리 총합/커널 오버헤드/에이전트 포함 시 여유가 거의 없습니다. 스케줄 실패/스왑 과다 사용 가능성 점검 바랍니다.

권장: 서비스 desired_count=1 유지, CloudWatch로 스왑/메모리 OOM 지표 모니터링, 필요 시 t3a.small 등으로 롤백 플랜 마련.


65-119: container_definitions에 memoryReservation 미전달 — soft limit 무시됨

mysql-dev에 정의된 memoryReservation(128MiB)이 컨테이너 정의로 전달되지 않습니다. 필드 매핑 추가하세요.

         cpu         = def.cpu
         memory      = def.memory
+        memoryReservation = lookup(def, "memoryReservation", null)

74-88: JVM 힙 상한 미설정 상태에서 256–384MiB 컨테이너 — 명시적 -Xms/-Xmx 권장

컨테이너 제한을 확실히 따르도록 힙을 고정하세요.

           "java",
+          "-Xms128m",
+          "-Xmx128m",
           "-Xlog:gc*:stdout:time,uptime,level,tags",
           "-Xlog:gc*:file=/logs/gc.log:time,uptime,level,tags",

(실사용 메모리에 맞춰 128m 값은 조정 가능)

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a8b9a10 and 70c9f87.

📒 Files selected for processing (8)
  • src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql (1 hunks)
  • src/test/java/eatda/repository/DatabaseSchemaTest.java (2 hunks)
  • terraform/common/alb/https-listener/main.tf (1 hunks)
  • terraform/common/locals.tf (2 hunks)
  • terraform/dev/locals.tf (1 hunks)
  • terraform/dev/scripts/user-data.sh (1 hunks)
  • terraform/dev/terraform.tfvars (2 hunks)
  • terraform/prod/s3/main.tf (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Notify Discord on `/noti` Comment
terraform/common/alb/https-listener/main.tf

[error] 88-88: No such file or directory: terraform/common/alb/https-listener/main.tf

src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql

[error] 88-88: No such file or directory: src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql

terraform/dev/scripts/user-data.sh

[error] 88-88: No such file or directory: terraform/dev/scripts/user-data.sh

terraform/dev/terraform.tfvars

[error] 88-88: No such file_or_directory: terraform/dev/terraform.tfvars

terraform/prod/s3/main.tf

[error] 88-88: No such file or directory: terraform/prod/s3/main.tf

src/test/java/eatda/repository/DatabaseSchemaTest.java

[error] 88-88: No such file or directory: src/test/java/eatda/repository/DatabaseSchemaTest.java

terraform/dev/locals.tf

[error] 88-88: No such file or directory: terraform/dev/locals.tf

terraform/common/locals.tf

[error] 88-88: No such file or directory: terraform/common/locals.tf

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test
  • GitHub Check: Deploy to Amazon ECS
🔇 Additional comments (4)
terraform/common/alb/https-listener/main.tf (1)

7-14: 기본 동작을 403 고정 응답으로 전환한 점 👍 — 디폴트 경로 의존 트래픽 없는지 점검

미등록 호스트 헤더 차단 목적에 부합합니다. 단, 과거 default_action에 의존한 헬스체크/레거시 도메인이 없는지 확인하세요.

terraform/common/locals.tf (2)

45-48: ARN 리전 name→id 정정 LGTM

정합성 개선입니다.


90-98: SSM/KMS ARN의 리전 세그먼트 정정 LGTM

일관성 향상. 추가 변경 없음.

src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql (1)

1-27: 동적 PREPARE 제거 — ALTER TABLE ... DROP COLUMN IF EXISTS로 단순화 (MySQL 8.0.19+)

파일: src/main/resources/db/migration/V9__drop_cheer_story_deprecated_image.sql
검증: ALTER TABLE … DROP COLUMN IF EXISTS는 MySQL 8.0.19(도입일: 2020-01-13)부터 지원됩니다. MySQL 8(>=8.0.19) 환경이면 아래로 교체하세요. H2 테스트 유지가 필요하면 DB별 마이그레이션 파일(V9__...mysql.sql / V9...__h2.sql)로 분리하세요.

-SET @col_exists := (SELECT COUNT(*)
-                    FROM INFORMATION_SCHEMA.COLUMNS
-                    WHERE TABLE_SCHEMA = DATABASE()
-                      AND TABLE_NAME = 'cheer'
-                      AND COLUMN_NAME = '_deprecated_image_key');
-
-SET @sql := IF(@col_exists > 0,
-               'ALTER TABLE cheer DROP COLUMN _deprecated_image_key',
-               'SELECT "Column cheer._deprecated_image_key does not exist, skip";');
-PREPARE stmt FROM @sql;
-EXECUTE stmt;
-DEALLOCATE PREPARE stmt;
-
-SET @col_exists := (SELECT COUNT(*)
-                    FROM INFORMATION_SCHEMA.COLUMNS
-                    WHERE TABLE_SCHEMA = DATABASE()
-                      AND TABLE_NAME = 'story'
-                      AND COLUMN_NAME = '_deprecated_image_key');
-
-SET @sql := IF(@col_exists > 0,
-               'ALTER TABLE story DROP COLUMN _deprecated_image_key',
-               'SELECT "Column story._deprecated_image_key does not exist, skip";');
-PREPARE stmt FROM @sql;
-EXECUTE stmt;
-DEALLOCATE PREPARE stmt;
+ALTER TABLE cheer DROP COLUMN IF EXISTS _deprecated_image_key;
+ALTER TABLE story DROP COLUMN IF EXISTS _deprecated_image_key;

@lvalentine6 lvalentine6 merged commit 739f230 into main Sep 19, 2025
18 of 19 checks passed
@github-actions
Copy link

🎉 This PR is included in version 1.8.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants