add aws config module

ctalarms-whitelist
lalanza808 4 years ago
parent 70a5102387
commit a6e7ef642c

@ -0,0 +1,43 @@
# Config
This modules sets up AWS Config for auditing the account and alerting on insecure conditions.
There is a list of pre-made Config rules authored by AWS here: https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html
I only picked the most obvious ones because there are a ton of available rules but they can cost a lot to turn them all on.
## Usage
```
module "cloudtrail" {
source = "github.com/lalanza808/tf-modules.git/security/cloudtrail"
force_destroy_bucket = true
}
module "sns_topic" {
source = "github.com/lalanza808/tf-modules.git/monitoring/sns-email-topic"
sns_emails = ["user@email.com"]
}
module "config" {
source = "github.com/lalanza808/tf-modules.git/monitoring/config"
sns_topic_arn = module.sns_topic.topic_arn
s3_buckets_logging_enabled = [
module.cloudtrail.s3_bucket
]
}
```
## Inputs
The main ones you would want to override are:
* `sns_topic_arn` - An SNS topic ARN for notifying when a Config rule has breached
* `s3_buckets_logging_enabled` - A list of buckets to create Config rules for monitoring Cloudtrail data plane operations log collection
See the full list of inputs here: [variables.tf](./variables.tf)
## Outputs
[output.tf](./output.tf)

@ -0,0 +1,144 @@
resource "aws_s3_bucket" "config_bucket" {
count = var.enable_aws_config ? 1 : 0
bucket_prefix = "${var.prefix}-config-"
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" "config_bucket_policy" {
count = var.enable_aws_config ? 1 : 0
bucket = aws_s3_bucket.config_bucket[0].id
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSConfigAclCheck",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:GetBucketAcl",
"Resource": "${aws_s3_bucket.config_bucket[0].arn}"
},
{
"Sid": "AWSConfigWrite",
"Effect": "Allow",
"Principal": {
"Service": "config.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "${aws_s3_bucket.config_bucket[0].arn}/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}
resource "aws_config_delivery_channel" "delivery_channel" {
count = var.enable_aws_config ? 1 : 0
name = aws_s3_bucket.config_bucket[0].id
s3_bucket_name = aws_s3_bucket.config_bucket[0].id
sns_topic_arn = var.sns_topic_arn
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_configuration_recorder_status" "config_status" {
count = var.enable_aws_config ? 1 : 0
name = aws_config_configuration_recorder.config_recorder[0].name
is_enabled = true
depends_on = [aws_config_delivery_channel.delivery_channel]
}
resource "aws_config_configuration_recorder" "config_recorder" {
count = var.enable_aws_config ? 1 : 0
name = aws_s3_bucket.config_bucket[0].id
role_arn = aws_iam_role.config_recorder_role[0].arn
recording_group {
all_supported = "true"
include_global_resource_types = "true"
}
}
resource "aws_iam_role" "config_recorder_role" {
count = var.enable_aws_config ? 1 : 0
name = aws_s3_bucket.config_bucket[0].id
tags = var.tags
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "config.amazonaws.com"
},
"Effect": "Allow"
}
]
}
POLICY
}
resource "aws_iam_role_policy" "config_s3" {
count = var.enable_aws_config ? 1 : 0
name = aws_iam_role.config_recorder_role[0].name
role = aws_iam_role.config_recorder_role[0].id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:*"
],
"Resource": [
"${aws_s3_bucket.config_bucket[0].arn}",
"${aws_s3_bucket.config_bucket[0].arn}/*"
],
"Effect": "Allow"
}
]
}
EOF
}
// Config service policy attachment
resource "aws_iam_role_policy_attachment" "config_role" {
count = var.enable_aws_config ? 1 : 0
role = aws_iam_role.config_recorder_role[0].name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSConfigRole"
}

