Skip to content

feat(infra): add cloudfront distribution for media bucket - #3798

Open
tasoo-oos wants to merge 1 commit into
mainfrom
t3053-cloudfront-media
Open

tasoo-oos wants to merge 1 commit into
mainfrom
t3053-cloudfront-media

Conversation

@tasoo-oos

@tasoo-oos tasoo-oos commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Description

codedang-media 버킷을 CloudFront(OAC) 뒤에 두고 media.codedang.com으로 제공합니다.

  • infra/aws/storage/cloudfront_media.tf: us-east-1 ACM 인증서(DNS 검증), OAC, 배포(PriceClass_200, 관리형 CachingOptimized)
  • infra/aws/storage/s3_media.tf: 버킷 정책에 CloudFront OAC 허용 추가
  • infra/aws/dns/media.tf: A/AAAA alias 레코드 (storage output을 terraform_remote_state로 참조)
  • FileService: MEDIA_CDN_URL이 설정되면 CDN URL 반환
  • StorageService: 신규 업로드에 Cache-Control: public, max-age=31536000, immutable 지정 (키가 랜덤 UUID)
  • next.config.ts: next/image에 media.codedang.com 허용

이 PR만으로는 동작이 바뀌지 않습니다. MEDIA_CDN_URL은 어떤 ConfigMap에도 설정하지 않았고, 기존 S3 URL이 contest poster와 rich-text에 저장되어 있어 버킷의 public read 정책도 유지했습니다.

Additional context

비용: 읽기 전용 조회 기준 기존 CloudFront 사용량은 월 약 2.1 GB, 10.5만 요청($0)으로, 계정 전체 무료 한도(1 TB, 1,000만 요청) 내로 예상됩니다.

리뷰 포인트

  • 프론트
    • next.js 쪽 config에 몇 줄 추가된 것이 있으니 알고만 계셔주시면 될 것 같습니다.
  • 백엔드
    • 파일 업로드 로직이 약간 바뀌었는데, 이것이 백엔드 팀의 convention에 맞는지
  • 인프라
    • dns가 db.tfstate를 읽는 의존성 추가 (k8s-iam에 선례 있음)
    • ACM 검증 레코드는 같은 apply 안에서 대기해야 하므로 storage에 유지

Before submitting the PR, please make sure you do the following

Closes TAS-3053

Summary by CodeRabbit

  • New Features
    • Added a dedicated media CDN at media.codedang.com for faster delivery of uploaded images and files, with HTTPS support.
    • New media uploads use the CDN URL when it’s configured. Existing URL behavior is preserved otherwise.
  • Improvements
    • Uploaded media is configured for long-term caching to improve repeat access.
    • Existing public media URLs remain supported.

Serve codedang-media through CloudFront (OAC) at media.codedang.com.
The bucket keeps its public read policy until persisted direct S3 URLs
are migrated. New uploads get an immutable Cache-Control header, and
FileService returns the CDN URL when MEDIA_CDN_URL is set (unset by
default, so behavior is unchanged until rollout).
@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 6807816e-965f-4cd5-986f-a42112ea0a62

📥 Commits

Reviewing files that changed from the base of the PR and between e94e356 and b885adc.

📒 Files selected for processing (9)
  • apps/backend/apps/admin/src/problem/services/file.service.ts
  • apps/backend/libs/storage/src/storage.service.ts
  • apps/frontend/next.config.ts
  • infra/aws/dns/main.tf
  • infra/aws/dns/media.tf
  • infra/aws/storage/cloudfront_media.tf
  • infra/aws/storage/main.tf
  • infra/aws/storage/outputs.tf
  • infra/aws/storage/s3_media.tf

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The changes add a CloudFront distribution and DNS records for media, configure uploads to return a CDN URL when MEDIA_CDN_URL is set, and allow the media hostname in frontend image configuration. Uploaded media objects receive a one-year immutable cache policy.

Changes

Media CDN delivery

Layer / File(s) Summary
CloudFront distribution and S3 access
infra/aws/storage/main.tf, infra/aws/storage/cloudfront_media.tf, infra/aws/storage/s3_media.tf, infra/aws/storage/outputs.tf
The storage configuration adds a media.codedang.com CloudFront distribution with a DNS-validated certificate and SigV4 S3 origin access control. The bucket policy retains its public-read statement and adds access for the distribution. Outputs expose the CDN URL and distribution details.
Media hostname DNS
infra/aws/dns/main.tf, infra/aws/dns/media.tf
The DNS configuration reads storage remote state and creates A and AAAA aliases for media.codedang.com that target the media distribution.
Upload URL and image configuration
apps/backend/apps/admin/src/problem/services/file.service.ts, apps/backend/libs/storage/src/storage.service.ts, apps/frontend/next.config.ts
File uploads return a URL using MEDIA_CDN_URL when configured, or use the previous URL selection otherwise. Uploaded objects receive a one-year immutable cache policy. Frontend image configuration allows HTTPS images from media.codedang.com.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant FileService
  participant StorageService
  participant S3MediaBucket
  participant Client
  participant CloudFront
  FileService->>StorageService: Upload media file
  StorageService->>S3MediaBucket: Store object with immutable cache policy
  FileService-->>Client: Return media CDN URL when configured
  Client->>CloudFront: Request media from media.codedang.com
  CloudFront->>S3MediaBucket: Fetch object through SigV4 origin access control
  S3MediaBucket-->>CloudFront: Return media object
  CloudFront-->>Client: Return media object
Loading

Merge Risk: ⚪ Minimal · up to b885a

This adds CloudFront delivery for media, with DNS aliases and support for a CDN URL in uploads. Behavior does not change until MEDIA_CDN_URL is set, and no concrete merge-blocking issue was found.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to b885a

The CDN has appropriate controls for its connection to S3, and the existing direct public-read access is not newly introduced. Review is warranted because DNS deployment now depends on state containing database credentials, and new uploads receive a one-year public cache lifetime that complicates removal of mistakenly published media.

Retained concerns

  • Medium · security · inferred: DNS deployment now requires access to the storage state snapshot that contains database credential material. Whether this expands an actor's effective permissions depends on existing IAM grants, which were not established.
  • Medium · security · inferred: New uploads can remain readable from public caches after an origin-side removal or incident rollback. UUID keys avoid normal overwrite conflicts, but do not provide a way to revoke already cached copies.
Security review details

Security Blast Radius

  • inferred — Public read exposure covers objects in the media bucket through both the new CDN and the retained direct S3 path. The latter predates the PR; the new cache lifetime changes how long copies of newly uploaded public media may remain available.

Security Findings and Attack Paths

  • inferred — An actor able to read the storage state for DNS application may gain access to database credential material in that snapshot. Existing state-bucket permissions were not established, so a newly granted privilege is not verified.

Trust Boundaries and Controls

  • observed — Upload entrypoints use a manager guard. CDN viewers are redirected to HTTPS and limited to GET and HEAD; CloudFront-to-S3 requests use signed OAC access. These controls do not restrict the retained direct public S3 grant.

Resilience and Maintainability Implications

  • inferred — UUID keys make normal uploads compatible with immutable caching, but application retries are not idempotent and cleanup does not cover every partial failure. An origin-side deletion also cannot retract a browser-held immutable copy.

Hardening Proposals

  • proposed — Export CDN alias targets through a state boundary that does not require DNS deployment to read database credentials, or verify and constrain the existing DNS deployment role's state access.
  • proposed — Define an incident-removal procedure for cached media and a staged migration of persisted S3 URLs before removing the legacy public-read grant.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #123 is closed and supplies historical context only. No active directly linked issue remains. Therefore, this pull request has no linked-issue coding requirements.
Out of Scope Changes check ✅ Passed The changes stay within the stated CloudFront media CDN scope. They add the OAC distribution, ACM certificate, DNS records, bucket-policy access, CDN URL selection, immutable caching, and frontend ima…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: adding a CloudFront distribution for the media bucket. It is concise, specific, and consistent with the infrastructure and application changes.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@tasoo-oos tasoo-oos self-assigned this Sep 29, 2026
@tasoo-oos
tasoo-oos marked this pull request as ready for review September 29, 2026 20:17
@tasoo-oos
tasoo-oos requested a review from egg-zz September 29, 2026 20:24

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants