Skip to content

Commit 8ebb551

Browse files
authored
Comply with more things (#6)
* Adds Prowler * Enables Access Analyzer * Fixes some checks
1 parent 54df6b5 commit 8ebb551

File tree

17 files changed

+222
-34
lines changed

17 files changed

+222
-34
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.terraform
1+
.terraform
2+
tools/prowler/output

README.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,36 @@
22

33
## Terraform for AWS plaground
44

5+
The goal of this AWS setup is to have an automated AWS Organization set up that:
6+
7+
1. Is fully compliant with SOC2
8+
1. Is fully compliant with AWS, CIS, and NIST security standards.
9+
1. Has minimal AWS cost overhead
10+
1. Facilitates easily testing out things in AWS test accounts
11+
12+
### Running locally
13+
514
This requires env vars with user credentials that can assume to adminstrator.
15+
If `aws sts get-caller-identity` works, you are good, otherwise:
616

7-
```
17+
```bash
818
export AWS_ACCESS_KEY_ID=
919
export AWS_SECRET_ACCESS_KEY=
1020
```
1121

12-
Currently only works in tenants/management with `terraform apply`.
22+
Currently only works in `tenants/management` with `terraform apply`.
23+
24+
Run `prowler` to populate Security Hub with any breaking things it fines by:
25+
`cd tools/prowler/ && ./install-prowler.sh && ./run-prowler.sh`
1326

1427
### TODO
1528

16-
- [] linters and formatters etc
17-
- [] saml2aws for logging in, what to use for IdP?
18-
- [] import everything in root account, test1 account, test2 account
19-
- [] get some securityhub things passing
20-
- [] setup github actions for terraform plan, terraform apply
21-
- [] terraform plugin caching
22-
- [] Setup AWS Config
23-
- [] lots more
29+
- [ ] linters and formatters etc
30+
- [ ] saml2aws for logging in, what to use for IdP?
31+
- [ ] get test1 and test2 accounts working with `terraform apply`
32+
- [ ] import everything in root account, test1 account, test2 account
33+
- [ ] get prowler checks to 100% green
34+
- [ ] setup github actions for terraform plan, terraform apply, prowler
35+
- [ ] terraform plugin caching
36+
- [ ] Setup AWS Config
37+
- [ ] lots more
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
resource "aws_iam_role" "aws_support_access" {
2+
name = "aws-support-access"
3+
assume_role_policy = <<EOF
4+
{
5+
"Version": "2012-10-17",
6+
"Statement": [
7+
{
8+
"Action": "sts:AssumeRole",
9+
"Principal": {
10+
"AWS": "${var.administrator_role_arn}"
11+
},
12+
"Effect": "Allow",
13+
"Sid": ""
14+
}
15+
]
16+
}
17+
EOF
18+
}
19+
20+
# See https://github.com/z0ph/MAMIP/blob/master/policies/AWSSupportAccess
21+
resource "aws_iam_role_policy_attachment" "aws_support_access" {
22+
role = aws_iam_role.aws_support_access.id
23+
policy_arn = "arn:aws:iam::aws:policy/AWSSupportAccess"
24+
}

modules/compliant-account/iam.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
resource "aws_iam_account_password_policy" "strict" {
2+
minimum_password_length = 32
3+
require_lowercase_characters = true
4+
require_numbers = true
5+
require_uppercase_characters = true
6+
require_symbols = true
7+
allow_users_to_change_password = true
8+
9+
password_reuse_prevention = 24
10+
max_password_age = 90
11+
}

modules/compliant-account/main.tf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
terraform {
2+
required_providers {
3+
aws = {
4+
source = "hashicorp/aws"
5+
version = "~> 5.10"
6+
}
7+
}
8+
9+
required_version = ">= 1.2.0"
10+
}
11+
12+
provider "aws" {
13+
region = "us-east-1"
14+
15+
assume_role {
16+
role_arn = "arn:aws:iam::053562908965:role/administrator"
17+
}
18+
19+
default_tags {
20+
tags = {
21+
ManagedBy = "terraform"
22+
}
23+
}
24+
}

modules/compliant-account/output.tf

Whitespace-only changes.

modules/compliant-account/prowler.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# For now, prowler is run by hand as a user via the administrator role. In the future,
2+
# this should be run on a schedule, by a prowler role with dedicated read-only
3+
# permissions and write permissions to Security. See the SecurityAudit policy.
4+
5+
resource "aws_securityhub_product_subscription" "prowler" {
6+
product_arn = "arn:aws:securityhub:us-east-1::product/prowler/prowler"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
variable "administrator_role_arn" {
2+
type = string
3+
}
4+
5+
variable "kms_key_arn" {
6+
type = string
7+
}

modules/compliant-account/vpc.tf

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Manage the default resources, and ensure they are appropriately locked down
2+
3+
data "aws_availability_zones" "available" {
4+
state = "available"
5+
}
6+
7+
# tfsec:ignore:aws-vpc-no-default-vpc
8+
# tfsec:ignore:aws-ec2-require-vpc-flow-logs-for-all-vpcs
9+
resource "aws_default_vpc" "default" {
10+
tags = {
11+
Name = "default-vpc"
12+
}
13+
}
14+
15+
# TODO(ckdake): set up vpc flow logging
16+
# resource "aws_flow_log" "default" {
17+
# log_destination = module.vpcflowlogs_s3_bucket.bucket_arn
18+
# log_destination_type = "s3"
19+
# traffic_type = "ALL"
20+
# vpc_id = aws_default_vpc.default.id
21+
# }
22+
23+
# Empty security group disables all ingress and egress traffic
24+
resource "aws_default_security_group" "default" {
25+
vpc_id = aws_default_vpc.default.id
26+
}
27+
28+
# Empty route table disables default routes
29+
resource "aws_default_route_table" "default" {
30+
default_route_table_id = aws_default_vpc.default.default_route_table_id
31+
}
32+
33+
# Empty ACL blocks all traffic on default vpc acl
34+
resource "aws_default_network_acl" "default" {
35+
default_network_acl_id = aws_default_vpc.default.default_network_acl_id
36+
tags = {
37+
Name = "default-vpc-default-acl"
38+
}
39+
40+
subnet_ids = [
41+
for default_subnet in aws_default_subnet.default_subnet : default_subnet.id
42+
]
43+
}
44+
45+
# Disable default addressing in default subnets, and name them
46+
# there are 6 azs in us-east-1. other zones have less!
47+
resource "aws_default_subnet" "default_subnet" {
48+
count = 6
49+
50+
availability_zone = element(data.aws_availability_zones.available.names[*], count.index)
51+
map_public_ip_on_launch = false
52+
53+
tags = {
54+
Name = "default-subnet"
55+
}
56+
}
57+
58+
resource "aws_ebs_default_kms_key" "aws_ebs_default_kms_key" {
59+
key_arn = var.kms_key_arn
60+
}
61+
62+
resource "aws_ebs_encryption_by_default" "aws_ebs_encryption_by_default" {
63+
enabled = true
64+
}

tenants/management/access-analyzer.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
resource "aws_accessanalyzer_analyzer" "aws_accessanalyzer_analyzer" {
2+
analyzer_name = "organization"
3+
type = "ORGANIZATION"
4+
}

tenants/management/iam.tf

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,3 @@
1-
resource "aws_iam_account_password_policy" "strict" {
2-
minimum_password_length = 32
3-
require_lowercase_characters = true
4-
require_numbers = true
5-
require_uppercase_characters = true
6-
require_symbols = true
7-
allow_users_to_change_password = true
8-
9-
password_reuse_prevention = 24
10-
max_password_age = 90
11-
}
12-
131
# Role to be used for any administrative tasks
142
data "aws_iam_policy_document" "administrator_assume_role_policy" {
153
statement {

tenants/management/main.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,10 @@ provider "aws" {
3131
}
3232
}
3333
}
34+
35+
module "compliant-account" {
36+
source = "../../modules/compliant-account"
37+
38+
administrator_role_arn = aws_iam_role.administrator.arn
39+
kms_key_arn = aws_kms_key.management.arn
40+
}

tenants/management/organization.tf

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
resource "aws_organizations_organization" "root" {
22
aws_service_access_principals = [
3-
"securityhub.amazonaws.com"
3+
"access-analyzer.amazonaws.com",
4+
"securityhub.amazonaws.com",
5+
"sso.amazonaws.com"
46
]
57

68
feature_set = "ALL"
79
}
810

911
resource "aws_organizations_account" "management" {
10-
name = "management"
11-
12-
parent_id = aws_organizations_organization.root.id
12+
name = "management"
13+
14+
parent_id = aws_organizations_organization.root.id
1315
}
1416

1517
resource "aws_organizations_organizational_unit" "test" {
@@ -18,13 +20,13 @@ resource "aws_organizations_organizational_unit" "test" {
1820
}
1921

2022
resource "aws_organizations_account" "test1" {
21-
name = "test1"
22-
23-
parent_id = aws_organizations_organizational_unit.test.id
23+
name = "test1"
24+
25+
parent_id = aws_organizations_organizational_unit.test.id
2426
}
2527

2628
resource "aws_organizations_account" "test2" {
27-
name = "test2"
28-
29-
parent_id = aws_organizations_organizational_unit.test.id
30-
}
29+
name = "test2"
30+
31+
parent_id = aws_organizations_organizational_unit.test.id
32+
}

tools/prowler/allowlist.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# See https://docs.prowler.cloud/en/latest/tutorials/allowlist/
2+
Allowlist:
3+
Accounts:
4+
"*":
5+
Checks:
6+
"fake_check":
7+
Regions:
8+
- "*"
9+
Resources:
10+
- "fake-resource"

tools/prowler/install-prowler.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
set -eou pipefail
4+
5+
pip install prowler

tools/prowler/run-prowler.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/bin/bash
2+
3+
set -eou pipefail
4+
5+
ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
6+
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)
7+
8+
AWS_ACCESS_KEY_ID=$(echo "$CREDENTIALS" | cut -f 1)
9+
AWS_SECRET_ACCESS_KEY=$(echo "$CREDENTIALS" | cut -f 2)
10+
AWS_SESSION_TOKEN=$(echo "$CREDENTIALS" | cut -f 3)
11+
export AWS_ACCESS_KEY_ID
12+
export AWS_SECRET_ACCESS_KEY
13+
export AWS_SESSION_TOKEN
14+
15+
prowler aws --region us-east-1 \
16+
--allowlist-file allowlist.yaml \
17+
--output-modes html \
18+
--log-level WARNING \
19+
--excluded-checks ec2_elastic_ip_shodan \
20+
--security-hub

0 commit comments

Comments
 (0)