@ -0,0 +1,40 @@
resource "aws_config_config_rule" "cloudtrail_enabled" {
count = var.enable_aws_config && var.rule_cloudtrail_enabled ? 1 : 0
name = "multi-region-cloud-trail-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "MULTI_REGION_CLOUD_TRAIL_ENABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "cloudtrail_validation_enabled" {
count = var.enable_aws_config && var.rule_cloudtrail_validation_enabled ? 1 : 0
name = "cloud-trail-log-validation-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "CLOUD_TRAIL_LOG_FILE_VALIDATION_ENABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "cloudtrail_cloudwatch_logs_enabled" {
count = var.enable_aws_config && var.rule_cloudtrail_cloudwatch_logs_enabled ? 1 : 0
name = "cloud-trail-cloud-watch-logs-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "CLOUD_TRAIL_CLOUD_WATCH_LOGS_ENABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}

@ -0,0 +1,12 @@
resource "aws_config_config_rule" "guardduty_enabled" {
count = var.enable_aws_config && var.rule_guardduty_enabled ? 1 : 0
name = "guardduty-enabled-centralized"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "GUARDDUTY_ENABLED_CENTRALIZED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}

@ -0,0 +1,138 @@
resource "aws_config_config_rule" "root_access_keys" {
count = var.enable_aws_config && var.rule_root_access_keys ? 1 : 0
name = "iam-root-access-key-check"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "IAM_ROOT_ACCESS_KEY_CHECK"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "root_mfa_enabled" {
count = var.enable_aws_config && var.rule_root_mfa_enabled ? 1 : 0
name = "root-account-mfa-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "ROOT_ACCOUNT_MFA_ENABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "root_hardware_mfa_enabled" {
count = var.enable_aws_config && var.rule_root_hardware_mfa_enabled ? 1 : 0
name = "root-account-hardware-mfa-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "ROOT_ACCOUNT_HARDWARE_MFA_ENABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "console_mfa_enabled" {
count = var.enable_aws_config && var.rule_console_mfa_enabled ? 1 : 0
name = "mfa-enabled-for-iam-console-access"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "MFA_ENABLED_FOR_IAM_CONSOLE_ACCESS"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "iam_user_unused" {
count = var.enable_aws_config && var.rule_iam_user_unused ? 1 : 0
name = "iam-user-unused-credentials-check"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "IAM_USER_UNUSED_CREDENTIALS_CHECK"
}
tags = var.tags
input_parameters = <<EOF
{
"maxCredentialUsageAge": "90"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "iam_password_policy_enabled" {
count = var.enable_aws_config && var.rule_iam_password_policy_enabled ? 1 : 0
name = "iam-password-policy-enabled"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "IAM_PASSWORD_POLICY"
}
tags = var.tags
input_parameters = <<EOF
{
"MinimumPasswordLength": "14",
"RequireUppercaseCharacters": "true",
"RequireLowercaseCharacters": "true",
"RequireSymbols": "true",
"RequireNumbers": "true",
"PasswordReusePrevention": "24",
"MaxPasswordAge": "90"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "iam_policy_no_admin" {
count = var.enable_aws_config && var.rule_iam_policy_no_admin ? 1 : 0
name = "iam-policy-no-statements-with-admin-access"
source {
owner = "AWS"
source_identifier = "IAM_POLICY_NO_STATEMENTS_WITH_ADMIN_ACCESS"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "access_keys_rotated" {
count = var.enable_aws_config && var.rule_access_keys_rotated ? 1 : 0
name = "access-keys-rotated"
maximum_execution_frequency = "TwentyFour_Hours"
source {
owner = "AWS"
source_identifier = "ACCESS_KEYS_ROTATED"
}
tags = var.tags
input_parameters = <<EOF
{
"maxAccessKeyAge": "90"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "iam_user_no_policies" {
count = var.enable_aws_config && var.rule_iam_user_no_policies ? 1 : 0
name = "iam-user-no-policies-check"
source {
owner = "AWS"
source_identifier = "IAM_USER_NO_POLICIES_CHECK"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}

@ -0,0 +1,29 @@
resource "aws_config_config_rule" "s3_public_read_prohibited" {
count = var.enable_aws_config && var.rule_s3_public_read_prohibited ? 1 : 0
name = "s3-bucket-public-read-prohibited"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "s3_logging_enabled" {
name = "s3-bucket-logging-enabled"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_LOGGING_ENABLED"
}
tags = var.tags
input_parameters = <<EOF
{
"targetBucket": "*",
"targetPrefix": "/"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}

@ -0,0 +1,60 @@
resource "aws_config_config_rule" "vpc_flow_logs_enabled" {
count = var.enable_aws_config && var.rule_vpc_flow_logs_enabled ? 1 : 0
name = "vpc-flow-logs-enabled"
source {
owner = "AWS"
source_identifier = "VPC_FLOW_LOGS_ENABLED"
}
tags = var.tags
input_parameters = <<EOF
{
"trafficType": "ALL"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "incoming_ssh_enabled" {
count = var.enable_aws_config && var.rule_incoming_ssh_enabled ? 1 : 0
name = "restricted-ssh"
source {
owner = "AWS"
source_identifier = "INCOMING_SSH_DISABLED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "restricted_common_ports" {
count = var.enable_aws_config && var.rule_restricted_common_ports ? 1 : 0
name = "restricted-common-ports"
source {
owner = "AWS"
source_identifier = "RESTRICTED_INCOMING_TRAFFIC"
}
tags = var.tags
input_parameters = <<EOF
{
"blockedPort1": "3306",
"blockedPort2": "3389"
}
EOF
depends_on = [aws_config_configuration_recorder.config_recorder]
}
resource "aws_config_config_rule" "default_security_group_closed" {
count = var.enable_aws_config && var.rule_default_security_group_closed ? 1 : 0
name = "vpc-default-security-group-closed"
source {
owner = "AWS"
source_identifier = "VPC_DEFAULT_SECURITY_GROUP_CLOSED"
}
tags = var.tags
depends_on = [aws_config_configuration_recorder.config_recorder]
}

@ -0,0 +1,2 @@
# Get AWS account info
data "aws_caller_identity" "current" {}

@ -0,0 +1,5 @@
// Resource attritbute output
output "config_bucket" {
value = aws_s3_bucket.config_bucket[0].id
}

@ -0,0 +1,99 @@
variable "enable_aws_config" {
default = true
description = "Whether or not you want Config"
}
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 "sns_topic_arn" {
default = ""
description = "SNS Topic to forward Config messages to"
}
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 = 90
description = "Number of days to maintain in S3 until transitioning to Glacier"
}
variable "lifecycle_object_expiration" {
default = 365
description = "Number of days to expire objects permanently"
}
variable "s3_buckets_logging_enabled" {
type = list
default = []
description = "A list of S3 buckets you want to run Config checks for ensuring logging is enabled"
}
variable "rule_cloudtrail_enabled" {
default = true
}
variable "rule_cloudtrail_validation_enabled" {
default = true
}
variable "rule_guardduty_enabled" {
default = true
}
variable "rule_root_access_keys" {
default = true
}
variable "rule_root_mfa_enabled" {
default = true
}
variable "rule_root_hardware_mfa_enabled" {
default = true
}
variable "rule_console_mfa_enabled" {
default = true
}
variable "rule_iam_user_unused" {
default = true
}
variable "rule_iam_password_policy_enabled" {
default = true
}
variable "rule_iam_policy_no_admin" {
default = true
}
variable "rule_access_keys_rotated" {
default = true
}
variable "rule_iam_user_no_policies" {
default = true
}
variable "rule_s3_public_read_prohibited" {
default = true
}
variable "rule_cloudtrail_cloudwatch_logs_enabled" {
default = true
}
variable "rule_s3_logging_enabled" {
default = true
}
variable "rule_vpc_flow_logs_enabled" {
default = true
}
variable "rule_incoming_ssh_enabled" {
default = true
}
variable "rule_restricted_common_ports" {
default = true
}
variable "rule_default_security_group_closed" {
default = true
}
variable "tags" {
default = {}
type = map
description = "Optional set of tags to apply to the infrastructure"
}
variable "prefix" {
default = "monitoring"
description = "String to prefix to all resources"
}
Loading…
Cancel
Save