diff --git a/.github/workflows/dsf_poc_cli.yml b/.github/workflows/dsf_poc_cli.yml index 8a5a1af67..79613268e 100644 --- a/.github/workflows/dsf_poc_cli.yml +++ b/.github/workflows/dsf_poc_cli.yml @@ -236,6 +236,7 @@ jobs: mv $EXAMPLE_DIR/versions.tf{,_} mv $EXAMPLE_DIR/cm.tf{,_} mv $EXAMPLE_DIR/cte_ddc_agents.tf{,_} + mv $EXAMPLE_DIR/fam_classification_integration_resources.tf{,_} terraform -chdir=$EXAMPLE_DIR destroy -var dam_license=license.mprv -auto-approve mv $EXAMPLE_DIR/main.tf{_,} mv $EXAMPLE_DIR/outputs.tf{_,} @@ -248,6 +249,7 @@ jobs: mv $EXAMPLE_DIR/versions.tf{_,} mv $EXAMPLE_DIR/cm.tf{_,} mv $EXAMPLE_DIR/cte_ddc_agents.tf{_,} + mv $EXAMPLE_DIR/fam_classification_integration_resources.tf{_,} fi - name: Terraform Validate diff --git a/examples/aws/poc/dsf_deployment/fam_classification_integration_resources.tf b/examples/aws/poc/dsf_deployment/fam_classification_integration_resources.tf new file mode 100644 index 000000000..eac768c9a --- /dev/null +++ b/examples/aws/poc/dsf_deployment/fam_classification_integration_resources.tf @@ -0,0 +1,153 @@ +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +resource "random_id" "fam_scan_results_bucket_suffix" { + byte_length = 4 # 4 bytes → 8 hex chars +} + +resource "aws_s3_bucket" "fam_scan_results_bucket" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + bucket = join("-", [local.deployment_name_salted, "fam", "scan", "results", "bucket", random_id.fam_scan_results_bucket_suffix.hex]) + force_destroy = true + tags = local.tags +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "fam_scan_results_bucket_encryption" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + bucket = aws_s3_bucket.fam_scan_results_bucket[0].id + + rule { + apply_server_side_encryption_by_default { + sse_algorithm = "AES256" + } + bucket_key_enabled = true + } +} + +resource "aws_s3_bucket_public_access_block" "fam_scan_results_bucket_pab" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + bucket = aws_s3_bucket.fam_scan_results_bucket[0].id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} + +resource "aws_s3_bucket_policy" "fam_scan_results_bucket_enforce_ssl" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + bucket = aws_s3_bucket.fam_scan_results_bucket[0].id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Sid = "DenyInsecureTransport" + Effect = "Deny" + Principal = "*" + Action = "s3:*" + Resource = [ + "arn:aws:s3:::${aws_s3_bucket.fam_scan_results_bucket[0].id}", + "arn:aws:s3:::${aws_s3_bucket.fam_scan_results_bucket[0].id}/*" + ] + Condition = { + Bool = { + "aws:SecureTransport" = "false" + } + } + } + ] + }) +} + +resource "aws_sqs_queue" "fam_scan_results_bucket_notifications_sqs" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + name = join("-", [local.deployment_name_salted, "fam", "scan", "results", "bucket", "notifications", "sqs"]) + sqs_managed_sse_enabled = true + + tags = local.tags +} + +resource "aws_sqs_queue_policy" "fam_scan_results_bucket_notifications_sqs_policy" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + queue_url = aws_sqs_queue.fam_scan_results_bucket_notifications_sqs[0].id + + policy = jsonencode({ + Version = "2012-10-17" + Id = "PolicyForS3ToSendMessageToSQS" + Statement = [ + { + Sid = "PolicyForS3ToSendMessageToSQS" + Effect = "Allow" + Principal = { + Service = "s3.amazonaws.com" + } + Action = "SQS:SendMessage" + Resource = aws_sqs_queue.fam_scan_results_bucket_notifications_sqs[0].arn + Condition = { + StringEquals = { + "aws:SourceAccount" = data.aws_caller_identity.current.account_id + } + ArnLike = { + "aws:SourceArn": "arn:aws:s3:*:*:${aws_s3_bucket.fam_scan_results_bucket[0].id}" + } + } + } + ] + }) +} + +resource "aws_s3_bucket_notification" "fam_scan_results_bucket_notification" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + bucket = aws_s3_bucket.fam_scan_results_bucket[0].id + + queue { + id = "fam_classification_scan_result_incoming" + queue_arn = aws_sqs_queue.fam_scan_results_bucket_notifications_sqs[0].arn + events = [ + "s3:ObjectCreated:Put", + "s3:ObjectCreated:CompleteMultipartUpload" + ] + filter_prefix = "scan_result/incoming/" + } + + depends_on = [aws_sqs_queue_policy.fam_scan_results_bucket_notifications_sqs_policy] +} + +resource "aws_iam_policy" "fam_classification_integration_policy" { + count = var.create_fam_classification_integration_resources ? 1 : 0 + name = join("-", [local.deployment_name_salted, "fam", "classification", "integration", "policy"]) + description = "Policy for FAM Classification service" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "s3:PutObject", + "s3:GetObject", + "s3:GetBucketNotification" + ] + Resource = [ + aws_s3_bucket.fam_scan_results_bucket[0].arn, + "${aws_s3_bucket.fam_scan_results_bucket[0].arn}/*" + ] + }, + { + Effect = "Allow" + Action = [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl" + ] + Resource = aws_sqs_queue.fam_scan_results_bucket_notifications_sqs[0].arn + } + ] + }) + tags = local.tags +} + + diff --git a/examples/aws/poc/dsf_deployment/outputs.tf b/examples/aws/poc/dsf_deployment/outputs.tf index 3e31f4b0b..54c1d8ffd 100644 --- a/examples/aws/poc/dsf_deployment/outputs.tf +++ b/examples/aws/poc/dsf_deployment/outputs.tf @@ -228,4 +228,12 @@ output "web_console_ciphertrust" { password = nonsensitive(local.password) user = local.ciphertrust_manager_web_console_username }, null) -} \ No newline at end of file +} + +output "fam_classification_integration_resources" { + value = try({ + scan_results_bucket_name = aws_s3_bucket.fam_scan_results_bucket[0].id + scan_results_bucket_notifications_sqs_name = aws_sqs_queue.fam_scan_results_bucket_notifications_sqs[0].name + classification_integration_iam_policy = aws_iam_policy.fam_classification_integration_policy[0].name + }, null) +} diff --git a/examples/aws/poc/dsf_deployment/variables.tf b/examples/aws/poc/dsf_deployment/variables.tf index dca9b4814..bc9503216 100644 --- a/examples/aws/poc/dsf_deployment/variables.tf +++ b/examples/aws/poc/dsf_deployment/variables.tf @@ -488,4 +488,10 @@ variable "ddc_agents_windows_count" { type = number default = 0 description = "Number of DDC agent windows servers. Provisioning CTE and/or DDC agent servers requires the enable_ciphertrust variable to be set to 'true'." +} + +variable "create_fam_classification_integration_resources" { + type = bool + default = false + description = "Whether to create the AWS S3 and SQS resources required for FAM classification integration between Hub and CipherTrust." } \ No newline at end of file