add cloudtrail module

ctalarms-whitelist
lalanza808 4 years ago
parent fc6de54755
commit 6dc0deb490

@ -0,0 +1,26 @@
# Cloudtrail
Configure AWS Cloudtrail in a given AWS account. Logs all S3 bucket data plane operations by default; see inputs for more info.
https://aws.amazon.com/cloudtrail/
## Usage
```
module "cloudtrail" {
source = "github.com/lalanza808/tf-modules.git/security/cloudtrail"
}
```
## Inputs
There are a few variables that can be tweaked here. You can also override the default behavior of logging all S3 bucket data plane operations to either log nothing or log some buckets.
* `default_log_bucket` - set to empty string to remove all bucket logging
* `activity_log_buckets` - list of bucket names to setup extra logging for
See the full list of inputs here: [variables.tf](./variables.tf)
## Outputs
[output.tf](./output.tf)

@ -0,0 +1,42 @@
resource "aws_iam_role" "cloudtrail_log_group_role" {
name = aws_s3_bucket.cloudtrail_bucket.id
tags = var.tags
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy" "cloudtrail_log_group_role_policy" {
name = aws_s3_bucket.cloudtrail_bucket.id
role = aws_iam_role.cloudtrail_log_group_role.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "logs:CreateLogStream",
"Resource": "${aws_cloudwatch_log_group.cloudtrail_log_group.arn}",
"Effect": "Allow"
},
{
"Action": "logs:PutLogEvents",
"Resource": "${aws_cloudwatch_log_group.cloudtrail_log_group.arn}",
"Effect": "Allow"
}
]
}
EOF
}

@ -0,0 +1,102 @@
resource "aws_kms_key" "cloudtrail" {
description = var.prefix
enable_key_rotation = var.enable_key_rotation
tags = var.tags
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {"AWS": [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
]},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow CloudTrail to encrypt logs",
"Effect": "Allow",
"Principal": {
"Service": ["cloudtrail.amazonaws.com"]
},
"Action": "kms:GenerateDataKey*",
"Resource": "*",
"Condition": {
"StringLike": {
"kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:${data.aws_caller_identity.current.account_id}:trail/*"
}
}
},
{
"Sid": "Allow CloudTrail to describe keys",
"Effect": "Allow",
"Principal": {"Service": ["cloudtrail.amazonaws.com"]},
"Action": "kms:DescribeKey",
"Resource": "*"
},
{
"Sid": "Allow principals in the account to decrypt log files",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Decrypt",
"kms:ReEncryptFrom"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "${data.aws_caller_identity.current.account_id}"
},
"StringLike": {
"kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:${data.aws_caller_identity.current.account_id}:trail/*"
}
}
},
{
"Sid": "Allow alias creation during setup",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:CreateAlias",
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "ec2.region.amazonaws.com",
"kms:CallerAccount": "${data.aws_caller_identity.current.account_id}"
}
}
},
{
"Sid": "Enable cross account log decryption",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"kms:Decrypt",
"kms:ReEncryptFrom"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:CallerAccount": "${data.aws_caller_identity.current.account_id}"
},
"StringLike": {
"kms:EncryptionContext:aws:cloudtrail:arn": "arn:aws:cloudtrail:*:${data.aws_caller_identity.current.account_id}:trail/*"
}
}
}
]
}
EOF
}
resource "aws_kms_alias" "kms" {
name = "alias/${var.prefix}-cloudtrail"
target_key_id = aws_kms_key.cloudtrail.key_id
}

