Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 17 additions & 26 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
# Terraform 관련 파일 무시
.terraform/ # terraform init 시 생성되는 폴더
*.tfstate # 상태 파일 (리소스 실제 정보 포함)
*.tfstate.* # 상태 파일 백업
terraform.tfstate
terraform.tfstate.*
# Terraform 상태 및 캐시 파일
*.tfstate
*.tfstate.*

# Terraform 변수 파일 (민감정보 방지)
*.tfvars
*.tfstate.backup
.terraform.lock.hcl
terraform.tfvars # 민감 정보 입력용 파일
*.auto.tfvars
crash.log # Terraform 충돌 로그
.terraform
override.tf
override.tf.json
# AWS CLI 자격 증명
.aws/ # ~/.aws/credentials, config 등
~/.aws/
.aws
# 시스템 자동 생성 파일 (Windows/macOS)
.DS_Store # macOS
Thumbs.db # Windows
ehthumbs.db # Windows
*.log # 일반 로그 파일
*.tmp # 임시 파일

# VSCode 설정 (선택사항)
.vscode/
# Terraform 실행 계획 파일
*.tfplan

# Crash log
crash.log

# Provider 바이너리/캐시 디렉토리
.terraform/

# IDE 또는 시스템 파일
.DS_Store
Thumbs.db
43 changes: 43 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

61 changes: 59 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,59 @@
# Application-Development
DevSecOps Architecture for a Virtual Enterprise – Application Development Repo
# 🛠️ Terraform 기반 AWS CI/CD 인프라 구축

이 프로젝트는 **Terraform IaC(Infra as Code)** 기반으로 AWS에 Jenkins 중심의 CI/CD 파이프라인 및 보안 분석 도구 환경을 자동화하는 구성을 담고 있습니다.
**모듈화 설계**로 유지보수성과 확장성을 확보하였으며, AMI 기반의 EC2 생성 방식으로 신속한 인스턴스 배포가 가능합니다.

---

## 🧭 전체 구성도

```plaintext

webhook
GitHub → Jenkins(CI) → ECR → Codedeploy(ECS)
↓ ↓(pull)
[SAST] [SCA] [DAST]
s3
lambda → securityhub → lambda → slack

- 인프라팀이 codedeploy 부분을 맡아주기로 해서 ecr 까지 만들었지만 분석도구 알림은
우리가 해야하는게 맞지않을까?

## 디렉토리 구조
terraform/
├── main.tf
├── variables.tf
├── terraform.tfvars
├── outputs.tf
├── modules/
│ ├── network/ # VPC, 서브넷, IGW 등 네트워크 구성
│ ├── security_group/ # 공용 보안 그룹 (모든 EC2 공유 사용)
│ ├── jenkins/ # Jenkins EC2 인스턴스
│ ├── sast/ # SonarQube 인스턴스 (SAST)
│ ├── sca/ # Dependency-Check 인스턴스 (SCA)
│ ├── dast/ # OWASP ZAP 인스턴스 (DAST)
│ └── ecr/ # Docker 이미지 저장소

20250719 1907부 수정
- 기존 IaC용 iam과 keypair를 사용하던 방식에서 인스턴스 별 iam 생성 및 IaC용 keypair
생성 후 사용하도록 변경

- IaC용 iam과 keypair는 테라폼 클라우드에서 갖고오므로 유지 ..

나는 감쟈 뭐해야하지

20250720 1800부 lambda 만들기 시작

20250721 2300부 1단계 람다 및 s3 생성 완료.

20250723 ecs, codedeploy, alb 생성 시작. subin 폴더 추가

20250723 1640부
- aws상에서 route53 설정 완료 후 acm 권한도 For_jenkins에 넣어줌. iac코드 반영은 안함.
- (root/main.tf)alb_certificate_arn = var.alb_certificate_arn #이것도 자동
생성으로 박아야 함.
103 changes: 103 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
module "jenkins" {
source = "./modules/jenkins"

ami_id = var.jenkins_ami_id

subnet_id = module.network.public_subnet_ids[0] # ✅ AZ1에 생성
vpc_id = module.network.vpc_id # 기존 사용 중이라면 유지

shared_key_name = module.shared_key.key_name
security_group_id = module.network.shared_security_group_id
}

module "shared_key" {
source = "./modules/shared_key"
}

module "network" {
source = "./modules/network"
name_prefix = "infra"
}

module "ecr"{
source = "./modules/ecr"
repository_name = var.ecr_repository_name
}

module "sast" {
source = "./modules/sast"
ami_id = var.sast_ami_id
subnet_id = module.network.public_subnet_ids[0]
security_group_id = module.network.shared_security_group_id
shared_key_name = module.shared_key.key_name
}

module "sca"{
source = "./modules/sca"
ami_id = var.sca_ami_id
subnet_id = module.network.public_subnet_ids[0]
security_group_id = module.network.shared_security_group_id
shared_key_name = module.shared_key.key_name
}

module "dast"{
source = "./modules/dast"
ami_id = var.dast_ami_id
subnet_id = module.network.public_subnet_ids[0]
security_group_id = module.network.shared_security_group_id
shared_key_name = module.shared_key.key_name
}

module "lambda_iam" {
source = "./modules/lambda/iam"
name = "lambda-common-role"
s3_bucket_arn = "arn:aws:s3:::webgoat-codedeploy-bucket" # 예시, 실제 값에 맞게 수정
}

module "s3" {
source = "./modules/s3"

dast_s3_bucket_name = var.dast_s3_bucket_name
sast_s3_bucket_name = var.sast_s3_bucket_name
}

module "lambda_sast" {
source = "./modules/lambda/sast"
function_name = "sast-s3-trigger-lambda"
iam_role_arn = module.lambda_iam.role_arn
slack_webhook_url = var.sast_slack_webhook_url
sast_s3_bucket_name = module.s3.sast_s3_bucket_name
sast_s3_filter_prefix = var.sast_s3_filter_prefix
sast_s3_bucket_arn = module.s3.sast_s3_bucket_arn
}

module "lambda_dast" {
source = "./modules/lambda/dast"
function_name = "dast-s3-trigger-lambda"
iam_role_arn = module.lambda_iam.role_arn
slack_webhook_url = var.dast_slack_webhook_url
dast_s3_bucket_name = module.s3.dast_s3_bucket_name
dast_s3_filter_prefix = var.dast_s3_filter_prefix
dast_s3_bucket_arn = module.s3.dast_s3_bucket_arn
}

module "alb" {
source = "./modules/alb"
vpc_id = module.network.vpc_id
public_subnet_ids = module.network.public_subnet_ids
alb_security_group_id = module.shared_security_group_id
alb_certificate_arn = var.alb_certificate_arn #이것도 자동 생성으로 박아야 함.
alb_name = var.alb_name
}

module "codedeploy" {
source = "./modules/codedeploy"
project_name = var.project_name

ecs_cluster_name = module.ecs.cluster_name
ecs_service = module.ecs.service_name

listener_arn = module.alb.listener_arn
blue_target_group_name = module.alb.blue_target_group_name
green_target_group_name = module.alb.green_target_group_name
}
Empty file added modules/alb/iam.tf
Empty file.
88 changes: 88 additions & 0 deletions modules/alb/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# ALB
# 외부 사용자를 위한 로드 밸런서이므로 외부에 노출해야해서 tfsec 경고 무시
resource "aws_lb" "main" {
name = var.alb_name
internal = false
load_balancer_type = "application"
security_groups = [var.alb_security_group_id]
subnets = var.public_subnet_ids

#인프라와 상이함. 인프라는 true
enable_deletion_protection = false

tabs = {
Name = val.alb_name
}
}


# Target Group
resource "aws_lb_target_group" "blue" {
name = "${var.alb_name}-blue"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id

health_check {
path = "/"
protocol = "HTTP"
matcher = "200-399"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
}
tags = {
Name = "${var.project_name}-blue-tg"
}
}

resource "aws_lb_target_group" "green" {
name = "${var.alb_name}-green"
port = 80
protocol = "HTTP"
vpc_id = var.vpc_id

# 우린 없음. target_type = "instance"
health_check {
path = "/"
protocol = "HTTP"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
}
tags = {
Name = "${var.alb_name}-green"
}
}

# ALB 리스너
resource "aws_lb_listener" "https" {
load_balancer_arn = aws_lb.main.arn
port = 443
protocol = "HTTPS"
ssl_policy = "ELBSecurityPolicy2016-08"
certificate_arn = var.alb_certificate_arn

default_action {
type = "forward"
target_group_arn = aws_lb_target_group.blue.arn
}
}

resource "aws_lb_listener" "https_redirect" {
load_balancer_arn = aws_lb.main.arn
port = 80
protocol = "HTTP"

default_action {
type = "redirect"

redirect {
port = "443"
protocol = "HTTPS"
status_code = "HTTP_301"
}
}
}
29 changes: 29 additions & 0 deletions modules/alb/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
output "alb_dns_name" {
description = "The DNS name of the ALB"
value = aws_lb.main.dns_name
}

output "alb_https_listener_arn" {
description = "The ARN of the HTTPS listener"
value = aws_lb_listener.https.arn
}

output "alb_http_listener_arn" {
description = "The ARN of the HTTP listener"
value = aws_lb_listener.http_redirect.arn
}

output "blue_target_group_name" {
description = "The name of the Blue target group"
value = aws_lb_target_group.blue.name
}

output "green_target_group_name" {
description = "The name of the Green target group"
value = aws_lb_target_group.green.name
}

output "blue_target_group_arn" {
description = "The ARN of the Blue target group"
value = aws_lb_target_group.blue.arn
}
Loading