Skip to content

Commit

Permalink
Comply with more things (#6)
Browse files Browse the repository at this point in the history
* Adds Prowler
* Enables Access Analyzer
* Fixes some checks
  • Loading branch information
ckdake authored Aug 4, 2023
1 parent 54df6b5 commit 8ebb551
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 34 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.terraform
.terraform
tools/prowler/output
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,36 @@

## Terraform for AWS plaground

The goal of this AWS setup is to have an automated AWS Organization set up that:

1. Is fully compliant with SOC2
1. Is fully compliant with AWS, CIS, and NIST security standards.
1. Has minimal AWS cost overhead
1. Facilitates easily testing out things in AWS test accounts

### Running locally

This requires env vars with user credentials that can assume to adminstrator.
If `aws sts get-caller-identity` works, you are good, otherwise:

```
```bash
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
```

Currently only works in tenants/management with `terraform apply`.
Currently only works in `tenants/management` with `terraform apply`.

Run `prowler` to populate Security Hub with any breaking things it fines by:
`cd tools/prowler/ && ./install-prowler.sh && ./run-prowler.sh`

### TODO

- [] linters and formatters etc
- [] saml2aws for logging in, what to use for IdP?
- [] import everything in root account, test1 account, test2 account
- [] get some securityhub things passing
- [] setup github actions for terraform plan, terraform apply
- [] terraform plugin caching
- [] Setup AWS Config
- [] lots more
- [ ] linters and formatters etc
- [ ] saml2aws for logging in, what to use for IdP?
- [ ] get test1 and test2 accounts working with `terraform apply`
- [ ] import everything in root account, test1 account, test2 account
- [ ] get prowler checks to 100% green
- [ ] setup github actions for terraform plan, terraform apply, prowler
- [ ] terraform plugin caching
- [ ] Setup AWS Config
- [ ] lots more
24 changes: 24 additions & 0 deletions modules/compliant-account/aws-support.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
resource "aws_iam_role" "aws_support_access" {
name = "aws-support-access"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"AWS": "${var.administrator_role_arn}"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}

# See https://github.com/z0ph/MAMIP/blob/master/policies/AWSSupportAccess
resource "aws_iam_role_policy_attachment" "aws_support_access" {
role = aws_iam_role.aws_support_access.id
policy_arn = "arn:aws:iam::aws:policy/AWSSupportAccess"
}
11 changes: 11 additions & 0 deletions modules/compliant-account/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
resource "aws_iam_account_password_policy" "strict" {
minimum_password_length = 32
require_lowercase_characters = true
require_numbers = true
require_uppercase_characters = true
require_symbols = true
allow_users_to_change_password = true

password_reuse_prevention = 24
max_password_age = 90
}
24 changes: 24 additions & 0 deletions modules/compliant-account/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.10"
}
}

required_version = ">= 1.2.0"
}

provider "aws" {
region = "us-east-1"

assume_role {
role_arn = "arn:aws:iam::053562908965:role/administrator"
}

default_tags {
tags = {
ManagedBy = "terraform"
}
}
}
Empty file.
7 changes: 7 additions & 0 deletions modules/compliant-account/prowler.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# For now, prowler is run by hand as a user via the administrator role. In the future,
# this should be run on a schedule, by a prowler role with dedicated read-only
# permissions and write permissions to Security. See the SecurityAudit policy.

resource "aws_securityhub_product_subscription" "prowler" {
product_arn = "arn:aws:securityhub:us-east-1::product/prowler/prowler"
}
File renamed without changes.
7 changes: 7 additions & 0 deletions modules/compliant-account/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "administrator_role_arn" {
type = string
}

variable "kms_key_arn" {
type = string
}
64 changes: 64 additions & 0 deletions modules/compliant-account/vpc.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Manage the default resources, and ensure they are appropriately locked down

data "aws_availability_zones" "available" {
state = "available"
}

# tfsec:ignore:aws-vpc-no-default-vpc
# tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs
resource "aws_default_vpc" "default" {
tags = {
Name = "default-vpc"
}
}

# TODO(ckdake): set up vpc flow logging
# resource "aws_flow_log" "default" {
# log_destination = module.vpcflowlogs_s3_bucket.bucket_arn
# log_destination_type = "s3"
# traffic_type = "ALL"
# vpc_id = aws_default_vpc.default.id
# }

# Empty security group disables all ingress and egress traffic
resource "aws_default_security_group" "default" {
vpc_id = aws_default_vpc.default.id
}

# Empty route table disables default routes
resource "aws_default_route_table" "default" {
default_route_table_id = aws_default_vpc.default.default_route_table_id
}

# Empty ACL blocks all traffic on default vpc acl
resource "aws_default_network_acl" "default" {
default_network_acl_id = aws_default_vpc.default.default_network_acl_id
tags = {
Name = "default-vpc-default-acl"
}

subnet_ids = [
for default_subnet in aws_default_subnet.default_subnet : default_subnet.id
]
}

# Disable default addressing in default subnets, and name them
# there are 6 azs in us-east-1. other zones have less!
resource "aws_default_subnet" "default_subnet" {
count = 6

availability_zone = element(data.aws_availability_zones.available.names[*], count.index)
map_public_ip_on_launch = false

tags = {
Name = "default-subnet"
}
}

resource "aws_ebs_default_kms_key" "aws_ebs_default_kms_key" {
key_arn = var.kms_key_arn
}

resource "aws_ebs_encryption_by_default" "aws_ebs_encryption_by_default" {
enabled = true
}
4 changes: 4 additions & 0 deletions tenants/management/access-analyzer.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
resource "aws_accessanalyzer_analyzer" "aws_accessanalyzer_analyzer" {
analyzer_name = "organization"
type = "ORGANIZATION"
}
12 changes: 0 additions & 12 deletions tenants/management/iam.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
resource "aws_iam_account_password_policy" "strict" {
minimum_password_length = 32
require_lowercase_characters = true
require_numbers = true
require_uppercase_characters = true
require_symbols = true
allow_users_to_change_password = true

password_reuse_prevention = 24
max_password_age = 90
}

# Role to be used for any administrative tasks
data "aws_iam_policy_document" "administrator_assume_role_policy" {
statement {
Expand Down
7 changes: 7 additions & 0 deletions tenants/management/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ provider "aws" {
}
}
}

module "compliant-account" {
source = "../../modules/compliant-account"

administrator_role_arn = aws_iam_role.administrator.arn
kms_key_arn = aws_kms_key.management.arn
}
24 changes: 13 additions & 11 deletions tenants/management/organization.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
resource "aws_organizations_organization" "root" {
aws_service_access_principals = [
"securityhub.amazonaws.com"
"access-analyzer.amazonaws.com",
"securityhub.amazonaws.com",
"sso.amazonaws.com"
]

feature_set = "ALL"
}

resource "aws_organizations_account" "management" {
name = "management"
email = "[email protected]"
parent_id = aws_organizations_organization.root.id
name = "management"
email = "[email protected]"
parent_id = aws_organizations_organization.root.id
}

resource "aws_organizations_organizational_unit" "test" {
Expand All @@ -18,13 +20,13 @@ resource "aws_organizations_organizational_unit" "test" {
}

resource "aws_organizations_account" "test1" {
name = "test1"
email = "[email protected]"
parent_id = aws_organizations_organizational_unit.test.id
name = "test1"
email = "[email protected]"
parent_id = aws_organizations_organizational_unit.test.id
}

resource "aws_organizations_account" "test2" {
name = "test2"
email = "[email protected]"
parent_id = aws_organizations_organizational_unit.test.id
}
name = "test2"
email = "[email protected]"
parent_id = aws_organizations_organizational_unit.test.id
}
10 changes: 10 additions & 0 deletions tools/prowler/allowlist.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# See https://docs.prowler.cloud/en/latest/tutorials/allowlist/
Allowlist:
Accounts:
"*":
Checks:
"fake_check":
Regions:
- "*"
Resources:
- "fake-resource"
5 changes: 5 additions & 0 deletions tools/prowler/install-prowler.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

set -eou pipefail

pip install prowler
20 changes: 20 additions & 0 deletions tools/prowler/run-prowler.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

set -eou pipefail

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
CREDENTIALS=$(aws sts assume-role --role-arn arn:aws:iam::"$ACCOUNT_ID":role/administrator --role-session-name prowler --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text)

AWS_ACCESS_KEY_ID=$(echo "$CREDENTIALS" | cut -f 1)
AWS_SECRET_ACCESS_KEY=$(echo "$CREDENTIALS" | cut -f 2)
AWS_SESSION_TOKEN=$(echo "$CREDENTIALS" | cut -f 3)
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
export AWS_SESSION_TOKEN

prowler aws --region us-east-1 \
--allowlist-file allowlist.yaml \
--output-modes html \
--log-level WARNING \
--excluded-checks ec2_elastic_ip_shodan \
--security-hub

0 comments on commit 8ebb551

Please sign in to comment.