Commit 42cf8d14 authored by Nuru's avatar Nuru Committed by GitHub

Upgrade to new securty-group standards (#133)

parent 262608ba
This diff is collapsed.
...@@ -10,12 +10,11 @@ name: terraform-aws-elasticache-redis ...@@ -10,12 +10,11 @@ name: terraform-aws-elasticache-redis
# Tags of this project # Tags of this project
tags: tags:
- aws - aws
- terraform
- terraform-modules
- databases
- redis
- elasticache
- cache - cache
- elasticache
- elasticache-redis
- terraform
- terraform-module
# Categories of this project # Categories of this project
categories: categories:
...@@ -41,17 +40,37 @@ badges: ...@@ -41,17 +40,37 @@ badges:
# List any related terraform modules that this module may be used with or that this module depends on. # List any related terraform modules that this module may be used with or that this module depends on.
related: related:
- name: "terraform-aws-security-group"
description: "Terraform module to provision an AWS Security Group."
url: "https://github.com/cloudposse/terraform-aws-security-group"
- name: "terraform-null-label" - name: "terraform-null-label"
description: "Terraform module designed to generate consistent names and tags for resources. Use terraform-null-label to implement a strict naming convention." description: "Terraform module designed to generate consistent names and tags for resources. Use terraform-null-label to implement a strict naming convention."
url: "https://github.com/cloudposse/terraform-null-label" url: "https://github.com/cloudposse/terraform-null-label"
# Short description of this project # Short description of this project
description: |- description: |-
Terraform module to provision an [`ElastiCache`](https://aws.amazon.com/elasticache/) Redis Cluster Terraform module to provision an [`ElastiCache`](https://aws.amazon.com/elasticache/) Redis Cluster
# How to use this project # How to use this project
usage: |- usage: |-
Note that this uses secure defaults. One of the ways this module can trip users up is with `transit_encryption_enabled` which is `true` by default. With this enabled, one does not simply `redis-cli` in without setting up an `stunnel`. Amazon provides [good docs on how to connect with it enabled](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html#connect-tls). If this is not desired behavior, set `transit_encryption_enabled=false`. Note that this uses secure defaults. One of the ways this module can trip users up is with `transit_encryption_enabled`
which is `true` by default. With this enabled, one does not simply `redis-cli` in without setting up an `stunnel`.
Amazon provides [good documentation on how to connect with it enabled](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html#connect-tls).
If this is not desired behavior, set `transit_encryption_enabled=false`.
This module creates, by default, a new security group for the Elasticache Redis Cluster. When a configuration
change (for example, a different security group name) cannot be applied to the security group, Terraform will
replace that security group with a new one with the new configuration. In order to allow Terraform to fully manage the security group, you
should not place any other resources in (or associate any other resources with) the security group this module
creates. Also, in order to keep things from breaking when this module replaces the security group, you should
not reference the created security group anywhere else (such as in rules in other security groups). If you
want to associate the cluster with a more stable security group that you can reference elsewhere, create that security group
outside this module (perhaps with [terraform-aws-security-group](https://github.com/cloudposse/terraform-aws-security-group))
and pass the security group ID in via `associated_security_group_ids`.
**Note about `zone_id`**: Previously, `zone_id` was a string. This caused problems (see [#82](https://github.com/cloudposse/terraform-aws-elasticache-redis/issues/82)).
Now `zone_id` should be supplied as a `list(string)`, either empty or with exactly 1 zone ID in order to avoid the problem.
For a complete example, see [examples/complete](examples/complete). For a complete example, see [examples/complete](examples/complete).
...@@ -62,41 +81,49 @@ usage: |- ...@@ -62,41 +81,49 @@ usage: |-
region = var.region region = var.region
} }
module "vpc" { module "this" {
source = "cloudposse/vpc/aws" source = "cloudposse/label/null"
# Cloud Posse recommends pinning every module to a specific version # Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x" # version = "x.x.x"
namespace = var.namespace namespace = var.namespace
stage = var.stage stage = var.stage
name = var.name name = var.name
}
module "vpc" {
source = "cloudposse/vpc/aws"
# Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x"
cidr_block = "172.16.0.0/16" cidr_block = "172.16.0.0/16"
context = module.this.context
} }
module "subnets" { module "subnets" {
source = "cloudposse/dynamic-subnets/aws" source = "cloudposse/dynamic-subnets/aws"
# Cloud Posse recommends pinning every module to a specific version # Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x" # version = "x.x.x"
availability_zones = var.availability_zones availability_zones = var.availability_zones
namespace = var.namespace
stage = var.stage
name = var.name
vpc_id = module.vpc.vpc_id vpc_id = module.vpc.vpc_id
igw_id = module.vpc.igw_id igw_id = module.vpc.igw_id
cidr_block = module.vpc.vpc_cidr_block cidr_block = module.vpc.vpc_cidr_block
nat_gateway_enabled = true nat_gateway_enabled = true
nat_instance_enabled = false nat_instance_enabled = false
context = module.this.context
} }
module "redis" { module "redis" {
source = "cloudposse/elasticache-redis/aws" source = "cloudposse/elasticache-redis/aws"
# Cloud Posse recommends pinning every module to a specific version # Cloud Posse recommends pinning every module to a specific version
# version = "x.x.x" # version = "x.x.x"
availability_zones = var.availability_zones availability_zones = var.availability_zones
namespace = var.namespace
stage = var.stage
name = var.name
zone_id = var.zone_id zone_id = var.zone_id
vpc_id = module.vpc.vpc_id vpc_id = module.vpc.vpc_id
allowed_security_group_ids = [module.vpc.vpc_default_security_group_id]
subnets = module.subnets.private_subnet_ids subnets = module.subnets.private_subnet_ids
cluster_size = var.cluster_size cluster_size = var.cluster_size
instance_type = var.instance_type instance_type = var.instance_type
...@@ -107,33 +134,14 @@ usage: |- ...@@ -107,33 +134,14 @@ usage: |-
at_rest_encryption_enabled = var.at_rest_encryption_enabled at_rest_encryption_enabled = var.at_rest_encryption_enabled
transit_encryption_enabled = var.transit_encryption_enabled transit_encryption_enabled = var.transit_encryption_enabled
security_group_rules = [
{
type = "egress"
from_port = 0
to_port = 65535
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
source_security_group_id = null
description = "Allow all outbound traffic"
},
{
type = "ingress"
from_port = 0
to_port = 65535
protocol = "-1"
cidr_blocks = []
source_security_group_id = module.vpc.vpc_default_security_group_id
description = "Allow all inbound traffic from trusted Security Groups"
},
]
parameter = [ parameter = [
{ {
name = "notify-keyspace-events" name = "notify-keyspace-events"
value = "lK" value = "lK"
} }
] ]
context = module.this.context
} }
``` ```
...@@ -160,5 +168,3 @@ contributors: ...@@ -160,5 +168,3 @@ contributors:
github: "christopherriley" github: "christopherriley"
- name: "RB" - name: "RB"
github: "nitrocode" github: "nitrocode"
- name: "Vladimir Syromyatnikov"
github: "SweetOps"
This diff is collapsed.
...@@ -10,7 +10,8 @@ stage = "test" ...@@ -10,7 +10,8 @@ stage = "test"
name = "redis-test" name = "redis-test"
instance_type = "cache.t2.micro" # Using a large instance vs a micro shaves 5-10 minutes off the run time of the test
instance_type = "cache.m6g.large"
cluster_size = 1 cluster_size = 1
......
...@@ -4,7 +4,7 @@ provider "aws" { ...@@ -4,7 +4,7 @@ provider "aws" {
module "vpc" { module "vpc" {
source = "cloudposse/vpc/aws" source = "cloudposse/vpc/aws"
version = "0.18.1" version = "0.28.0"
cidr_block = "172.16.0.0/16" cidr_block = "172.16.0.0/16"
...@@ -13,7 +13,7 @@ module "vpc" { ...@@ -13,7 +13,7 @@ module "vpc" {
module "subnets" { module "subnets" {
source = "cloudposse/dynamic-subnets/aws" source = "cloudposse/dynamic-subnets/aws"
version = "0.33.0" version = "0.39.7"
availability_zones = var.availability_zones availability_zones = var.availability_zones
vpc_id = module.vpc.vpc_id vpc_id = module.vpc.vpc_id
...@@ -25,12 +25,22 @@ module "subnets" { ...@@ -25,12 +25,22 @@ module "subnets" {
context = module.this.context context = module.this.context
} }
# Create a zone in order to validate fix for https://github.com/cloudposse/terraform-aws-elasticache-redis/issues/82
resource "aws_route53_zone" "private" {
name = format("elasticache-redis-terratest-%s.testing.cloudposse.co", try(module.this.attributes[0], "default"))
vpc {
vpc_id = module.vpc.vpc_id
}
}
module "redis" { module "redis" {
source = "../../" source = "../../"
availability_zones = var.availability_zones availability_zones = var.availability_zones
zone_id = var.zone_id zone_id = [aws_route53_zone.private.id]
vpc_id = module.vpc.vpc_id vpc_id = module.vpc.vpc_id
allowed_security_groups = [module.vpc.vpc_default_security_group_id]
subnets = module.subnets.private_subnet_ids subnets = module.subnets.private_subnet_ids
cluster_size = var.cluster_size cluster_size = var.cluster_size
instance_type = var.instance_type instance_type = var.instance_type
...@@ -42,26 +52,9 @@ module "redis" { ...@@ -42,26 +52,9 @@ module "redis" {
transit_encryption_enabled = var.transit_encryption_enabled transit_encryption_enabled = var.transit_encryption_enabled
cloudwatch_metric_alarms_enabled = var.cloudwatch_metric_alarms_enabled cloudwatch_metric_alarms_enabled = var.cloudwatch_metric_alarms_enabled
security_group_rules = [ # Verify that we can safely change security groups (name changes forces new SG)
{ security_group_create_before_destroy = true
type = "egress" security_group_name = length(var.sg_name) > 0 ? [var.sg_name] : []
from_port = 0
to_port = 65535
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
source_security_group_id = null
description = "Allow all outbound traffic"
},
{
type = "ingress"
from_port = 0
to_port = 65535
protocol = "-1"
cidr_blocks = []
source_security_group_id = module.vpc.vpc_default_security_group_id
description = "Allow all inbound traffic from trusted Security Groups"
},
]
parameter = [ parameter = [
{ {
...@@ -70,5 +63,7 @@ module "redis" { ...@@ -70,5 +63,7 @@ module "redis" {
} }
] ]
security_group_delete_timeout = "5m"
context = module.this.context context = module.this.context
} }
...@@ -18,6 +18,11 @@ output "cluster_id" { ...@@ -18,6 +18,11 @@ output "cluster_id" {
description = "Redis cluster ID" description = "Redis cluster ID"
} }
output "cluster_security_group_id" {
value = module.redis.security_group_id
description = "Cluster Security Group ID"
}
output "cluster_endpoint" { output "cluster_endpoint" {
value = module.redis.endpoint value = module.redis.endpoint
description = "Redis primary endpoint" description = "Redis primary endpoint"
...@@ -27,18 +32,3 @@ output "cluster_host" { ...@@ -27,18 +32,3 @@ output "cluster_host" {
value = module.redis.host value = module.redis.host
description = "Redis hostname" description = "Redis hostname"
} }
output "cluster_security_group_id" {
value = module.redis.security_group_id
description = "Redis Security Group ID"
}
output "cluster_security_group_arn" {
value = module.redis.security_group_arn
description = "Redis Security Group ARN"
}
output "cluster_security_group_name" {
value = module.redis.security_group_name
description = "Redis Security Group name"
}
...@@ -47,3 +47,9 @@ variable "cloudwatch_metric_alarms_enabled" { ...@@ -47,3 +47,9 @@ variable "cloudwatch_metric_alarms_enabled" {
type = bool type = bool
description = "Boolean flag to enable/disable CloudWatch metrics alarms" description = "Boolean flag to enable/disable CloudWatch metrics alarms"
} }
variable "sg_name" {
type = string
default = ""
description = "Name to give to created security group"
}
\ No newline at end of file
#
# Security Group Resources
#
locals {
enabled = module.this.enabled
legacy_egress_rule = local.use_legacy_egress ? {
key = "legacy-egress"
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = var.egress_cidr_blocks
description = "Allow outbound traffic to existing CIDR blocks"
} : null
legacy_cidr_ingress_rule = length(var.allowed_cidr_blocks) == 0 ? null : {
key = "legacy-cidr-ingress"
type = "ingress"
from_port = var.port
to_port = var.port
protocol = "tcp"
cidr_blocks = var.allowed_cidr_blocks
description = "Allow inbound traffic from CIDR blocks"
}
sg_rules = {
legacy = merge(local.legacy_egress_rule, local.legacy_cidr_ingress_rule),
extra = var.additional_security_group_rules
}
}
module "aws_security_group" {
source = "cloudposse/security-group/aws"
version = "0.4.2"
allow_all_egress = local.allow_all_egress
security_group_name = var.security_group_name
rules_map = local.sg_rules
rule_matrix = [{
key = "in"
source_security_group_ids = local.allowed_security_group_ids
cidr_blocks = var.allowed_cidr_blocks
rules = [{
key = "in"
type = "ingress"
from_port = var.port
to_port = var.port
protocol = "tcp"
description = "Selectively allow inbound traffic"
}]
}]
vpc_id = var.vpc_id
security_group_description = local.security_group_description
create_before_destroy = var.security_group_create_before_destroy
security_group_create_timeout = var.security_group_create_timeout
security_group_delete_timeout = var.security_group_delete_timeout
enabled = local.enabled && local.create_security_group
context = module.this.context
}
locals { locals {
elasticache_subnet_group_name = var.elasticache_subnet_group_name != "" ? var.elasticache_subnet_group_name : join("", aws_elasticache_subnet_group.default.*.name) elasticache_subnet_group_name = var.elasticache_subnet_group_name != "" ? var.elasticache_subnet_group_name : join("", aws_elasticache_subnet_group.default.*.name)
...@@ -11,20 +78,6 @@ locals { ...@@ -11,20 +78,6 @@ locals {
) )
elasticache_member_clusters = module.this.enabled ? tolist(aws_elasticache_replication_group.default.0.member_clusters) : [] elasticache_member_clusters = module.this.enabled ? tolist(aws_elasticache_replication_group.default.0.member_clusters) : []
security_group_enabled = module.this.enabled && var.security_group_enabled
}
module "security_group" {
source = "cloudposse/security-group/aws"
version = "0.3.1"
use_name_prefix = var.security_group_use_name_prefix
rules = var.security_group_rules
description = var.security_group_description
vpc_id = var.vpc_id
enabled = local.security_group_enabled
context = module.this.context
} }
resource "aws_elasticache_subnet_group" "default" { resource "aws_elasticache_subnet_group" "default" {
...@@ -61,19 +114,22 @@ resource "aws_elasticache_replication_group" "default" { ...@@ -61,19 +114,22 @@ resource "aws_elasticache_replication_group" "default" {
automatic_failover_enabled = var.automatic_failover_enabled automatic_failover_enabled = var.automatic_failover_enabled
multi_az_enabled = var.multi_az_enabled multi_az_enabled = var.multi_az_enabled
subnet_group_name = local.elasticache_subnet_group_name subnet_group_name = local.elasticache_subnet_group_name
security_group_ids = compact(concat(module.security_group.*.id, var.security_groups)) # It would be nice to remove duplicate security group IDs, if there are any, using `compact`,
maintenance_window = var.maintenance_window # but that causes problems, and having duplicates does not seem to cause problems.
notification_topic_arn = var.notification_topic_arn # See https://github.com/hashicorp/terraform/issues/29799
engine_version = var.engine_version security_group_ids = concat(local.associated_security_group_ids, [module.aws_security_group.id])
at_rest_encryption_enabled = var.at_rest_encryption_enabled maintenance_window = var.maintenance_window
transit_encryption_enabled = var.auth_token != null ? coalesce(true, var.transit_encryption_enabled) : var.transit_encryption_enabled notification_topic_arn = var.notification_topic_arn
kms_key_id = var.at_rest_encryption_enabled ? var.kms_key_id : null engine_version = var.engine_version
snapshot_name = var.snapshot_name at_rest_encryption_enabled = var.at_rest_encryption_enabled
snapshot_arns = var.snapshot_arns transit_encryption_enabled = var.transit_encryption_enabled || var.auth_token != null
snapshot_window = var.snapshot_window kms_key_id = var.at_rest_encryption_enabled ? var.kms_key_id : null
snapshot_retention_limit = var.snapshot_retention_limit snapshot_name = var.snapshot_name
final_snapshot_identifier = var.final_snapshot_identifier snapshot_arns = var.snapshot_arns
apply_immediately = var.apply_immediately snapshot_window = var.snapshot_window
snapshot_retention_limit = var.snapshot_retention_limit
final_snapshot_identifier = var.final_snapshot_identifier
apply_immediately = var.apply_immediately
tags = module.this.tags tags = module.this.tags
...@@ -137,10 +193,10 @@ module "dns" { ...@@ -137,10 +193,10 @@ module "dns" {
source = "cloudposse/route53-cluster-hostname/aws" source = "cloudposse/route53-cluster-hostname/aws"
version = "0.12.2" version = "0.12.2"
enabled = module.this.enabled && var.zone_id != "" ? true : false enabled = module.this.enabled && length(var.zone_id) > 0 ? true : false
dns_name = var.dns_subdomain != "" ? var.dns_subdomain : module.this.id dns_name = var.dns_subdomain != "" ? var.dns_subdomain : module.this.id
ttl = 60 ttl = 60
zone_id = var.zone_id zone_id = try(var.zone_id[0], var.zone_id)
records = var.cluster_mode_enabled ? [join("", aws_elasticache_replication_group.default.*.configuration_endpoint_address)] : [join("", aws_elasticache_replication_group.default.*.primary_endpoint_address)] records = var.cluster_mode_enabled ? [join("", aws_elasticache_replication_group.default.*.configuration_endpoint_address)] : [join("", aws_elasticache_replication_group.default.*.primary_endpoint_address)]
context = module.this.context context = module.this.context
......
...@@ -4,18 +4,13 @@ output "id" { ...@@ -4,18 +4,13 @@ output "id" {
} }
output "security_group_id" { output "security_group_id" {
value = module.security_group.id value = module.aws_security_group.id
description = "Redis Security Group ID" description = "The ID of the created security group"
}
output "security_group_arn" {
value = module.security_group.arn
description = "Redis Security Group ARN"
} }
output "security_group_name" { output "security_group_name" {
value = module.security_group.name value = module.aws_security_group.name
description = "Redis Security Group name" description = "The name of the created security group"
} }
output "port" { output "port" {
...@@ -25,7 +20,12 @@ output "port" { ...@@ -25,7 +20,12 @@ output "port" {
output "endpoint" { output "endpoint" {
value = var.cluster_mode_enabled ? join("", aws_elasticache_replication_group.default.*.configuration_endpoint_address) : join("", aws_elasticache_replication_group.default.*.primary_endpoint_address) value = var.cluster_mode_enabled ? join("", aws_elasticache_replication_group.default.*.configuration_endpoint_address) : join("", aws_elasticache_replication_group.default.*.primary_endpoint_address)
description = "Redis primary endpoint" description = "Redis primary or configuration endpoint, whichever is appropriate for the given cluster mode"
}
output "reader_endpoint_address" {
value = join("", aws_elasticache_replication_group.default.*.reader_endpoint_address)
description = "The address of the endpoint for the reader node in the replication group, if the cluster mode is disabled."
} }
output "member_clusters" { output "member_clusters" {
...@@ -37,3 +37,18 @@ output "host" { ...@@ -37,3 +37,18 @@ output "host" {
value = module.dns.hostname value = module.dns.hostname
description = "Redis hostname" description = "Redis hostname"
} }
output "arn" {
value = join("", aws_elasticache_replication_group.default.*.arn)
description = "Elasticache Replication Group ARN"
}
output "engine_version_actual" {
value = join("", aws_elasticache_replication_group.default.*.engine_version_actual)
description = "The running version of the cache engine"
}
output "cluster_enabled" {
value = join("", aws_elasticache_replication_group.default.*.cluster_enabled)
description = "Indicates if cluster mode is enabled"
}
# security_group_inputs Version: 1
##
variable "create_security_group" {
type = bool
default = true
description = "Set `true` to create and configure a new security group. If false, `associated_security_group_ids` must be provided."
}
locals {
create_security_group = var.use_existing_security_groups == null ? var.create_security_group : !var.use_existing_security_groups
}
variable "associated_security_group_ids" {
type = list(string)
default = []
description = <<-EOT
A list of IDs of Security Groups to associate the created resource with, in addition to the created security group.
These security groups will not be modified and, if `create_security_group` is `false`, must provide all the required access.
EOT
}
locals {
associated_security_group_ids = concat(var.existing_security_groups, var.associated_security_group_ids)
}
variable "allowed_security_group_ids" {
type = list(string)
default = []
description = <<-EOT
A list of IDs of Security Groups to allow access to the security group created by this module.
EOT
}
locals {
allowed_security_group_ids = concat(var.allowed_security_groups, var.allowed_security_group_ids)
}
variable "security_group_name" {
type = list(string)
default = []
description = <<-EOT
The name to assign to the created security group. Must be unique within the VPC.
If not provided, will be derived from the `null-label.context` passed in.
If `create_before_destroy` is true, will be used as a name prefix.
EOT
}
variable "security_group_description" {
type = string
default = "Security group for Elasticache Redis"
description = <<-EOT
The description to assign to the created Security Group.
Warning: Changing the description causes the security group to be replaced.
Set this to `null` to maintain parity with releases <= `0.34.0`.
EOT
}
locals {
security_group_description = var.security_group_description == null ? "Managed by Terraform" : var.security_group_description
}
variable "security_group_create_before_destroy" {
type = bool
default = true
description = <<-EOT
Set `true` to enable Terraform `create_before_destroy` behavior on the created security group.
We only recommend setting this `false` if you are upgrading this module and need to keep
the existing security group from being replaced.
Note that changing this value will always cause the security group to be replaced.
EOT
}
variable "security_group_create_timeout" {
type = string
default = "10m"
description = "How long to wait for the security group to be created."
}
variable "security_group_delete_timeout" {
type = string
default = "15m"
description = <<-EOT
How long to retry on `DependencyViolation` errors during security group deletion.
EOT
}
variable "allow_all_egress" {
type = bool
default = null
description = <<-EOT
If `true`, the created security group will allow egress on all ports and protocols to all IP address.
If this is false and no egress rules are otherwise specified, then no egress will be allowed.
Defaults to `true` unless the deprecated `egress_cidr_blocks` is provided and is not `["0.0.0.0/0"]`, in which case defaults to `false`.
EOT
}
variable "additional_security_group_rules" {
type = list(any)
default = []
description = <<-EOT
A list of Security Group rule objects to add to the created security group, in addition to the ones
this module normally creates. (To suppress the module's rules, set `create_security_group` to false
and supply your own security group via `associated_security_group_ids`.)
The keys and values of the objects are fully compatible with the `aws_security_group_rule` resource, except
for `security_group_id` which will be ignored, and the optional "key" which, if provided, must be unique and known at "plan" time.
To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule .
EOT
}
...@@ -54,26 +54,27 @@ func TestExamplesComplete(t *testing.T) { ...@@ -54,26 +54,27 @@ func TestExamplesComplete(t *testing.T) {
// Run `terraform output` to get the value of an output variable // Run `terraform output` to get the value of an output variable
clusterHost := terraform.Output(t, terraformOptions, "cluster_host") clusterHost := terraform.Output(t, terraformOptions, "cluster_host")
// Verify we're getting back the outputs we expect // Verify we're getting back the outputs we expect
assert.Equal(t, "eg-test-redis-test-"+randId+".testing.cloudposse.co", clusterHost) // assert.Equal(t, "eg-test-redis-test-"+randId+".testing.cloudposse.co", clusterHost)
assert.Equal(t, "eg-test-redis-test-"+randId+".elasticache-redis-terratest-"+randId+".testing.cloudposse.co", clusterHost)
// Run `terraform output` to get the value of an output variable // Run `terraform output` to get the value of an output variable
clusterId := terraform.Output(t, terraformOptions, "cluster_id") clusterId := terraform.Output(t, terraformOptions, "cluster_id")
// Verify we're getting back the outputs we expect // Verify we're getting back the outputs we expect
assert.Equal(t, "eg-test-redis-test-"+randId, clusterId) assert.Equal(t, "eg-test-redis-test-"+randId, clusterId)
// Run `terraform output` to get the value of an output variable
securityGroupName := terraform.Output(t, terraformOptions, "cluster_security_group_name")
expectedSecurityGroupName := "eg-test-redis-test-" + randId
// Verify we're getting back the outputs we expect
assert.Equal(t, expectedSecurityGroupName, securityGroupName)
// Run `terraform output` to get the value of an output variable terraformOptions.Vars = map[string]interface{}{
securityGroupID := terraform.Output(t, terraformOptions, "cluster_security_group_id") "attributes": attributes,
// Verify we're getting back the outputs we expect "sg_name": "changed",
assert.Contains(t, securityGroupID, "sg-", "SG ID should contains substring 'sg-'") }
// Run `terraform output` to get the value of an output variable terraformOptions.Parallelism = 1
securityGroupARN := terraform.Output(t, terraformOptions, "cluster_security_group_arn")
// Verify we're getting back the outputs we expect // This will run `terraform apply` and fail the test if there are any errors
assert.Contains(t, securityGroupARN, "arn:aws:ec2", "SG ID should contains substring 'arn:aws:ec2'") // We are checking to make sure that changing the security group name
// does not fail with a dependency error.
terraform.Apply(t, terraformOptions)
// Restore parallelism for destroy operation
terraformOptions.Parallelism = 10
} }
module github.com/cloudposse/terraform-aws-elasticache-redis module github.com/cloudposse/terraform-aws-elasticache-redis
go 1.14 go 1.16
require ( require (
github.com/gruntwork-io/terratest v0.34.7 github.com/gruntwork-io/terratest v0.33.0
github.com/stretchr/testify v1.5.1 github.com/stretchr/testify v1.5.1
) )
This diff is collapsed.
variable "use_existing_security_groups" {
type = bool
description = <<-EOT
DEPRECATED: Use `create_security_group` instead.
Historical description: Flag to enable/disable creation of Security Group in the module.
Set to `true` to disable Security Group creation and provide a list of existing security Group IDs in `existing_security_groups` to place the cluster into.
Historical default: `false`
EOT
default = null
}
variable "existing_security_groups" {
type = list(string)
default = []
description = <<-EOT
DEPRECATED: Use `associated_security_group_ids` instead.
Historical description: List of existing Security Group IDs to place the cluster into.
Set `use_existing_security_groups` to `true` to enable using `existing_security_groups` as Security Groups for the cluster.
EOT
}
variable "allowed_security_groups" {
type = list(string)
default = []
description = <<-EOT
DEPRECATED: Use `allowed_security_group_ids` instead.
EOT
}
variable "allowed_cidr_blocks" {
type = list(string)
default = []
description = <<-EOT
DEPRECATED: Use `additional_security_group_rules` instead.
Historical description: List of CIDR blocks that are allowed ingress to the cluster's Security Group created in the module
EOT
}
variable "egress_cidr_blocks" {
type = list(any)
default = null
description = <<-EOT
DEPRECATED: Use `allow_all_egress` and `additional_security_group_rules` instead.
Historical description: Outbound traffic address.
Historical default: ["0.0.0.0/0"]
EOT
}
locals {
# Use the legacy egress rule unless:
# - var.egress_cidr_blocks is null, which means use the default, which is allow all egress
# - var.allow_all_egress is true, which explicitly means allow all egress
# - var.egress_cidr_blocks is exactly ["0.0.0.0/0"], which we interpret to mean "allow all egress"
use_legacy_egress = !(var.egress_cidr_blocks == null || var.allow_all_egress == true || (
try(length(var.egress_cidr_blocks), 0) == 1 && try(var.egress_cidr_blocks[0], "") == "0.0.0.0/0")
)
# If var.allow_all_egress is null, default to true unless some alternate legacy rule was provided
allow_all_egress = var.allow_all_egress == null ? !local.use_legacy_egress : var.allow_all_egress
}
variable "vpc_id" { variable "vpc_id" {
type = string type = string
description = "VPC ID" description = "VPC ID"
...@@ -9,49 +11,6 @@ variable "subnets" { ...@@ -9,49 +11,6 @@ variable "subnets" {
default = [] default = []
} }
variable "security_group_enabled" {
type = bool
description = "Whether to create default Security Group for ElastiCache."
default = true
}
variable "security_group_description" {
type = string
default = "ElastiCache Security Group"
description = "The Security Group description."
}
variable "security_group_use_name_prefix" {
type = bool
default = false
description = "Whether to create a default Security Group with unique name beginning with the normalized prefix."
}
variable "security_group_rules" {
type = list(any)
default = [
{
type = "egress"
from_port = 0
to_port = 65535
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "Allow all outbound traffic"
}
]
description = <<-EOT
A list of maps of Security Group rules.
The values of map is fully complated with `aws_security_group_rule` resource.
To get more info see https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule .
EOT
}
variable "security_groups" {
description = "A list of Security Group IDs to associate with ElastiCache."
type = list(string)
default = []
}
variable "elasticache_subnet_group_name" { variable "elasticache_subnet_group_name" {
type = string type = string
description = "Subnet group name for the ElastiCache instance" description = "Subnet group name for the ElastiCache instance"
...@@ -112,7 +71,10 @@ variable "at_rest_encryption_enabled" { ...@@ -112,7 +71,10 @@ variable "at_rest_encryption_enabled" {
variable "transit_encryption_enabled" { variable "transit_encryption_enabled" {
type = bool type = bool
default = true default = true
description = "Whether to enable encryption in transit. If this is enabled, use the [following guide](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html#connect-tls) to access redis" description = <<-EOT
Set `true` to enable encryption in transit. Forced `true` if `var.auth_token` is set.
If this is enabled, use the [following guide](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/in-transit-encryption.html#connect-tls) to access redis.
EOT
} }
variable "notification_topic_arn" { variable "notification_topic_arn" {
...@@ -171,9 +133,13 @@ variable "availability_zones" { ...@@ -171,9 +133,13 @@ variable "availability_zones" {
} }
variable "zone_id" { variable "zone_id" {
type = string type = any
default = "" default = []
description = "Route53 DNS Zone ID" description = <<-EOT
Route53 DNS Zone ID as list of string (0 or 1 items). If empty, no custom DNS name will be published.
If the list contains a single Zone ID, a custom DNS name will be pulished in that zone.
Can also be a plain string, but that use is DEPRECATED because of Terraform issues.
EOT
} }
variable "dns_subdomain" { variable "dns_subdomain" {
...@@ -206,6 +172,7 @@ variable "snapshot_arns" { ...@@ -206,6 +172,7 @@ variable "snapshot_arns" {
default = [] default = []
} }
variable "snapshot_name" { variable "snapshot_name" {
type = string type = string
description = "The name of a snapshot from which to restore data into the new node group. Changing the snapshot_name forces a new resource." description = "The name of a snapshot from which to restore data into the new node group. Changing the snapshot_name forces a new resource."
...@@ -253,3 +220,4 @@ variable "cloudwatch_metric_alarms_enabled" { ...@@ -253,3 +220,4 @@ variable "cloudwatch_metric_alarms_enabled" {
description = "Boolean flag to enable/disable CloudWatch metrics alarms" description = "Boolean flag to enable/disable CloudWatch metrics alarms"
default = false default = false
} }
terraform { terraform {
required_version = ">= 0.13.0" required_version = ">= 0.14.0"
required_providers { required_providers {
aws = { aws = {
source = "hashicorp/aws" source = "hashicorp/aws"
version = ">= 2.0" version = ">= 3.26"
}
null = {
source = "hashicorp/null"
version = ">= 2.0"
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment