Skip to content

Commit

Permalink
add redshift submodule
Browse files Browse the repository at this point in the history
  • Loading branch information
badra001 committed Jan 28, 2025
1 parent b97cf0e commit a00112a
Show file tree
Hide file tree
Showing 10 changed files with 415 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,5 @@
- emr
- add emr-workspace

* 2.6.0 -- 2025-01-28
- redshift: new submodule
2 changes: 1 addition & 1 deletion common/version.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
locals {
_module_version = "2.5.2"
_module_version = "2.6.0"
}
90 changes: 90 additions & 0 deletions redshift/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# About redshift

This describes how to use the aws-common-security-groups submodule for redshift.

Default and auxilliary ports are included in this. They are opened to everything.

## Usage

```hcl
module "redshift" {
source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//redshift?ref=tf-ugprade"
vpc_id = var.vpc_id
## optional
# name = "m-redshift"
# ingress_prefix_list_names = [ "wifi-networks.core", "vpn-networks.core" ]
# egress_prefix_list_names = [ ]
## tags for Name, CostAllocation, and Environment are pre-set, but they can be overriden
# tags = { }
}
```

## ingress\_networks
This is the list of network CIDR blocks for inbound access to the ports defined for Redshift.
There is a default set of CIDR blocks provided if this field is not populated. This is comprised of the
Census networks:
* 148.129.0.0/16: Census class B
* 172.16.0.0/12: Census private class B
* 192.168.0.0/16: Census private class C
* 10.0.0.0/8: Census private class A

Passing a null or empty list to this field will ignore the ingress setting on these networks.

