Skip to content

Commit

Permalink
break out into a new repo, add examples/README
Browse files Browse the repository at this point in the history
  • Loading branch information
grothja committed Sep 13, 2021
0 parents commit 78f3252
Show file tree
Hide file tree
Showing 22 changed files with 7,400 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Local .terraform directories
**/.terraform/*

# Terraform lockfile
.terraform.lock.hcl

# .tfstate files
*.tfstate
*.tfstate.*
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 National Institute of Allergy and Infectious Diseases (NIAID)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
130 changes: 130 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# AWS Config Managed Rules Terraform Module

This Terraform module will create, manage, and update [AWS-managed Config Rules](https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config_use-managed-rules.html). It has the following features:

- 200+ managed rule definitions for easy deployment:
- Each rule includes a description and a severity setting (e.g. `Low`, `Medium`, `High`, and `Critical`)
- Optional and required parameters for a rule can be passed in via Terraform variables
- Rules can be modified (and added) by the users of this module without updating the module
- New rules will be added over time by the maintainers
- Deploy managed rules in a specific AWS account (the default) or for an [Organization](https://docs.aws.amazon.com/config/latest/developerguide/config-rule-multi-account-deployment.html)
- Deploy [Rule Packs](#rule-packs), which are groups of rules that correspond to a compliance standard (e.g. NIST 800-53, CIS Best Practices, etc.)
- Packs deployed are de-duplicated (you can specify Packs which have overlapping rules without deploying the same rule multiple times)
- Optionally exclude specific rules

## Why

This module was created because we wanted a Terraform-native way to deploy groups of AWS-managed Config Rules across our Organization and within specific accounts. The natural choice is to deploy [Conformance Packs](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html), but these have some downsides:

- Rules are specified in each pack, so if you want to change the definition of a config for a rule across multiple packs, you have to edit each YAML file.
- If you want to exclude rules, you have to search in the pack for the rule and delete them from each
- Rule duplication
- Rule visibility: changing individually deployed Terraform rules is more granular than packs

## Usage

See the `examples` directory for more details and complete examples. But as a quick example, if you wanted to:

- Deploy all the rules associated with NIST 800-53 rev 4 and Operational Best Practices for Logging
- Change the `access-keys-rotated` age time in days to `60`
- Exclude `ec2-imdsv2-check` rule
- Change the Config Rule description for the `acm-certificate-expiration-check` rule

You would do something like:

```hcl
module "managed_rules" {
source = "."
rule_packs = [
"Operational-Best-Practices-for-Operational-Best-Practices-for-Logging",
"Operational-Best-Practices-for-NIST-800-53-rev-4",
]
access_keys_rotated_parameters = {
maxAccessKeyAge = "60"
}
rules_to_exclude = [
"ec2-imdsv2-check",
]
rule_overrides = {
acm-certificate-expiration-check = {
description = "Some other description I think people will like"
}
}
}
```

## Internals

This section discusses some of the internal construction of this module. The information provided is not necessary to get started, but helpful to understand what's being done, advanced configuration, how it's built, etc.

### Rule Packs

A rule pack is a list/array of rules associated to a security/compliance standard like NIST 800-53. The rules that make up these packs are derived from [AWS's Conformance Packs](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html). In the `files` directory of this repo, you will find two files:

- A YAML file containing all of the Config Rules associated with each pack
- A text file containing only a newline separated list of all the packs

The text file is included to provide the users of this module with an easy to read list of all the packs that exist. These are what you pass to the `rule_packs` Terraform input variable if you want to deploy packs.

The YAML file provides a human and machine readable association of the AWS-managed Config Rules to the Conformance Packs. This is used by the Terraform module to derive which rules are associated to which pack.

These files are generated by the maintainers of this module running `scripts/generate-rule-pack-info.rb` and committing the results to the repository.

### Managed Rule Structure

The managed rules are defined in the `local.managed_rules` variable; the following is a sample of a few rule definitions that we will go over in detail:

```hcl
locals {
managed_rules = {
access-keys-rotated = {
description = "Checks if the active access keys are rotated within the number of days specified in maxAccessKeyAge. The rule is NON_COMPLIANT if the access keys have not been rotated for more than maxAccessKeyAge number of days."
input_parameters = var.access_keys_rotated_parameters
severity = "Medium"
}
account-part-of-organizations = {
description = "Checks if an AWS account is part of AWS Organizations. The rule is NON_COMPLIANT if an AWS account is not part of AWS Organizations or AWS Organizations master account ID does not match rule parameter MasterAccountId."
input_parameters = var.account_part_of_organizations_parameters
severity = "Low"
}
acm-certificate-expiration-check = {
description = "Checks if AWS Certificate Manager Certificates in your account are marked for expiration within the specified number of days. Certificates provided by ACM are automatically renewed. ACM does not automatically renew certificates that you import."
input_parameters = var.acm_certificate_expiration_check_parameters
resource_types_scope = ["AWS::ACM::Certificate"]
severity = "Medium"
}
}
}
```

Things to note:

- The rule name is the key to each item in the map
- The rule name corresponds to the managed rule [identifier](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/config_config_rule#source_identifier)
- Most [managed rule](https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html) names match the identifier, just upper-cased and using underscores instead of hyphens. A handful do not; this module changes the name of the rule to match the identifier when the two do not match up.
- AWS Config has a 256 character limit for descriptions. Descriptions were taken from the [managed rule](https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html) list, but occasionally had to be truncated to make them fit.
- For rules with input parameters, a variable will be present in the form of `rule_name_parameters`. When possible, these are typed to provide guidance and guardrails, but until [optional types](https://www.terraform.io/docs/language/expressions/type-constraints.html#experimental-optional-object-type-attributes) in Terraform are fully supported, many parameters are not typed.
- Regardless of what the Config Rule says in terms of types (e.g. `int`, etc.) from what we've seen, the rule ultimately expects the value passed in to be a string. Keep this in mind when passing in input parameters
- Severity has no impact on the Config Rule and provided purely as metadata for consumption in downstream tooling. Rule severity was derived from looking at rules/controls in [Security Hub standards](https://docs.aws.amazon.com/securityhub/latest/userguide/standards-available.html), and when not available, at the best judgement of this module's maintainers
- Rules can be overridden and new rules can be added. If AWS came out with a new rule called `account-name-starts-with`, and you wanted to add support for it right away, you could add the following as an input variable to the module:

```
rule_overrides = {
account-name-starts-with = {
description = "Checks if an AWS account's name starts with the string provided. The rule is NON_COMPLIANT if an AWS account does not start with the name provided"
severity = "Medium" # completely optional, since 'severity' is metadata only
input_parameters = {
accountNameStartsWith = "myorgname"
}
}
}
```

This variable can also be used to change/override any settings for any managed config rule previously defined
38 changes: 38 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module "managed_rules" {
source = "../../"

organization_managed = false # this is the default setting

# You can exclude AWS accounts when deploying Organization rules
# excluded_accounts = [
# "123456789012",
# ]

rule_packs = [
"Operational-Best-Practices-for-CIS-Critical-Security-Controls-v8-IG3",
"Operational-Best-Practices-for-NIST-800-53-rev-4",
]

# Extra rules not included in the Packs you want to deploy
rules_to_include = [
"dax-encryption-enabled",
]

rules_to_exclude = [
"lambda-concurrency-check",
]

redshift_cluster_maintenancesettings_check_parameters = {
allowVersionUpgrade = "true"
}

rule_overrides = {
acm-certificate-expiration-check = {
description = "Checks if AWS Certificate Manager Certificates in your account..."

input_parameters = {
daysToExpiration = tostring(var.acm_certificate_expiration_check)
}
}
}
}
4 changes: 4 additions & 0 deletions examples/complete/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
output "rules_applied" {
description = "A list of Config Rules applied by the module"
value = keys(module.managed_rules.rules[0])
}
5 changes: 5 additions & 0 deletions examples/complete/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variable "acm_certificate_expiration_check" {
description = "Time in days before alerting that your ACM cert will expire"
default = 30
type = number
}
10 changes: 10 additions & 0 deletions examples/complete/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 0.14"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.36"
}
}
}
33 changes: 33 additions & 0 deletions examples/metadata-only/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This module will do/manage nothing by default when instantiated, but it will
# return an output which has all the managed rules, with their descriptions and
# severities included.
#
# In this example, we'll call this module send the JSON-encoded results to S3

module "managed_config_rules" {
source = "../../"
}

resource "aws_s3_bucket" "config_rule_desc" {
bucket_prefix = "config-rule-descriptions"
acl = "private"

versioning {
enabled = true
}

server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
}

resource "aws_s3_bucket_object" "managed_rules_desc" {
bucket = aws_s3_bucket.config_rule_desc.bucket
key = "managed-rules-descriptions.json"
content_type = "application/json"
content = jsonencode(module.managed_config_rules.all_rule_descriptions)
}
10 changes: 10 additions & 0 deletions examples/metadata-only/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 0.14"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.36"
}
}
}
71 changes: 71 additions & 0 deletions files/pack-rules-list.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
AWS-Control-Tower-Detective-Guardrails
Operational-Best-Practices-for-ABS-CCIGv2-Material
Operational-Best-Practices-for-ABS-CCIGv2-Standard
Operational-Best-Practices-for-ACSC-Essential8
Operational-Best-Practices-for-ACSC-ISM
Operational-Best-Practices-for-AI-and-ML
Operational-Best-Practices-for-APRA-CPG-234
Operational-Best-Practices-for-AWS-Identity-and-Access-Management
Operational-Best-Practices-for-AWS-Well-Architected-Reliability-Pillar
Operational-Best-Practices-for-AWS-Well-Architected-Security-Pillar
Operational-Best-Practices-for-Amazon-DynamoDB-with-Remediation
Operational-Best-Practices-for-Amazon-DynamoDB
Operational-Best-Practices-for-Amazon-S3-with-Remediation
Operational-Best-Practices-for-Amazon-S3
Operational-Best-Practices-for-Asset-Management
Operational-Best-Practices-for-BCP-and-DR
Operational-Best-Practices-for-BNM-RMiT
Operational-Best-Practices-for-CCN-ENS-High
Operational-Best-Practices-for-CCN-ENS-Low
Operational-Best-Practices-for-CCN-ENS-Medium
Operational-Best-Practices-for-CIS-AWS-FB-v1.3-Level1
Operational-Best-Practices-for-CIS-AWS-FB-v1.3-Level2
Operational-Best-Practices-for-CIS-AWS-v1.4-Level1
Operational-Best-Practices-for-CIS-AWS-v1.4-Level2
Operational-Best-Practices-for-CIS-Critical-Security-Controls-v8-IG1
Operational-Best-Practices-for-CIS-Critical-Security-Controls-v8-IG2
Operational-Best-Practices-for-CIS-Critical-Security-Controls-v8-IG3
Operational-Best-Practices-for-CIS-Top20
Operational-Best-Practices-for-CIS
Operational-Best-Practices-for-CMMC-Level-1
Operational-Best-Practices-for-CMMC-Level-2
Operational-Best-Practices-for-CMMC-Level-3
Operational-Best-Practices-for-CMMC-Level-4
Operational-Best-Practices-for-CMMC-Level-5
Operational-Best-Practices-for-Compute-Services
Operational-Best-Practices-for-Data-Resiliency
Operational-Best-Practices-for-Database-Services
Operational-Best-Practices-for-Datalakes-and-Analytics-Services
Operational-Best-Practices-for-EC2
Operational-Best-Practices-for-Encryption-and-Keys
Operational-Best-Practices-for-FDA-21CFR-Part-11
Operational-Best-Practices-for-FFIEC
Operational-Best-Practices-for-FedRAMP-Low
Operational-Best-Practices-for-FedRAMP
Operational-Best-Practices-for-HIPAA-Security
Operational-Best-Practices-for-KISMS
Operational-Best-Practices-for-Load-Balancing
Operational-Best-Practices-for-Logging
Operational-Best-Practices-for-MAS-Notice-655
Operational-Best-Practices-for-MAS-TRMG
Operational-Best-Practices-for-Management-Governance-Services
Operational-Best-Practices-for-Monitoring
Operational-Best-Practices-for-NBC-TRMG
Operational-Best-Practices-for-NCSC-CAF
Operational-Best-Practices-for-NCSC-CloudSec-Principles
Operational-Best-Practices-for-NERC-CIP
Operational-Best-Practices-for-NIST-1800-25
Operational-Best-Practices-for-NIST-800-171
Operational-Best-Practices-for-NIST-800-53-rev-4
Operational-Best-Practices-for-NIST-800-53-rev-5
Operational-Best-Practices-for-NIST-CSF
Operational-Best-Practices-for-NYDFS-23-NYCRR-500
Operational-Best-Practices-for-NZISM
Operational-Best-Practices-for-Networking-Services
Operational-Best-Practices-for-PCI-DSS
Operational-Best-Practices-for-Publicly-Accessible-Resources
Operational-Best-Practices-for-RBI-Basic-Cyber-Security-Framework
Operational-Best-Practices-for-RBI-MasterDirection
Operational-Best-Practices-for-Security-Services
Operational-Best-Practices-for-Serverless
Operational-Best-Practices-for-Storage-Services
Loading

0 comments on commit 78f3252

Please sign in to comment.