Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Lacework CloudTrail should send logs to CloudWatch #135

Open
TheShahin opened this issue Jul 6, 2023 · 1 comment
Open

feat: Lacework CloudTrail should send logs to CloudWatch #135

TheShahin opened this issue Jul 6, 2023 · 1 comment

Comments

@TheShahin
Copy link

TheShahin commented Jul 6, 2023

Feature Request

Describe the Feature Request
The CloudTrail created by this Terraform module should support setting up a proper logging integration with CloudWatch.

Is your feature request related to a problem? Please describe
The created CloudTrail is non-compliant with CIS Benchmarks and is listed as a Medium severity in Lacework's generated reports for compliance with AWS ISO 27001:2013 and AWS ISO/IEC 27002:2022.

The non-compliance in question is lacework-global-55.

Describe Preferred Solution
The module creates resources that by default are compliant with CIS Benchmarks.

Add input variables cloudwatch_logs_encryption_enabled, cloudwatch_logs_encryption_key_arn, and cloudwatch_logs_iam_role_arn, and set them in the aws_cloudtrail resource. If no IAM role ARN is provided then one should be created by the module.

Additional Context
I think the changes needed are the following:

variables.tf:

variable "cloudwatch_logs_encryption_enabled" {
  type    = bool
  default = true
}

variable "cloudwatch_logs_encryption_key_arn" {
  type    = string
  default = ""
}

variable "cloudwatch_logs_iam_role_arn" {
  type    = string
  default = ""
}

main.tf:

locals {
  ...
  create_cloudwatch_iam_role = var.cloudwatch_logs_encryption_enabled && var.cloudwatch_logs_iam_role_arn == null
  
  cloudwatch_key_arn = var.cloudwatch_logs_encryption_enabled ? (length(var.cloudwatch_logs_encryption_key_arn) > 0 ? var.cloudwatch_logs_encryption_key_arn : aws_kms_key.lacework_kms_key[0].arn) : ""

  cloudwatch_logstream_arn = "${aws_cloudwatch_log_group.cloudtrail_log_group.arn}:log-stream:${data.aws_caller_identity.current.account_id}_CloudTrail_${data.aws_region.current.name}*" # Reference: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/send-cloudtrail-events-to-cloudwatch-logs.html
}

data "aws_iam_policy_document" "kms_key_policy" {
  ...

  dynamic "statement" {
    for_each = (var.cloudwatch_logs_encryption_enabled && length(var.cloudwatch_logs_encryption_key_arn) == 0) ? [1] : []
    content {
      sid    = "Allow CloudWatch service to encrypt/decrypt"
      effect = "Allow"

      actions = [
        "kms:Encrypt*",
        "kms:Decrypt*",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:Describe*"
      ]

      resources = ["*"]
      
      principals {
        type = "Service"
        identifiers = [
          "logs.${data.aws_region.current.name}.amazonaws.com",
        ]
      }

      condition {
        test     = "ArnEquals"
        variable = "kms:EncryptionContext:aws:logs:arn"
        values = [
          "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:${var.cloudtrail_name}",
        ]
      }
    }
  }
}

resource "aws_cloudwatch_log_group" "cloudtrail_log_group" {
  name              = var.cloudtrail_name
  kms_key_id        = local.cloudwatch_key_arn
  retention_in_days = 90
}

data "aws_iam_policy_document" "cloudtrail_assume_role" {
  count = local.create_cloudwatch_iam_role ? 1 : 0
  
  statement {
    effect = "Allow"

    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "Service"
      identifiers = [
        "cloudtrail.amazonaws.com"
      ]
    }
  }
}


data "aws_iam_policy_document" "cloudtrail_logging" {
  count = local.create_cloudwatch_iam_role ? 1 : 0

  statement {
    sid    = "AWSCloudTrailCreateLogStream"
    effect = "Allow"

    actions = [
      "logs:CreateLogStream",
    ]

    resources = [
      local.cloudwatch_logstream_resource,
    ]
  }

  statement {
    sid    = "AWSCloudTrailPutLogEvents"
    effect = "Allow"

    actions = [
      "logs:PutLogEvents",
    ]

    resources = [
      local.cloudwatch_logstream_resource,
    ]
  }
}

resource "aws_iam_policy" "cloudtrail_logging" {
  count = local.create_cloudwatch_iam_role ? 1 : 0
  
  name        = var.cloudtrail_name
  policy      = data.aws_iam_policy_document.cloudtrail_logging[count.index].json
  description = "Allows CloudTrail to create log streams and to put logs in CloudWatch"
}

resource "aws_iam_role" "cloudtrail_logging" {
  count = local.create_cloudwatch_iam_role ? 1 : 0

  name               = var.cloudtrail_name
  assume_role_policy = data.aws_iam_policy_document.cloudtrail_assume_role[count.index].json
}

resource "aws_iam_role_policy_attachment" "cloudtrail_logging" {
  count = local.create_cloudwatch_iam_role ? 1 : 0

  role       = aws_iam_role.cloudtrail_logging[count.index].name
  policy_arn = aws_iam_policy.cloudtrail_logging[count.index].arn
}

resource "aws_cloudtrail" "lacework_cloudtrail" {
  ...
  enable_logging             = true
  cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.cloudtrail_log_group.arn}:*"
  cloud_watch_logs_role_arn  = local.create_cloudwatch_iam_role ? coalesce(var.cloudwatch_logs_iam_role_arn, aws_iam_role.cloudtrail_logging.arn) : null
  enable_log_file_validation = var.enable_log_file_validation
  ...
}

Please note that this code has not been properly tested. I've simply adjusted Terraform configurations that I've found elsewhere.

Thanks!

@TheShahin
Copy link
Author

Any news on this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant