Skip to content

Commit

Permalink
Add support for VPC Endpoints in AWS pre-reqs (#24)
Browse files Browse the repository at this point in the history
Signed-off-by: Jim Enright <[email protected]>
  • Loading branch information
jimright authored Aug 16, 2023
1 parent a6b5a20 commit e83dddb
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
14 changes: 14 additions & 0 deletions modules/terraform-cdp-aws-pre-reqs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,20 @@ In each directory an example `terraform.tfvars.sample` values file is included t
| [aws_s3_object.cdp_backup_storage_object](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/s3_object) | resource |
| [aws_s3_object.cdp_log_storage_object](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/s3_object) | resource |
| [aws_security_group.cdp_default_sg](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group) | resource |
| [aws_security_group.cdp_endpoint_sg](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group) | resource |
| [aws_security_group.cdp_knox_sg](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group) | resource |
| [aws_security_group_rule.cdp_default_sg_egress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_default_sg_ingress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_default_sg_ingress_self](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_endpoint_ingress_self](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_endpoint_sg_egress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_endpoint_sg_ingress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_knox_sg_egress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_knox_sg_ingress](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.cdp_knox_sg_ingress_self](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/security_group_rule) | resource |
| [aws_vpc_endpoint.gateway_endpoints](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/vpc_endpoint) | resource |
| [aws_vpc_endpoint.interface_endpoints](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/vpc_endpoint) | resource |
| [aws_vpc_endpoint.s3_global_interface_endpoint](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/resources/vpc_endpoint) | resource |
| [random_id.bucket_suffix](https://registry.terraform.io/providers/hashicorp/random/3.4.3/docs/resources/id) | resource |
| [time_sleep.iam_propagation](https://registry.terraform.io/providers/hashicorp/time/0.9.1/docs/resources/sleep) | resource |
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/caller_identity) | data source |
Expand All @@ -97,6 +104,8 @@ In each directory an example `terraform.tfvars.sample` values file is included t
| [aws_iam_policy_document.cdp_xaccount_role_policy_doc](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/iam_policy_document) | data source |
| [aws_subnets.vpc_subnets](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/subnets) | data source |
| [aws_vpc.cdp_vpc](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/vpc) | data source |
| [aws_vpc_endpoint_service.gateway_endpoints](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/vpc_endpoint_service) | data source |
| [aws_vpc_endpoint_service.interface_endpoints](https://registry.terraform.io/providers/hashicorp/aws/4.67.0/docs/data-sources/vpc_endpoint_service) | data source |
| [http_http.bucket_access_policy_doc](https://registry.terraform.io/providers/hashicorp/http/3.2.1/docs/data-sources/http) | data source |
| [http_http.datalake_admin_s3_policy_doc](https://registry.terraform.io/providers/hashicorp/http/3.2.1/docs/data-sources/http) | data source |
| [http_http.datalake_backup_policy_doc](https://registry.terraform.io/providers/hashicorp/http/3.2.1/docs/data-sources/http) | data source |
Expand All @@ -119,11 +128,13 @@ In each directory an example `terraform.tfvars.sample` values file is included t
| <a name="input_bucket_access_policy_doc"></a> [bucket\_access\_policy\_doc](#input\_bucket\_access\_policy\_doc) | Bucket Access Data Access Policy | `string` | `null` | no |
| <a name="input_bucket_access_policy_name"></a> [bucket\_access\_policy\_name](#input\_bucket\_access\_policy\_name) | Bucket Access Data Access Policy Name | `string` | `null` | no |
| <a name="input_cdp_default_sg_egress_cidrs"></a> [cdp\_default\_sg\_egress\_cidrs](#input\_cdp\_default\_sg\_egress\_cidrs) | List of egress CIDR blocks for CDP Default Security Group Egress rule | `list(string)` | <pre>[<br> "0.0.0.0/0"<br>]</pre> | no |
| <a name="input_cdp_endpoint_sg_egress_cidrs"></a> [cdp\_endpoint\_sg\_egress\_cidrs](#input\_cdp\_endpoint\_sg\_egress\_cidrs) | List of egress CIDR blocks for VPC Endpoint Security Group Egress rule | `list(string)` | <pre>[<br> "0.0.0.0/0"<br>]</pre> | no |
| <a name="input_cdp_knox_sg_egress_cidrs"></a> [cdp\_knox\_sg\_egress\_cidrs](#input\_cdp\_knox\_sg\_egress\_cidrs) | List of egress CIDR blocks for CDP Knox Security Group Egress rule | `list(string)` | <pre>[<br> "0.0.0.0/0"<br>]</pre> | no |
| <a name="input_cdp_private_subnet_ids"></a> [cdp\_private\_subnet\_ids](#input\_cdp\_private\_subnet\_ids) | List of private subnet ids. Required if create\_vpc is false. | `list(any)` | `null` | no |
| <a name="input_cdp_public_subnet_ids"></a> [cdp\_public\_subnet\_ids](#input\_cdp\_public\_subnet\_ids) | List of public subnet ids. Required if create\_vpc is false. | `list(any)` | `null` | no |
| <a name="input_cdp_vpc_id"></a> [cdp\_vpc\_id](#input\_cdp\_vpc\_id) | VPC ID for CDP environment. Required if create\_vpc is false. | `string` | `null` | no |
| <a name="input_create_vpc"></a> [create\_vpc](#input\_create\_vpc) | Flag to specify if the VPC should be created | `bool` | `true` | no |
| <a name="input_create_vpc_endpoints"></a> [create\_vpc\_endpoints](#input\_create\_vpc\_endpoints) | Flag to specify if VPC Endpoints should be created | `bool` | `true` | no |
| <a name="input_data_storage"></a> [data\_storage](#input\_data\_storage) | Data storage locations for CDP environment | <pre>object({<br> data_storage_bucket = string<br> data_storage_object = string<br> })</pre> | `null` | no |
| <a name="input_datalake_admin_role_name"></a> [datalake\_admin\_role\_name](#input\_datalake\_admin\_role\_name) | Datalake Admin role Name | `string` | `null` | no |
| <a name="input_datalake_admin_s3_policy_doc"></a> [datalake\_admin\_s3\_policy\_doc](#input\_datalake\_admin\_s3\_policy\_doc) | Location or Contents of Datalake Admin S3 Data Access Policy | `string` | `null` | no |
Expand All @@ -147,8 +158,11 @@ In each directory an example `terraform.tfvars.sample` values file is included t
| <a name="input_ranger_audit_s3_policy_doc"></a> [ranger\_audit\_s3\_policy\_doc](#input\_ranger\_audit\_s3\_policy\_doc) | Location or Contents of Ranger S3 Audit Data Access Policy | `string` | `null` | no |
| <a name="input_ranger_audit_s3_policy_name"></a> [ranger\_audit\_s3\_policy\_name](#input\_ranger\_audit\_s3\_policy\_name) | Ranger S3 Audit Data Access Policy Name | `string` | `null` | no |
| <a name="input_security_group_default_name"></a> [security\_group\_default\_name](#input\_security\_group\_default\_name) | Default Security Group for CDP environment | `string` | `null` | no |
| <a name="input_security_group_endpoint_name"></a> [security\_group\_endpoint\_name](#input\_security\_group\_endpoint\_name) | Security Group for VPC Endpoints | `string` | `null` | no |
| <a name="input_security_group_knox_name"></a> [security\_group\_knox\_name](#input\_security\_group\_knox\_name) | Knox Security Group for CDP environment | `string` | `null` | no |
| <a name="input_vpc_cidr"></a> [vpc\_cidr](#input\_vpc\_cidr) | VPC CIDR Block | `string` | `"10.10.0.0/16"` | no |
| <a name="input_vpc_endpoint_gateway_services"></a> [vpc\_endpoint\_gateway\_services](#input\_vpc\_endpoint\_gateway\_services) | List of AWS services used for VPC Gateway Endpoints | `list(string)` | <pre>[<br> "s3"<br>]</pre> | no |
| <a name="input_vpc_endpoint_interface_services"></a> [vpc\_endpoint\_interface\_services](#input\_vpc\_endpoint\_interface\_services) | List of AWS services used for VPC Interface Endpoints | `list(string)` | <pre>[<br> "sts",<br> "rds",<br> "elasticloadbalancing",<br> "elasticfilesystem",<br> "eks",<br> "ecr.dkr",<br> "ecr.api",<br> "ec2",<br> "cloudformation",<br> "autoscaling"<br>]</pre> | no |
| <a name="input_xaccount_account_policy_doc"></a> [xaccount\_account\_policy\_doc](#input\_xaccount\_account\_policy\_doc) | Location of cross acount policy document | `string` | `null` | no |
| <a name="input_xaccount_policy_name"></a> [xaccount\_policy\_name](#input\_xaccount\_policy\_name) | Cross Account Policy name | `string` | `null` | no |
| <a name="input_xaccount_role_name"></a> [xaccount\_role\_name](#input\_xaccount\_role\_name) | Cross account Assume role Name | `string` | `null` | no |
Expand Down
16 changes: 16 additions & 0 deletions modules/terraform-cdp-aws-pre-reqs/data.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,22 @@ data "aws_subnets" "vpc_subnets" {
}
}

# Find details about S3 Gateway endpoint services
data "aws_vpc_endpoint_service" "gateway_endpoints" {
for_each = toset(var.vpc_endpoint_gateway_services)

service = each.key
service_type = "Gateway"
}

# Find details about S3 Gateway endpoint services
data "aws_vpc_endpoint_service" "interface_endpoints" {
for_each = toset(var.vpc_endpoint_interface_services)

service = each.key
service_type = "Interface"
}

# HTTP get request to download policy documents
# ..Cross Account Policy
data "http" "xaccount_account_policy_doc" {
Expand Down
2 changes: 2 additions & 0 deletions modules/terraform-cdp-aws-pre-reqs/defaults.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ locals {

security_group_knox_name = coalesce(var.security_group_knox_name, "${var.env_prefix}-knox-sg")

security_group_endpoint_name = coalesce(var.security_group_endpoint_name, "${var.env_prefix}-endpoint-sg")

security_group_rules_ingress = [
{
# CIDR ingress
Expand Down
104 changes: 104 additions & 0 deletions modules/terraform-cdp-aws-pre-reqs/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,110 @@ resource "aws_security_group_rule" "cdp_knox_sg_egress" {
protocol = "all"
}

# VPC Endpoint SG
resource "aws_security_group" "cdp_endpoint_sg" {

count = var.create_vpc_endpoints ? 1 : 0

vpc_id = local.vpc_id
name = local.security_group_endpoint_name
description = local.security_group_endpoint_name
tags = merge(local.env_tags, { Name = local.security_group_endpoint_name })
}

# Create self reference ingress rule to allow communication within the security group
resource "aws_security_group_rule" "cdp_endpoint_ingress_self" {

count = var.create_vpc_endpoints ? 1 : 0

security_group_id = aws_security_group.cdp_endpoint_sg[0].id
type = "ingress"
from_port = 0
to_port = 0
description = "Self-reference ingress rule"
protocol = "all"
self = true
}

# Create security group rules from combining the default and extra list of ingress rules
resource "aws_security_group_rule" "cdp_endpoint_sg_ingress" {
count = var.create_vpc_endpoints ? length(concat(local.security_group_rules_ingress, local.security_group_rules_extra_ingress)) : 0

description = "Ingress rules for Endpoint Security Group"
security_group_id = aws_security_group.cdp_endpoint_sg[0].id
type = "ingress"
cidr_blocks = tolist(concat(local.security_group_rules_ingress, local.security_group_rules_extra_ingress))[count.index].cidr
from_port = tolist(concat(local.security_group_rules_ingress, local.security_group_rules_extra_ingress))[count.index].port
to_port = tolist(concat(local.security_group_rules_ingress, local.security_group_rules_extra_ingress))[count.index].port
protocol = tolist(concat(local.security_group_rules_ingress, local.security_group_rules_extra_ingress))[count.index].protocol
}

# Terraform removes the default ALLOW ALL egress. Let's recreate this
resource "aws_security_group_rule" "cdp_endpoint_sg_egress" {

count = var.create_vpc_endpoints ? 1 : 0

description = "Egress rule for Endpoint CDP Security Group"
security_group_id = aws_security_group.cdp_endpoint_sg[0].id
type = "egress"
cidr_blocks = var.cdp_endpoint_sg_egress_cidrs
from_port = 0
to_port = 0
protocol = "all"
}

# ------- VPC Endpoints -------
# S3 Gateway endpoint
resource "aws_vpc_endpoint" "gateway_endpoints" {

for_each = {
for k, v in toset(var.vpc_endpoint_gateway_services) : k => v
if var.create_vpc_endpoints == true
}

vpc_id = local.vpc_id
service_name = data.aws_vpc_endpoint_service.gateway_endpoints[each.key].service_name
vpc_endpoint_type = "Gateway"
route_table_ids = concat([local.default_route_table_id], local.public_route_table_ids, local.private_route_table_ids)

tags = merge(local.env_tags, { Name = "${var.env_prefix}-${each.key}-gateway-endpoint" })
}

# Interface endpoints
# From list in vpc_endpoint_interface_services
resource "aws_vpc_endpoint" "interface_endpoints" {

for_each = {
for k, v in toset(var.vpc_endpoint_interface_services) : k => v
if var.create_vpc_endpoints == true
}

vpc_id = local.vpc_id
service_name = data.aws_vpc_endpoint_service.interface_endpoints[each.key].service_name
vpc_endpoint_type = "Interface"
private_dns_enabled = true

subnet_ids = concat(local.public_subnet_ids, local.private_subnet_ids)
security_group_ids = [aws_security_group.cdp_endpoint_sg[0].id]

tags = merge(local.env_tags, { Name = "${var.env_prefix}-${each.key}-interface-endpoint" })
}
# S3-Global Interface endpoint
resource "aws_vpc_endpoint" "s3_global_interface_endpoint" {

count = var.create_vpc_endpoints ? 1 : 0

vpc_id = local.vpc_id
service_name = "com.amazonaws.s3-global.accesspoint"
vpc_endpoint_type = "Interface"
private_dns_enabled = true

subnet_ids = concat(local.public_subnet_ids, local.private_subnet_ids)
security_group_ids = [aws_security_group.cdp_endpoint_sg[0].id]

tags = merge(local.env_tags, { Name = "${var.env_prefix}-s3-global-interface-endpoint" })
}

# ------- S3 Buckets -------
resource "random_id" "bucket_suffix" {
count = var.random_id_for_bucket ? 1 : 0
Expand Down
52 changes: 52 additions & 0 deletions modules/terraform-cdp-aws-pre-reqs/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ variable "security_group_knox_name" {
default = null
}

variable "security_group_endpoint_name" {
type = string

description = "Security Group for VPC Endpoints"

default = null
}

variable "ingress_extra_cidrs_and_ports" {
type = object({
cidrs = list(string)
Expand Down Expand Up @@ -170,6 +178,50 @@ variable "cdp_knox_sg_egress_cidrs" {
default = ["0.0.0.0/0"]
}

variable "cdp_endpoint_sg_egress_cidrs" {
type = list(string)

description = "List of egress CIDR blocks for VPC Endpoint Security Group Egress rule"

default = ["0.0.0.0/0"]
}

variable "create_vpc_endpoints" {
type = bool

description = "Flag to specify if VPC Endpoints should be created"

default = true
}

variable "vpc_endpoint_gateway_services" {
type = list(string)

description = "List of AWS services used for VPC Gateway Endpoints"

default = ["s3"]

}

variable "vpc_endpoint_interface_services" {
type = list(string)

description = "List of AWS services used for VPC Interface Endpoints"

default = [
"sts",
"rds",
"elasticloadbalancing",
"elasticfilesystem",
"eks",
"ecr.dkr",
"ecr.api",
"ec2",
"cloudformation",
"autoscaling",
]
}

# ------- Storage Resources -------
variable "random_id_for_bucket" {
type = bool
Expand Down

0 comments on commit e83dddb

Please sign in to comment.