From 781c0bf3c8914fa154f78a608191cab52b6a9fff Mon Sep 17 00:00:00 2001 From: 3olly Date: Mon, 23 Jun 2025 04:26:40 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=ED=8F=B4=EB=8D=94=EA=B5=AC=EC=A1=B0?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20error=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- operation-team-account/.gitignore | 22 ++++++ operation-team-account/main.tf | 25 +++++++ .../cloudwatch_logs_to_firehose/main.tf | 7 ++ .../cloudwatch_logs_to_firehose/variables.tf | 19 +++++ .../modules/firehose/main.tf | 71 +++++++++++++++++++ .../modules/firehose/variables.tf | 7 ++ .../modules/opensearch/main.tf | 43 +++++++++++ .../modules/opensearch/outputs.tf | 3 + .../modules/opensearch/variables.tf | 9 +++ operation-team-account/modules/s3/main.tf | 17 +++++ operation-team-account/modules/s3/outputs.tf | 3 + .../modules/securitylake/main.tf | 9 +++ .../modules/securitylake/variables.tf | 0 operation-team-account/outputs.tf | 1 + operation-team-account/providers.tf | 4 ++ operation-team-account/variables.tf | 14 ++++ 16 files changed, 254 insertions(+) create mode 100644 operation-team-account/.gitignore create mode 100644 operation-team-account/main.tf create mode 100644 operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf create mode 100644 operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf create mode 100644 operation-team-account/modules/firehose/main.tf create mode 100644 operation-team-account/modules/firehose/variables.tf create mode 100644 operation-team-account/modules/opensearch/main.tf create mode 100644 operation-team-account/modules/opensearch/outputs.tf create mode 100644 operation-team-account/modules/opensearch/variables.tf create mode 100644 operation-team-account/modules/s3/main.tf create mode 100644 operation-team-account/modules/s3/outputs.tf create mode 100644 operation-team-account/modules/securitylake/main.tf create mode 100644 operation-team-account/modules/securitylake/variables.tf create mode 100644 operation-team-account/outputs.tf create mode 100644 operation-team-account/providers.tf create mode 100644 operation-team-account/variables.tf diff --git a/operation-team-account/.gitignore b/operation-team-account/.gitignore new file mode 100644 index 00000000..e5ab9a69 --- /dev/null +++ b/operation-team-account/.gitignore @@ -0,0 +1,22 @@ +# Terraform 관련 파일 무시 +.terraform/ # terraform init 시 생성되는 폴더 +*.tfstate # 상태 파일 (리소스 실제 정보 포함) +*.tfstate.* # 상태 파일 백업 +*.tfvars +*.tfstate.backup +.terraform.lock.hcl +terraform.tfvars # 민감 정보 입력용 파일 +crash.log # Terraform 충돌 로그 +.terraform +# AWS CLI 자격 증명 +.aws/ # ~/.aws/credentials, config 등 + +# 시스템 자동 생성 파일 (Windows/macOS) +.DS_Store # macOS +Thumbs.db # Windows +ehthumbs.db # Windows +*.log # 일반 로그 파일 +*.tmp # 임시 파일 + +# VSCode 설정 (선택사항) +.vscode/ diff --git a/operation-team-account/main.tf b/operation-team-account/main.tf new file mode 100644 index 00000000..beb1c54c --- /dev/null +++ b/operation-team-account/main.tf @@ -0,0 +1,25 @@ +module "s3" { + source = "./modules/s3" +} + +module "opensearch" { + source = "./modules/opensearch" +} + +module "firehose" { + source = "./modules/firehose" + opensearch_domain_arn = module.opensearch.domain_arn + s3_bucket_arn = module.s3.bucket_arn +} + +module "cloudwatch_logs_to_firehose" { + source = "./modules/cloudwatch_logs_to_firehose" + + subscription_filter_name = "cw-to-firehose" + log_group_name = var.log_group_name + firehose_arn = var.firehose_arn + role_arn = var.role_arn +} +module "securitylake" { + source = "./modules/securitylake" +} diff --git a/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf b/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf new file mode 100644 index 00000000..7164b9ab --- /dev/null +++ b/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf @@ -0,0 +1,7 @@ +resource "aws_cloudwatch_log_subscription_filter" "logs_to_firehose" { + name = var.subscription_filter_name + log_group_name = var.log_group_name + filter_pattern = "" # 모든 로그 전달 + destination_arn = var.firehose_arn + role_arn = var.role_arn +} diff --git a/operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf b/operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf new file mode 100644 index 00000000..254047c4 --- /dev/null +++ b/operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf @@ -0,0 +1,19 @@ +variable "subscription_filter_name" { + description = "CloudWatch Logs Subscription Filter 이름" + type = string +} + +variable "log_group_name" { + description = "대상 CloudWatch 로그 그룹 이름" + type = string +} + +variable "firehose_arn" { + description = "로그를 전송할 Kinesis Firehose ARN" + type = string +} + +variable "role_arn" { + description = "CloudWatch Logs → Firehose 연결용 IAM Role ARN" + type = string +} diff --git a/operation-team-account/modules/firehose/main.tf b/operation-team-account/modules/firehose/main.tf new file mode 100644 index 00000000..a6061fc9 --- /dev/null +++ b/operation-team-account/modules/firehose/main.tf @@ -0,0 +1,71 @@ +resource "aws_iam_role" "firehose_role" { + name = "siem-firehose-role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { + Service = "firehose.amazonaws.com" + }, + Action = "sts:AssumeRole" + } + ] + }) +} + +resource "aws_iam_role_policy" "firehose_policy" { + name = "firehose-access" + role = aws_iam_role.firehose_role.id + + policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Action = [ + "es:DescribeElasticsearchDomain", + "es:DescribeElasticsearchDomains", + "es:DescribeElasticsearchDomainConfig", + "es:ESHttpPost", + "es:ESHttpPut", + "es:ESHttpGet" + ], + Resource = "*" + }, + { + Effect = "Allow", + Action = [ + "s3:PutObject", + "s3:GetBucketLocation", + "s3:ListBucket" + ], + Resource = "*" + } + ] + }) +} + +resource "aws_kinesis_firehose_delivery_stream" "to_opensearch" { + name = "siem-delivery" + destination = "opensearch" + + opensearch_configuration { + domain_arn = var.opensearch_domain_arn + role_arn = aws_iam_role.firehose_role.arn + index_name = "cw-logs" + type_name = "log" + + s3_backup_mode = "FailedDocumentsOnly" + + s3_configuration { + role_arn = aws_iam_role.firehose_role.arn + bucket_arn = var.s3_bucket_arn + buffering_interval = 300 + buffering_size = 5 + compression_format = "UNCOMPRESSED" + prefix = "backup/" + } + } +} \ No newline at end of file diff --git a/operation-team-account/modules/firehose/variables.tf b/operation-team-account/modules/firehose/variables.tf new file mode 100644 index 00000000..93dd87a1 --- /dev/null +++ b/operation-team-account/modules/firehose/variables.tf @@ -0,0 +1,7 @@ +variable "opensearch_domain_arn" { + type = string +} + +variable "s3_bucket_arn" { + type = string +} \ No newline at end of file diff --git a/operation-team-account/modules/opensearch/main.tf b/operation-team-account/modules/opensearch/main.tf new file mode 100644 index 00000000..3f9a6152 --- /dev/null +++ b/operation-team-account/modules/opensearch/main.tf @@ -0,0 +1,43 @@ +data "aws_caller_identity" "current" {} + +resource "aws_opensearch_domain" "siem" { + domain_name = "siem-domain" + engine_version = "OpenSearch_2.9" + + cluster_config { + instance_type = "t3.small.search" + instance_count = 1 + } + + ebs_options { + ebs_enabled = true + volume_size = 10 + } + + domain_endpoint_options { + enforce_https = true + tls_security_policy = "Policy-Min-TLS-1-2-2019-07" + } + + node_to_node_encryption { + enabled = true + } + + encrypt_at_rest { + enabled = true + } + + access_policies = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { + AWS = "arn:aws:sts::${data.aws_caller_identity.current.account_id}:assumed-role/${var.sso_role_name}/${var.sso_user_name}" + }, + Action = "es:*", + Resource = "arn:aws:es:ap-northeast-2:${data.aws_caller_identity.current.account_id}:domain/siem-domain/*" + } + ] + }) +} diff --git a/operation-team-account/modules/opensearch/outputs.tf b/operation-team-account/modules/opensearch/outputs.tf new file mode 100644 index 00000000..5272c407 --- /dev/null +++ b/operation-team-account/modules/opensearch/outputs.tf @@ -0,0 +1,3 @@ +output "domain_arn" { + value = aws_opensearch_domain.siem.arn +} \ No newline at end of file diff --git a/operation-team-account/modules/opensearch/variables.tf b/operation-team-account/modules/opensearch/variables.tf new file mode 100644 index 00000000..b581630a --- /dev/null +++ b/operation-team-account/modules/opensearch/variables.tf @@ -0,0 +1,9 @@ +variable "sso_role_name" { + description = "SSO에서 부여된 IAM 역할 이름" + type = string +} + +variable "sso_user_name" { + description = "SSO 세션 사용자 이름 (예: 이메일)" + type = string +} diff --git a/operation-team-account/modules/s3/main.tf b/operation-team-account/modules/s3/main.tf new file mode 100644 index 00000000..b7689d5f --- /dev/null +++ b/operation-team-account/modules/s3/main.tf @@ -0,0 +1,17 @@ +resource "random_id" "bucket_id" { + byte_length = 4 +} + +resource "aws_s3_bucket" "firehose_backup" { + bucket = "siem-firehose-backup-${random_id.bucket_id.hex}" + force_destroy = true +} + +resource "aws_s3_bucket_public_access_block" "block" { + bucket = aws_s3_bucket.firehose_backup.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} \ No newline at end of file diff --git a/operation-team-account/modules/s3/outputs.tf b/operation-team-account/modules/s3/outputs.tf new file mode 100644 index 00000000..f4bd5c26 --- /dev/null +++ b/operation-team-account/modules/s3/outputs.tf @@ -0,0 +1,3 @@ +output "bucket_arn" { + value = aws_s3_bucket.firehose_backup.arn +} \ No newline at end of file diff --git a/operation-team-account/modules/securitylake/main.tf b/operation-team-account/modules/securitylake/main.tf new file mode 100644 index 00000000..64267b84 --- /dev/null +++ b/operation-team-account/modules/securitylake/main.tf @@ -0,0 +1,9 @@ +resource "aws_security_lake" "this" { + enable_all = true +} + +resource "aws_security_lake_organization_configuration" "org_config" { + auto_enable = { + all_regions = true + } +} diff --git a/operation-team-account/modules/securitylake/variables.tf b/operation-team-account/modules/securitylake/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/operation-team-account/outputs.tf b/operation-team-account/outputs.tf new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/operation-team-account/outputs.tf @@ -0,0 +1 @@ + diff --git a/operation-team-account/providers.tf b/operation-team-account/providers.tf new file mode 100644 index 00000000..f0ae24f2 --- /dev/null +++ b/operation-team-account/providers.tf @@ -0,0 +1,4 @@ +provider "aws" { + region = "ap-northeast-2" + profile = "my-profile" +} \ No newline at end of file diff --git a/operation-team-account/variables.tf b/operation-team-account/variables.tf new file mode 100644 index 00000000..45c6698d --- /dev/null +++ b/operation-team-account/variables.tf @@ -0,0 +1,14 @@ +variable "log_group_name" { + description = "CloudWatch 로그 그룹 이름" + type = string +} + +variable "firehose_arn" { + description = "Kinesis Firehose ARN" + type = string +} + +variable "role_arn" { + description = "CloudWatch → Firehose 연결용 IAM Role ARN" + type = string +} From e9aea3750d4397c92d6d3fe6afde28d83f79a806 Mon Sep 17 00:00:00 2001 From: 3olly Date: Mon, 23 Jun 2025 04:40:19 +0900 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20terrform=20init=20=EC=95=88=20?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- operation-team-account/main.tf | 13 +++-- .../modules/cloudwatch/main.tf | 33 ++++++++++++ .../variables.tf | 0 .../cloudwatch_logs_to_firehose/main.tf | 7 --- .../modules/firehose/main.tf | 54 ++++++++++++++----- .../modules/firehose/outputs.tf | 9 ++++ .../modules/opensearch/main.tf | 29 ++++++---- .../modules/opensearch/variables.tf | 6 +++ .../modules/securitylake/main.tf | 43 +++++++++++++-- .../modules/securitylake/variables.tf | 0 operation-team-account/variables.tf | 12 ++--- 11 files changed, 158 insertions(+), 48 deletions(-) create mode 100644 operation-team-account/modules/cloudwatch/main.tf rename operation-team-account/modules/{cloudwatch_logs_to_firehose => cloudwatch}/variables.tf (100%) delete mode 100644 operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf create mode 100644 operation-team-account/modules/firehose/outputs.tf delete mode 100644 operation-team-account/modules/securitylake/variables.tf diff --git a/operation-team-account/main.tf b/operation-team-account/main.tf index beb1c54c..d6d9a6be 100644 --- a/operation-team-account/main.tf +++ b/operation-team-account/main.tf @@ -3,7 +3,10 @@ module "s3" { } module "opensearch" { - source = "./modules/opensearch" + source = "./modules/opensearch" + sso_role_name = var.sso_role_name + sso_user_name = var.sso_user_name + firehose_role_arn = module.firehose.firehose_role_arn } module "firehose" { @@ -12,13 +15,13 @@ module "firehose" { s3_bucket_arn = module.s3.bucket_arn } -module "cloudwatch_logs_to_firehose" { - source = "./modules/cloudwatch_logs_to_firehose" +module "cloudwatch" { + source = "./modules/cloudwatch" subscription_filter_name = "cw-to-firehose" log_group_name = var.log_group_name - firehose_arn = var.firehose_arn - role_arn = var.role_arn + firehose_arn = module.firehose.delivery_stream_arn + role_arn = module.firehose.firehose_role_arn } module "securitylake" { source = "./modules/securitylake" diff --git a/operation-team-account/modules/cloudwatch/main.tf b/operation-team-account/modules/cloudwatch/main.tf new file mode 100644 index 00000000..bbe3e6e7 --- /dev/null +++ b/operation-team-account/modules/cloudwatch/main.tf @@ -0,0 +1,33 @@ +resource "aws_cloudwatch_log_subscription_filter" "logs_to_firehose" { + name = var.subscription_filter_name + log_group_name = var.log_group_name + filter_pattern = "{ $.level = \"ERROR\" }" # ERROR 레벨만 전달 + destination_arn = var.firehose_arn + role_arn = var.role_arn +} + +resource "aws_cloudwatch_log_group" "target" { + name = var.log_group_name + retention_in_days = 14 # 14일 지나면 자동 삭제 +} + +resource "aws_cloudwatch_metric_filter" "error_count" { + name = "ErrorCount" + log_group_name = aws_cloudwatch_log_group.target.name + pattern = "\"ERROR\"" + metric_transformation { + name = "ErrorCount" + namespace = "MyApp/SIEM" + value = "1" + } +} + +resource "aws_cloudwatch_metric_alarm" "error_alarm" { + alarm_name = "HighErrorCount" + namespace = "MyApp/SIEM" + metric_name = aws_cloudwatch_metric_filter.error_count.metric_transformation[0].name + threshold = 100 + comparison_operator = "GreaterThanThreshold" + evaluation_periods = 1 + alarm_actions = [aws_sns_topic.alerts.arn] +} diff --git a/operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf b/operation-team-account/modules/cloudwatch/variables.tf similarity index 100% rename from operation-team-account/modules/cloudwatch_logs_to_firehose/variables.tf rename to operation-team-account/modules/cloudwatch/variables.tf diff --git a/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf b/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf deleted file mode 100644 index 7164b9ab..00000000 --- a/operation-team-account/modules/cloudwatch_logs_to_firehose/main.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "aws_cloudwatch_log_subscription_filter" "logs_to_firehose" { - name = var.subscription_filter_name - log_group_name = var.log_group_name - filter_pattern = "" # 모든 로그 전달 - destination_arn = var.firehose_arn - role_arn = var.role_arn -} diff --git a/operation-team-account/modules/firehose/main.tf b/operation-team-account/modules/firehose/main.tf index a6061fc9..10c23bcb 100644 --- a/operation-team-account/modules/firehose/main.tf +++ b/operation-team-account/modules/firehose/main.tf @@ -20,33 +20,46 @@ resource "aws_iam_role_policy" "firehose_policy" { role = aws_iam_role.firehose_role.id policy = jsonencode({ - Version = "2012-10-17", + Version = "2012-10-17" Statement = [ + # 1) OpenSearch 접근 권한: 도메인 자체와 색인 아래 객체만 허용 { - Effect = "Allow", - Action = [ + Effect = "Allow" + Action = [ "es:DescribeElasticsearchDomain", "es:DescribeElasticsearchDomains", "es:DescribeElasticsearchDomainConfig", "es:ESHttpPost", "es:ESHttpPut", - "es:ESHttpGet" - ], - Resource = "*" + "es:ESHttpGet", + ] + Resource = [ + var.opensearch_domain_arn, + "${var.opensearch_domain_arn}/*", + ] + }, + + # 2) S3 버킷 접근 권한: 버킷 메타데이터 조회와 객체 Put만 해당 버킷으로 제한 + { + Effect = "Allow" + Action = [ + "s3:ListBucket", # 버킷 목록 조회(버킷 이름에 한정) + "s3:GetBucketLocation", # 리전 조회 + ] + Resource = var.s3_bucket_arn }, { - Effect = "Allow", - Action = [ - "s3:PutObject", - "s3:GetBucketLocation", - "s3:ListBucket" - ], - Resource = "*" + Effect = "Allow" + Action = [ + "s3:PutObject", # 객체 업로드 + ] + Resource = "${var.s3_bucket_arn}/*" } ] }) } + resource "aws_kinesis_firehose_delivery_stream" "to_opensearch" { name = "siem-delivery" destination = "opensearch" @@ -64,8 +77,21 @@ resource "aws_kinesis_firehose_delivery_stream" "to_opensearch" { bucket_arn = var.s3_bucket_arn buffering_interval = 300 buffering_size = 5 - compression_format = "UNCOMPRESSED" + compression_format = "GZIP" prefix = "backup/" } } +} +# S3 버킷에 Lifecycle 정책 붙이기 +resource "aws_s3_bucket_lifecycle_configuration" "firehose_backup" { + bucket = aws_s3_bucket.firehose_backup.id + + rule { + id = "ExpireBackup" + status = "Enabled" + + filter { prefix = "backup/" } + + expiration { days = 7 } # 7일 지난 백업은 자동 삭제 + } } \ No newline at end of file diff --git a/operation-team-account/modules/firehose/outputs.tf b/operation-team-account/modules/firehose/outputs.tf new file mode 100644 index 00000000..02f54d53 --- /dev/null +++ b/operation-team-account/modules/firehose/outputs.tf @@ -0,0 +1,9 @@ +output "delivery_stream_arn" { + value = aws_kinesis_firehose_delivery_stream.to_opensearch.arn + description = "ARN of the Firehose delivery stream" +} + +output "firehose_role_arn" { + value = aws_iam_role.firehose_role.arn + description = "ARN of the Firehose IAM role" +} diff --git a/operation-team-account/modules/opensearch/main.tf b/operation-team-account/modules/opensearch/main.tf index 3f9a6152..fdede2c7 100644 --- a/operation-team-account/modules/opensearch/main.tf +++ b/operation-team-account/modules/opensearch/main.tf @@ -28,16 +28,23 @@ resource "aws_opensearch_domain" "siem" { } access_policies = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Principal = { - AWS = "arn:aws:sts::${data.aws_caller_identity.current.account_id}:assumed-role/${var.sso_role_name}/${var.sso_user_name}" - }, - Action = "es:*", - Resource = "arn:aws:es:ap-northeast-2:${data.aws_caller_identity.current.account_id}:domain/siem-domain/*" + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + AWS = [ + "arn:aws:sts::${data.aws_caller_identity.current.account_id}:assumed-role/${var.sso_role_name}/${var.sso_user_name}", + var.firehose_role_arn, + ] } - ] - }) + Action = "es:*" + # 도메인 및 그 하위 인덱스·도큐먼트 전체 리소스 + Resource = [ + aws_opensearch_domain.siem.arn, + "${aws_opensearch_domain.siem.arn}/*", + ] + } + ] + }) } diff --git a/operation-team-account/modules/opensearch/variables.tf b/operation-team-account/modules/opensearch/variables.tf index b581630a..449a8fe3 100644 --- a/operation-team-account/modules/opensearch/variables.tf +++ b/operation-team-account/modules/opensearch/variables.tf @@ -7,3 +7,9 @@ variable "sso_user_name" { description = "SSO 세션 사용자 이름 (예: 이메일)" type = string } + +variable "firehose_role_arn" { + description = "ARN of the Firehose IAM role to allow write access" + type = string +} + diff --git a/operation-team-account/modules/securitylake/main.tf b/operation-team-account/modules/securitylake/main.tf index 64267b84..5f77218b 100644 --- a/operation-team-account/modules/securitylake/main.tf +++ b/operation-team-account/modules/securitylake/main.tf @@ -1,9 +1,42 @@ -resource "aws_security_lake" "this" { - enable_all = true +# 1. 메타스토어 관리자 IAM 역할 생성 +resource "aws_iam_role" "securitylake_manager" { + name = "securitylake-meta-store-manager" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Effect = "Allow", + Principal = { Service = "securitylake.amazonaws.com" }, + Action = "sts:AssumeRole" + } + ] + }) +} + +# 2. 조직 단위 Security Lake 활성화 (조직 전체 설정) +resource "aws_securitylake_organization_configuration" "org_config" { + auto_enable { + all_regions = false + regions = ["ap-northeast-2"] + } } -resource "aws_security_lake_organization_configuration" "org_config" { - auto_enable = { - all_regions = true +# 3. 특정 리전(ap-northeast-2)에서 Data Lake 활성화 및 라이프사이클 설정 +resource "aws_securitylake_data_lake" "this" { + meta_store_manager_role_arn = aws_iam_role.securitylake_manager.arn + + configuration { + region = "ap-northeast-2" + + lifecycle_configuration { + expiration { + days = 30 # 데이터 30일 보관 + } + transition { + days = 7 + storage_class = "ONEZONE_IA" # 7일 후 저비용 스토리지로 전환 + } + } } } diff --git a/operation-team-account/modules/securitylake/variables.tf b/operation-team-account/modules/securitylake/variables.tf deleted file mode 100644 index e69de29b..00000000 diff --git a/operation-team-account/variables.tf b/operation-team-account/variables.tf index 45c6698d..d532342d 100644 --- a/operation-team-account/variables.tf +++ b/operation-team-account/variables.tf @@ -1,14 +1,14 @@ -variable "log_group_name" { - description = "CloudWatch 로그 그룹 이름" +variable "sso_role_name" { + description = "SSO에서 부여된 IAM 역할 이름" type = string } -variable "firehose_arn" { - description = "Kinesis Firehose ARN" +variable "sso_user_name" { + description = "SSO 세션 사용자 이름" type = string } -variable "role_arn" { - description = "CloudWatch → Firehose 연결용 IAM Role ARN" +variable "log_group_name" { + description = "전송할 CloudWatch Log Group 이름" type = string } From 05d2f060ead3090f7241fcf5e967e7c08b4e2225 Mon Sep 17 00:00:00 2001 From: 3olly Date: Wed, 25 Jun 2025 19:26:56 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20tfsec=20=ED=86=B5=EA=B3=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20KMS=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/firehose/main.tf | 2 +- operation-team-account/modules/s3/main.tf | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/operation-team-account/modules/firehose/main.tf b/operation-team-account/modules/firehose/main.tf index 10c23bcb..f1dd71d1 100644 --- a/operation-team-account/modules/firehose/main.tf +++ b/operation-team-account/modules/firehose/main.tf @@ -27,7 +27,7 @@ resource "aws_iam_role_policy" "firehose_policy" { Effect = "Allow" Action = [ "es:DescribeElasticsearchDomain", - "es:DescribeElasticsearchDomains", + "es:DescribeElasticsearchDomains", # Note: 이 액션은 리소스 지정이 불가능하여 "*" 사용 필요 "es:DescribeElasticsearchDomainConfig", "es:ESHttpPost", "es:ESHttpPut", diff --git a/operation-team-account/modules/s3/main.tf b/operation-team-account/modules/s3/main.tf index b7689d5f..b0977c44 100644 --- a/operation-team-account/modules/s3/main.tf +++ b/operation-team-account/modules/s3/main.tf @@ -14,4 +14,22 @@ resource "aws_s3_bucket_public_access_block" "block" { block_public_policy = true ignore_public_acls = true restrict_public_buckets = true -} \ No newline at end of file +} + +resource "aws_kms_key" "s3_cmk" { + description = "KMS key for encrypting Firehose backup S3 bucket" + deletion_window_in_days = 10 + enable_key_rotation = true +} + +# 암호화 설정 +resource "aws_s3_bucket_server_side_encryption_configuration" "default" { + bucket = aws_s3_bucket.firehose_backup.id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "aws:kms" + kms_master_key_id = aws_kms_key.s3_cmk.arn + } + } +} From cb7baa156d2dac1ef70b89b5fddab164c0f84949 Mon Sep 17 00:00:00 2001 From: 3olly Date: Thu, 26 Jun 2025 01:30:41 +0900 Subject: [PATCH 4/5] fix: version upgrade --- operation-team-account/modules/firehose/main.tf | 13 ------------- operation-team-account/modules/s3/main.tf | 14 ++++++++++++++ operation-team-account/providers.tf | 9 +++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/operation-team-account/modules/firehose/main.tf b/operation-team-account/modules/firehose/main.tf index f1dd71d1..8de6d326 100644 --- a/operation-team-account/modules/firehose/main.tf +++ b/operation-team-account/modules/firehose/main.tf @@ -82,16 +82,3 @@ resource "aws_kinesis_firehose_delivery_stream" "to_opensearch" { } } } -# S3 버킷에 Lifecycle 정책 붙이기 -resource "aws_s3_bucket_lifecycle_configuration" "firehose_backup" { - bucket = aws_s3_bucket.firehose_backup.id - - rule { - id = "ExpireBackup" - status = "Enabled" - - filter { prefix = "backup/" } - - expiration { days = 7 } # 7일 지난 백업은 자동 삭제 - } -} \ No newline at end of file diff --git a/operation-team-account/modules/s3/main.tf b/operation-team-account/modules/s3/main.tf index b0977c44..5f469c5a 100644 --- a/operation-team-account/modules/s3/main.tf +++ b/operation-team-account/modules/s3/main.tf @@ -16,6 +16,20 @@ resource "aws_s3_bucket_public_access_block" "block" { restrict_public_buckets = true } +# S3 버킷에 Lifecycle 정책 붙이기 +resource "aws_s3_bucket_lifecycle_configuration" "firehose_backup" { + bucket = aws_s3_bucket.firehose_backup.id + + rule { + id = "ExpireBackup" + status = "Enabled" + + filter { prefix = "backup/" } + + expiration { days = 7 } # 7일 지난 백업은 자동 삭제 + } +} + resource "aws_kms_key" "s3_cmk" { description = "KMS key for encrypting Firehose backup S3 bucket" deletion_window_in_days = 10 diff --git a/operation-team-account/providers.tf b/operation-team-account/providers.tf index f0ae24f2..39e5a494 100644 --- a/operation-team-account/providers.tf +++ b/operation-team-account/providers.tf @@ -1,3 +1,12 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.11.0" + } + } +} + provider "aws" { region = "ap-northeast-2" profile = "my-profile" From 801a49bdff50c941a5c2b9a1f5225358d0dedf51 Mon Sep 17 00:00:00 2001 From: 3olly Date: Fri, 27 Jun 2025 01:29:57 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20tf=20validate=20error=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/cloudwatch/main.tf | 33 ++------- .../modules/securitylake/main.tf | 74 +++++++++---------- 2 files changed, 43 insertions(+), 64 deletions(-) diff --git a/operation-team-account/modules/cloudwatch/main.tf b/operation-team-account/modules/cloudwatch/main.tf index 255d617c..90ed3de3 100644 --- a/operation-team-account/modules/cloudwatch/main.tf +++ b/operation-team-account/modules/cloudwatch/main.tf @@ -1,33 +1,12 @@ +resource "aws_cloudwatch_log_group" "target" { + name = var.log_group_name + retention_in_days = 14 +} + resource "aws_cloudwatch_log_subscription_filter" "logs_to_firehose" { name = var.subscription_filter_name log_group_name = var.log_group_name - filter_pattern = "{ $.level = \"ERROR\" }" # ERROR 레벨만 전달 + filter_pattern = "{ $.level = \"ERROR\" }" destination_arn = var.firehose_arn role_arn = var.role_arn } - -resource "aws_cloudwatch_log_group" "target" { - name = var.log_group_name - retention_in_days = 14 # 14일 지나면 자동 삭제 -} - -resource "aws_cloudwatch_metric_filter" "error_count" { - name = "ErrorCount" - log_group_name = aws_cloudwatch_log_group.target.name - pattern = "\"ERROR\"" - metric_transformation { - name = "ErrorCount" - namespace = "MyApp/SIEM" - value = "1" - } -} - -resource "aws_cloudwatch_metric_alarm" "error_alarm" { - alarm_name = "HighErrorCount" - namespace = "MyApp/SIEM" - metric_name = aws_cloudwatch_metric_filter.error_count.metric_transformation[0].name - threshold = 100 - comparison_operator = "GreaterThanThreshold" - evaluation_periods = 1 - alarm_actions = [aws_sns_topic.alerts.arn] -} diff --git a/operation-team-account/modules/securitylake/main.tf b/operation-team-account/modules/securitylake/main.tf index 5933d4a8..01a11d10 100644 --- a/operation-team-account/modules/securitylake/main.tf +++ b/operation-team-account/modules/securitylake/main.tf @@ -1,42 +1,42 @@ -# 1. 메타스토어 관리자 IAM 역할 생성 -resource "aws_iam_role" "securitylake_manager" { - name = "securitylake-meta-store-manager" +# # 1. 메타스토어 관리자 IAM 역할 생성 +# resource "aws_iam_role" "securitylake_manager" { +# name = "securitylake-meta-store-manager" - assume_role_policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Principal = { Service = "securitylake.amazonaws.com" }, - Action = "sts:AssumeRole" - } - ] - }) -} +# assume_role_policy = jsonencode({ +# Version = "2012-10-17", +# Statement = [ +# { +# Effect = "Allow", +# Principal = { Service = "securitylake.amazonaws.com" }, +# Action = "sts:AssumeRole" +# } +# ] +# }) +# } -# 2. 조직 단위 Security Lake 활성화 (조직 전체 설정) -resource "aws_securitylake_organization_configuration" "org_config" { - auto_enable { - all_regions = false - regions = ["ap-northeast-2"] - } -} +# # 2. 조직 단위 Security Lake 활성화 (조직 전체 설정) +# resource "aws_securitylake_organization_configuration" "org_config" { +# auto_enable { +# all_regions = false +# regions = ["ap-northeast-2"] +# } +# } -# 3. 특정 리전(ap-northeast-2)에서 Data Lake 활성화 및 라이프사이클 설정 -resource "aws_securitylake_data_lake" "this" { - meta_store_manager_role_arn = aws_iam_role.securitylake_manager.arn +# # 3. 특정 리전(ap-northeast-2)에서 Data Lake 활성화 및 라이프사이클 설정 +# resource "aws_securitylake_data_lake" "this" { +# meta_store_manager_role_arn = aws_iam_role.securitylake_manager.arn - configuration { - region = "ap-northeast-2" +# configuration { +# region = "ap-northeast-2" - lifecycle_configuration { - expiration { - days = 30 # 데이터 30일 보관 - } - transition { - days = 7 - storage_class = "ONEZONE_IA" # 7일 후 저비용 스토리지로 전환 - } - } - } -} +# lifecycle_configuration { +# expiration { +# days = 30 # 데이터 30일 보관 +# } +# transition { +# days = 7 +# storage_class = "ONEZONE_IA" # 7일 후 저비용 스토리지로 전환 +# } +# } +# } +# }