You can use this Terraform file to set up the IAM role, IAM policies, an SNS topic, and an S3 bucket to integrate with Scanner. You provide the value for s3_bucket_to_index, and Scanner provides the values for scanner_aws_account_id and scanner_external_id.
It will also create a new SNS topic and update your S3 bucket to send s3:ObjectCreated notifications to this topic. The SNS topic will then relay those notifications to the SQS queue in your Scanner instance.
variable "scanner_external_id" { description ="Scanner provides an External ID to use here." type = string}variable "scanner_aws_account_id" { description ="Scanner provides its AWS Account ID to use here." type = string}variable "s3_bucket_to_index" { description ="Enter the name of the S3 bucket that you would like Scanner to index." type = string}# The IAM role used by Scanner to access the S3 filesresource "aws_iam_role" "scanner_role" { name ="ScannerRole" assume_role_policy = jsonencode({ Version ="2012-10-17" Statement = [ { Effect ="Allow" Principal = { AWS = var.scanner_aws_account_id } Action ="sts:AssumeRole" Condition = { StringEquals = { "sts:ExternalId" = var.scanner_external_id } } } ] })}# The S3 bucket where Scanner will store all index filesresource "aws_s3_bucket" "scanner_index_files_bucket" { bucket ="scanner-index-files-${var.scanner_external_id}" // NOTE: With this flag, Terraform will disallow the deletion of the entire // stack. Unfortunately Terraform does not yet provide a way to protect only // some resources while deleting the rest. lifecycle { prevent_destroy =true }}resource "aws_s3_bucket_public_access_block" "scanner_index_files_bucket_public_access_block" { bucket = aws_s3_bucket.scanner_index_files_bucket.id block_public_acls =true block_public_policy =true ignore_public_acls =true restrict_public_buckets =true}resource "aws_s3_bucket_server_side_encryption_configuration" "scanner_index_files_bucket_encryption_config" { bucket = aws_s3_bucket.scanner_index_files_bucket.id rule { bucket_key_enabled =true apply_server_side_encryption_by_default { sse_algorithm ="aws:kms" } }}resource "aws_s3_bucket_lifecycle_configuration" "scanner_index_files_bucket_lifecycle_configuration" { bucket = aws_s3_bucket.scanner_index_files_bucket.id rule { id ="ExpireTagging" status ="Enabled" filter { tag { key ="Scnr-Lifecycle" value ="expire" } } expiration { days =1 } } rule { id ="AbortIncompleteMultiPartUploads" status ="Enabled" abort_incomplete_multipart_upload { days_after_initiation =1 } }}# The SNS topic to notify Scanner when the log files buckets have new filesresource "aws_sns_topic" "scnr_logs_bucket_event_notification_topic" { name ="scnr-LogsBucketEventNotificationTopic"}resource "aws_sns_topic_subscription" "scnr_logs_bucket_event_notification_topic_subscription" { topic_arn = aws_sns_topic.scnr_logs_bucket_event_notification_topic.arn protocol ="sqs" endpoint ="arn:aws:sqs:${data.aws_region.current.name}:${var.scanner_aws_account_id}:scnr-S3ObjectCreatedNotificationsQueue" raw_message_delivery =true}resource "aws_s3_bucket_notification" "logs_bucket_event_notification" { bucket = var.s3_bucket_to_index topic { topic_arn = aws_sns_topic.scnr_logs_bucket_event_notification_topic.arn events = ["s3:ObjectCreated:*"] }}# The IAM policy allowing the Scanner IAM role to access the S3 bucketsresource "aws_iam_policy" "scanner_policy" { name ="ScannerPolicy" policy = jsonencode({ Version ="2012-10-17" Statement = [ { Effect ="Allow" Action = ["s3:GetBucketLocation","s3:GetBucketTagging","s3:ListAllMyBuckets" ] Resource ="*" }, { Effect ="Allow" Action = ["s3:GetBucketNotification","s3:GetObject","s3:GetObjectTagging","s3:ListBucket", ] Resource = ["arn:aws:s3:::${var.s3_bucket_to_index}","arn:aws:s3:::${var.s3_bucket_to_index}/*" ] }, { Effect ="Allow" Action = ["s3:DeleteObject","s3:DeleteObjectTagging","s3:DeleteObjectVersion","s3:DeleteObjectVersionTagging","s3:GetLifecycleConfiguration","s3:GetObject","s3:GetObjectTagging","s3:ListBucket","s3:PutObject","s3:PutObjectTagging", ] Resource = ["arn:aws:s3:::scanner-index-files-${var.scanner_external_id}","arn:aws:s3:::scanner-index-files-${var.scanner_external_id}/*" ] } ] })}resource "aws_iam_policy_attachment" "scanner_policy_attachment" { name ="ScannerPolicyAttachment" roles = [aws_iam_role.scanner_role.name] policy_arn = aws_iam_policy.scanner_policy.arn}output "scanner_role_arn" { description = "The ARN of the new Scanner IAM Role" value = aws_iam_role.scanner_role.arn}data "aws_caller_identity" "current" {}data "aws_region" "current" {}
If your S3 buckets are in multiple regions
If the S3 buckets that you want to index are in multiple regions, edit this Terraform file to do the following:
Create one aws_sns_topic per region.
Create an aws_sns_topic_subscription for each SNS topic, all pointing to the same SQS queue in your Scanner instance.
Create an aws_s3_bucket_notification for each S3 bucket, and point it to the SNS topic that is in the same region as the S3 bucket.