123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- # Kenisis firehose stream
- # Record Transformation Required, called "processing_configuration" in Terraform
- resource "aws_kinesis_firehose_delivery_stream" "kinesis_firehose" {
- name = var.firehose_name
- destination = "splunk"
- s3_configuration {
- role_arn = aws_iam_role.kinesis_firehose.arn
- prefix = var.s3_prefix
- bucket_arn = aws_s3_bucket.kinesis_firehose_s3_bucket.arn
- buffer_size = var.kinesis_firehose_buffer
- buffer_interval = var.kinesis_firehose_buffer_interval
- compression_format = var.s3_compression_format
- }
- splunk_configuration {
- hec_endpoint = var.hec_url
- hec_token = var.hec_token
- hec_acknowledgment_timeout = var.hec_acknowledgment_timeout
- hec_endpoint_type = var.hec_endpoint_type
- s3_backup_mode = var.s3_backup_mode
- processing_configuration {
- enabled = "true"
- processors {
- type = "Lambda"
- parameters {
- parameter_name = "LambdaArn"
- parameter_value = "${aws_lambda_function.firehose_lambda_transform.arn}:$LATEST"
- }
- parameters {
- parameter_name = "RoleArn"
- parameter_value = aws_iam_role.kinesis_firehose.arn
- }
- }
- }
- cloudwatch_logging_options {
- enabled = var.enable_fh_cloudwatch_logging
- log_group_name = aws_cloudwatch_log_group.kinesis_logs.name
- log_stream_name = aws_cloudwatch_log_stream.kinesis_logs.name
- }
- }
- tags = var.tags
- }
- #S3 Bucket for Kinesis Firehose s3_backup_mode
- #Certificate CRLs need to be publicly accessible
- # tfsec:ignore:aws-s3-enable-versioning tfsec:ignore:aws-s3-no-public-buckets tfsec:ignore:aws-s3-enable-bucket-logging tfsec:ignore:aws-s3-block-public-acls
- resource "aws_s3_bucket" "kinesis_firehose_s3_bucket" { # tfsec:ignore:aws-s3-block-public-policy tfsec:ignore:aws-s3-ignore-public-acls tfsec:ignore:aws-s3-specify-public-access-block
- # checkov:skip=CKV_AWS_18: see tfsec ignore - logging not enabled
- # checkov:skip=CKV_AWS_21: see tfsec ignore - S3 object versioning is disabled
- # checkov:skip=CKV_AWS_144: S3 bucket has no cross-region replication enabled
-
- bucket = var.s3_bucket_name
- tags = var.tags
- }
- resource "aws_s3_bucket_acl" "kinesis_firehose_s3_bucket" {
- bucket = aws_s3_bucket.kinesis_firehose_s3_bucket.id
- acl = "private"
- }
- resource "aws_kms_key" "kinesis_firehose_s3_bucket" {
- enable_key_rotation = true
- deletion_window_in_days = 30
- tags = var.tags
- }
- resource "aws_s3_bucket_server_side_encryption_configuration" "kinesis_firehose_s3_bucket" {
- bucket = aws_s3_bucket.kinesis_firehose_s3_bucket.id
- rule {
- apply_server_side_encryption_by_default {
- kms_master_key_id = aws_kms_key.kinesis_firehose_s3_bucket.arn
- sse_algorithm = "aws:kms"
- }
- }
- }
- resource "aws_s3_bucket_lifecycle_configuration" "kinesis_firehose_s3_bucket" {
- bucket = aws_s3_bucket.kinesis_firehose_s3_bucket.id
- rule {
- id = "expire-old-logs"
- status = "Enabled"
- filter {
- prefix = ""
- }
- expiration {
- days = var.s3_expiration
- }
- noncurrent_version_expiration {
- noncurrent_days = var.s3_expiration
- }
- abort_incomplete_multipart_upload {
- days_after_initiation = 7
- }
- }
- }
- resource "aws_s3_bucket_public_access_block" "kinesis_firehose_s3_bucket" {
- count = var.s3_bucket_block_public_access_enabled
- bucket = aws_s3_bucket.kinesis_firehose_s3_bucket.id
- block_public_acls = true
- block_public_policy = true
- ignore_public_acls = true
- restrict_public_buckets = true
- }
- # Cloudwatch logging group for Kinesis Firehose
- # tfsec:ignore:aws-cloudwatch-log-group-customer-key # OK to use AWS key for this
- resource "aws_cloudwatch_log_group" "kinesis_logs" {
- name = "/aws/kinesisfirehose/${var.firehose_name}"
- retention_in_days = var.cloudwatch_log_retention
- tags = var.tags
- }
- # Create the stream
- resource "aws_cloudwatch_log_stream" "kinesis_logs" {
- name = var.log_stream_name
- log_group_name = aws_cloudwatch_log_group.kinesis_logs.name
- }
- ## handle the sensitivity of the hec_token variable
- #data "aws_kms_secrets" "splunk_hec_token" {
- # secret {
- # name = "hec_token"
- # payload = var.hec_token
- #
- # context = var.encryption_context
- # }
- #}
- # Role for the transformation Lambda function attached to the kinesis stream
- resource "aws_iam_role" "kinesis_firehose_lambda" {
- name = var.kinesis_firehose_lambda_role_name
- path = "/lambda/"
- description = "Role for Lambda function to transformation CloudWatch logs into Splunk compatible format"
- force_detach_policies = true
- assume_role_policy = <<POLICY
- {
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "sts:AssumeRole",
- "Principal": {
- "Service": "lambda.amazonaws.com"
- }
- }
- ],
- "Version": "2012-10-17"
- }
- POLICY
- tags = var.tags
- }
- data "aws_iam_policy_document" "lambda_policy_doc" {
- # checkov:skip=CKV_AWS_111: see tfsec aws-iam-no-policy-wildcard ignore comment
- statement {
- actions = [
- "logs:GetLogEvents",
- ]
- resources = [
- var.arn_cloudwatch_logs_to_ship,
- ]
- effect = "Allow"
- }
- statement {
- actions = [
- "firehose:PutRecordBatch",
- ]
- resources = [
- aws_kinesis_firehose_delivery_stream.kinesis_firehose.arn,
- ]
- }
- statement {
- actions = [
- "logs:PutLogEvents",
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- statement {
- actions = [
- "logs:CreateLogGroup",
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- statement {
- actions = [
- "logs:CreateLogStream",
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- # FTD: Needs KMS access
- statement {
- actions = [
- "kms:GenerateDataKey",
- "kms:Decrypt"
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- }
- resource "aws_iam_policy" "lambda_transform_policy" {
- name = var.lambda_iam_policy_name
- policy = data.aws_iam_policy_document.lambda_policy_doc.json
- }
- resource "aws_iam_role_policy_attachment" "lambda_policy_role_attachment" {
- role = aws_iam_role.kinesis_firehose_lambda.name
- policy_arn = aws_iam_policy.lambda_transform_policy.arn
- }
- # Create the lambda function
- # The lambda function to transform data from compressed format in Cloudwatch to something Splunk can handle (uncompressed)
- # tfsec:ignore:aws-lambda-enable-tracing We do not enable X-Ray Tracing for Lambda
- resource "aws_lambda_function" "firehose_lambda_transform" {
- # checkov:skip=CKV_AWS_50: see tfsec ignore X-Ray Tracing
- function_name = var.lambda_function_name
- description = "Transform data from CloudWatch format to Splunk compatible format"
- filename = data.archive_file.lambda_function.output_path
- role = aws_iam_role.kinesis_firehose_lambda.arn
- handler = "kinesis-firehose-cloudwatch-logs-processor.handler"
- source_code_hash = data.archive_file.lambda_function.output_base64sha256
- runtime = var.nodejs_runtime
- timeout = var.lambda_function_timeout
- tags = var.tags
- }
- # kinesis-firehose-cloudwatch-logs-processor.js was taken by copy/paste from the AWS UI. It is predefined blueprint
- # code supplied to AWS by Splunk.
- data "archive_file" "lambda_function" {
- type = "zip"
- source_file = "${path.module}/files/kinesis-firehose-cloudwatch-logs-processor.js"
- output_path = "${path.module}/files/kinesis-firehose-cloudwatch-logs-processor.zip"
- }
- # Role for Kenisis Firehose
- resource "aws_iam_role" "kinesis_firehose" {
- name = var.kinesis_firehose_role_name
- path = "/aws_services/"
- description = "IAM Role for Kenisis Firehose"
- force_detach_policies = true
- assume_role_policy = <<POLICY
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Principal": {
- "Service": "firehose.amazonaws.com"
- },
- "Action": "sts:AssumeRole",
- "Effect": "Allow"
- }
- ]
- }
- POLICY
- tags = var.tags
- }
- data "aws_iam_policy_document" "kinesis_firehose_policy_document" {
- # checkov:skip=CKV_AWS_111: see tfsec aws-iam-no-policy-wildcard ignore comment
- statement {
- actions = [
- "s3:AbortMultipartUpload",
- "s3:GetBucketLocation",
- "s3:GetObject",
- "s3:ListBucket",
- "s3:ListBucketMultipartUploads",
- "s3:PutObject",
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- aws_s3_bucket.kinesis_firehose_s3_bucket.arn,
- "${aws_s3_bucket.kinesis_firehose_s3_bucket.arn}/*",
- ]
- effect = "Allow"
- }
- statement {
- actions = [
- "lambda:InvokeFunction",
- "lambda:GetFunctionConfiguration",
- ]
- resources = [
- "${aws_lambda_function.firehose_lambda_transform.arn}:$LATEST",
- ]
- }
- statement {
- actions = [
- "logs:PutLogEvents",
- ]
- resources = [
- aws_cloudwatch_log_group.kinesis_logs.arn,
- aws_cloudwatch_log_stream.kinesis_logs.arn,
- ]
- effect = "Allow"
- }
- # FTD: Needs KMS access
- statement {
- actions = [
- "kms:GenerateDataKey",
- "kms:Decrypt"
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- }
- resource "aws_iam_policy" "kinesis_firehose_iam_policy" {
- name = var.kinesis_firehose_iam_policy_name
- policy = data.aws_iam_policy_document.kinesis_firehose_policy_document.json
- }
- resource "aws_iam_role_policy_attachment" "kinesis_fh_role_attachment" {
- role = aws_iam_role.kinesis_firehose.name
- policy_arn = aws_iam_policy.kinesis_firehose_iam_policy.arn
- }
- resource "aws_iam_role" "cloudwatch_to_firehose_trust" {
- name = var.cloudwatch_to_firehose_trust_iam_role_name
- path = "/aws_services/"
- description = "Role for CloudWatch Log Group subscription"
- force_detach_policies = true
- assume_role_policy = <<ROLE
- {
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "sts:AssumeRole",
- "Principal": {
- "Service": "logs.${var.region}.amazonaws.com"
- }
- }
- ],
- "Version": "2012-10-17"
- }
- ROLE
- }
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- data "aws_iam_policy_document" "cloudwatch_to_fh_access_policy" {
- # checkov:skip=CKV_AWS_111: see tfsec aws-iam-no-policy-wildcard ignore comment
- statement {
- actions = [
- "firehose:*",
- ]
- effect = "Allow"
- resources = [
- aws_kinesis_firehose_delivery_stream.kinesis_firehose.arn,
- ]
- }
- statement {
- actions = [
- "iam:PassRole",
- ]
- effect = "Allow"
- resources = [
- aws_iam_role.cloudwatch_to_firehose_trust.arn,
- ]
- }
- # FTD: Needs KMS access
- statement {
- actions = [
- "kms:GenerateDataKey",
- "kms:Decrypt"
- ]
- # tfsec:ignore:aws-iam-no-policy-wildcards - baseline this setting first. We use wildcards in policies
- resources = [
- "*",
- ]
- effect = "Allow"
- }
- }
- resource "aws_iam_policy" "cloudwatch_to_fh_access_policy" {
- name = var.cloudwatch_to_fh_access_policy_name
- description = "Cloudwatch to Firehose Subscription Policy"
- policy = data.aws_iam_policy_document.cloudwatch_to_fh_access_policy.json
- }
- resource "aws_iam_role_policy_attachment" "cloudwatch_to_fh" {
- role = aws_iam_role.cloudwatch_to_firehose_trust.name
- policy_arn = aws_iam_policy.cloudwatch_to_fh_access_policy.arn
- }
- resource "aws_cloudwatch_log_subscription_filter" "cloudwatch_log_filter" {
- name = var.cloudwatch_log_filter_name
- role_arn = aws_iam_role.cloudwatch_to_firehose_trust.arn
- destination_arn = aws_kinesis_firehose_delivery_stream.kinesis_firehose.arn
- log_group_name = var.name_cloudwatch_logs_to_ship
- filter_pattern = var.subscription_filter_pattern
- }
|