@ -0,0 +1,27 @@
data "aws_caller_identity" "current" {}
resource "aws_cloudtrail" "cloudtrail_bucket_logging" {
name = aws_s3_bucket.cloudtrail_bucket.id
s3_bucket_name = aws_s3_bucket.cloudtrail_bucket.id
include_global_service_events = var.include_global_service_events
is_multi_region_trail = var.is_multi_region_trail
enable_logging = var.enable_logging
enable_log_file_validation = var.enable_log_file_validation
cloud_watch_logs_role_arn = aws_iam_role.cloudtrail_log_group_role.arn
cloud_watch_logs_group_arn = aws_cloudwatch_log_group.cloudtrail_log_group.arn
kms_key_id = aws_kms_key.cloudtrail.arn
tags = var.tags
event_selector {
read_write_type = "All"
include_management_events = var.include_management_events
data_resource {
type = "AWS::S3::Object"
values = compact(concat(
[var.default_log_bucket],
formatlist("arn:aws:s3:::%s/", var.activity_log_buckets)
))
}
}
}

@ -0,0 +1,13 @@
// Resource attritbute output
output "s3_bucket" {
value = aws_s3_bucket.cloudtrail_bucket.id
}
output "trail_name" {
value = aws_cloudtrail.cloudtrail_bucket_logging.id
}
output "log_group_name" {
value = aws_cloudwatch_log_group.cloudtrail_log_group.name
}

@ -0,0 +1,71 @@
resource "aws_s3_bucket" "cloudtrail_bucket" {
bucket_prefix = "${var.prefix}-cloudtrail-"
acl = "private"
force_destroy = var.force_destroy_bucket
tags = var.tags
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
lifecycle_rule {
id = "archive_glacier"
enabled = var.lifecycle_enabled
prefix = var.lifecycle_prefix
transition {
days = var.lifecycle_glacier_transition_days
storage_class = "GLACIER"
}
expiration {
days = var.lifecycle_object_expiration
}
}
}
resource "aws_s3_bucket_policy" "cloudtrail_bucket_policy" {
bucket = aws_s3_bucket.cloudtrail_bucket.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "${aws_s3_bucket.cloudtrail_bucket.arn}"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": {
"Service": "cloudtrail.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "${aws_s3_bucket.cloudtrail_bucket.arn}/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}
resource "aws_cloudwatch_log_group" "cloudtrail_log_group" {
name = aws_s3_bucket.cloudtrail_bucket.id
retention_in_days = var.cloudwatch_log_retention
tags = var.tags
}

@ -0,0 +1,65 @@
variable "include_management_events" {
default = true
description = "Whether or not you want to include management events"
}
variable "lifecycle_enabled" {
default = true
description = "Whether or not to enable lifecycle rules"
}
variable "lifecycle_prefix" {
default = ""
description = "S3 object prefix to manage lifecycle - blank is all objects"
}
variable "lifecycle_glacier_transition_days" {
default = 365
description = "Number of days to maintain in S3 until transitioning to Glacier"
}
variable "enable_key_rotation" {
default = true
}
variable "lifecycle_object_expiration" {
default = 1825
description = "Number of days to expire objects permanently"
}
variable "cloudwatch_log_retention" {
default = 90
description = "Number of days to maintain Cloudtrail events in Cloudwatch Logs"
}
variable "force_destroy_bucket" {
default = false
description = "Whether or not you want the bucket to force removal of all objects upon deletion - otherwise throws error when deleting"
}
variable "include_global_service_events" {
default = true
description = "Whether or not to include global service events"
}
variable "is_multi_region_trail" {
default = true
description = "Whether or not to use all regions"
}
variable "enable_logging" {
default = true
description = "Whether or not to enable logging"
}
variable "enable_log_file_validation" {
default = true
description = "Whether or not to enable log validation"
}
variable "tags" {
default = {}
type = map
description = "Optional set of tags to apply to the infrastructure"
}
variable "prefix" {
default = "security"
description = "String to prefix to all resources"
}
variable "activity_log_buckets" {
description = "List of bucket ARNs to collect data plane operation logs for in addition to API events"
type = list
default = []
}
variable "default_log_bucket" {
default = "arn:aws:s3:::"
description = "The default buckets to log - all buckets in the account - override to empty string"
}
Loading…
Cancel
Save