Conversation
|
Note
|
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Description check | PR 설명은 템플릿 구조를 따르고 관련 이슈(#1052)를 명시하며 작업 내용을 언급했으나, 주요 변경사항의 세부 항목(1., 2., 3.)이 비워져 있어 불완전합니다. | 주요 변경사항 섹션에 구체적인 변경 내용을 기재하세요. 예: 1. 네트워크 모듈 추가, 2. 컴퓨트 모듈 추가, 3. dev/prod 환경 설정 구성 등 | |
| Linked Issues check | ❓ Inconclusive | PR이 #1052에서 요청한 테라폼 기반 인프라 IaC 구현을 실현하고 있으나, 연결된 이슈에 구체적인 체크리스트나 요구사항이 기재되지 않아 완전한 검증이 어렵습니다. | 이슈 #1052의 상세 작업 내용 섹션에 체크리스트나 구체적 요구사항을 명시하여 변경 사항의 완성도를 검증할 수 있는 기준을 제공하세요. |
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | PR 제목은 '테라폼 기반 인프라 IaC'라는 변경 사항의 핵심을 요약하고 있으며, 실제 변경 내용(dev/prod 환경의 테라폼 네트워크 및 컴퓨트 모듈 추가)과 일치합니다. |
| Out of Scope Changes check | ✅ Passed | 모든 변경사항(network, compute 모듈 및 dev/prod 환경 설정)이 테라폼 기반 인프라 IaC 구현이라는 범위 내에 있으며, 외부 스코프 변경은 없습니다. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
✨ Finishing touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
feat/1052
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (7)
backend/terraform/modules/network/outputs.tf (1)
1-19: 출력값에 설명(description)을 추가하고, 누락된 리소스 재검토가 필요합니다.현재 모든 출력값이 설명 없이 정의되어 있어, 이를 사용하는 다른 모듈이나 환경에서 각 값의 용도를 명확히 이해하기 어렵습니다. Terraform의 모범 사례에 따라 각 출력값에
description필드를 추가하는 것이 권장됩니다.output "vpc_id" { value = aws_vpc.main.id + description = "VPC ID" } output "subnet_id" { value = aws_subnet.public.id + description = "Public subnet ID for EC2 instances" }또한 네트워크 모듈에서 생성한 IGW(
aws_internet_gateway.igw)도 필요시 출력값으로 노출하는 것을 검토하시기 바랍니다.backend/terraform/environment/dev/provider.tf (1)
1-14: AWS 프로바이더 버전과 추가 구성 검토를 권장합니다.현재 설정은 기본적으로 작동하지만, AWS 프로바이더 버전 호환성과 태그 일관성 개선을 위해 다음을 검토하시기 바랍니다:
AWS 프로바이더 버전:
~> 6.12버전이 현재 프로젝트의 요구사항과 부합하는지 확인이 필요합니다. 최신 버전 사용 시 새로운 기능과 보안 패치의 이점을 받을 수 있습니다.기본 태그 구성: 모든 리소스에 일관되게 적용할 기본 태그를 정의하면, 비용 추적과 리소스 관리가 용이해집니다.
provider "aws" { region = var.region + + default_tags { + tags = { + Environment = var.environment + Project = var.project + } + } }backend/terraform/environment/prod/provider.tf (1)
1-14: Dev 환경과의 일관성 유지를 위해 공통 설정 검토를 권장합니다.Prod 프로바이더 설정이 Dev과 동일한 구조를 따르고 있어 일관성이 좋습니다. 다만 두 환경에서 동일한 설정(버전 요구사항, 기본 태그 등)이 중복되고 있으므로, Terraform 모듈이나 로컬 변수를 활용한 공통화를 고려하시기 바랍니다.
또한 Dev 환경의 프로바이더 리뷰 코멘트에서 제안한 기본 태그(default_tags) 추가도 Prod에도 적용하시기 바랍니다.
backend/terraform/environment/dev/variables.tf (1)
1-49: 환경 변수 정의가 잘 구조화되었으나, 사전 요구사항 명시가 필요합니다.개발 환경에 적합한 기본값들이 잘 설정되어 있습니다. 다만 다음 사항을 검토하시기 바랍니다:
1. EC2 Key Pair 사전 요구사항
key_name_was와key_name_db는 AWS에 사전에 생성된 EC2 키 페어를 참조합니다. 만약 해당 키 페어가 존재하지 않으면 배포가 실패합니다. README나 배포 문서에 이러한 사전 요구사항을 명시하시기 바랍니다.# 사전 요구사항 다음 EC2 키 페어가 사전에 AWS 콘솔에서 생성되어야 합니다: - mulkkam-dev-was - mulkkam-dev-db2. 선택적 개선사항
프로덕션 환경에서의 확장성을 고려하면, 키 페어 이름을 변수로 받아서 일관되게 생성하는 방식도 고려할 수 있습니다:variable "key_name_was" { type = string default = "mulkkam-dev-was" + description = "EC2 Key Pair name for WAS instance (must pre-exist)" }backend/terraform/modules/compute/main.tf (2)
41-55: CloudWatch 상세 모니터링 활성화 권장세 인스턴스 모두 기본 모니터링만 활성화되어 있습니다(5분 단위 메트릭). 프로덕션 환경과 향후 성능 분석을 위해 상세 모니터링(1분 단위)을 활성화하세요:
monitoring = true이렇게 하면 CPU, 네트워크, 디스크 I/O 등을 더 세밀하게 추적할 수 있어, 성능 문제 조기 발견이 가능합니다. 비용은 약간 증가하지만 프로덕션 인프라로서는 가치 있는 투자입니다.
Also applies to: 57-72, 74-89
106-120: User data 스크립트 개선: SSM agent 설치 방식 재검토현재 SSM agent를 snap으로 설치하고 있습니다:
snap install amazon-ssm-agent --classic문제점:
- Ubuntu Jammy 22.04는 Debian/APT 기반 배포판인데, snap은 컨테이너 기반 패키징으로 시작이 느리고 안정성이 낮을 수 있음
- Debian 공식 리포지토리에서
amazon-ssm-agentdeb 패키지 설치가 표준개선안:
apt-get install -y amazon-ssm-agent systemctl enable amazon-ssm-agent systemctl start amazon-ssm-agent또한 user data 상단에
set -e외에도 전체 오류 처리를 강화하세요:#!/bin/bash set -euo pipefail trap 'echo "Error on line $LINENO"' ERR apt-get update -y apt-get install -y docker.io amazon-ssm-agent systemctl enable docker docker systemctl enable amazon-ssm-agent systemctl start docker systemctl start amazon-ssm-agent이렇게 하면 스크립트 실행 중 오류 발생 시 정확한 라인을 파악할 수 있고, 더 안정적인 agent 설치가 가능합니다.
backend/terraform/modules/compute/variables.tf (1)
46-52: key_name 변수에 설명(description) 추가 필요
key_name_was와key_name_db변수는 다른 변수들과 달리description필드가 없습니다. 운영자 입장에서 이 변수들의 용도를 명확히 이해해야 합니다.개선안:
variable "key_name_was" { type = string description = "EC2 key pair name for WAS instance SSH access" } variable "key_name_db" { type = string description = "EC2 key pair name for DB instance SSH access" }추가 고려사항:
현재 두 변수 모두 기본값이 없습니다. 이는 사용자가 반드시 값을 제공해야 한다는 의미인데, 이것이 의도라면 명확히 문서화하는 게 좋습니다. 또는 다음 예시처럼 기본값을 제공할 수도 있습니다:
variable "key_name_was" { type = string description = "..." default = "mulkkam-was-key" }변수 정의의 일관성은 운영 팀의 인프라 이해도를 높이고, 자동화 스크립트 작성을 쉽게 하므로 중요합니다.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
backend/terraform/environment/dev/main.tf(1 hunks)backend/terraform/environment/dev/provider.tf(1 hunks)backend/terraform/environment/dev/variables.tf(1 hunks)backend/terraform/environment/prod/provider.tf(1 hunks)backend/terraform/environment/prod/variables.tf(1 hunks)backend/terraform/modules/compute/main.tf(1 hunks)backend/terraform/modules/compute/outputs.tf(1 hunks)backend/terraform/modules/compute/variables.tf(1 hunks)backend/terraform/modules/network/main.tf(1 hunks)backend/terraform/modules/network/outputs.tf(1 hunks)backend/terraform/modules/network/variables.tf(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
backend/**
⚙️ CodeRabbit configuration file
backend/**: - 1. 팀 및 공식 컨벤션, 가독성, 예외처리, 테스트/확장/유지보수성, 모듈화, API/DB/보안 설계 기준을 기반으로 리뷰해주세요.
- 최신 트렌드, 불필요한 로직, 클린코드, 리팩토링, 서비스/도메인 설계, 공통 예외 처리, 확장성도 함께 확인해주세요.
- 각 피드백은 문제점·대안·장단점을 짧고 논리적으로, 예시 코드가 있다면 간결히 포함해 주세요.
- 팀 내 스타일 통일성도 확인해주세요.
- 미작성한 테스트 코드 케이스가 있다면, 어떤 테스트가 필요한지 제안해주세요. (예: 컨트롤러는 인수 테스트, 나머지는 단위 테스트)
- 리뷰 남겨주는 부분은 해당 라인 범위의 코멘트에 작성해주세요.
Files:
backend/terraform/modules/network/outputs.tfbackend/terraform/modules/network/main.tfbackend/terraform/environment/dev/variables.tfbackend/terraform/environment/dev/main.tfbackend/terraform/environment/prod/provider.tfbackend/terraform/modules/compute/variables.tfbackend/terraform/environment/dev/provider.tfbackend/terraform/modules/network/variables.tfbackend/terraform/modules/compute/main.tfbackend/terraform/modules/compute/outputs.tfbackend/terraform/environment/prod/variables.tf
🪛 Checkov (3.2.334)
backend/terraform/modules/compute/main.tf
[medium] 41-55: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 41-55: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 41-55: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
[medium] 57-72: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 57-72: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 57-72: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
[medium] 74-89: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 74-89: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 74-89: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
🔇 Additional comments (3)
backend/terraform/environment/dev/main.tf (1)
1-26: 모듈 구성 및 의존성 관리가 잘 이루어졌습니다.네트워크 모듈과 컴퓨트 모듈 간의 관계가 명확하게 정의되어 있으며, 네트워크 모듈의 출력값이 컴퓨트 모듈의 입력으로 올바르게 연결되어 있습니다. 모듈 간 의존성도 출력값을 통해 자동으로 관리되고 있어 좋습니다.
backend/terraform/modules/network/variables.tf (1)
1-24: 변수 정의가 명확하고 일관성 있게 작성되었습니다.모든 변수가 적절한 설명과 함께 타입이 명시되어 있어, 이 모듈을 사용하는 환경에서 필요한 입력값을 명확히 이해할 수 있습니다.
backend/terraform/modules/network/main.tf (1)
55-84: Nginx 보안 그룹은 예상되로 설정되었습니다.Nginx 보안 그룹이 외부에서의 80/443 포트 접근을 올바르게 허용하고 있습니다.
| variable "key_name" { | ||
| type = string | ||
| default = "mulkkam-prod-~~(tmp)" | ||
| } |
There was a problem hiding this comment.
프로덕션 key_name 임시값 정리 필수
key_name 변수에 "mulkkam-prod-~~(tmp)"라는 표식이 있습니다. 이는 아직 실제 AWS 키 페어 이름으로 교체되지 않은 임시값입니다.
해결 필요 사항:
- AWS에서 실제 키 페어 이름 확인 또는 생성 (예:
mulkkam-prod-key,mulkkam-prod-app등) - 변수 기본값을 실제 키 이름으로 교체
variable "key_name" {
type = string
default = "mulkkam-prod-key" # 실제 키 페어 이름으로 변경
}또는 기본값을 제거하고 terraform.tfvars 또는 CLI에서 명시적으로 전달하는 방식도 좋습니다:
variable "key_name" {
type = string
# description을 추가하면 운영자에게 명확함
description = "AWS EC2 key pair name for SSH access"
}그 후 배포 시:
terraform apply -var="key_name=mulkkam-prod-key"현재 상태로는 prod 환경 배포가 불가능하므로, 먼저 실제 키 페어를 준비한 후 변수값을 확정하세요.
🤖 Prompt for AI Agents
backend/terraform/environment/prod/variables.tf lines 41-44: 현재 key_name 변수에
"mulkkam-prod-~~(tmp)"라는 임시값이 남아 있어 프로덕션 배포 불가 상태입니다; 해결 방법은 실제 AWS EC2 키 페어
이름으로 기본값을 교체하거나 기본값을 제거하고 description을 추가한 뒤 terraform.tfvars 또는 CLI로 명시적으로
key_name을 전달하도록 변경하세요; 구체적으로는 AWS에서 프로덕션용 키 페어 이름을 확인하거나 새로 생성한 뒤 해당 이름을 기본값에
설정하거나 기본값을 삭제해 운영자가 apply 시 -var 또는 tfvars로 값을 넘기게 하세요.
| resource "aws_instance" "nginx" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_nginx | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.nginx_sg_id] | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
|
|
||
| associate_public_ip_address = true | ||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-nginx" | ||
| Env = var.environment | ||
| } | ||
| } | ||
|
|
||
| resource "aws_instance" "was" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_was | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.was_sg_id] | ||
| key_name = var.key_name_was | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
|
|
||
| associate_public_ip_address = true | ||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-was" | ||
| Env = var.environment | ||
| } | ||
| } | ||
|
|
||
| resource "aws_instance" "db" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_db | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.db_sg_id] | ||
| key_name = var.key_name_db | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
| associate_public_ip_address = true | ||
|
|
||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-db" | ||
| Env = var.environment | ||
| } | ||
| } |
There was a problem hiding this comment.
IMDSv1 비활성화 및 보안 메타데이터 옵션 추가 필수
현재 EC2 인스턴스 설정에 metadata_options가 없어, 기본적으로 IMDSv1이 활성화되어 있습니다. 이는 SSRF(Server-Side Request Forgery) 공격에 노출되는 보안 취약점입니다. IMDSv2는 토큰 기반 인증이 필수라 한 번의 요청으로 권한을 탈취할 수 없으므로, 모든 EC2 인스턴스에서 IMDSv2를 강제해야 합니다.
세 인스턴스 모두에 다음을 추가하세요:
metadata_options {
http_endpoint = "enabled"
http_tokens = "required" # IMDSv2 강제
http_put_response_hop_limit = 1
}🧰 Tools
🪛 Checkov (3.2.334)
[medium] 41-55: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 41-55: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 41-55: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
[medium] 57-72: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 57-72: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 57-72: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
[medium] 74-89: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 74-89: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 74-89: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
🤖 Prompt for AI Agents
In backend/terraform/modules/compute/main.tf around lines 41 to 89, the
aws_instance resources for nginx, was and db lack a metadata_options block so
IMDSv1 remains allowed; add a metadata_options block to each aws_instance with
http_endpoint = "enabled", http_tokens = "required" and
http_put_response_hop_limit = 1 to enforce IMDSv2 (token-based) for all
instances.
| resource "aws_instance" "nginx" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_nginx | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.nginx_sg_id] | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
|
|
||
| associate_public_ip_address = true | ||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-nginx" | ||
| Env = var.environment | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's explore the terraform directory structure
find backend/terraform -type f -name "*.tf" | head -20Repository: woowacourse-teams/2025-mul-kkam
Length of output: 615
🏁 Script executed:
# Let's read the main.tf file to see the full context
cat -n backend/terraform/modules/compute/main.tfRepository: woowacourse-teams/2025-mul-kkam
Length of output: 4020
🏁 Script executed:
# Check the variables.tf file to see key_name definitions
cat -n backend/terraform/modules/compute/variables.tfRepository: woowacourse-teams/2025-mul-kkam
Length of output: 1523
🏁 Script executed:
# Look for local variable definitions, especially local.common_user_data
grep -n "local.common_user_data\|locals\|user_data" backend/terraform/modules/compute/main.tf | head -30Repository: woowacourse-teams/2025-mul-kkam
Length of output: 292
nginx 인스턴스의 SSH 접근 설정 불일치 검토
현재 구성에서 nginx 인스턴스는 key_name 속성이 없는 반면, was와 db 인스턴스는 각각 var.key_name_was, var.key_name_db를 사용하고 있습니다. 이로 인해 nginx는 SSH 키 기반 접근이 불가능한 상태입니다.
왜 이것이 문제인가:
- 세 인스턴스가 서로 다른 접근 정책을 가져 운영 복잡도가 증가합니다
- 긴급 상황이나 트러블슈팅 시 nginx 접근 방식이 다르면 일관성 있는 대응이 어렵습니다
- 현재 설정이 의도적인 보안 정책인지, 아니면 누락인지 불명확합니다
현재 상태 분석:
- 세 인스턴스 모두 SSM Session Manager용 IAM 역할(AmazonSSMManagedInstanceCore)을 보유하고 있습니다
- 모든 인스턴스에서
local.common_user_data를 통해 SSM 에이전트가 설치됩니다 (snap 경로) - 따라서 현재로서는 SSM을 통한 접근만 가능합니다
권장 선택지:
선택지 1 (일관성 중심): nginx에도 key_name 변수 추가
- 모든 인스턴스가 SSH와 SSM 모두로 접근 가능하게 통일
- 운영 관점에서 인스턴스 간 접근 방식의 일관성 확보
- 구현:
variables.tf에variable "key_name_nginx"추가 후 nginx 리소스에key_name = var.key_name_nginx설정
선택지 2 (보안 중심): nginx는 SSM 전용으로 운영하고, was/db도 SSM으로 통일
- SSH 포트를 열지 않음으로써 공격 표면 축소
- 모든 접근이 AWS CloudTrail로 감시되므로 감시/감사 강화
- 다만 초기 구성 후 SSH 미포함 접근이 필요한 경우, SSM 에이전트 정상 작동이 필수
다음 단계:
의도된 설계가 무엇인지 명확히 한 후, 그에 맞춰 세 인스턴스의 접근 정책을 통일하세요. 선택지 1이라면 key_name_nginx 변수를 추가하고, 선택지 2라면 was와 db에서도 key_name 속성을 제거하는 것이 일관성 있습니다. 선택 사항을 코드 주석이나 문서로 명시하면 향후 운영 시 혼동을 방지할 수 있습니다.
🧰 Tools
🪛 Checkov (3.2.334)
[medium] 41-55: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 41-55: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 41-55: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
🤖 Prompt for AI Agents
In backend/terraform/modules/compute/main.tf around lines 41-55 the nginx
aws_instance lacks a key_name while was/db instances use key_name variables,
causing inconsistent SSH access; decide the intended design and make instances
consistent: if you want SSH+SSM for all, add variable "key_name_nginx" to
variables.tf and set key_name = var.key_name_nginx on the nginx resource (and
document it); if you want SSM-only, remove key_name usage from the was and db
instance resources (and update docs/variables to reflect no SSH keys); also
ensure security group rules and README reflect the chosen approach.
| resource "aws_instance" "was" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_was | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.was_sg_id] | ||
| key_name = var.key_name_was | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
|
|
||
| associate_public_ip_address = true | ||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-was" | ||
| Env = var.environment | ||
| } | ||
| } | ||
|
|
||
| resource "aws_instance" "db" { | ||
| ami = data.aws_ami.ubuntu.id | ||
| instance_type = var.instance_type_db | ||
| subnet_id = var.subnet_id | ||
| vpc_security_group_ids = [var.db_sg_id] | ||
| key_name = var.key_name_db | ||
| iam_instance_profile = aws_iam_instance_profile.ec2_ssm_profile.name | ||
| associate_public_ip_address = true | ||
|
|
||
| user_data = local.common_user_data | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-${var.environment}-db" | ||
| Env = var.environment | ||
| } | ||
| } |
There was a problem hiding this comment.
공개 IP 할당 전략 재검토 필요
현재 구성에서 **was와 db 인스턴스도 associate_public_ip_address = true**로 설정되어 있습니다. 이는 불필요한 보안 노출입니다:
- nginx: 리버스 프록시로 외부 트래픽을 받아야 하므로 공개 IP 필요 ✓
- was: 애플리케이션 서버로 nginx를 통해서만 접근하면 되므로 공개 IP 불필요
- db: 데이터베이스는 내부 네트워크만 통신해야 하므로 공개 IP는 매우 위험 ✗
개선 방향:
- was 인스턴스 (Line 65):
associate_public_ip_address = false또는 제거 - db 인스턴스 (Line 81): 반드시
associate_public_ip_address = false로 설정
아키텍처 관점에서 was/db는 private subnet에 배치하고, 보안 그룹으로만 인스턴스 간 통신을 제어하는 것이 정석입니다. 현재 구성이 모두 동일 subnet에 있다면, 최소한 공개 IP는 비활성화하세요.
# was: 공개 IP 제거
# associate_public_ip_address = true 제거
# db: 명시적으로 비활성화
associate_public_ip_address = false🧰 Tools
🪛 Checkov (3.2.334)
[medium] 57-72: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 57-72: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 57-72: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
[medium] 74-89: Ensure that detailed monitoring is enabled for EC2 instances
(CKV_AWS_126)
[high] 74-89: EC2 instance should not have public IP.
(CKV_AWS_88)
[high] 74-89: Ensure Instance Metadata Service Version 1 is not enabled
(CKV_AWS_79)
🤖 Prompt for AI Agents
In backend/terraform/modules/compute/main.tf around lines 57 to 89, the was and
db aws_instance resources are assigning public IPs which is a security risk;
update the was instance (around line 65) to remove or set
associate_public_ip_address = false and explicitly set
associate_public_ip_address = false for the db instance (around line 81); ensure
instances are placed in private subnets and rely on nginx/proxies and security
groups for external access rather than public IPs.
| output "nginx_instances" { | ||
| value = aws_instance.nginx | ||
| } | ||
|
|
||
| output "was_instances" { | ||
| value = aws_instance.was | ||
| } | ||
|
|
||
| output "db_instances" { | ||
| value = aws_instance.db | ||
| } | ||
|
|
||
| output "nginx_eips" { | ||
| value = aws_eip.nginx_eip.public_ip | ||
| } | ||
|
|
||
| output "nginx_public_ip" { | ||
| value = aws_instance.nginx.public_ip | ||
| } | ||
|
|
||
| output "was_private_ip" { | ||
| value = aws_instance.was.private_ip | ||
| } | ||
|
|
||
| output "db_private_ip" { | ||
| value = aws_instance.db.private_ip | ||
| } |
There was a problem hiding this comment.
출력값의 일관성 및 보안 개선이 필요합니다 (중요).
현재 컴퓨트 모듈의 출력값들이 세 가지 문제를 안고 있습니다:
1. 전체 리소스 객체 노출의 문제
aws_instance 전체 객체를 노출하면, 모듈의 내부 구현이 외부에 결합되고, 의도하지 않은 모든 속성(비밀번호, 보안 설정 등)이 노출될 위험이 있습니다. 보안 그룹 접근 시 특정 필요한 속성만 노출하는 것이 모범 사례입니다.
2. 출력값의 불일치
일부는 전체 리소스(nginx_instances), 일부는 특정 속성(nginx_public_ip)을 노출하고 있어 일관성이 없습니다. 이는 모듈 사용자에게 혼동을 초래합니다.
3. 설명 부재
모든 출력값에 설명이 없어서 각 값의 목적을 이해하기 어렵습니다.
개선 방안:
특정 필요한 속성만 개별적으로 노출하도록 리팩토링하는 것을 강력히 권장합니다:
-output "nginx_instances" {
- value = aws_instance.nginx
-}
-
-output "was_instances" {
- value = aws_instance.was
-}
-
-output "db_instances" {
- value = aws_instance.db
-}
-
output "nginx_eips" {
- value = aws_eip.nginx_eip.public_ip
+ value = aws_eip.nginx_eip.public_ip
+ description = "Elastic IP address for Nginx instance"
}
output "nginx_public_ip" {
value = aws_instance.nginx.public_ip
+ description = "Public IP address of Nginx instance (via EC2)"
}
output "was_private_ip" {
value = aws_instance.was.private_ip
+ description = "Private IP address of WAS instance"
}
output "db_private_ip" {
value = aws_instance.db.private_ip
+ description = "Private IP address of DB instance"
}추가로, 각 인스턴스의 ID나 기타 필요한 속성은 별도의 명시적 출력값으로 정의하시기 바랍니다.
🤖 Prompt for AI Agents
backend/terraform/modules/compute/outputs.tf lines 1-27: 현재 전체 aws_instance 객체를
출력하고 일부만 속성을 노출해 일관성 및 보안 문제가 있으므로 전체 리소스 객체 출력(aws_instance.nginx,
aws_instance.was, aws_instance.db)을 제거하고 각 인스턴스별로 필요한 속성만 출력하도록 변경하세요(예: id,
arn, public_ip 또는 private_ip, 보안그룹 IDs 등), 모든 출력값에 간단한 description을 추가해 목적을 명확히
하고 네이밍을 일관되게 맞추며 EIP는 aws_eip 리소스의 명시적 속성(public_ip, allocation_id 등)만 노출하도록
리팩터링하세요.
| variable "project" { | ||
| type = string | ||
| description = "Project name" | ||
| } | ||
|
|
||
| variable "environment" { | ||
| type = string | ||
| description = "environment (dev, prod, etc)" | ||
| } | ||
|
|
||
| variable "subnet_id" { | ||
| type = string | ||
| description = "Subnet ID where EC2 instances will be launched" | ||
| } | ||
|
|
||
| variable "nginx_sg_id" { | ||
| type = string | ||
| description = "Security group ID for nginx" | ||
| } | ||
|
|
||
| variable "was_sg_id" { | ||
| type = string | ||
| description = "Security group ID for WAS" | ||
| } | ||
|
|
||
| variable "db_sg_id" { | ||
| type = string | ||
| description = "Security group ID for DB" | ||
| } | ||
|
|
||
| variable "instance_type_nginx" { | ||
| type = string | ||
| description = "Instance type for nginx" | ||
| } | ||
|
|
||
| variable "instance_type_was" { | ||
| type = string | ||
| description = "Instance type for WAS" | ||
| } | ||
|
|
||
| variable "instance_type_db" { | ||
| type = string | ||
| description = "Instance type for DB" | ||
| } | ||
|
|
||
| variable "key_name_was" { | ||
| type = string | ||
| } | ||
|
|
||
| variable "key_name_db" { | ||
| type = string | ||
| } | ||
|
|
||
| variable "region" { | ||
| type = string | ||
| description = "AWS region (e.g., ap-northeast-2)" | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -path "*/terraform/modules/compute/main.tf" -type fRepository: woowacourse-teams/2025-mul-kkam
Length of output: 118
🏁 Script executed:
find . -path "*/terraform/modules/compute/*" -type f | head -20Repository: woowacourse-teams/2025-mul-kkam
Length of output: 214
🏁 Script executed:
cat -n ./backend/terraform/modules/compute/main.tfRepository: woowacourse-teams/2025-mul-kkam
Length of output: 4020
🏁 Script executed:
# Check if there's any documentation or README explaining the terraform design
find ./backend/terraform -name "README*" -o -name "*.md" | xargs grep -l "nginx\|key_name\|SSM" 2>/dev/nullRepository: woowacourse-teams/2025-mul-kkam
Length of output: 59
🏁 Script executed:
# Check the root terraform directory structure
ls -la ./backend/terraform/Repository: woowacourse-teams/2025-mul-kkam
Length of output: 299
🏁 Script executed:
# Check environment configuration
find ./backend/terraform/environment -type f | head -20Repository: woowacourse-teams/2025-mul-kkam
Length of output: 359
🏁 Script executed:
# Search for key_name references in the entire terraform directory
rg "key_name" ./backend/terraform/ -A 2 -B 2Repository: woowacourse-teams/2025-mul-kkam
Length of output: 2862
nginx 인스턴스의 SSH 접근 방식 불일치 검토 필요
terraform 코드를 확인한 결과, 귀사의 지적이 정확합니다. compute 모듈의 세 인스턴스가 서로 다른 접근 방식을 사용하고 있습니다:
- nginx:
key_name미설정 → SSM 전용 접근 - was:
key_name = var.key_name_was→ SSH + SSM 접근 가능 - db:
key_name = var.key_name_db→ SSH + SSM 접근 가능
이러한 비대칭적 설계는 의도된 것으로 보입니다(nginx를 공개 IP 기반 리버스 프록시로 보호하면서, was/db는 직접 SSH 접근을 허용). 다만 운영 관점에서 고려할 점들이 있습니다:
현재 설계의 함의:
- 접근 방식의 일관성 부재: 세 서버에 다른 접근 절차를 적용해야 하므로 운영 복잡도 증가
- 향후 확장성 제약: nginx에 SSH 접근이 필요해지면 모듈 구조부터 수정해야 함
- 팀 내 표준화 부족: 접근 방식 선택의 이유가 명확히 문서화되지 않아 새로운 팀원의 이해도 저하
권장사항:
다음 중 하나를 명확히 선택하고 설계 결정을 주석으로 기록하세요:
- 옵션 1 (권장): 모든 인스턴스에
key_name제공 → 일관된 운영 절차, nginx도 필요시 직접 접근 가능 - 옵션 2: nginx만 SSM 전용, was/db도
key_name제거 → 보안 강화, 단 운영상 비용 증가
현재 snap 기반 SSM 에이전트 설치 방식도 패키지 관리자(apt)를 통한 공식 설치로 변경하면 더욱 안정적입니다.
| # WAS: nginx만 접근 가능 | ||
| resource "aws_security_group" "was_sg" { | ||
| name = "${var.project}-was-sg" | ||
| vpc_id = aws_vpc.main.id | ||
|
|
||
| ingress { | ||
| from_port = 8080 | ||
| to_port = 8080 | ||
| protocol = "tcp" | ||
| cidr_blocks = ["0.0.0.0/0"] | ||
| description = "Allow all traffic to 8080" | ||
| } | ||
|
|
||
| egress { | ||
| from_port = 0 | ||
| to_port = 0 | ||
| protocol = "-1" | ||
| cidr_blocks = ["0.0.0.0/0"] | ||
| } | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-was-sg" | ||
| } | ||
| } |
There was a problem hiding this comment.
WAS 보안 그룹의 인바운드 규칙이 의도와 일치하지 않습니다 (심각).
코멘트에는 "WAS: nginx만 접근 가능"이라 명시되어 있으나, 실제로는 cidr_blocks = ["0.0.0.0/0"]로 설정되어 인터넷의 모든 곳에서 8080 포트에 접근 가능한 상태입니다. 이는 심각한 보안 문제입니다.
문제점:
- 의도(코멘트)와 구현이 일치하지 않음
- 불필요한 공격 표면(attack surface) 노출
- 보안 정책 위반
해결 방안:
보안 그룹 간 참조(source_security_group_id)를 사용하여 Nginx 보안 그룹에서만 접근하도록 제한해야 합니다. 보안 그룹에서 특정 보안 그룹의 트래픽만 허용하려면 source_security_group_id를 사용하는 것이 모범 사례입니다.
-# WAS: nginx만 접근 가능
resource "aws_security_group" "was_sg" {
name = "${var.project}-was-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
- cidr_blocks = ["0.0.0.0/0"]
- description = "Allow all traffic to 8080"
+ source_security_group_id = aws_security_group.nginx_sg.id
+ description = "Allow traffic from Nginx only"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project}-was-sg"
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # WAS: nginx만 접근 가능 | |
| resource "aws_security_group" "was_sg" { | |
| name = "${var.project}-was-sg" | |
| vpc_id = aws_vpc.main.id | |
| ingress { | |
| from_port = 8080 | |
| to_port = 8080 | |
| protocol = "tcp" | |
| cidr_blocks = ["0.0.0.0/0"] | |
| description = "Allow all traffic to 8080" | |
| } | |
| egress { | |
| from_port = 0 | |
| to_port = 0 | |
| protocol = "-1" | |
| cidr_blocks = ["0.0.0.0/0"] | |
| } | |
| tags = { | |
| Name = "${var.project}-was-sg" | |
| } | |
| } | |
| resource "aws_security_group" "was_sg" { | |
| name = "${var.project}-was-sg" | |
| vpc_id = aws_vpc.main.id | |
| ingress { | |
| from_port = 8080 | |
| to_port = 8080 | |
| protocol = "tcp" | |
| source_security_group_id = aws_security_group.nginx_sg.id | |
| description = "Allow traffic from Nginx only" | |
| } | |
| egress { | |
| from_port = 0 | |
| to_port = 0 | |
| protocol = "-1" | |
| cidr_blocks = ["0.0.0.0/0"] | |
| } | |
| tags = { | |
| Name = "${var.project}-was-sg" | |
| } | |
| } |
🤖 Prompt for AI Agents
In backend/terraform/modules/network/main.tf around lines 86-109, the WAS
security group currently allows 0.0.0.0/0 on port 8080 which contradicts the
comment "WAS: nginx만 접근 가능"; replace the cidr_blocks ingress rule with a
security-group-only rule by removing cidr_blocks and adding
source_security_group_id = aws_security_group.nginx_sg.id (or the actual nginx
SG resource reference), update the description to reflect "Allow traffic from
nginx SG only", and ensure the ingress block only permits TCP port 8080 from
that security group; keep the egress unchanged.
| # DB: WAS만 접근 가능 | ||
| resource "aws_security_group" "db_sg" { | ||
| vpc_id = aws_vpc.main.id | ||
| name = "${var.project}-db-sg" | ||
|
|
||
| ingress { | ||
| from_port = 3306 | ||
| to_port = 3306 | ||
| protocol = "tcp" | ||
| cidr_blocks = [var.vpc_cidr] | ||
| } | ||
|
|
||
| egress { | ||
| from_port = 0 | ||
| to_port = 0 | ||
| protocol = "-1" | ||
| cidr_blocks = ["0.0.0.0/0"] | ||
| } | ||
|
|
||
| tags = { | ||
| Name = "${var.project}-db-sg" | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
DB 보안 그룹 규칙을 더욱 제한적으로 개선할 것을 권장합니다.
현재 DB 보안 그룹이 VPC CIDR 전체에서의 3306 포트 접근을 허용하고 있습니다. 이는 동작하지만, 최소 권한 원칙(principle of least privilege) 관점에서는 개선의 여지가 있습니다.
현재 상태의 문제점:
- VPC 내 모든 인스턴스가 DB에 접근 가능
- WAS 인스턴스만 DB에 접근 필요한데, 다른 리소스도 접근 가능
- 향후 VPC에 다른 리소스가 추가될 때 불필요한 노출 위험
개선 방안:
WAS 보안 그룹의 규칙 수정과 함께, DB 보안 그룹도 WAS 보안 그룹을 명시적 소스로 지정하는 것이 권장됩니다:
# DB: WAS만 접근 가능
resource "aws_security_group" "db_sg" {
vpc_id = aws_vpc.main.id
name = "${var.project}-db-sg"
ingress {
from_port = 3306
to_port = 3306
protocol = "tcp"
- cidr_blocks = [var.vpc_cidr]
+ source_security_group_id = aws_security_group.was_sg.id
+ description = "Allow traffic from WAS only"
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "${var.project}-db-sg"
}
}장점:
- 최소 권한 원칙 준수
- 코드 의도와 구현의 일치
- VPC 구조 변경 시에도 보안 정책 자동 유지
- 보안 감사 및 이해가 용이
🤖 Prompt for AI Agents
In backend/terraform/modules/network/main.tf around lines 111 to 133, the DB
security group currently allows MySQL (3306) from the entire VPC CIDR; change
the ingress to allow port 3306 only from the WAS security group instead. Replace
cidr_blocks = [var.vpc_cidr] with a security_groups (or
source_security_group_id) reference to the WAS security group resource (e.g.,
aws_security_group.was_sg.id or a passed-in was_sg_id variable), ensure the WAS
SG resource/variable exists and is created before the DB SG, and keep the egress
unchanged; update tags/comments accordingly to reflect the tighter rule.
🔗 관련 이슈
📝 작업 내용
주요 변경사항
📸 스크린샷 (Optional)
Summary by CodeRabbit
릴리스 노트
✏️ Tip: You can customize this high-level summary in your review settings.