Skip to content
This repository has been archived by the owner on Jul 31, 2020. It is now read-only.

Commit

Permalink
Merge pull request #8 from trussworks/mk-protect
Browse files Browse the repository at this point in the history
SCPs to protect IAM roles and S3 buckets
  • Loading branch information
Michael Kania authored Mar 9, 2020
2 parents 56f25b8 + 01a78b7 commit 6712406
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 7 deletions.
49 changes: 43 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
# AWS Organization SCP Terraform Module

Inspired by the great work documenting AWS security practices in [asecure.cloud](https://asecure.cloud/whatsnew), this module is meant to define common Service Control Policies (SCP) to apply to accounts or Organizational Units (OU) in an AWS Organization. The following policies are supported

* Deny the root user from taking any action
## Organizations

* Deny the ability for an AWS account to leave an AWS organization
* Require S3 objects be encrypted
* Deny all access to an AWS account

## IAM

* Deny the root user from taking any action
* Deny the ability to create IAM users and access keys in an AWS account
* Protect sensitive IAM roles from modification or deletion

## S3

* Protect sensitive S3 buckets from deletion

## KMS

* Deny the ability to delete KMS keys

## Route53

* Deny the ability to delete Route53 zones
* Deny all access to an AWS account
* Deny the ability to delete Cloudwatch logs

## CloudWatch Logs

* Deny the ability to delete CloudWatch Logs

## Usage

Expand Down Expand Up @@ -36,7 +56,7 @@ resource "aws_organizations_organizational_unit" "suspended" {
module "org_scps" {
source = "trussworks/org-scp/aws"
version = "~> 1.2.0"
version = "~> 1.4.0"
# applies to all accounts
# - don't allow all accounts to be able to leave the org
Expand All @@ -53,9 +73,22 @@ module "org_scps" {
# applies to all prod accounts
# - don't allow deleting KMS keys
# - don't allow deleting Route53 zones
# - don't allow deleting CloudWatch logs
# - protect terraform statefile bucket
# - protect OrganizationAccountAccessRole
deny_deleting_kms_keys_target_ids = [aws_organizations_organizational_unit.prod.id]
deny_deleting_route53_zones_target_ids = [aws_organizations_organizational_unit.prod.id]
deny_deleting_cloudwatch_logs_target_ids = [aws_organizations_organizational_unit.prod.id]
protect_s3_bucket_target_ids = [aws_organizations_organizational_unit.prod.id]
protect_iam_role_target_ids = [aws_organizations_organizational_unit.prod.id]
protect_s3_bucket_resources = [
"arn:aws:s3:::prod-terraform-state-us-west-2",
"arn:aws:s3:::prod-terraform-state-us-west-2/*"
]
protect_iam_role_resources = [
"arn:aws:iam::*:role/OrganizationAccountAccessRole"
]
# applies to all suspended accounts
# - don't allow any access
Expand All @@ -76,11 +109,15 @@ module "org_scps" {
|------|-------------|------|---------|:-----:|
| deny\_all\_access\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP dening all access | `list(string)` | `[]` | no |
| deny\_creating\_iam\_users\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying the ability to create IAM users or Access Keys | `list(string)` | `[]` | no |
| deny\_deleting\_cloudwatch\_logs\_target\_ids | Target ids (AWS Account or Organizational Unit) to delete VPC flow logs, log groups, or log streams | `list(string)` | `[]` | no |
| deny\_deleting\_cloudwatch\_logs\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying deletion of CloudWatch, flowlogs, log groups, or log streams | `list(string)` | `[]` | no |
| deny\_deleting\_kms\_keys\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying deleting KMS keys | `list(string)` | `[]` | no |
| deny\_deleting\_route53\_zones\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying deleting Route53 Hosted Zones | `list(string)` | `[]` | no |
| deny\_leaving\_orgs\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying the ability to leave the AWS Organization | `list(string)` | `[]` | no |
| deny\_root\_account\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP denying the root user from taking any action | `list(string)` | `[]` | no |
| protect\_iam\_role\_resources | IAM role resource ARNs to protect from modification and deletion | `list(string)` | <pre>[<br> ""<br>]</pre> | no |
| protect\_iam\_role\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP protecting IAM roles | `list(string)` | `[]` | no |
| protect\_s3\_bucket\_resources | S3 bucket resource ARNs to protect from bucket and object deletion | `list(string)` | <pre>[<br> ""<br>]</pre> | no |
| protect\_s3\_bucket\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP protecting S3 buckets and objects | `list(string)` | `[]` | no |
| require\_s3\_encryption\_target\_ids | Target ids (AWS Account or Organizational Unit) to attach an SCP requiring S3 encryption | `list(string)` | `[]` | no |

## Outputs
Expand Down
69 changes: 69 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,72 @@ resource "aws_organizations_policy_attachment" "deny_deleting_cloudwatch_logs" {
policy_id = aws_organizations_policy.deny_deleting_cloudwatch_logs.id
target_id = element(var.deny_deleting_cloudwatch_logs_target_ids.*, count.index)
}

#
# Protect S3 Buckets
#

data "aws_iam_policy_document" "protect_s3_buckets" {
statement {
effect = "Deny"
actions = [
"s3:DeleteBucket",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
]
resources = var.protect_s3_bucket_resources
}
}

resource "aws_organizations_policy" "protect_s3_buckets" {
count = length(var.protect_s3_bucket_target_ids)
name = "protect-s3-buckets"
description = "Protect S3 buckets form bucket and object deletion"
content = data.aws_iam_policy_document.protect_s3_buckets.json
}

resource "aws_organizations_policy_attachment" "protect_s3_buckets" {
count = length(var.protect_s3_bucket_target_ids)

policy_id = aws_organizations_policy.protect_s3_buckets[0].id
target_id = element(var.protect_s3_bucket_target_ids.*, count.index)
}

#
# Protect IAM roles
#

data "aws_iam_policy_document" "protect_iam_roles" {
statement {
effect = "Deny"
actions = [
"iam:AttachRolePolicy",
"iam:DeleteRole",
"iam:DeleteRolePermissionsBoundary",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:PutRolePermissionsBoundary",
"iam:PutRolePolicy",
"iam:UpdateAssumeRolePolicy",
"iam:UpdateRole",
"iam:UpdateRoleDescription"
]
resources = var.protect_iam_role_resources
}
}

resource "aws_organizations_policy" "protect_iam_roles" {
count = length(var.protect_iam_role_target_ids)

name = "protect-iam-roles"
description = "Protect IAM roles from modification or deletion"
content = data.aws_iam_policy_document.protect_iam_roles.json
}

resource "aws_organizations_policy_attachment" "protect_iam_roles" {
count = length(var.protect_iam_role_target_ids)

policy_id = aws_organizations_policy.protect_iam_roles[0].id
target_id = element(var.protect_iam_role_target_ids.*, count.index)
}

26 changes: 25 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,31 @@ variable "require_s3_encryption_target_ids" {
}

variable "deny_deleting_cloudwatch_logs_target_ids" {
description = "Target ids (AWS Account or Organizational Unit) to delete VPC flow logs, log groups, or log streams"
description = "Target ids (AWS Account or Organizational Unit) to attach an SCP denying deletion of CloudWatch, flowlogs, log groups, or log streams"
type = list(string)
default = []
}

variable "protect_s3_bucket_target_ids" {
description = "Target ids (AWS Account or Organizational Unit) to attach an SCP protecting S3 buckets and objects"
type = list(string)
default = []
}

variable "protect_s3_bucket_resources" {
description = "S3 bucket resource ARNs to protect from bucket and object deletion"
type = list(string)
default = [""]
}

variable "protect_iam_role_target_ids" {
description = "Target ids (AWS Account or Organizational Unit) to attach an SCP protecting IAM roles"
type = list(string)
default = []
}

variable "protect_iam_role_resources" {
description = "IAM role resource ARNs to protect from modification and deletion"
type = list(string)
default = [""]
}

0 comments on commit 6712406

Please sign in to comment.