mirror of
https://github.com/Sea-Haven-Industries/sh-openswe-traces.git
synced 2026-09-30 09:13:16 +00:00
Freeze SAM CD and add terraform/ for seahaven-prod with account-suffixed buckets so HCP owns deploy before mgmt cutover. Suppress CKV_AWS_40 for the LangSmith export IAM user with documented mitigations.
219 lines
4.5 KiB
HCL
219 lines
4.5 KiB
HCL
resource "aws_s3_bucket" "logs" {
|
|
bucket = local.logs_bucket_name
|
|
|
|
tags = {
|
|
role = "s3-access-logs"
|
|
}
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_public_access_block" "logs" {
|
|
bucket = aws_s3_bucket.logs.id
|
|
|
|
block_public_acls = true
|
|
block_public_policy = true
|
|
ignore_public_acls = true
|
|
restrict_public_buckets = true
|
|
}
|
|
|
|
resource "aws_s3_bucket_ownership_controls" "logs" {
|
|
bucket = aws_s3_bucket.logs.id
|
|
|
|
rule {
|
|
object_ownership = "BucketOwnerEnforced"
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_server_side_encryption_configuration" "logs" {
|
|
bucket = aws_s3_bucket.logs.id
|
|
|
|
rule {
|
|
apply_server_side_encryption_by_default {
|
|
# SSE-S3 only: S3 log delivery cannot write to an SSE-KMS bucket.
|
|
sse_algorithm = "AES256"
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_lifecycle_configuration" "logs" {
|
|
bucket = aws_s3_bucket.logs.id
|
|
|
|
rule {
|
|
id = "expire-access-logs"
|
|
status = "Enabled"
|
|
|
|
filter {}
|
|
|
|
expiration {
|
|
days = 365
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_policy" "logs" {
|
|
bucket = aws_s3_bucket.logs.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Sid = "S3ServerAccessLogsWrite"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "logging.s3.amazonaws.com"
|
|
}
|
|
Action = "s3:PutObject"
|
|
Resource = "${aws_s3_bucket.logs.arn}/s3-access/*"
|
|
Condition = {
|
|
ArnLike = {
|
|
"aws:SourceArn" = aws_s3_bucket.traces.arn
|
|
}
|
|
StringEquals = {
|
|
"aws:SourceAccount" = local.account_id
|
|
}
|
|
}
|
|
},
|
|
{
|
|
Sid = "DenyInsecureTransport"
|
|
Effect = "Deny"
|
|
Principal = "*"
|
|
Action = "s3:*"
|
|
Resource = [
|
|
aws_s3_bucket.logs.arn,
|
|
"${aws_s3_bucket.logs.arn}/*",
|
|
]
|
|
Condition = {
|
|
Bool = {
|
|
"aws:SecureTransport" = "false"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
resource "aws_s3_bucket" "traces" {
|
|
bucket = local.traces_bucket_name
|
|
|
|
lifecycle {
|
|
prevent_destroy = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_public_access_block" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
block_public_acls = true
|
|
block_public_policy = true
|
|
ignore_public_acls = true
|
|
restrict_public_buckets = true
|
|
}
|
|
|
|
resource "aws_s3_bucket_ownership_controls" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
rule {
|
|
object_ownership = "BucketOwnerEnforced"
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_versioning" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
versioning_configuration {
|
|
status = "Enabled"
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_server_side_encryption_configuration" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
rule {
|
|
apply_server_side_encryption_by_default {
|
|
sse_algorithm = "aws:kms"
|
|
kms_master_key_id = aws_kms_key.traces.arn
|
|
}
|
|
bucket_key_enabled = true
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_lifecycle_configuration" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
rule {
|
|
id = "archive-exports-to-deep-archive"
|
|
status = "Enabled"
|
|
|
|
filter {
|
|
prefix = var.export_prefix
|
|
}
|
|
|
|
transition {
|
|
days = 90
|
|
storage_class = "DEEP_ARCHIVE"
|
|
}
|
|
}
|
|
|
|
rule {
|
|
id = "expire-noncurrent-versions"
|
|
status = "Enabled"
|
|
|
|
filter {}
|
|
|
|
noncurrent_version_expiration {
|
|
noncurrent_days = 90
|
|
}
|
|
}
|
|
|
|
rule {
|
|
id = "abort-incomplete-multipart"
|
|
status = "Enabled"
|
|
|
|
filter {}
|
|
|
|
abort_incomplete_multipart_upload {
|
|
days_after_initiation = 7
|
|
}
|
|
}
|
|
}
|
|
|
|
resource "aws_s3_bucket_logging" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
target_bucket = aws_s3_bucket.logs.id
|
|
target_prefix = "s3-access/"
|
|
|
|
depends_on = [aws_s3_bucket_policy.logs]
|
|
}
|
|
|
|
resource "aws_s3_bucket_policy" "traces" {
|
|
bucket = aws_s3_bucket.traces.id
|
|
|
|
# No SSE-header enforcement Deny. LangSmith's exporter does not send an
|
|
# "aws:kms" SSE header, so a "must be aws:kms" Deny blocks its writes — and
|
|
# StringNotEqualsIfExists on a Deny also blocks header-less puts. Encryption
|
|
# is guaranteed by the bucket DEFAULT (SSE-KMS with our CMK).
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Sid = "DenyInsecureTransport"
|
|
Effect = "Deny"
|
|
Principal = "*"
|
|
Action = "s3:*"
|
|
Resource = [
|
|
aws_s3_bucket.traces.arn,
|
|
"${aws_s3_bucket.traces.arn}/*",
|
|
]
|
|
Condition = {
|
|
Bool = {
|
|
"aws:SecureTransport" = "false"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|