## ingress\_prefix\_list\_names
In order to use a managed prefix list, you may pass a list of names in this field. The prefix lists
will be looked up and the resultant IDs used in the security group for inbound port access to Redshift.
This will fail if the prefix list does not exist.

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_security_group.this_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_ec2_managed_prefix_list.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source |
| [aws_ec2_managed_prefix_list.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ec2_managed_prefix_list) | data source |
| [aws_vpc.this_vpc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_description"></a> [description](#input\_description) | Security Group Description | `string` | `"Redshift Security Group"` | no |
| <a name="input_egress_networks"></a> [egress\_networks](#input\_egress\_networks) | List of egress networks (all ports) | `list(string)` | <pre>[<br/> "0.0.0.0/0"<br/>]</pre> | no |
| <a name="input_egress_prefix_list_names"></a> [egress\_prefix\_list\_names](#input\_egress\_prefix\_list\_names) | List of prefix list names for eggress access | `list(string)` | `[]` | no |
| <a name="input_egress_security_groups"></a> [egress\_security\_groups](#input\_egress\_security\_groups) | List of egress security groups (all ports) | `list(string)` | `[]` | no |
| <a name="input_enable_self"></a> [enable\_self](#input\_enable\_self) | Enable\|Disable self full access | `bool` | `false` | no |
| <a name="input_ingress_networks"></a> [ingress\_networks](#input\_ingress\_networks) | List of ingress networks for external access (not all ports). Use null to disable built-in settings | `list(string)` | <pre>[<br/> "0.0.0.0/0"<br/>]</pre> | no |
| <a name="input_ingress_prefix_list_names"></a> [ingress\_prefix\_list\_names](#input\_ingress\_prefix\_list\_names) | List of prefix list names for ingress access | `list(string)` | `[]` | no |
| <a name="input_ingress_security_groups"></a> [ingress\_security\_groups](#input\_ingress\_security\_groups) | List of ingress security groups for all ports | `list(string)` | `[]` | no |
| <a name="input_name"></a> [name](#input\_name) | Security Group Name | `string` | `"m-redshift"` | no |
| <a name="input_short_description"></a> [short\_description](#input\_short\_description) | Security Group Short Description | `string` | `"redshift"` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Extra security group tags | `map` | <pre>{<br/> "CostAllocation": "csvd:infrastructure",<br/> "Environment": "csvd-infrastructure"<br/>}</pre> | no |
| <a name="input_use_vpc_cidr"></a> [use\_vpc\_cidr](#input\_use\_vpc\_cidr) | Enable\|Disable use of VPC CIDR block in the ingress\_networks | `bool` | `false` | no |
| <a name="input_vpc_full_name"></a> [vpc\_full\_name](#input\_vpc\_full\_name) | VPC Name | `string` | `""` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID Number | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_this_security_group_arn"></a> [this\_security\_group\_arn](#output\_this\_security\_group\_arn) | Created security group ARN |
| <a name="output_this_security_group_id"></a> [this\_security\_group\_id](#output\_this\_security\_group\_id) | Created security group ID |
15 changes: 15 additions & 0 deletions redshift/data.prefix_lists.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
data "aws_ec2_managed_prefix_list" "ingress" {
for_each = toset(var.ingress_prefix_list_names)
filter {
name = "prefix-list-name"
values = [each.key]
}
}

data "aws_ec2_managed_prefix_list" "egress" {
for_each = toset(var.egress_prefix_list_names)
filter {
name = "prefix-list-name"
values = [each.key]
}
}
172 changes: 172 additions & 0 deletions redshift/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**
* # About redshift
*
* This describes how to use the aws-common-security-groups submodule for redshift.
*
* Default and auxilliary ports are included in this. They are opened to everything.
*
* ## Usage
*
* ```hcl
* module "redshift" {
* source = "git@github.e.it.census.gov:terraform-modules/aws-common-security-groups.git//redshift?ref=tf-ugprade"
*
* vpc_id = var.vpc_id
* ## optional
* # name = "m-redshift"
* # ingress_prefix_list_names = [ "wifi-networks.core", "vpn-networks.core" ]
* # egress_prefix_list_names = [ ]
*
* ## tags for Name, CostAllocation, and Environment are pre-set, but they can be overriden
* # tags = { }
* }
* ```
*
* ## ingress_networks
* This is the list of network CIDR blocks for inbound access to the ports defined for Redshift.
* There is a default set of CIDR blocks provided if this field is not populated. This is comprised of the
* Census networks:
* * 148.129.0.0/16: Census class B
* * 172.16.0.0/12: Census private class B
* * 192.168.0.0/16: Census private class C
* * 10.0.0.0/8: Census private class A
*
* Passing a null or empty list to this field will ignore the ingress setting on these networks.
*
* ## ingress_prefix_list_names
* In order to use a managed prefix list, you may pass a list of names in this field. The prefix lists
* will be looked up and the resultant IDs used in the security group for inbound port access to Redshift.
* This will fail if the prefix list does not exist.
*/

data "aws_vpc" "this_vpc" {
count = var.use_vpc_cidr ? 1 : 0
id = var.vpc_id
}

## data "aws_security_group" "ingress_security_groups" {
## for_each = toset(var.ingress_security_groups))
## id = each.key
## }
##
## data "aws_security_group" "egress_security_groups" {
## for_each = toset(var.egress_security_groups)
## id = each.key
## }

locals {
vpc_networks = var.use_vpc_cidr ? [data.aws_vpc.this_vpc[0].cidr_block] : []
external_ingress_networks = compact(concat(local.vpc_networks, local.ingress_networks))
## ingress_sg_names = zipmap(var.ingress_security_groups, data.aws_security_group.ingress_security_groups[*].name)
## egress_sg_names = zipmap(var.egress_security_groups, data.aws_security_group.egress_security_groups[*].name)
## self = var.enable_self ? [1] : []
short_description = var.short_description == "" ? var.description : var.short_description
}

resource "aws_security_group" "this_security_group" {
name = local.name
description = var.description
vpc_id = var.vpc_id

# ingresss external port list (list + vpc if enabaled)
dynamic "ingress" {
for_each = (var.ingress_networks != null && length(local.ingress_networks) > 0) ? local.port_map["external"] : toset([])
iterator = p
content {
description = "${local.short_description}: ${p.value["description"]}"
from_port = p.value["from"]
to_port = p.value["to"]
protocol = p.value["proto"]
cidr_blocks = length(local.external_ingress_networks) > 0 ? local.external_ingress_networks : p.value["cidr"]
}
}


# ingress with prefix lists
dynamic "ingress" {
for_each = length(var.ingress_prefix_list_names) > 0 ? local.port_map["external"] : toset([])
iterator = p
content {
description = "${local.short_description}: ${p.value["description"]}"
from_port = p.value["from"]
to_port = p.value["to"]
protocol = p.value["proto"]
prefix_list_ids = [for pl in data.aws_ec2_managed_prefix_list.ingress : pl.id]
}
}


# ingress security group ids (just defined ports)
dynamic "ingress" {
for_each = length(local.ingress_sg) > 0 ? local.port_map["external"] : toset([])
iterator = p
content {
description = "${local.short_description}: ${p.value["description"]}"
from_port = p.value["from"]
to_port = p.value["to"]
protocol = p.value["proto"]
security_groups = local.ingress_sg
}
}


# ingress self (list with one or zero items)
dynamic "ingress" {
for_each = var.enable_self ? local.port_map["external"] : toset([])
iterator = p
content {
description = "${local.short_description}: ${p.value["description"]}"
from_port = p.value["from"]
to_port = p.value["to"]
protocol = p.value["proto"]
self = true
}
}


# egress all
# for_each = (var.egress_networks != null && length(local.egress_networks) > 0) ? local.port_map["external"] : toset([])
egress {
description = "${local.short_description}: All"
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = local.egress_networks
}

# egress security group ids (all)
dynamic "egress" {
for_each = length(local.egress_sg) > 0 ? { 1 = 1 } : {}
iterator = sg
content {
description = "${local.short_description}"
from_port = 0
to_port = 0
protocol = -1
security_groups = local.egress_sg
}
}

# egress with prefix lists
dynamic "egress" {
for_each = length(var.egress_prefix_list_names) > 0 ? { 1 = 1 } : {}
iterator = p
content {
description = "${local.short_description}"
from_port = 0
to_port = 0
protocol = -1
prefix_list_ids = [for pl in data.aws_ec2_managed_prefix_list.egress : pl.id]
}
}

tags = merge(
var.tags,
{
"Name" = "sg-${local.name}"
"boc:created_by" = "terraform"
"boc:tf_module_version" = local._module_version
"boc:vpc:info" = join(" ", compact([var.vpc_id, var.vpc_full_name]))
}
)
}
9 changes: 9 additions & 0 deletions redshift/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "this_security_group_id" {
description = "Created security group ID"
value = aws_security_group.this_security_group.id
}

output "this_security_group_arn" {
description = "Created security group ARN"
value = aws_security_group.this_security_group.arn
}
33 changes: 33 additions & 0 deletions redshift/ports.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ports = list of list of
# from_port
# to_port
# proto
# description
# cidr_block
# list of: all, external (more added as needed)

locals {
description = "module: Redshift"
n_all = ["0.0.0.0/0"]
n_census = ["148.129.0.0/16", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"]
source_groups = ["all", "external"]

name = var.name
ports = [
[5439, 5439, "tcp", "redshift", local.n_census, ["external"]],
]

# these are ignored
ingress_networks = var.ingress_networks == null ? [] : var.ingress_networks
egress_networks = var.egress_networks == null ? [] : var.egress_networks

# these are ignored
ingress_sg = var.ingress_security_groups
egress_sg = var.egress_security_groups

p_fields = ["from", "to", "proto", "description", "cidr", "source_group"]
p_map = [for p in local.ports : zipmap(local.p_fields, p)]
port_map = { for s in local.source_groups :
s => [for p in local.p_map : p if contains(p["source_group"], s)]
}
}
Loading

0 comments on commit a00112a

Please sign in to comment.