add serialization and deserialization
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
### ALB resources
|
||||
|
||||
# TODO:
|
||||
# support not logging
|
||||
|
||||
data "template_file" "bucket_policy" {
|
||||
template = "${file("${path.module}/bucket_policy.json")}"
|
||||
|
||||
vars {
|
||||
log_bucket = "${var.log_bucket}"
|
||||
log_prefix = "${var.log_prefix}"
|
||||
account_id = "${var.aws_account_id}"
|
||||
principle_account_id = "${lookup(var.principle_account_id, var.aws_region)}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_alb" "main" {
|
||||
name = "${var.alb_name}"
|
||||
subnets = ["${var.subnets}"]
|
||||
security_groups = ["${var.alb_security_groups}"]
|
||||
internal = "${var.alb_is_internal}"
|
||||
|
||||
access_logs {
|
||||
bucket = "${var.log_bucket}"
|
||||
prefix = "${var.log_prefix}"
|
||||
enabled = "${var.log_bucket != ""}"
|
||||
}
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.alb_name)))}"
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "log_bucket" {
|
||||
count = "${var.log_bucket != "" ? 1 : 0}"
|
||||
bucket = "${var.log_bucket}"
|
||||
policy = "${data.template_file.bucket_policy.rendered}"
|
||||
force_destroy = true
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.log_bucket)))}"
|
||||
}
|
||||
|
||||
resource "aws_alb_target_group" "target_group" {
|
||||
name = "${var.alb_name}-tg"
|
||||
port = "${var.backend_port}"
|
||||
protocol = "${upper(var.backend_protocol)}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
|
||||
health_check {
|
||||
interval = 30
|
||||
path = "${var.health_check_path}"
|
||||
port = "traffic-port"
|
||||
healthy_threshold = 3
|
||||
unhealthy_threshold = 3
|
||||
timeout = 5
|
||||
protocol = "${var.backend_protocol}"
|
||||
}
|
||||
|
||||
stickiness {
|
||||
type = "lb_cookie"
|
||||
cookie_duration = "${var.cookie_duration}"
|
||||
enabled = "${ var.cookie_duration == 1 ? false : true}"
|
||||
}
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s-tg", var.alb_name)))}"
|
||||
}
|
||||
|
||||
resource "aws_alb_listener" "front_end_http" {
|
||||
load_balancer_arn = "${aws_alb.main.arn}"
|
||||
port = "80"
|
||||
protocol = "HTTP"
|
||||
|
||||
default_action {
|
||||
target_group_arn = "${aws_alb_target_group.target_group.id}"
|
||||
type = "forward"
|
||||
}
|
||||
|
||||
count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTP" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTP" ? 1 : 0}"
|
||||
}
|
||||
|
||||
resource "aws_alb_listener" "front_end_https" {
|
||||
load_balancer_arn = "${aws_alb.main.arn}"
|
||||
port = "443"
|
||||
protocol = "HTTPS"
|
||||
certificate_arn = "${var.certificate_arn}"
|
||||
ssl_policy = "ELBSecurityPolicy-2015-05"
|
||||
|
||||
default_action {
|
||||
target_group_arn = "${aws_alb_target_group.target_group.id}"
|
||||
type = "forward"
|
||||
}
|
||||
|
||||
count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "HTTPS" || trimspace(element(split(",", var.alb_protocols), 2)) == "HTTPS" ? 1 : 0}"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
output "alb_id" {
|
||||
value = "${aws_alb.main.id}"
|
||||
}
|
||||
|
||||
output "alb_dns_name" {
|
||||
value = "${aws_alb.main.dns_name}"
|
||||
}
|
||||
|
||||
output "alb_zone_id" {
|
||||
value = "${aws_alb.main.zone_id}"
|
||||
}
|
||||
|
||||
output "target_group_arn" {
|
||||
value = "${aws_alb_target_group.target_group.arn}"
|
||||
}
|
||||
|
||||
output "principle_account_id" {
|
||||
value = "${lookup(var.principle_account_id, var.aws_region)}"
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Module variables
|
||||
*/
|
||||
|
||||
variable "alb_is_internal" {
|
||||
description = "Determines if the ALB is internal. Default: false"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "alb_name" {
|
||||
description = "The name of the ALB as will show in the AWS EC2 ELB console."
|
||||
default = "my-alb"
|
||||
}
|
||||
|
||||
variable "alb_protocols" {
|
||||
description = "A comma delimited list of the protocols the ALB accepts. e.g.: HTTPS"
|
||||
default = "HTTPS"
|
||||
}
|
||||
|
||||
variable "alb_security_groups" {
|
||||
description = "A comma separated string of security groups with which we associate the ALB. e.g. 'sg-edcd9784,sg-edcd9785'"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "aws_region" {
|
||||
description = "AWS region to use."
|
||||
}
|
||||
|
||||
variable "aws_account_id" {
|
||||
description = "AWS account ID."
|
||||
}
|
||||
|
||||
variable "backend_port" {
|
||||
description = "The port the service on the EC2 instances listen on."
|
||||
default = 80
|
||||
}
|
||||
|
||||
variable "backend_protocol" {
|
||||
description = "The protocol the backend service speaks. Options: HTTP, HTTPS, TCP, SSL (secure tcp)."
|
||||
default = "HTTP"
|
||||
}
|
||||
|
||||
variable "certificate_arn" {
|
||||
description = "The ARN of the SSL Certificate. e.g. 'arn:aws:iam::123456789012:server-certificate/ProdServerCert'"
|
||||
}
|
||||
|
||||
variable "cookie_duration" {
|
||||
description = "If load balancer connection stickiness is desired, set this to the duration that cookie should be valid. If no stickiness is wanted, leave it blank. e.g.: 300"
|
||||
default = "1"
|
||||
}
|
||||
|
||||
variable "health_check_path" {
|
||||
description = "The URL the ELB should use for health checks. e.g. /health"
|
||||
default = "/"
|
||||
}
|
||||
|
||||
variable "log_bucket" {
|
||||
description = "S3 bucket for storing ALB access logs."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "log_prefix" {
|
||||
description = "S3 prefix within the log_bucket under which logs are stored."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "principle_account_id" {
|
||||
description = "A map of ELB/ALB root account numbers used to set up logging."
|
||||
|
||||
default = {
|
||||
us-east-1 = "127311923021"
|
||||
us-east-2 = "033677994240"
|
||||
us-west-1 = "027434742980"
|
||||
us-west-2 = "797873946194"
|
||||
ca-central-1 = "985666609251"
|
||||
eu-west-1 = "156460612806"
|
||||
eu-central-1 = "054676820928"
|
||||
eu-west-2 = "652711504416"
|
||||
ap-northeast-1 = "582318560864"
|
||||
ap-northeast-2 = "600734575887"
|
||||
ap-southeast-1 = "114774131450"
|
||||
ap-southeast-2 = "783225319266"
|
||||
ap-south-1 = "718504428378"
|
||||
sa-east-1 = "507241528517"
|
||||
us-gov-west-1 = "048591011584"
|
||||
cn-north-1 = "638102146993"
|
||||
}
|
||||
}
|
||||
|
||||
variable "subnets" {
|
||||
description = "A list of subnets to associate with the ALB. e.g. ['subnet-1a2b3c4d','subnet-1a2b3c4e','subnet-1a2b3c4f']"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "VPC id where the ALB and other resources will be deployed."
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "A map of tags to add to all resources"
|
||||
default = {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
provider "aws" {
|
||||
region = "${var.aws_region}"
|
||||
}
|
||||
|
||||
module "vpc" {
|
||||
source = "github.com/terraform-community-modules/tf_aws_vpc"
|
||||
name = "my-vpc"
|
||||
cidr = "10.0.0.0/16"
|
||||
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
|
||||
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
|
||||
enable_nat_gateway = "true"
|
||||
azs = ["us-west-2a", "us-west-2b", "us-west-2c"]
|
||||
}
|
||||
|
||||
module "sg_https_web" {
|
||||
source = "github.com/terraform-community-modules/tf_aws_sg//sg_https_only"
|
||||
security_group_name = "my-sg-https"
|
||||
vpc_id = "${module.vpc.vpc_id}"
|
||||
}
|
||||
|
||||
module "alb" {
|
||||
source = "../../alb/"
|
||||
alb_security_groups = ["${module.sg_https_web.security_group_id_web}"]
|
||||
aws_account_id = "${var.aws_account_id}"
|
||||
aws_region = "${var.aws_region}"
|
||||
certificate_arn = "${var.certificate_arn}"
|
||||
log_bucket = "${var.log_bucket}"
|
||||
log_prefix = "${var.log_prefix}"
|
||||
subnets = "${module.vpc.public_subnets}"
|
||||
vpc_id = "${module.vpc.vpc_id}"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Outputs used for tests
|
||||
*/
|
||||
|
||||
output "principle_account_id" {
|
||||
value = "${module.alb.principle_account_id}"
|
||||
}
|
||||
|
||||
output "vpc_id" {
|
||||
value = "${module.vpc.vpc_id}"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "aws_account_id" {}
|
||||
|
||||
variable "aws_region" {
|
||||
default = "us-west-2"
|
||||
}
|
||||
|
||||
variable "certificate_arn" {}
|
||||
|
||||
variable "log_bucket" {}
|
||||
|
||||
variable "log_prefix" {}
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// Module: tf_aws_asg
|
||||
//
|
||||
|
||||
// This template creates the following resources
|
||||
// - A launch configuration
|
||||
// - A auto-scaling group
|
||||
// - It's meant to be used for ASGs that *don't*
|
||||
// need an ELB associated with them.
|
||||
|
||||
// Provider specific configs
|
||||
provider "aws" {
|
||||
access_key = "${var.aws_access_key}"
|
||||
secret_key = "${var.aws_secret_key}"
|
||||
region = "${var.aws_region}"
|
||||
}
|
||||
|
||||
resource "aws_launch_configuration" "launch_config" {
|
||||
name = "${var.lc_name}"
|
||||
image_id = "${var.ami_id}"
|
||||
instance_type = "${var.instance_type}"
|
||||
iam_instance_profile = "${var.iam_instance_profile}"
|
||||
key_name = "${var.key_name}"
|
||||
security_groups = ["${var.security_group}"]
|
||||
user_data = "${file(var.user_data)}"
|
||||
}
|
||||
|
||||
resource "aws_autoscaling_group" "main_asg" {
|
||||
//We want this to explicitly depend on the launch config above
|
||||
depends_on = ["aws_launch_configuration.launch_config"]
|
||||
name = "${var.asg_name}"
|
||||
|
||||
// Split out the AZs string into an array
|
||||
// The chosen availability zones *must* match
|
||||
// the AZs the VPC subnets are tied to.
|
||||
availability_zones = ["${split(",", var.azs)}"]
|
||||
// Split out the subnets string into an array
|
||||
vpc_zone_identifier = ["${split(",", var.subnet_azs)}"]
|
||||
|
||||
// Uses the ID from the launch config created above
|
||||
launch_configuration = "${aws_launch_configuration.launch_config.id}"
|
||||
|
||||
max_size = "${var.asg_number_of_instances}"
|
||||
min_size = "${var.asg_minimum_number_of_instances}"
|
||||
desired_capacity = "${var.asg_number_of_instances}"
|
||||
health_check_grace_period = "${var.health_check_grace_period}"
|
||||
health_check_type = "${var.health_check_type}"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// Module: tf_aws_asg
|
||||
//
|
||||
|
||||
// Output the ID of the Launch Config
|
||||
output "launch_config_id" {
|
||||
value = "${aws_launch_configuration.launch_config.id}"
|
||||
}
|
||||
|
||||
// Output the ID of the Launch Config
|
||||
output "asg_id" {
|
||||
value = "${aws_autoscaling_group.main_asg.id}"
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// Module: tf_aws_asg
|
||||
//
|
||||
|
||||
// Module specific variables
|
||||
|
||||
// Launch Configuration Variables
|
||||
|
||||
variable "lc_name" {}
|
||||
variable "ami_id" {}
|
||||
variable "instance_type" {}
|
||||
variable "iam_instance_profile" {}
|
||||
variable "key_name" {}
|
||||
variable "security_group" {
|
||||
description = "The security group the instances to use"
|
||||
}
|
||||
|
||||
variable "user_data" {
|
||||
description = "The path to a file with user_data for the instances"
|
||||
}
|
||||
|
||||
// Auto-Scaling Group
|
||||
variable "asg_name" {}
|
||||
variable "asg_number_of_instances" {
|
||||
description = "The number of instances we want in the ASG"
|
||||
// We use this to populate the following ASG settings
|
||||
// - max_size
|
||||
// - desired_capacity
|
||||
}
|
||||
|
||||
variable "asg_minimum_number_of_instances" {
|
||||
description = "The minimum number of instances the ASG should maintain"
|
||||
default = 1
|
||||
// Defaults to 1
|
||||
// Can be set to 0 if you never want the ASG to replace failed instances
|
||||
}
|
||||
|
||||
variable "health_check_grace_period" {
|
||||
description = "Number of seconds for a health check to time out"
|
||||
default = 300
|
||||
}
|
||||
variable "health_check_type" {
|
||||
default = "EC2"
|
||||
//Types available are:
|
||||
// - ELB
|
||||
// - EC2
|
||||
// * http://docs.aws.amazon.com/cli/latest/reference/autoscaling/create-auto-scaling-group.html#options
|
||||
}
|
||||
|
||||
variable "subnet_azs" {
|
||||
description = "The VPC subnet IDs"
|
||||
// comma separated list
|
||||
}
|
||||
|
||||
variable "azs" {
|
||||
description = "Availability Zones"
|
||||
// comma separated list
|
||||
}
|
||||
|
||||
// Variables for providers used in this module
|
||||
variable "aws_access_key" {}
|
||||
variable "aws_secret_key" {}
|
||||
variable "aws_region" {}
|
||||
@@ -0,0 +1,29 @@
|
||||
module "my_autoscaling_group" {
|
||||
|
||||
source = "../"
|
||||
|
||||
lc_name = "${var.lc_name}"
|
||||
|
||||
ami_id = "${var.ami_id}"
|
||||
|
||||
instance_type = "${var.instance_type}"
|
||||
|
||||
iam_instance_profile = "${var.iam_instance_profile}"
|
||||
|
||||
key_name = "${var.key_name}"
|
||||
|
||||
security_group = "${var.security_group_id}"
|
||||
|
||||
user_data = "${var.user_data_file}"
|
||||
|
||||
asg_name = "${var.asg_name}"
|
||||
asg_number_of_instances = "${var.asg_number_of_instances}"
|
||||
asg_minimum_number_of_instances = "${var.asg_minimum_number_of_instances}"
|
||||
|
||||
load_balancer_names = "${var.elb_names}"
|
||||
|
||||
health_check_type = "${var.health_check_type}"
|
||||
|
||||
availability_zones = "${var.availability_zones}"
|
||||
vpc_zone_subnets = "${var.vpc_zone_subnets}"
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
variable "lc_name" {
|
||||
default = "example_lc"
|
||||
}
|
||||
variable "ami_id" {
|
||||
default = "ami-sadfasd"
|
||||
}
|
||||
variable "instance_type" {
|
||||
default = "m3.medium"
|
||||
}
|
||||
variable "iam_instance_profile" {
|
||||
default = "test_profile"
|
||||
}
|
||||
variable "key_name" {
|
||||
default = "my_keypair_name"
|
||||
}
|
||||
variable "security_group_id" {
|
||||
default = "sg-abcdef"
|
||||
}
|
||||
variable "user_data_file" {
|
||||
default = "user-data.sh"
|
||||
}
|
||||
variable "asg_name" {
|
||||
default = "my-custom-asg"
|
||||
}
|
||||
variable "asg_number_of_instances" {
|
||||
default = 2
|
||||
}
|
||||
variable "asg_minimum_number_of_instances" {
|
||||
default = 1
|
||||
}
|
||||
variable "elb_names" {
|
||||
default = "my-elb-name"
|
||||
}
|
||||
variable "health_check_type" {
|
||||
default = "ELB"
|
||||
}
|
||||
variable "availability_zones" {
|
||||
default = "us-west-2a,us-west-2b"
|
||||
}
|
||||
variable "vpc_zone_subnets" {
|
||||
default = "subnet-d2jdfd,subnet-2ell2kd"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Module: tf_aws_asg_elb
|
||||
*
|
||||
* This template creates the following resources
|
||||
* - A launch configuration
|
||||
* - A auto-scaling group
|
||||
*
|
||||
* It requires you create an ELB instance before you use it.
|
||||
*/
|
||||
|
||||
resource "aws_launch_configuration" "launch_config" {
|
||||
name = "${var.lc_name}"
|
||||
image_id = "${var.ami_id}"
|
||||
instance_type = "${var.instance_type}"
|
||||
iam_instance_profile = "${var.iam_instance_profile}"
|
||||
key_name = "${var.key_name}"
|
||||
security_groups = ["${var.security_group}"]
|
||||
user_data = "${file(var.user_data)}"
|
||||
}
|
||||
|
||||
resource "aws_autoscaling_group" "main_asg" {
|
||||
# We want this to explicitly depend on the launch config above
|
||||
depends_on = ["aws_launch_configuration.launch_config"]
|
||||
|
||||
name = "${var.asg_name}"
|
||||
|
||||
# The chosen availability zones *must* match the AZs the VPC subnets are tied to.
|
||||
availability_zones = ["${split(",", var.availability_zones)}"]
|
||||
vpc_zone_identifier = ["${split(",", var.vpc_zone_subnets)}"]
|
||||
|
||||
# Uses the ID from the launch config created above
|
||||
launch_configuration = "${aws_launch_configuration.launch_config.id}"
|
||||
|
||||
max_size = "${var.asg_number_of_instances}"
|
||||
min_size = "${var.asg_minimum_number_of_instances}"
|
||||
desired_capacity = "${var.asg_number_of_instances}"
|
||||
|
||||
health_check_grace_period = "${var.health_check_grace_period}"
|
||||
health_check_type = "${var.health_check_type}"
|
||||
|
||||
load_balancers = ["${split(",", var.load_balancer_names)}"]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Module: tf_aws_asg_elb
|
||||
*
|
||||
* Outputs:
|
||||
* - launch_config_id
|
||||
* - asg_id
|
||||
*/
|
||||
|
||||
# Output the ID of the Launch Config
|
||||
output "launch_config_id" {
|
||||
value = "${aws_launch_configuration.launch_config.id}"
|
||||
}
|
||||
|
||||
# Output the ID of the Launch Config
|
||||
output "asg_id" {
|
||||
value = "${aws_autoscaling_group.main_asg.id}"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Module: tf_aws_asg_elb
|
||||
*/
|
||||
|
||||
#
|
||||
# Launch Configuration Variables
|
||||
#
|
||||
variable "lc_name" {}
|
||||
variable "ami_id" {
|
||||
description = "The AMI to use with the launch configuration"
|
||||
}
|
||||
variable "instance_type" {}
|
||||
variable "iam_instance_profile" {
|
||||
description = "The IAM role the launched instance will use"
|
||||
}
|
||||
variable "key_name" {
|
||||
description = "The SSH public key name (in EC2 key-pairs) to be injected into instances"
|
||||
}
|
||||
variable "security_group" {
|
||||
description = "ID of SG the launched instance will use"
|
||||
}
|
||||
variable "user_data" {
|
||||
description = "The path to a file with user_data for the instances"
|
||||
}
|
||||
|
||||
#
|
||||
# Auto-Scaling Group
|
||||
#
|
||||
variable "asg_name" {}
|
||||
|
||||
/* We use this to populate the following ASG settings
|
||||
* - max_size
|
||||
* - desired_capacity
|
||||
*/
|
||||
variable "asg_number_of_instances" {
|
||||
description = "The number of instances we want in the ASG"
|
||||
}
|
||||
|
||||
/*
|
||||
* Can be set to 0 if you never want the ASG to replace failed instances
|
||||
*/
|
||||
variable "asg_minimum_number_of_instances" {
|
||||
description = "The minimum number of instances the ASG should maintain"
|
||||
default = 1
|
||||
}
|
||||
variable "health_check_grace_period" {
|
||||
description = "Number of seconds for a health check to time out"
|
||||
default = 300
|
||||
}
|
||||
/*
|
||||
* Types available are:
|
||||
* - ELB
|
||||
* - EC2
|
||||
*
|
||||
* @see-also: http://docs.aws.amazon.com/cli/latest/reference/autoscaling/create-auto-scaling-group.html#options
|
||||
*/
|
||||
variable "health_check_type" {
|
||||
description = "The health check used by the ASG to determine health"
|
||||
default = "ELB"
|
||||
}
|
||||
|
||||
variable "load_balancer_names" {
|
||||
description = "A comma seperated list string of ELB names the ASG should associate instances with"
|
||||
}
|
||||
|
||||
/*
|
||||
* A string list of AZs, ex:
|
||||
* "us-east-1a,us-east-1c,us-east-1e"
|
||||
*/
|
||||
variable "availability_zones" {
|
||||
description = "A comma seperated list string of AZs the ASG will be associated with"
|
||||
}
|
||||
|
||||
/*
|
||||
* A string list of VPC subnet IDs, ex:
|
||||
* "subnet-d2t4sad,subnet-434ladkn"
|
||||
*/
|
||||
variable "vpc_zone_subnets" {
|
||||
description = "A comma seperated list string of VPC subnets to associate with ASG, should correspond with var.availability_zones zones"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
resource "aws_kms_key" "aurora" {
|
||||
description = "RDS master key for ${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
deletion_window_in_days = 30
|
||||
enable_key_rotation = "true"
|
||||
}
|
||||
|
||||
resource "aws_kms_alias" "aurora" {
|
||||
name = "alias/${var.name}-${data.aws_vpc.vpc.tags["Name"]}-rds-key"
|
||||
target_key_id = "${aws_kms_key.aurora.key_id}"
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
data "aws_vpc" "vpc" {
|
||||
id = "${var.vpc_id}"
|
||||
}
|
||||
|
||||
resource "aws_rds_cluster" "aurora" {
|
||||
cluster_identifier = "tf-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
availability_zones = ["${var.azs}"]
|
||||
database_name = "${var.database_name}"
|
||||
master_username = "${var.master_username}"
|
||||
master_password = "${var.master_password}"
|
||||
engine = "${var.engine}"
|
||||
backup_retention_period = "${var.backup_retention_period}"
|
||||
preferred_backup_window = "${var.preferred_backup_window}"
|
||||
vpc_security_group_ids = ["${aws_security_group.aurora_security_group.id}"]
|
||||
storage_encrypted = "${var.storage_encrypted}"
|
||||
kms_key_id = "${aws_kms_key.aurora.arn}"
|
||||
apply_immediately = "${var.apply_immediately}"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.aurora_subnet_group.id}"
|
||||
db_cluster_parameter_group_name = "${aws_rds_cluster_parameter_group.aurora_cluster_parameter_group.id}"
|
||||
final_snapshot_identifier = "final-snapshot-${var.name}-${data.aws_vpc.vpc.tags["Name"]}" # Useful in dev
|
||||
|
||||
#skip_final_snapshot = true # Useful in dev - defaults to false
|
||||
iam_database_authentication_enabled = "${var.iam_database_authentication_enabled}"
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = "true" # https://www.terraform.io/docs/configuration/resources.html#prevent_destroy
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_rds_cluster_instance" "aurora_instance" {
|
||||
count = "${var.cluster_size}"
|
||||
identifier = "tf-rds-aurora-${var.name}-${data.aws_vpc.vpc.tags["Name"]}-${count.index}"
|
||||
engine = "${var.engine}"
|
||||
cluster_identifier = "${aws_rds_cluster.aurora.id}"
|
||||
instance_class = "${var.instance_class}"
|
||||
publicly_accessible = "${var.publicly_accessible}"
|
||||
db_subnet_group_name = "${aws_db_subnet_group.aurora_subnet_group.id}"
|
||||
db_parameter_group_name = "${aws_db_parameter_group.aurora_parameter_group.id}"
|
||||
apply_immediately = "${var.apply_immediately}"
|
||||
monitoring_role_arn = "${aws_iam_role.aurora_instance_role.arn}"
|
||||
monitoring_interval = "5"
|
||||
|
||||
tags {
|
||||
Name = "tf-rds-aurora-${var.name}-${data.aws_vpc.vpc.tags["Name"]}-${count.index}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "aurora_subnet_group" {
|
||||
name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
subnet_ids = ["${var.subnets}"]
|
||||
|
||||
tags {
|
||||
Name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_db_parameter_group" "aurora_parameter_group" {
|
||||
name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
family = "${var.family}"
|
||||
description = "Terraform-managed parameter group for ${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
|
||||
parameter = ["${var.db_parameters}"]
|
||||
|
||||
tags {
|
||||
Name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_rds_cluster_parameter_group" "aurora_cluster_parameter_group" {
|
||||
name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
family = "${var.family}"
|
||||
description = "Terraform-managed cluster parameter group for ${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
|
||||
parameter = ["${var.cluster_parameters}"]
|
||||
|
||||
tags {
|
||||
Name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_db_option_group" "aurora_option_group" {
|
||||
name = "tf-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
option_group_description = "Terraform-managed option group for ${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
engine_name = "${var.engine}"
|
||||
major_engine_version = "${var.major_engine_version}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "aurora_instance_role" {
|
||||
name = "tf-role-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
assume_role_policy = "${file("${path.module}/files/iam/assume_role_rds_monitoring.json")}"
|
||||
path = "/tf/${var.env}/${var.name}-${data.aws_vpc.vpc.tags["Name"]}/" # edits?
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "aurora_policy_rds_monitoring" {
|
||||
role = "${aws_iam_role.aurora_instance_role.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
output "rds_cluster_id" {
|
||||
value = "${aws_rds_cluster.aurora.id}"
|
||||
}
|
||||
|
||||
output "writer_endpoint" {
|
||||
value = "${aws_rds_cluster.aurora.endpoint}"
|
||||
}
|
||||
|
||||
output "reader_endpoint" {
|
||||
value = "${aws_rds_cluster.aurora.reader_endpoint}"
|
||||
}
|
||||
|
||||
output "security_group_id"{
|
||||
value = "${aws_security_group.aurora_security_group.id}"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
resource "aws_security_group" "aurora_security_group" {
|
||||
name = "tf-sg-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
description = "Terraform-managed RDS security group for ${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
vpc_id = "${data.aws_vpc.vpc.id}"
|
||||
|
||||
tags {
|
||||
Name = "tf-sg-rds-${var.name}-${data.aws_vpc.vpc.tags["Name"]}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "aurora_ingress" {
|
||||
count = "${length(var.allowed_security_groups)}"
|
||||
type = "ingress"
|
||||
from_port = "${var.db_port}"
|
||||
to_port = "${var.db_port}"
|
||||
protocol = "tcp"
|
||||
source_security_group_id = "${element(var.allowed_security_groups, count.index)}"
|
||||
security_group_id = "${aws_security_group.aurora_security_group.id}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "aurora_networks_ingress" {
|
||||
type = "ingress"
|
||||
from_port = "${var.db_port}"
|
||||
to_port = "${var.db_port}"
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["${var.allowed_cidr}"]
|
||||
security_group_id = "${aws_security_group.aurora_security_group.id}"
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
variable "env" {}
|
||||
|
||||
variable "allowed_cidr" {
|
||||
type = "list"
|
||||
default = ["127.0.0.1/32"]
|
||||
description = "A list of Security Group ID's to allow access to."
|
||||
}
|
||||
|
||||
variable "allowed_security_groups" {
|
||||
type = "list"
|
||||
default = []
|
||||
description = "A list of Security Group ID's to allow access to."
|
||||
}
|
||||
|
||||
variable "azs" {
|
||||
description = "A list of Availability Zones in the Region"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "cluster_size" {
|
||||
description = "Number of cluster instances to create"
|
||||
}
|
||||
|
||||
variable "db_port" {
|
||||
default = 3306
|
||||
}
|
||||
|
||||
variable "instance_class" {
|
||||
description = "Instance class to use when creating RDS cluster"
|
||||
default = "db.t2.medium"
|
||||
}
|
||||
|
||||
variable "publicly_accessible" {
|
||||
description = "Should the instance get a public IP address?"
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
description = "Name for the Redis replication group i.e. cmsCommon"
|
||||
}
|
||||
|
||||
variable "subnets" {
|
||||
description = "Subnets to use in creating RDS subnet group (must already exist)"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "cluster_parameters" {
|
||||
description = "A list of cluster parameter maps to apply"
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "db_parameters" {
|
||||
description = "A list of db parameter maps to apply"
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
|
||||
# see aws_rds_cluster documentation for these variables
|
||||
variable "database_name" { }
|
||||
variable "master_username" { }
|
||||
variable "master_password" { }
|
||||
|
||||
variable "backup_retention_period" {
|
||||
description = "The days to retain backups for"
|
||||
default = "30"
|
||||
}
|
||||
|
||||
variable "preferred_backup_window" {
|
||||
description = "The daily time range during which automated backups are created"
|
||||
default = "01:00-03:00"
|
||||
}
|
||||
variable "storage_encrypted" { default = true }
|
||||
variable "apply_immediately" { default = false }
|
||||
variable "iam_database_authentication_enabled" { default = false }
|
||||
variable "major_engine_version" { default = "5.6" }
|
||||
variable "engine" { default = "aurora" }
|
||||
variable "family" { default = "aurora5.6"}
|
||||
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "VPC ID"
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
resource "aws_security_group" "bastion" {
|
||||
name = var.name
|
||||
vpc_id = var.vpc_id
|
||||
description = "Bastion security group (only SSH inbound access is allowed)"
|
||||
|
||||
tags = {
|
||||
Name = var.name
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "ssh_ingress" {
|
||||
type = "ingress"
|
||||
from_port = "22"
|
||||
to_port = "22"
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.allowed_cidr
|
||||
ipv6_cidr_blocks = var.allowed_ipv6_cidr
|
||||
security_group_id = aws_security_group.bastion.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "ssh_sg_ingress" {
|
||||
count = length(var.allowed_security_groups)
|
||||
type = "ingress"
|
||||
from_port = "22"
|
||||
to_port = "22"
|
||||
protocol = "tcp"
|
||||
source_security_group_id = element(var.allowed_security_groups, count.index)
|
||||
security_group_id = aws_security_group.bastion.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "bastion_all_egress" {
|
||||
type = "egress"
|
||||
from_port = "0"
|
||||
to_port = "65535"
|
||||
protocol = "all"
|
||||
|
||||
cidr_blocks = [
|
||||
"0.0.0.0/0",
|
||||
]
|
||||
|
||||
ipv6_cidr_blocks = [
|
||||
"::/0",
|
||||
]
|
||||
|
||||
security_group_id = aws_security_group.bastion.id
|
||||
}
|
||||
|
||||
data "template_file" "user_data" {
|
||||
template = file("${path.module}/${var.user_data_file}")
|
||||
|
||||
vars = {
|
||||
s3_bucket_name = var.s3_bucket_name
|
||||
s3_bucket_uri = var.s3_bucket_uri
|
||||
ssh_user = var.ssh_user
|
||||
keys_update_frequency = var.keys_update_frequency
|
||||
enable_hourly_cron_updates = var.enable_hourly_cron_updates
|
||||
additional_user_data_script = var.additional_user_data_script
|
||||
}
|
||||
}
|
||||
|
||||
//resource "aws_instance" "bastion" {
|
||||
// ami = "${var.ami}"
|
||||
// instance_type = "${var.instance_type}"
|
||||
// iam_instance_profile = "${var.iam_instance_profile}"
|
||||
// subnet_id = "${var.subnet_id}"
|
||||
// vpc_security_group_ids = ["${aws_security_group.bastion.id}"]
|
||||
// user_data = "${template_file.user_data.rendered}"
|
||||
//
|
||||
// count = 1
|
||||
//
|
||||
// tags {
|
||||
// Name = "${var.name}"
|
||||
// }
|
||||
//}
|
||||
|
||||
resource "aws_launch_configuration" "bastion" {
|
||||
name_prefix = "${var.name}-"
|
||||
image_id = var.ami
|
||||
instance_type = var.instance_type
|
||||
user_data = data.template_file.user_data.rendered
|
||||
enable_monitoring = var.enable_monitoring
|
||||
|
||||
security_groups = compact(
|
||||
concat(
|
||||
[aws_security_group.bastion.id],
|
||||
split(",", var.security_group_ids),
|
||||
),
|
||||
)
|
||||
|
||||
root_block_device {
|
||||
volume_size = var.instance_volume_size_gb
|
||||
}
|
||||
|
||||
iam_instance_profile = var.iam_instance_profile
|
||||
associate_public_ip_address = var.associate_public_ip_address
|
||||
key_name = var.key_name
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_autoscaling_group" "bastion" {
|
||||
name = var.apply_changes_immediately ? aws_launch_configuration.bastion.name : var.name
|
||||
|
||||
vpc_zone_identifier = var.subnet_ids
|
||||
|
||||
desired_capacity = "1"
|
||||
min_size = "1"
|
||||
max_size = "1"
|
||||
health_check_grace_period = "60"
|
||||
health_check_type = "EC2"
|
||||
force_delete = false
|
||||
wait_for_capacity_timeout = 0
|
||||
launch_configuration = aws_launch_configuration.bastion.name
|
||||
|
||||
enabled_metrics = [
|
||||
"GroupMinSize",
|
||||
"GroupMaxSize",
|
||||
"GroupDesiredCapacity",
|
||||
"GroupInServiceInstances",
|
||||
"GroupPendingInstances",
|
||||
"GroupStandbyInstances",
|
||||
"GroupTerminatingInstances",
|
||||
"GroupTotalInstances",
|
||||
]
|
||||
|
||||
tags = concat(
|
||||
[
|
||||
{
|
||||
"key" = "Name"
|
||||
"value" = var.name
|
||||
"propagate_at_launch" = true
|
||||
},
|
||||
{
|
||||
"key" = "EIP"
|
||||
"value" = var.eip
|
||||
"propagate_at_launch" = true
|
||||
},
|
||||
],
|
||||
var.extra_tags,
|
||||
)
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
output "ssh_user" {
|
||||
value = var.ssh_user
|
||||
}
|
||||
|
||||
output "security_group_id" {
|
||||
value = aws_security_group.bastion.id
|
||||
}
|
||||
|
||||
output "asg_id" {
|
||||
value = aws_autoscaling_group.bastion.id
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# This is just a sample definition for bastion AMI
|
||||
module "bastion_ami" {
|
||||
source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs"
|
||||
instance_type = "t2.micro"
|
||||
region = "eu-west-1"
|
||||
distribution = "trusty"
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
# This is just a sample definition of IAM instance profile which is allowed to read-only from S3, and associate ElasticIP addresses.
|
||||
resource "aws_iam_instance_profile" "s3_readonly-allow_associateaddress" {
|
||||
name = "s3_readonly-allow_associateaddress"
|
||||
role = "${aws_iam_role.s3_readonly-allow_associateaddress.name}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "s3_readonly-allow_associateaddress" {
|
||||
name = "s3_readonly-allow_associateaddress-role"
|
||||
path = "/"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "ec2.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "s3_readonly-allow_associateaddress_policy" {
|
||||
name = "s3_readonly-allow_associateaddress-policy"
|
||||
role = "${aws_iam_role.s3_readonly-allow_associateaddress.id}"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1425916919000",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ec2:AssociateAddress",
|
||||
"s3:List*",
|
||||
"s3:Get*"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# This is just a sample definition of IAM instance profile which is allowed to read-only from S3.
|
||||
resource "aws_iam_instance_profile" "s3_readonly" {
|
||||
name = "s3_readonly"
|
||||
role = "${aws_iam_role.s3_readonly.name}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "s3_readonly" {
|
||||
name = "s3_readonly"
|
||||
path = "/"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"Service": "ec2.amazonaws.com"
|
||||
},
|
||||
"Action": "sts:AssumeRole"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "s3_readonly_policy" {
|
||||
name = "s3_readonly-policy"
|
||||
role = "${aws_iam_role.s3_readonly.id}"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1425916919000",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:List*",
|
||||
"s3:Get*"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# This is an example of how to put public keys into S3 bucket and manage them in Terraform
|
||||
variable "ssh_public_key_names" {
|
||||
default = ["user1", "user2", "admin"]
|
||||
type = list(string)
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "ssh_public_keys" {
|
||||
region = "eu-west-1"
|
||||
bucket = "public-keys-demo-bucket"
|
||||
acl = "private"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Id": "Policy142469412148",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "Stmt1424694110324",
|
||||
"Effect": "Allow",
|
||||
"Principal": {
|
||||
"AWS": "arn:aws:iam::123456789012:root"
|
||||
},
|
||||
"Action": [
|
||||
"s3:List*",
|
||||
"s3:Get*"
|
||||
],
|
||||
"Resource": "arn:aws:s3:::public-keys-demo-bucket"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_object" "ssh_public_keys" {
|
||||
count = length(var.ssh_public_key_names)
|
||||
|
||||
bucket = aws_s3_bucket.ssh_public_keys.bucket
|
||||
key = "${element(var.ssh_public_key_names, count.index)}.pub"
|
||||
|
||||
# Make sure that you put files into correct location and name them accordingly (`public_keys/{keyname}.pub`)
|
||||
source = "public_keys/${element(var.ssh_public_key_names, count.index)}.pub"
|
||||
|
||||
depends_on = [aws_s3_bucket.ssh_public_keys]
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
variable "allowed_cidr" {
|
||||
type = list(string)
|
||||
|
||||
default = [
|
||||
"0.0.0.0/0",
|
||||
]
|
||||
|
||||
description = "A list of CIDR Networks to allow ssh access to."
|
||||
}
|
||||
|
||||
variable "allowed_ipv6_cidr" {
|
||||
type = list(string)
|
||||
|
||||
default = [
|
||||
"::/0",
|
||||
]
|
||||
|
||||
description = "A list of IPv6 CIDR Networks to allow ssh access to."
|
||||
}
|
||||
|
||||
variable "allowed_security_groups" {
|
||||
type = list(string)
|
||||
default = []
|
||||
description = "A list of Security Group ID's to allow access to."
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
default = "bastion"
|
||||
}
|
||||
|
||||
variable "extra_tags" {
|
||||
type = list(object({ key = string, value = string, propagate_at_launch = bool }))
|
||||
default = []
|
||||
description = "A list of tags to associate to the bastion instance."
|
||||
}
|
||||
|
||||
variable "ami" {
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
default = "t2.micro"
|
||||
}
|
||||
|
||||
variable "instance_volume_size_gb" {
|
||||
description = "The root volume size, in gigabytes"
|
||||
default = "8"
|
||||
}
|
||||
|
||||
variable "iam_instance_profile" {
|
||||
}
|
||||
|
||||
variable "user_data_file" {
|
||||
default = "user_data.sh"
|
||||
}
|
||||
|
||||
variable "s3_bucket_name" {
|
||||
}
|
||||
|
||||
variable "s3_bucket_uri" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "enable_monitoring" {
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "ssh_user" {
|
||||
default = "ubuntu"
|
||||
}
|
||||
|
||||
variable "enable_hourly_cron_updates" {
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "keys_update_frequency" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "additional_user_data_script" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
default = "eu-west-1"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
}
|
||||
|
||||
variable "security_group_ids" {
|
||||
description = "Comma seperated list of security groups to apply to the bastion."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "subnet_ids" {
|
||||
default = []
|
||||
description = "A list of subnet ids"
|
||||
}
|
||||
|
||||
variable "eip" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "associate_public_ip_address" {
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "key_name" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "apply_changes_immediately" {
|
||||
description = "Whether to apply the changes at once and recreate auto-scaling group"
|
||||
default = false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
terraform {
|
||||
required_version = ">= 0.12"
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
# --- IAM user allowing access to the bucket ---
|
||||
data "aws_iam_policy_document" "iam_policy" {
|
||||
statement {
|
||||
actions = [
|
||||
"s3:GetObject",
|
||||
"s3:GetObjectAcl",
|
||||
"s3:PutObject",
|
||||
"s3:PutObjectAcl",
|
||||
"s3:DeleteObject",
|
||||
"s3:*"
|
||||
]
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}/*"]
|
||||
}
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"s3:ListBucket"
|
||||
]
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}"]
|
||||
}
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"s3:GetBucketLocation",
|
||||
"s3:ListAllMyBuckets"
|
||||
]
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_user" "u" {
|
||||
name = "cf-user-${var.bucket_name}"
|
||||
path = "/"
|
||||
|
||||
count = var.create_user_with_policy == true ? 1 : 0
|
||||
}
|
||||
|
||||
resource "aws_iam_access_key" "k" {
|
||||
user = aws_iam_user.u.name
|
||||
pgp_key = var.pgp_key
|
||||
|
||||
count = var.create_user_with_policy == true ? 1 : 0
|
||||
}
|
||||
|
||||
resource "aws_iam_user_policy" "up" {
|
||||
name = "cf-policy-${var.bucket_name}"
|
||||
user = aws_iam_user.u.name
|
||||
policy = var.iam_policy == "" ? format("%s", data.aws_iam_policy_document.iam_policy.json) : var.iam_policy
|
||||
|
||||
count = var.create_user_with_policy == true ? 1 : 0
|
||||
}
|
||||
|
||||
# --- S3 bucket ---
|
||||
|
||||
data "aws_iam_policy_document" "s3_policy_cf_bucket" {
|
||||
statement {
|
||||
actions = ["s3:GetObject"]
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}/*"]
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
|
||||
}
|
||||
}
|
||||
|
||||
statement {
|
||||
actions = ["s3:ListBucket"]
|
||||
resources = ["arn:aws:s3:::${var.bucket_name}"]
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "bucket" {
|
||||
bucket = var.bucket_name
|
||||
acl = "private"
|
||||
policy = data.aws_iam_policy_document.s3_policy_cf_bucket.json
|
||||
|
||||
tags = merge("${var.tags}", map("Name", format("%s-bucket", var.name)))
|
||||
}
|
||||
|
||||
# --- CloudFront ---
|
||||
|
||||
resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
|
||||
comment = "access-identity-${var.name}"
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket" "log_bucket" {
|
||||
bucket = var.log_bucket
|
||||
#policy = "${data.aws_iam_policy_document.s3_policy_cf_logs.json}"
|
||||
force_destroy = true
|
||||
|
||||
tags = merge(var.tags, map("Name", format("%s", var.log_bucket)))
|
||||
}
|
||||
|
||||
resource "aws_cloudfront_distribution" "cf" {
|
||||
enabled = "true"
|
||||
is_ipv6_enabled = var.ipv6_enabled
|
||||
comment = var.comment
|
||||
default_root_object = "index.html"
|
||||
price_class = var.price_class
|
||||
|
||||
logging_config = {
|
||||
include_cookies = "${var.log_include_cookies}"
|
||||
bucket = "${var.log_bucket}.s3.amazonaws.com"
|
||||
prefix = "${var.log_prefix}"
|
||||
}
|
||||
|
||||
aliases = ["${var.domains}"]
|
||||
|
||||
origin {
|
||||
domain_name = aws_s3_bucket.bucket.bucket_domain_name
|
||||
origin_id = var.bucket_name
|
||||
|
||||
s3_origin_config {
|
||||
origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
|
||||
}
|
||||
}
|
||||
|
||||
viewer_certificate {
|
||||
acm_certificate_arn = var.certificate_arn
|
||||
ssl_support_method = "sni-only"
|
||||
minimum_protocol_version = "TLSv1"
|
||||
}
|
||||
|
||||
default_cache_behavior {
|
||||
allowed_methods = var.allowed_methods
|
||||
cached_methods = var.cached_methods
|
||||
target_origin_id = var.bucket_name
|
||||
compress = var.compress
|
||||
|
||||
forwarded_values {
|
||||
query_string = false
|
||||
|
||||
cookies {
|
||||
forward = "none"
|
||||
}
|
||||
}
|
||||
|
||||
viewer_protocol_policy = var.viewer_protocol_policy
|
||||
min_ttl = var.min_ttl
|
||||
default_ttl = var.default_ttl
|
||||
max_ttl = var.max_ttl
|
||||
}
|
||||
|
||||
restrictions {
|
||||
geo_restriction {
|
||||
restriction_type = "none"
|
||||
}
|
||||
}
|
||||
|
||||
tags = merge("${var.tags}", map("Name", format("%s", var.name)))
|
||||
|
||||
depends_on = ["aws_s3_bucket.log_bucket"]
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#The identifier for the distribution. For example: EDFDVBD632BHDS5.
|
||||
output "cf_id" {
|
||||
value = "${aws_cloudfront_distribution.cf.id}"
|
||||
}
|
||||
|
||||
#The ARN (Amazon Resource Name) for the distribution. For example: arn:aws:cloudfront::123456789012:distribution/EDFDVBD632BHDS5, where 123456789012 is your AWS account ID.
|
||||
output "cf_arn" {
|
||||
value = "${aws_cloudfront_distribution.cf.arn}"
|
||||
}
|
||||
|
||||
#The current status of the distribution. Deployed if the distribution's information is fully propagated throughout the Amazon CloudFront system.
|
||||
output "cf_status" {
|
||||
value = "${aws_cloudfront_distribution.cf.status}"
|
||||
}
|
||||
|
||||
#active_trusted_signers - The key pair IDs that CloudFront is aware of for each trusted signer, if the distribution is set up to serve private content with signed URLs.
|
||||
output "cf_active_trusted_signers" {
|
||||
value = "${aws_cloudfront_distribution.cf.active_trusted_signers}"
|
||||
}
|
||||
|
||||
#The domain name corresponding to the distribution. For example: d604721fxaaqy9.cloudfront.net.
|
||||
output "cf_domain_name" {
|
||||
value = "${aws_cloudfront_distribution.cf.domain_name}"
|
||||
}
|
||||
|
||||
#The current version of the distribution's information. For example: E2QWRUHAPOMQZL.
|
||||
output "cf_etag" {
|
||||
value = "${aws_cloudfront_distribution.cf.etag}"
|
||||
}
|
||||
|
||||
#The CloudFront Route 53 zone ID that can be used to route an Alias Resource Record Set to. This attribute is simply an alias for the zone ID Z2FDTNDATAQYW2.
|
||||
output "cf_hosted_zone_id" {
|
||||
value = "${aws_cloudfront_distribution.cf.hosted_zone_id}"
|
||||
}
|
||||
|
||||
#S3 bucket id
|
||||
output "s3_bucket_id" {
|
||||
value = "${aws_s3_bucket.bucket.id}"
|
||||
}
|
||||
|
||||
#S3 bucket arn
|
||||
output "s3_bucket_arn" {
|
||||
value = "${aws_s3_bucket.bucket.arn}"
|
||||
}
|
||||
|
||||
|
||||
#The access key ID.
|
||||
output "iam_access_key_id" {
|
||||
value = "${aws_iam_access_key.k.id}"
|
||||
}
|
||||
|
||||
#The IAM user associated with this access key.
|
||||
output "iam_access_user" {
|
||||
value = "${aws_iam_access_key.k.user}"
|
||||
}
|
||||
|
||||
#The fingerprint of the PGP key used to encrypt the secret
|
||||
output "iam_access_key_fingerprint" {
|
||||
value = "${aws_iam_access_key.k.key_fingerprint}"
|
||||
}
|
||||
|
||||
# The secret access key. Note that this will be written to the state file. Please supply a pgp_key instead, which will prevent the secret from being stored in plain text
|
||||
output "iam_access_secret" {
|
||||
value = "${aws_iam_access_key.k.secret}"
|
||||
}
|
||||
|
||||
# The encrypted secret, base64 encoded. ~> NOTE: The encrypted secret may be decrypted using the command line, for example: terraform output secret | base64 --decode | keybase pgp decrypt.
|
||||
output "iam_access_encrypted_secret" {
|
||||
value = "${aws_iam_access_key.k.encrypted_secret}"
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
variable "name" {}
|
||||
|
||||
variable "certificate_arn" {
|
||||
description = "Existing certificate arn."
|
||||
}
|
||||
|
||||
variable "domains" {
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "bucket_name" {
|
||||
default = "tf-cf-bucket"
|
||||
}
|
||||
|
||||
variable "compress" {
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "ipv6_enabled" {
|
||||
default = "true"
|
||||
}
|
||||
|
||||
variable "comment" {
|
||||
default = "Managed by Terraform"
|
||||
}
|
||||
|
||||
variable "log_include_cookies" {
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "log_bucket" { }
|
||||
|
||||
variable "log_prefix" {
|
||||
default = "cf_logs"
|
||||
}
|
||||
|
||||
variable "price_class" {
|
||||
default = "PriceClass_100"
|
||||
}
|
||||
|
||||
variable "viewer_protocol_policy" {
|
||||
#default = "allow-all"
|
||||
default = "redirect-to-https"
|
||||
}
|
||||
|
||||
variable "allowed_methods" {
|
||||
type = "list"
|
||||
default = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
|
||||
}
|
||||
variable "cached_methods" {
|
||||
type = "list"
|
||||
default = ["GET", "HEAD"]
|
||||
}
|
||||
|
||||
variable "min_ttl" {
|
||||
default = "0"
|
||||
}
|
||||
variable "max_ttl" {
|
||||
default = "31536000"
|
||||
}
|
||||
variable "default_ttl" {
|
||||
default = "60"
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "create_user_with_policy" {
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "iam_policy" {
|
||||
type = "string"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "pgp_key" {
|
||||
default = ""
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
resource "aws_customer_gateway" "default" {
|
||||
count = "${var.customer_gateway_id == "" ? 1 : 0}"
|
||||
bgp_asn = "${var.bgp_asn}"
|
||||
ip_address = "${var.ip_address}"
|
||||
type = "ipsec.1"
|
||||
|
||||
tags {
|
||||
Name = "${var.name}"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpn_connection" "default" {
|
||||
vpn_gateway_id = "${var.vpn_gateway_id}"
|
||||
customer_gateway_id = "${coalesce(var.customer_gateway_id, aws_customer_gateway.default.id)}"
|
||||
type = "ipsec.1"
|
||||
static_routes_only = "${var.static_routes_only}"
|
||||
|
||||
tags {
|
||||
Name = "${var.name}"
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_vpn_connection_route" "default" {
|
||||
count = "${length(var.destination_cidr_blocks)}"
|
||||
destination_cidr_block = "${element(var.destination_cidr_blocks, count.index)}"
|
||||
vpn_connection_id = "${aws_vpn_connection.default.id}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
#if route_source=static and there are more route_tables than cidr_blocks(or an equal amount)
|
||||
# then add static routes in every specified route table for each destination_cidr_block=>VPN Gateway
|
||||
resource "aws_route" "more_tables" {
|
||||
count = "${(var.add_static_routes_to_tables == "true" ? 1 : 0) * (var.route_table_count >= length(var.destination_cidr_blocks) ? 1 : 0 ) * var.route_table_count * length(var.destination_cidr_blocks)}"
|
||||
route_table_id = "${element(var.route_table_ids, count.index % floor(max(length(var.route_table_ids),length(var.destination_cidr_blocks))))}"
|
||||
destination_cidr_block = "${element(var.destination_cidr_blocks, floor(count.index / max(length(var.route_table_ids),length(var.destination_cidr_blocks))))}"
|
||||
gateway_id = "${var.vpn_gateway_id}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
#if route_source=static and there are more cidr_blocks than route_tables
|
||||
# then add static routes in every specified route table for each destination_cidr_block=>VPN Gateway
|
||||
resource "aws_route" "more_cidrs" {
|
||||
count = "${(var.add_static_routes_to_tables == "true" ? 1 : 0) * (length(var.destination_cidr_blocks) > var.route_table_count ? 1 : 0 ) * var.route_table_count * length(var.destination_cidr_blocks)}"
|
||||
route_table_id = "${element(var.route_table_ids, floor(count.index / max(length(var.route_table_ids),length(var.destination_cidr_blocks))))}"
|
||||
destination_cidr_block = "${element(var.destination_cidr_blocks, count.index % floor(max(length(var.route_table_ids),length(var.destination_cidr_blocks))))}"
|
||||
gateway_id = "${var.vpn_gateway_id}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
output "cgw_id" {
|
||||
value = "${aws_customer_gateway.default.id}"
|
||||
}
|
||||
|
||||
output "cgw_ip_address" {
|
||||
value = "${aws_customer_gateway.default.ip_address}"
|
||||
}
|
||||
|
||||
output "cgw_bgp_asn" {
|
||||
value = "${aws_customer_gateway.default.bgp_asn}"
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
variable "name" {
|
||||
description = "Decriptive name used to label tagged resources."
|
||||
}
|
||||
|
||||
variable "vpn_gateway_id" {
|
||||
description = "Specify which VPN Gateway the Customer Gateway will be associated with."
|
||||
}
|
||||
|
||||
|
||||
variable "customer_gateway_id" {
|
||||
description = "Specify which Customer Gateway to use. If specified the variables ip_address and bgp_asn will not be used"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ip_address" {
|
||||
description = "IP address of the Customer Gateway external interface."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "bgp_asn" {
|
||||
description = "BGP ASN of the Customer Gateway. By convention, use 65000 if you are not running BGP."
|
||||
default = 65000
|
||||
}
|
||||
|
||||
variable "destination_cidr_blocks" {
|
||||
type = "list"
|
||||
description = "List of comman separated CIDR blocks which should be routed to the Customer Gateway(s)."
|
||||
}
|
||||
|
||||
variable "route_table_ids" {
|
||||
type = "list"
|
||||
description = "List of command separated Route Table IDs where routes to destination_cidr_blocks will be created."
|
||||
}
|
||||
|
||||
variable "route_table_count" {
|
||||
description = "Number of elements in the route_table_ids list. Here because Terraform cannot calculate count from dynamic values. This should be removed when Terraform 0.9 is released."
|
||||
}
|
||||
|
||||
variable "static_routes_only" {
|
||||
description = "Whether the VPN connection uses static routes exclusively. Static routes must be used for devices that don't support BGP. Accepts either true or false."
|
||||
}
|
||||
|
||||
variable "add_static_routes_to_tables" {
|
||||
description = "Determines whether static routes will be added to all route tables in route_table_ids list or if vgw route propagation will be used instead. If set to true, then route_table_ids, route_table_count, and destination_cidr_blocks must also be provided."
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Provider specific configs
|
||||
provider "aws" {
|
||||
access_key = "${var.aws_access_key}"
|
||||
secret_key = "${var.aws_secret_key}"
|
||||
region = "${var.aws_region}"
|
||||
}
|
||||
|
||||
// EC2 Instance Resource for Module
|
||||
resource "aws_instance" "ec2_instance" {
|
||||
ami = "${var.ami_id}"
|
||||
count = "${var.number_of_instances}"
|
||||
subnet_id = "${var.subnet_id}"
|
||||
instance_type = "${var.instance_type}"
|
||||
user_data = "${file(var.user_data)}"
|
||||
tags {
|
||||
created_by = "${lookup(var.tags,"created_by")}"
|
||||
// Takes the instance_name input variable and adds
|
||||
// the count.index to the name., e.g.
|
||||
// "example-host-web-1"
|
||||
Name = "${var.instance_name}-${count.index}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Output the ID of the EC2 instance created
|
||||
output "ec2_instance_id" {
|
||||
value = "${aws_instance.ec2_instance.id}"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Module specific variables
|
||||
|
||||
variable "instance_name" {
|
||||
description = "Used to populate the Name tag. This is done in main.tf"
|
||||
}
|
||||
|
||||
variable "instance_type" {}
|
||||
|
||||
variable "subnet_id" {
|
||||
description = "The VPC subnet the instance(s) will go in"
|
||||
}
|
||||
|
||||
variable "ami_id" {
|
||||
description = "The AMI to use"
|
||||
}
|
||||
|
||||
variable "number_of_instances" {
|
||||
description = "number of instances to make"
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "user_data" {
|
||||
description = "The path to a file with user_data for the instances"
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
default = {
|
||||
created_by = "terraform"
|
||||
}
|
||||
}
|
||||
|
||||
// Variables for providers used in this module
|
||||
variable "aws_access_key" {}
|
||||
variable "aws_secret_key" {}
|
||||
variable "aws_region" {}
|
||||
@@ -0,0 +1,57 @@
|
||||
data "template_file" "consul" {
|
||||
template = "${file("${path.module}/templates/consul.json")}"
|
||||
|
||||
vars {
|
||||
env = "${aws_ecs_cluster.cluster.name}"
|
||||
image = "${var.consul_image}"
|
||||
registrator_image = "${var.registrator_image}"
|
||||
consul_memory_reservation = "${var.consul_memory_reservation}"
|
||||
registrator_memory_reservation = "${var.registrator_memory_reservation}"
|
||||
awslogs_group = "consul-agent-${aws_ecs_cluster.cluster.name}"
|
||||
awslogs_stream_prefix = "consul-agent-${aws_ecs_cluster.cluster.name}"
|
||||
awslogs_region = "${var.region}"
|
||||
}
|
||||
}
|
||||
|
||||
# End Data block
|
||||
|
||||
resource "aws_ecs_task_definition" "consul" {
|
||||
count = "${var.enable_agents ? 1 : 0}"
|
||||
family = "consul-agent-${aws_ecs_cluster.cluster.name}"
|
||||
container_definitions = "${data.template_file.consul.rendered}"
|
||||
network_mode = "host"
|
||||
task_role_arn = "${aws_iam_role.consul_task.arn}"
|
||||
|
||||
volume {
|
||||
name = "consul-config-dir"
|
||||
host_path = "/etc/consul"
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "docker-sock"
|
||||
host_path = "/var/run/docker.sock"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_log_group" "consul" {
|
||||
count = "${var.enable_agents ? 1 : 0}"
|
||||
name = "${aws_ecs_task_definition.consul.family}"
|
||||
|
||||
tags {
|
||||
VPC = "${data.aws_vpc.vpc.tags["Name"]}"
|
||||
Application = "${aws_ecs_task_definition.consul.family}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_ecs_service" "consul" {
|
||||
count = "${var.enable_agents ? 1 : 0}"
|
||||
name = "consul-agent-${aws_ecs_cluster.cluster.name}"
|
||||
cluster = "${aws_ecs_cluster.cluster.id}"
|
||||
task_definition = "${aws_ecs_task_definition.consul.arn}"
|
||||
desired_count = "${var.servers}"
|
||||
deployment_minimum_healthy_percent = "60"
|
||||
|
||||
placement_constraints {
|
||||
type = "distinctInstance"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# Thank God for Circle CI for this post
|
||||
# https://circleci.com/blog/graceful-shutdown-using-aws/
|
||||
|
||||
resource "aws_autoscaling_lifecycle_hook" "graceful_shutdown_asg_hook" {
|
||||
name = "graceful_shutdown_asg"
|
||||
autoscaling_group_name = "${aws_autoscaling_group.ecs.name}"
|
||||
default_result = "CONTINUE"
|
||||
heartbeat_timeout = "${var.heartbeat_timeout}"
|
||||
lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING"
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
resource "aws_iam_instance_profile" "ecs_profile" {
|
||||
name_prefix = "${replace(format("%.102s", replace("tf-ECSProfile-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
role = "${aws_iam_role.ecs_role.name}"
|
||||
path = "${var.iam_path}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "ecs_role" {
|
||||
name_prefix = "${replace(format("%.32s", replace("tf-ECSInRole-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
path = "${var.iam_path}"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": ["ecs.amazonaws.com", "ec2.amazonaws.com"]
|
||||
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# It may be useful to add the following for troubleshooting the InstanceStatus
|
||||
# Health check if using the fitnesskeeper/consul docker image
|
||||
# "ec2:Describe*",
|
||||
# "autoscaling:Describe*",
|
||||
|
||||
resource "aws_iam_policy" "ecs_policy" {
|
||||
name_prefix = "${replace(format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
description = "A terraform created policy for ECS"
|
||||
path = "${var.iam_path}"
|
||||
count = "${length(var.custom_iam_policy) > 0 ? 0 : 1}"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ecs:CreateCluster",
|
||||
"ecs:DeregisterContainerInstance",
|
||||
"ecs:DiscoverPollEndpoint",
|
||||
"ecs:Poll",
|
||||
"ecs:RegisterContainerInstance",
|
||||
"ecs:StartTelemetrySession",
|
||||
"ecs:Submit*",
|
||||
"ecr:GetAuthorizationToken",
|
||||
"ecr:BatchCheckLayerAvailability",
|
||||
"ecr:GetDownloadUrlForLayer",
|
||||
"ecr:BatchGetImage",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_policy" "custom_ecs_policy" {
|
||||
name_prefix = "${replace(format("%.102s", replace("tf-ECSInPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
description = "A terraform created policy for ECS"
|
||||
path = "${var.iam_path}"
|
||||
count = "${length(var.custom_iam_policy) > 0 ? 1 : 0}"
|
||||
|
||||
policy = "${var.custom_iam_policy}"
|
||||
}
|
||||
|
||||
resource "aws_iam_policy_attachment" "attach_ecs" {
|
||||
name = "ecs-attachment"
|
||||
roles = ["${aws_iam_role.ecs_role.name}"]
|
||||
policy_arn = "${element(concat(aws_iam_policy.ecs_policy.*.arn, aws_iam_policy.custom_ecs_policy.*.arn), 0)}"
|
||||
}
|
||||
|
||||
# IAM Resources for Consul and Registrator Agents
|
||||
|
||||
data "aws_iam_policy_document" "consul_task_policy" {
|
||||
statement {
|
||||
actions = [
|
||||
"ec2:Describe*",
|
||||
"autoscaling:Describe*",
|
||||
]
|
||||
|
||||
resources = ["*"]
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "assume_role_consul_task" {
|
||||
statement {
|
||||
actions = ["sts:AssumeRole"]
|
||||
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = ["ecs-tasks.amazonaws.com"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "consul_task" {
|
||||
count = "${var.enable_agents ? 1 : 0}"
|
||||
name_prefix = "${replace(format("%.32s", replace("tf-agentTaskRole-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
path = "${var.iam_path}"
|
||||
assume_role_policy = "${data.aws_iam_policy_document.assume_role_consul_task.json}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "consul_ecs_task" {
|
||||
count = "${var.enable_agents ? 1 : 0}"
|
||||
name_prefix = "${replace(format("%.102s", replace("tf-agentTaskPol-${var.name}-", "_", "-")), "/\\s/", "-")}"
|
||||
role = "${aws_iam_role.consul_task.id}"
|
||||
policy = "${data.aws_iam_policy_document.consul_task_policy.json}"
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
data "aws_ami" "ecs_ami" {
|
||||
most_recent = true
|
||||
owners = ["amazon"]
|
||||
|
||||
filter {
|
||||
name = "name"
|
||||
values = ["amzn-ami-${var.ami_version}-amazon-ecs-optimized"]
|
||||
}
|
||||
}
|
||||
|
||||
data "template_file" "user_data" {
|
||||
template = "${file("${path.module}/templates/user_data.tpl")}"
|
||||
|
||||
vars {
|
||||
additional_user_data_script = "${var.additional_user_data_script}"
|
||||
cluster_name = "${aws_ecs_cluster.cluster.name}"
|
||||
docker_storage_size = "${var.docker_storage_size}"
|
||||
dockerhub_token = "${var.dockerhub_token}"
|
||||
dockerhub_email = "${var.dockerhub_email}"
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_vpc" "vpc" {
|
||||
id = "${var.vpc_id}"
|
||||
}
|
||||
|
||||
resource "aws_launch_configuration" "ecs" {
|
||||
name_prefix = "${coalesce(var.name_prefix, "ecs-${var.name}-")}"
|
||||
image_id = "${var.ami == "" ? format("%s", data.aws_ami.ecs_ami.id) : var.ami}" # Workaround until 0.9.6
|
||||
instance_type = "${var.instance_type}"
|
||||
key_name = "${var.key_name}"
|
||||
iam_instance_profile = "${aws_iam_instance_profile.ecs_profile.name}"
|
||||
security_groups = ["${concat(list(aws_security_group.ecs.id), var.security_group_ids)}"]
|
||||
associate_public_ip_address = "${var.associate_public_ip_address}"
|
||||
spot_price = "${var.spot_bid_price}"
|
||||
|
||||
ebs_block_device {
|
||||
device_name = "${var.ebs_block_device}"
|
||||
volume_size = "${var.docker_storage_size}"
|
||||
volume_type = "gp2"
|
||||
delete_on_termination = true
|
||||
}
|
||||
|
||||
user_data = "${coalesce(var.user_data, data.template_file.user_data.rendered)}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_autoscaling_group" "ecs" {
|
||||
name_prefix = "asg-${aws_launch_configuration.ecs.name}-"
|
||||
vpc_zone_identifier = ["${var.subnet_id}"]
|
||||
launch_configuration = "${aws_launch_configuration.ecs.name}"
|
||||
min_size = "${var.min_servers}"
|
||||
max_size = "${var.max_servers}"
|
||||
desired_capacity = "${var.servers}"
|
||||
termination_policies = ["OldestLaunchConfiguration", "ClosestToNextInstanceHour", "Default"]
|
||||
load_balancers = ["${var.load_balancers}"]
|
||||
enabled_metrics = ["${var.enabled_metrics}"]
|
||||
|
||||
tags = [{
|
||||
key = "Name"
|
||||
value = "${var.name} ${var.tagName}"
|
||||
propagate_at_launch = true
|
||||
}]
|
||||
|
||||
tags = ["${var.extra_tags}"]
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
|
||||
timeouts {
|
||||
delete = "${var.heartbeat_timeout + var.asg_delete_extra_timeout}s"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "ecs" {
|
||||
name = "ecs-sg-${var.name}"
|
||||
description = "Container Instance Allowed Ports"
|
||||
vpc_id = "${data.aws_vpc.vpc.id}"
|
||||
|
||||
ingress {
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.allowed_cidr_blocks}"
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.allowed_cidr_blocks}"
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags {
|
||||
Name = "ecs-sg-${var.name}"
|
||||
}
|
||||
}
|
||||
|
||||
# Make this a var that an get passed in?
|
||||
resource "aws_ecs_cluster" "cluster" {
|
||||
name = "${var.name}"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
output "cluster_id" {
|
||||
value = "${aws_ecs_cluster.cluster.id}"
|
||||
}
|
||||
|
||||
output "cluster_name" {
|
||||
value = "${aws_ecs_cluster.cluster.name}"
|
||||
}
|
||||
|
||||
output "instance_role_arn" {
|
||||
value = "${aws_iam_role.ecs_role.arn}"
|
||||
}
|
||||
|
||||
output "instance_role_id" {
|
||||
value = "${aws_iam_role.ecs_role.id}"
|
||||
}
|
||||
|
||||
output "autoscaling_group" {
|
||||
value = {
|
||||
id = "${aws_autoscaling_group.ecs.id}"
|
||||
name = "${aws_autoscaling_group.ecs.name}"
|
||||
arn = "${aws_autoscaling_group.ecs.arn}"
|
||||
}
|
||||
}
|
||||
|
||||
output "iam_role" {
|
||||
value = {
|
||||
name = "${aws_iam_role.ecs_role.name}"
|
||||
arn = "${aws_iam_role.ecs_role.arn}"
|
||||
}
|
||||
}
|
||||
|
||||
output "security_group" {
|
||||
value = {
|
||||
id = "${aws_security_group.ecs.id}"
|
||||
name = "${aws_security_group.ecs.name}"
|
||||
arn = "${aws_security_group.ecs.arn}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
variable "additional_user_data_script" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "allowed_cidr_blocks" {
|
||||
default = ["0.0.0.0/0"]
|
||||
type = "list"
|
||||
description = "List of subnets to allow into the ECS Security Group. Defaults to ['0.0.0.0/0']"
|
||||
}
|
||||
|
||||
variable "ami" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ami_version" {
|
||||
default = "*"
|
||||
}
|
||||
|
||||
variable "associate_public_ip_address" {
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "consul_image" {
|
||||
description = "Image to use when deploying consul, defaults to the hashicorp consul image"
|
||||
default = "consul:latest"
|
||||
}
|
||||
|
||||
variable "consul_memory_reservation" {
|
||||
description = "The soft limit (in MiB) of memory to reserve for the container, defaults 20"
|
||||
default = "32"
|
||||
}
|
||||
|
||||
variable "docker_storage_size" {
|
||||
default = "22"
|
||||
description = "EBS Volume size in Gib that the ECS Instance uses for Docker images and metadata "
|
||||
}
|
||||
|
||||
variable "dockerhub_email" {
|
||||
default = ""
|
||||
description = "Email Address used to authenticate to dockerhub. http://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html"
|
||||
}
|
||||
|
||||
variable "dockerhub_token" {
|
||||
default = ""
|
||||
description = "Auth Token used for dockerhub. http://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html"
|
||||
}
|
||||
|
||||
variable "enable_agents" {
|
||||
default = false
|
||||
description = "Enable Consul Agent and Registrator tasks on each ECS Instance"
|
||||
}
|
||||
|
||||
variable "ebs_block_device" {
|
||||
default = "/dev/xvdcz"
|
||||
description = "EBS block devices to attach to the instance. (default: /dev/xvdcz)"
|
||||
}
|
||||
|
||||
variable "extra_tags" {
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "heartbeat_timeout" {
|
||||
description = "Heartbeat Timeout setting for how long it takes for the graceful shutodwn hook takes to timeout. This is useful when deploying clustered applications like consul that benifit from having a deploy between autoscaling create/destroy actions. Defaults to 180"
|
||||
default = "180"
|
||||
}
|
||||
|
||||
variable "asg_delete_extra_timeout" {
|
||||
description = "Extra time that `terraform apply` will wait for ASG deletion (default 600). This is added on top of `heartbeat_timeout`. This variable is customizable for when the instances take longer than 600sec to shut down once shutdown is initiated."
|
||||
default = "600"
|
||||
}
|
||||
|
||||
variable "iam_path" {
|
||||
default = "/"
|
||||
description = "IAM path, this is useful when creating resources with the same name across multiple regions. Defaults to /"
|
||||
}
|
||||
|
||||
variable "custom_iam_policy" {
|
||||
default = ""
|
||||
description = "Custom IAM policy (JSON). If set will overwrite the default one"
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
default = "t2.micro"
|
||||
description = "AWS Instance type, if you change, make sure it is compatible with AMI, not all AMIs allow all instance types "
|
||||
}
|
||||
|
||||
variable "key_name" {
|
||||
description = "SSH key name in your AWS account for AWS instances."
|
||||
}
|
||||
|
||||
variable "load_balancers" {
|
||||
type = "list"
|
||||
default = []
|
||||
description = "A list of elastic load balancer names to add to the autoscaling group names. Only valid for classic load balancers."
|
||||
}
|
||||
|
||||
variable "min_servers" {
|
||||
description = "Minimum number of ECS servers to run."
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "max_servers" {
|
||||
description = "Maximum number of ECS servers to run."
|
||||
default = 10
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
description = "AWS ECS Cluster Name"
|
||||
}
|
||||
|
||||
variable "name_prefix" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
default = "us-east-1"
|
||||
description = "The region of AWS, for AMI lookups."
|
||||
}
|
||||
|
||||
variable "registrator_image" {
|
||||
default = "gliderlabs/registrator:latest"
|
||||
description = "Image to use when deploying registrator agent, defaults to the gliderlabs registrator:latest image"
|
||||
}
|
||||
|
||||
variable "registrator_memory_reservation" {
|
||||
description = "The soft limit (in MiB) of memory to reserve for the container, defaults 20"
|
||||
default = "32"
|
||||
}
|
||||
|
||||
variable "security_group_ids" {
|
||||
type = "list"
|
||||
description = "A list of Security group IDs to apply to the launch configuration"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "servers" {
|
||||
default = "1"
|
||||
description = "The number of servers to launch."
|
||||
}
|
||||
|
||||
variable "spot_bid_price" {
|
||||
default = ""
|
||||
description = "If specified, spot instances will be requested at this bid price. If not specified, on-demand instances will be used."
|
||||
}
|
||||
|
||||
variable "subnet_id" {
|
||||
type = "list"
|
||||
description = "The AWS Subnet ID in which you want to delpoy your instances"
|
||||
}
|
||||
|
||||
variable "tagName" {
|
||||
default = "ECS Node"
|
||||
description = "Name tag for the servers"
|
||||
}
|
||||
|
||||
variable "user_data" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "The AWS VPC ID which you want to deploy your instances"
|
||||
}
|
||||
|
||||
variable "enabled_metrics" {
|
||||
description = "A list of metrics to collect"
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
resource "aws_iam_role" "sns" {
|
||||
name = "${var.autoscaling_group_name}-notifies-sns"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "autoscaling.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# creating policy document and attaching as inline policies instead of using the AutoScalingNotificationAccessRole
|
||||
# managed policy due to Terraform issue https://github.com/hashicorp/terraform/issues/5979.
|
||||
|
||||
data "aws_iam_policy_document" "auto_scaling_notification_access" {
|
||||
statement {
|
||||
sid = "1"
|
||||
|
||||
actions = [
|
||||
"sqs:SendMessage",
|
||||
"sqs:GetQueueUrl",
|
||||
"sns:Publish",
|
||||
]
|
||||
|
||||
resources = [
|
||||
"*",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "asg_notification_sns" {
|
||||
name = "${aws_iam_role.sns.name}-asg-notification-policy"
|
||||
role = "${aws_iam_role.sns.id}"
|
||||
policy = "${data.aws_iam_policy_document.auto_scaling_notification_access.json}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "lambda" {
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "lambda.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "lambda" {
|
||||
statement {
|
||||
sid = "1"
|
||||
|
||||
actions = [
|
||||
"autoscaling:CompleteLifecycleAction",
|
||||
"logs:CreateLogGroup",
|
||||
"logs:CreateLogStream",
|
||||
"logs:PutLogEvents",
|
||||
"ec2:DescribeInstances",
|
||||
"ec2:DescribeInstanceAttribute",
|
||||
"ec2:DescribeInstanceStatus",
|
||||
"ec2:DescribeHosts",
|
||||
"ecs:ListContainerInstances",
|
||||
"ecs:SubmitContainerStateChange",
|
||||
"ecs:SubmitTaskStateChange",
|
||||
"ecs:DescribeContainerInstances",
|
||||
"ecs:UpdateContainerInstancesState",
|
||||
"ecs:ListTasks",
|
||||
"ecs:DescribeTasks",
|
||||
"sns:Publish",
|
||||
"sns:ListSubscriptions",
|
||||
]
|
||||
|
||||
resources = [
|
||||
"*",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "lambda" {
|
||||
name = "${aws_iam_role.lambda.name}-policy"
|
||||
role = "${aws_iam_role.lambda.id}"
|
||||
policy = "${data.aws_iam_policy_document.lambda.json}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "asg_notification_lambda" {
|
||||
name = "${aws_iam_role.lambda.name}-asg-notification-policy"
|
||||
role = "${aws_iam_role.lambda.id}"
|
||||
policy = "${data.aws_iam_policy_document.auto_scaling_notification_access.json}"
|
||||
}
|
||||
|
||||
data "archive_file" "index" {
|
||||
type = "zip"
|
||||
source_dir = "${path.module}/index"
|
||||
output_path = "${path.module}/files/index.zip"
|
||||
}
|
||||
|
||||
resource "aws_lambda_function" "lambda" {
|
||||
runtime = "python3.6"
|
||||
filename = "${path.module}/files/index.zip"
|
||||
function_name = "${substr(var.autoscaling_group_name,0,min(64, length(var.autoscaling_group_name)))}"
|
||||
role = "${aws_iam_role.lambda.arn}"
|
||||
handler = "index.lambda_handler"
|
||||
timeout = "${var.function_sleep_time * 2}"
|
||||
|
||||
source_code_hash = "${data.archive_file.index.output_base64sha256}"
|
||||
|
||||
environment {
|
||||
variables = {
|
||||
REGION = "${var.region}"
|
||||
CLUSTER_NAME = "${var.cluster_name}"
|
||||
SLEEP_TIME = "${var.function_sleep_time}"
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
# A workaround when running this code on different machines is to ignore changes, as described here:
|
||||
# https://github.com/hashicorp/terraform/issues/7613#issuecomment-241603087
|
||||
ignore_changes = ["filename"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lambda_permission" "sns" {
|
||||
statement_id = "AllowExecutionFromSNS"
|
||||
function_name = "${aws_lambda_function.lambda.arn}"
|
||||
action = "lambda:InvokeFunction"
|
||||
principal = "sns.amazonaws.com"
|
||||
source_arn = "${aws_sns_topic.asg_sns.arn}"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "asg_sns" {
|
||||
name = "${var.autoscaling_group_name}-sns-topic"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_subscription" "asg_sns" {
|
||||
topic_arn = "${aws_sns_topic.asg_sns.arn}"
|
||||
protocol = "lambda"
|
||||
endpoint = "${aws_lambda_function.lambda.arn}"
|
||||
}
|
||||
|
||||
resource "aws_autoscaling_lifecycle_hook" "terminate" {
|
||||
count = "${var.lambda_enabled}"
|
||||
name = "${var.autoscaling_group_name}-terminate-hook"
|
||||
autoscaling_group_name = "${var.autoscaling_group_name}"
|
||||
default_result = "${var.hook_default_result}"
|
||||
heartbeat_timeout = "${var.hook_heartbeat_timeout}"
|
||||
lifecycle_transition = "autoscaling:EC2_INSTANCE_TERMINATING"
|
||||
notification_target_arn = "${aws_sns_topic.asg_sns.arn}"
|
||||
role_arn = "${aws_iam_role.sns.arn}"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
variable "region" {}
|
||||
|
||||
variable "cluster_name" {}
|
||||
|
||||
variable "autoscaling_group_name" {}
|
||||
|
||||
variable "function_sleep_time" {
|
||||
description = "Number of seconds the function should sleep before checking ECS Instance Task Count again"
|
||||
default = 15
|
||||
}
|
||||
|
||||
variable "lambda_enabled" {
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "hook_heartbeat_timeout" {
|
||||
default = 900
|
||||
}
|
||||
|
||||
variable "hook_default_result" {
|
||||
default = "ABANDON"
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
data "aws_iam_policy_document" "pganalyze_task_policy" {
|
||||
statement {
|
||||
actions = [
|
||||
"ec2:Describe*",
|
||||
"autoscaling:Describe*",
|
||||
"ec2:DescribeAddresses",
|
||||
"ec2:DescribeInstances",
|
||||
"ec2:DescribeTags",
|
||||
]
|
||||
|
||||
resources = ["*"]
|
||||
}
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"cloudwatch:GetMetricStatistics",
|
||||
"logs:DescribeLogStreams",
|
||||
"logs:GetLogEvents",
|
||||
"logs:PutLogEvents",
|
||||
]
|
||||
|
||||
resources = [
|
||||
"*",
|
||||
]
|
||||
}
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"rds:DownloadDBLogFilePortion",
|
||||
]
|
||||
|
||||
resources = [
|
||||
"*",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "assume_role_pganalyze_task" {
|
||||
statement {
|
||||
actions = ["sts:AssumeRole"]
|
||||
|
||||
principals {
|
||||
type = "Service"
|
||||
identifiers = ["ecs-tasks.amazonaws.com"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "pganalyze_task" {
|
||||
count = "${local.service_count}"
|
||||
name = "tf-pganalyze-${var.task_identifier}-ecsTaskRole"
|
||||
path = "/"
|
||||
assume_role_policy = "${data.aws_iam_policy_document.assume_role_pganalyze_task.json}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "pganalyze_ecs_task" {
|
||||
count = "${local.service_count}"
|
||||
name = "tf-pganalyze-${var.task_identifier}-ecsTaskPolicy"
|
||||
role = "${aws_iam_role.pganalyze_task.id}"
|
||||
policy = "${data.aws_iam_policy_document.pganalyze_task_policy.json}"
|
||||
}
|
||||
|
||||
# ecsServiceRole for pganalyze
|
||||
|
||||
resource "aws_iam_role" "ecsServiceRole" {
|
||||
count = "${local.service_count}"
|
||||
name = "tf-pganalyze-${var.task_identifier}-ecsSvcRole"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": ["ecs.amazonaws.com"]
|
||||
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "attach-ecsServiceRole" {
|
||||
count = "${local.service_count}"
|
||||
role = "${aws_iam_role.ecsServiceRole.name}"
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
locals {
|
||||
service_count = "${length(var.pga_api_key) > 0 ? 1 : 0}"
|
||||
}
|
||||
|
||||
data "aws_ecs_cluster" "ecs" {
|
||||
cluster_name = "${var.ecs_cluster}"
|
||||
}
|
||||
|
||||
data "aws_region" "current" {
|
||||
current = true
|
||||
}
|
||||
|
||||
data "template_file" "pganalyze" {
|
||||
template = "${file("${path.module}/files/pganalyze.json")}"
|
||||
|
||||
vars {
|
||||
task_identifier = "${var.task_identifier}"
|
||||
db_url = "postgres://${var.db_username}:${var.db_password}@${var.rds_endpoint}/${var.db_name}"
|
||||
image = "${var.docker_image}"
|
||||
pga_api_key = "${var.pga_api_key}"
|
||||
aws_instance_id = "${var.aws_instance_id}" # we can almost certainly derive this
|
||||
aws_region = "${data.aws_region.current.name}"
|
||||
awslogs_group = "${var.log_group}"
|
||||
awslogs_region = "${data.aws_region.current.name}"
|
||||
awslogs_stream_prefix = "tf"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_ecs_task_definition" "pganalyze" {
|
||||
count = "${local.service_count}"
|
||||
family = "pganalyze-${var.env}-${var.task_identifier}"
|
||||
container_definitions = "${data.template_file.pganalyze.rendered}"
|
||||
network_mode = "bridge"
|
||||
task_role_arn = "${aws_iam_role.pganalyze_task.arn}"
|
||||
}
|
||||
|
||||
resource "aws_ecs_service" "pganalyze" {
|
||||
count = "${local.service_count}"
|
||||
name = "pganalyze-${var.env}-${var.task_identifier}"
|
||||
cluster = "${data.aws_ecs_cluster.ecs.id}"
|
||||
task_definition = "${aws_ecs_task_definition.pganalyze.arn}"
|
||||
desired_count = 1
|
||||
|
||||
placement_strategy {
|
||||
type = "binpack"
|
||||
field = "memory"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
variable "env" {
|
||||
description = "Environment tag (default 'dev')"
|
||||
default = "dev"
|
||||
}
|
||||
|
||||
variable "ecs_cluster" {
|
||||
description = "Name of ECS cluster in which the service will be deployed"
|
||||
}
|
||||
|
||||
variable "docker_image" {
|
||||
description = "Docker image containing pganalyze collector (default is upstream stable)"
|
||||
default = "quay.io/pganalyze/collector:stable"
|
||||
}
|
||||
|
||||
variable "pga_api_key" {
|
||||
description = "pganalyze API key associated with database (register the database in the pganalyze console to obtain this)"
|
||||
}
|
||||
|
||||
variable "aws_instance_id" {
|
||||
description = "some AWS instance id?"
|
||||
}
|
||||
|
||||
variable "task_identifier" {
|
||||
description = "Unique identifier for this pganalyze task (used in log prefix, service name etc.)"
|
||||
}
|
||||
|
||||
variable "db_username" {
|
||||
description = "Username of pganalyze monitoring role"
|
||||
}
|
||||
|
||||
variable "db_password" {
|
||||
description = "Password of pganalyze monitoring role"
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
description = "Name of database to be monitored"
|
||||
}
|
||||
|
||||
variable "rds_endpoint" {
|
||||
description = "Endpoint of RDS instance to be monitored"
|
||||
}
|
||||
|
||||
variable "log_group" {
|
||||
description = "CloudWatch Log Group that will receive collector logs (must exist already)"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# Cloudwatch resources inspired by https://github.com/azavea/terraform-aws-redis-elasticache
|
||||
# Stubbing this out, we should have conversation about monitoring before we make this the default behavior
|
||||
# For this module
|
||||
/*
|
||||
|
||||
resource "aws_cloudwatch_metric_alarm" "cache_cpu" {
|
||||
count = "${var.redis_clusters}"
|
||||
|
||||
alarm_name = "alarm-${var.name}-${local.vpc_name}-CacheCluster00${count.index + 1}CPUUtilization"
|
||||
alarm_description = "Redis cluster CPU utilization"
|
||||
comparison_operator = "GreaterThanThreshold"
|
||||
evaluation_periods = "1"
|
||||
metric_name = "CPUUtilization"
|
||||
namespace = "AWS/ElastiCache"
|
||||
period = "300"
|
||||
statistic = "Average"
|
||||
|
||||
threshold = "${var.alarm_cpu_threshold}"
|
||||
|
||||
dimensions {
|
||||
CacheClusterId = "${aws_elasticache_replication_group.redis.id}-00${count.index + 1}"
|
||||
}
|
||||
|
||||
alarm_actions = ["${var.alarm_actions}"]
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_metric_alarm" "cache_memory" {
|
||||
count = "${var.redis_clusters}"
|
||||
|
||||
alarm_name = "alarm-${var.name}-${local.vpc_name}-CacheCluster00${count.index + 1}FreeableMemory"
|
||||
alarm_description = "Redis cluster freeable memory"
|
||||
comparison_operator = "LessThanThreshold"
|
||||
evaluation_periods = "1"
|
||||
metric_name = "FreeableMemory"
|
||||
namespace = "AWS/ElastiCache"
|
||||
period = "60"
|
||||
statistic = "Average"
|
||||
|
||||
threshold = "${var.alarm_memory_threshold}"
|
||||
|
||||
dimensions {
|
||||
CacheClusterId = "${aws_elasticache_replication_group.redis.id}-00${count.index + 1}"
|
||||
}
|
||||
|
||||
alarm_actions = ["${var.alarm_actions}"]
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
data "aws_vpc" "vpc" {
|
||||
id = var.vpc_id
|
||||
}
|
||||
|
||||
locals {
|
||||
vpc_name = lookup(data.aws_vpc.vpc.tags, "Name", var.vpc_id)
|
||||
}
|
||||
|
||||
resource "random_id" "salt" {
|
||||
byte_length = 8
|
||||
keepers = {
|
||||
redis_version = var.redis_version
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_elasticache_replication_group" "redis" {
|
||||
replication_group_id = format("%.20s", "${var.name}-${var.env}")
|
||||
replication_group_description = "Terraform-managed ElastiCache replication group for ${var.name}-${var.env}-${local.vpc_name}"
|
||||
number_cache_clusters = var.redis_clusters
|
||||
node_type = var.redis_node_type
|
||||
automatic_failover_enabled = var.redis_failover
|
||||
auto_minor_version_upgrade = var.auto_minor_version_upgrade
|
||||
availability_zones = var.availability_zones
|
||||
multi_az_enabled = var.multi_az_enabled
|
||||
engine = "redis"
|
||||
at_rest_encryption_enabled = var.at_rest_encryption_enabled
|
||||
kms_key_id = var.kms_key_id
|
||||
transit_encryption_enabled = var.transit_encryption_enabled
|
||||
auth_token = var.transit_encryption_enabled ? var.auth_token : null
|
||||
engine_version = var.redis_version
|
||||
port = var.redis_port
|
||||
parameter_group_name = aws_elasticache_parameter_group.redis_parameter_group.id
|
||||
subnet_group_name = aws_elasticache_subnet_group.redis_subnet_group.id
|
||||
security_group_names = var.security_group_names
|
||||
security_group_ids = [aws_security_group.redis_security_group.id]
|
||||
snapshot_arns = var.snapshot_arns
|
||||
snapshot_name = var.snapshot_name
|
||||
apply_immediately = var.apply_immediately
|
||||
maintenance_window = var.redis_maintenance_window
|
||||
notification_topic_arn = var.notification_topic_arn
|
||||
snapshot_window = var.redis_snapshot_window
|
||||
snapshot_retention_limit = var.redis_snapshot_retention_limit
|
||||
tags = merge(tomap({"Name" = format("tf-elasticache-%s-%s", var.name, local.vpc_name)}), var.tags)
|
||||
}
|
||||
|
||||
resource "aws_elasticache_parameter_group" "redis_parameter_group" {
|
||||
name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${local.vpc_name}-${random_id.salt.hex}", "_", "-"))), "/\\s/", "-")
|
||||
|
||||
description = "Terraform-managed ElastiCache parameter group for ${var.name}-${var.env}-${local.vpc_name}"
|
||||
|
||||
# Strip the patch version from redis_version var
|
||||
family = "redis${replace(var.redis_version, "/\\.[\\d]+$/", "")}"
|
||||
dynamic "parameter" {
|
||||
for_each = var.redis_parameters
|
||||
content {
|
||||
name = parameter.value.name
|
||||
value = parameter.value.value
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_elasticache_subnet_group" "redis_subnet_group" {
|
||||
name = replace(format("%.255s", lower(replace("tf-redis-${var.name}-${var.env}-${local.vpc_name}", "_", "-"))), "/\\s/", "-")
|
||||
subnet_ids = var.subnets
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
output "redis_security_group_id" {
|
||||
value = aws_security_group.redis_security_group.id
|
||||
}
|
||||
|
||||
output "parameter_group" {
|
||||
value = aws_elasticache_parameter_group.redis_parameter_group.id
|
||||
}
|
||||
|
||||
output "redis_subnet_group_name" {
|
||||
value = aws_elasticache_subnet_group.redis_subnet_group.name
|
||||
}
|
||||
|
||||
output "id" {
|
||||
value = aws_elasticache_replication_group.redis.id
|
||||
}
|
||||
|
||||
output "port" {
|
||||
value = var.redis_port
|
||||
}
|
||||
|
||||
output "endpoint" {
|
||||
value = aws_elasticache_replication_group.redis.primary_endpoint_address
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
resource "aws_security_group" "redis_security_group" {
|
||||
name = format("%.255s", "tf-sg-ec-${var.name}-${var.env}-${local.vpc_name}")
|
||||
description = "Terraform-managed ElastiCache security group for ${var.name}-${var.env}-${local.vpc_name}"
|
||||
vpc_id = data.aws_vpc.vpc.id
|
||||
|
||||
tags = {
|
||||
Name = "tf-sg-ec-${var.name}-${var.env}-${local.vpc_name}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "redis_ingress" {
|
||||
count = length(var.allowed_security_groups)
|
||||
type = "ingress"
|
||||
from_port = var.redis_port
|
||||
to_port = var.redis_port
|
||||
protocol = "tcp"
|
||||
source_security_group_id = element(var.allowed_security_groups, count.index)
|
||||
security_group_id = aws_security_group.redis_security_group.id
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "redis_networks_ingress" {
|
||||
type = "ingress"
|
||||
from_port = var.redis_port
|
||||
to_port = var.redis_port
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.allowed_cidr
|
||||
security_group_id = aws_security_group.redis_security_group.id
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
# These vars would be used by cloudwatch.tf and should be uncommented if we decide to use them.
|
||||
variable "alarm_cpu_threshold" {
|
||||
default = "75"
|
||||
}
|
||||
|
||||
variable "alarm_memory_threshold" {
|
||||
# 10MB
|
||||
default = "10000000"
|
||||
}
|
||||
|
||||
variable "alarm_actions" {
|
||||
type = "list"
|
||||
}
|
||||
*/
|
||||
|
||||
variable "apply_immediately" {
|
||||
description = "Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is false."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "allowed_cidr" {
|
||||
description = "A list of Security Group ID's to allow access to."
|
||||
type = list(string)
|
||||
default = ["127.0.0.1/32"]
|
||||
}
|
||||
|
||||
variable "allowed_security_groups" {
|
||||
description = "A list of Security Group ID's to allow access to."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "env" {
|
||||
description = "env to deploy into, should typically dev/staging/prod"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "name" {
|
||||
description = "Name for the Redis replication group i.e. UserObject"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "redis_clusters" {
|
||||
description = "Number of Redis cache clusters (nodes) to create"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "redis_failover" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "multi_az_enabled" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "redis_node_type" {
|
||||
description = "Instance type to use for creating the Redis cache clusters"
|
||||
type = string
|
||||
default = "cache.m3.medium"
|
||||
}
|
||||
|
||||
variable "redis_port" {
|
||||
type = number
|
||||
default = 6379
|
||||
}
|
||||
|
||||
variable "subnets" {
|
||||
type = list(string)
|
||||
description = "List of VPC Subnet IDs for the cache subnet group"
|
||||
}
|
||||
|
||||
# might want a map
|
||||
variable "redis_version" {
|
||||
description = "Redis version to use, defaults to 3.2.10"
|
||||
type = string
|
||||
default = "3.2.10"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "VPC ID"
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "redis_parameters" {
|
||||
description = "additional parameters modifyed in parameter group"
|
||||
type = list(map(any))
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "redis_maintenance_window" {
|
||||
description = "Specifies the weekly time range for when maintenance on the cache cluster is performed. The format is ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). The minimum maintenance window is a 60 minute period"
|
||||
type = string
|
||||
default = "fri:08:00-fri:09:00"
|
||||
}
|
||||
|
||||
variable "redis_snapshot_window" {
|
||||
description = "The daily time range (in UTC) during which ElastiCache will begin taking a daily snapshot of your cache cluster. The minimum snapshot window is a 60 minute period"
|
||||
type = string
|
||||
default = "06:30-07:30"
|
||||
}
|
||||
|
||||
variable "redis_snapshot_retention_limit" {
|
||||
description = "The number of days for which ElastiCache will retain automatic cache cluster snapshots before deleting them. For example, if you set SnapshotRetentionLimit to 5, then a snapshot that was taken today will be retained for 5 days before being deleted. If the value of SnapshotRetentionLimit is set to zero (0), backups are turned off. Please note that setting a snapshot_retention_limit is not supported on cache.t1.micro or cache.t2.* cache nodes"
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "Tags for redis nodes"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "auto_minor_version_upgrade" {
|
||||
description = "Specifies whether a minor engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "availability_zones" {
|
||||
description = "A list of EC2 availability zones in which the replication group's cache clusters will be created. The order of the availability zones in the list is not important"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "at_rest_encryption_enabled" {
|
||||
description = "Whether to enable encryption at rest"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "kms_key_id" {
|
||||
description = "The ARN of the key that you wish to use if encrypting at rest. If not supplied, uses service managed encryption. Can be specified only if at_rest_encryption_enabled = true"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "transit_encryption_enabled" {
|
||||
description = "Whether to enable encryption in transit. Requires 3.2.6 or >=4.0 redis_version"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "auth_token" {
|
||||
description = "The password used to access a password protected server. Can be specified only if transit_encryption_enabled = true. If specified must contain from 16 to 128 alphanumeric characters or symbols"
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "security_group_names" {
|
||||
description = "A list of cache security group names to associate with this replication group"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "snapshot_arns" {
|
||||
description = "A single-element string list containing an Amazon Resource Name (ARN) of a Redis RDB snapshot file stored in Amazon S3. Example: arn:aws:s3:::my_bucket/snapshot1.rdb"
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "snapshot_name" {
|
||||
description = " The name of a snapshot from which to restore data into the new node group. Changing the snapshot_name forces a new resource"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "notification_topic_arn" {
|
||||
description = "An Amazon Resource Name (ARN) of an SNS topic to send ElastiCache notifications to. Example: arn:aws:sns:us-east-1:012345678999:my_sns_topic"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
locals {
|
||||
domain_name = var.use_prefix ? join("", [var.domain_prefix, var.domain_name]) : var.domain_name
|
||||
inside_vpc = length(var.vpc_options["subnet_ids"]) > 0 ? true : false
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
data "aws_iam_policy_document" "es_management_access" {
|
||||
count = false == local.inside_vpc ? 1 : 0
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"es:*",
|
||||
]
|
||||
|
||||
resources = [
|
||||
aws_elasticsearch_domain.es[0].arn,
|
||||
"${aws_elasticsearch_domain.es[0].arn}/*",
|
||||
]
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
|
||||
identifiers = distinct(compact(var.management_iam_roles))
|
||||
}
|
||||
|
||||
condition {
|
||||
test = "IpAddress"
|
||||
variable = "aws:SourceIp"
|
||||
|
||||
values = distinct(compact(var.management_public_ip_addresses))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_elasticsearch_domain" "es" {
|
||||
count = false == local.inside_vpc ? 1 : 0
|
||||
|
||||
depends_on = [aws_iam_service_linked_role.es]
|
||||
|
||||
domain_name = local.domain_name
|
||||
elasticsearch_version = var.es_version
|
||||
|
||||
encrypt_at_rest {
|
||||
enabled = var.encrypt_at_rest
|
||||
kms_key_id = var.kms_key_id
|
||||
}
|
||||
|
||||
domain_endpoint_options {
|
||||
enforce_https = var.enforce_https
|
||||
tls_security_policy = var.tls_security_policy
|
||||
}
|
||||
|
||||
cluster_config {
|
||||
instance_type = var.instance_type
|
||||
instance_count = var.instance_count
|
||||
dedicated_master_enabled = var.instance_count >= var.dedicated_master_threshold ? true : false
|
||||
dedicated_master_count = var.instance_count >= var.dedicated_master_threshold ? 3 : 0
|
||||
dedicated_master_type = var.instance_count >= var.dedicated_master_threshold ? var.dedicated_master_type != "false" ? var.dedicated_master_type : var.instance_type : ""
|
||||
zone_awareness_enabled = var.es_zone_awareness
|
||||
dynamic "zone_awareness_config" {
|
||||
for_each = var.es_zone_awareness ? [var.es_zone_awareness_count] : []
|
||||
content {
|
||||
availability_zone_count = zone_awareness_config.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
advanced_options = var.advanced_options
|
||||
|
||||
dynamic "log_publishing_options" {
|
||||
for_each = var.log_publishing_options
|
||||
content {
|
||||
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
|
||||
# which keys might be set in maps assigned here, so it has
|
||||
# produced a comprehensive set here. Consider simplifying
|
||||
# this after confirming which keys can be set in practice.
|
||||
|
||||
cloudwatch_log_group_arn = log_publishing_options.value.cloudwatch_log_group_arn
|
||||
enabled = lookup(log_publishing_options.value, "enabled", null)
|
||||
log_type = log_publishing_options.value.log_type
|
||||
}
|
||||
}
|
||||
|
||||
node_to_node_encryption {
|
||||
enabled = var.node_to_node_encryption_enabled
|
||||
}
|
||||
|
||||
ebs_options {
|
||||
ebs_enabled = var.ebs_volume_size > 0 ? true : false
|
||||
volume_size = var.ebs_volume_size
|
||||
volume_type = var.ebs_volume_type
|
||||
}
|
||||
|
||||
snapshot_options {
|
||||
automated_snapshot_start_hour = var.snapshot_start_hour
|
||||
}
|
||||
|
||||
tags = merge(
|
||||
{
|
||||
"Domain" = local.domain_name
|
||||
},
|
||||
var.tags,
|
||||
)
|
||||
}
|
||||
|
||||
resource "aws_elasticsearch_domain_policy" "es_management_access" {
|
||||
count = false == local.inside_vpc ? 1 : 0
|
||||
|
||||
domain_name = local.domain_name
|
||||
access_policies = data.aws_iam_policy_document.es_management_access[0].json
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*Add a new set of data.aws_iam_policy_document, aws_elasticsearch_domain, aws_elasticsearch_domain_policy. Because currently terraform/aws_elasticsearch_domain
|
||||
does not handle properly null/empty "vpc_options" */
|
||||
|
||||
data "aws_iam_policy_document" "es_vpc_management_access" {
|
||||
count = local.inside_vpc ? 1 : 0
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"es:*",
|
||||
]
|
||||
|
||||
resources = [
|
||||
aws_elasticsearch_domain.es_vpc[0].arn,
|
||||
"${aws_elasticsearch_domain.es_vpc[0].arn}/*",
|
||||
]
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
|
||||
identifiers = distinct(compact(var.management_iam_roles))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_service_linked_role" "es" {
|
||||
count = var.create_iam_service_linked_role ? 1 : 0
|
||||
aws_service_name = "es.amazonaws.com"
|
||||
}
|
||||
|
||||
resource "aws_elasticsearch_domain" "es_vpc" {
|
||||
count = local.inside_vpc ? 1 : 0
|
||||
|
||||
depends_on = [aws_iam_service_linked_role.es]
|
||||
|
||||
domain_name = local.domain_name
|
||||
elasticsearch_version = var.es_version
|
||||
|
||||
encrypt_at_rest {
|
||||
enabled = var.encrypt_at_rest
|
||||
kms_key_id = var.kms_key_id
|
||||
}
|
||||
|
||||
domain_endpoint_options {
|
||||
enforce_https = var.enforce_https
|
||||
tls_security_policy = var.tls_security_policy
|
||||
}
|
||||
|
||||
cluster_config {
|
||||
instance_type = var.instance_type
|
||||
instance_count = var.instance_count
|
||||
dedicated_master_enabled = var.instance_count >= var.dedicated_master_threshold ? true : false
|
||||
dedicated_master_count = var.instance_count >= var.dedicated_master_threshold ? 3 : 0
|
||||
dedicated_master_type = var.instance_count >= var.dedicated_master_threshold ? var.dedicated_master_type != "false" ? var.dedicated_master_type : var.instance_type : ""
|
||||
zone_awareness_enabled = var.es_zone_awareness
|
||||
dynamic "zone_awareness_config" {
|
||||
for_each = var.es_zone_awareness ? [var.es_zone_awareness_count] : []
|
||||
content {
|
||||
availability_zone_count = zone_awareness_config.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
advanced_options = var.advanced_options
|
||||
|
||||
dynamic "log_publishing_options" {
|
||||
for_each = var.log_publishing_options
|
||||
content {
|
||||
# TF-UPGRADE-TODO: The automatic upgrade tool can't predict
|
||||
# which keys might be set in maps assigned here, so it has
|
||||
# produced a comprehensive set here. Consider simplifying
|
||||
# this after confirming which keys can be set in practice.
|
||||
|
||||
cloudwatch_log_group_arn = log_publishing_options.value.cloudwatch_log_group_arn
|
||||
enabled = lookup(log_publishing_options.value, "enabled", null)
|
||||
log_type = log_publishing_options.value.log_type
|
||||
}
|
||||
}
|
||||
|
||||
node_to_node_encryption {
|
||||
enabled = var.node_to_node_encryption_enabled
|
||||
}
|
||||
|
||||
vpc_options {
|
||||
subnet_ids = var.vpc_options["subnet_ids"]
|
||||
security_group_ids = var.vpc_options["security_group_ids"]
|
||||
}
|
||||
|
||||
ebs_options {
|
||||
ebs_enabled = var.ebs_volume_size > 0 ? true : false
|
||||
volume_size = var.ebs_volume_size
|
||||
volume_type = var.ebs_volume_type
|
||||
}
|
||||
|
||||
snapshot_options {
|
||||
automated_snapshot_start_hour = var.snapshot_start_hour
|
||||
}
|
||||
|
||||
tags = merge(
|
||||
{
|
||||
"Domain" = local.domain_name
|
||||
},
|
||||
var.tags,
|
||||
)
|
||||
}
|
||||
|
||||
resource "aws_elasticsearch_domain_policy" "es_vpc_management_access" {
|
||||
count = local.inside_vpc ? 1 : 0
|
||||
|
||||
domain_name = local.domain_name
|
||||
access_policies = data.aws_iam_policy_document.es_vpc_management_access[0].json
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
output "arn" {
|
||||
description = "Amazon Resource Name (ARN) of the domain"
|
||||
value = element(
|
||||
concat(
|
||||
aws_elasticsearch_domain.es_vpc.*.arn,
|
||||
aws_elasticsearch_domain.es.*.arn,
|
||||
[""],
|
||||
),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
output "domain_id" {
|
||||
description = "Unique identifier for the domain"
|
||||
value = element(
|
||||
concat(
|
||||
aws_elasticsearch_domain.es_vpc.*.domain_id,
|
||||
aws_elasticsearch_domain.es.*.domain_id,
|
||||
[""],
|
||||
),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
output "domain_name" {
|
||||
description = "The name of the Elasticsearch domain"
|
||||
value = element(
|
||||
concat(
|
||||
aws_elasticsearch_domain.es_vpc.*.domain_name,
|
||||
aws_elasticsearch_domain.es.*.domain_name,
|
||||
[""],
|
||||
),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
output "endpoint" {
|
||||
description = "Domain-specific endpoint used to submit index, search, and data upload requests"
|
||||
value = element(
|
||||
concat(
|
||||
aws_elasticsearch_domain.es_vpc.*.endpoint,
|
||||
aws_elasticsearch_domain.es.*.endpoint,
|
||||
[""],
|
||||
),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
output "kibana_endpoint" {
|
||||
description = "Domain-specific endpoint for kibana without https scheme"
|
||||
value = element(
|
||||
concat(
|
||||
aws_elasticsearch_domain.es_vpc.*.kibana_endpoint,
|
||||
aws_elasticsearch_domain.es.*.kibana_endpoint,
|
||||
[""],
|
||||
),
|
||||
0,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
variable "create_iam_service_linked_role" {
|
||||
description = "Whether to create IAM service linked role for AWS ElasticSearch service. Can be only one per AWS account."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "domain_name" {
|
||||
description = "Domain name for Elasticsearch cluster"
|
||||
type = string
|
||||
default = "es-domain"
|
||||
}
|
||||
|
||||
variable "es_version" {
|
||||
description = "Version of Elasticsearch to deploy (default 5.1)"
|
||||
type = string
|
||||
default = "5.1"
|
||||
}
|
||||
|
||||
variable "instance_type" {
|
||||
description = "ES instance type for data nodes in the cluster (default t2.small.elasticsearch)"
|
||||
type = string
|
||||
default = "t2.small.elasticsearch"
|
||||
}
|
||||
|
||||
variable "instance_count" {
|
||||
description = "Number of data nodes in the cluster (default 6)"
|
||||
type = number
|
||||
default = 6
|
||||
}
|
||||
|
||||
variable "dedicated_master_type" {
|
||||
description = "ES instance type to be used for dedicated masters (default same as instance_type)"
|
||||
type = string
|
||||
default = "false"
|
||||
}
|
||||
|
||||
variable "encrypt_at_rest" {
|
||||
description = "Enable encrption at rest (only specific instance family types support it: m4, c4, r4, i2, i3 default: false)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "management_iam_roles" {
|
||||
description = "List of IAM role ARNs from which to permit management traffic (default ['*']). Note that a client must match both the IP address and the IAM role patterns in order to be permitted access."
|
||||
type = list(string)
|
||||
default = ["*"]
|
||||
}
|
||||
|
||||
variable "management_public_ip_addresses" {
|
||||
description = "List of IP addresses from which to permit management traffic (default []). Note that a client must match both the IP address and the IAM role patterns in order to be permitted access."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "es_zone_awareness" {
|
||||
description = "Enable zone awareness for Elasticsearch cluster (default false)"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "es_zone_awareness_count" {
|
||||
description = "Number of availability zones used for data nodes (default 2)"
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "ebs_volume_size" {
|
||||
description = "Optionally use EBS volumes for data storage by specifying volume size in GB (default 0)"
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "ebs_volume_type" {
|
||||
description = "Storage type of EBS volumes, if used (default gp2)"
|
||||
type = string
|
||||
default = "gp2"
|
||||
}
|
||||
|
||||
variable "kms_key_id" {
|
||||
description = "KMS key used for elasticsearch"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "snapshot_start_hour" {
|
||||
description = "Hour at which automated snapshots are taken, in UTC (default 0)"
|
||||
type = number
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "vpc_options" {
|
||||
description = "A map of supported vpc options"
|
||||
type = map(list(string))
|
||||
|
||||
default = {
|
||||
security_group_ids = []
|
||||
subnet_ids = []
|
||||
}
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "tags to apply to all resources"
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "use_prefix" {
|
||||
description = "Flag indicating whether or not to use the domain_prefix. Default: true"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "domain_prefix" {
|
||||
description = "String to be prefixed to search domain. Default: tf-"
|
||||
type = string
|
||||
default = "tf-"
|
||||
}
|
||||
|
||||
variable "dedicated_master_threshold" {
|
||||
description = "The number of instances above which dedicated master nodes will be used. Default: 10"
|
||||
type = number
|
||||
default = 10
|
||||
}
|
||||
|
||||
variable "advanced_options" {
|
||||
description = "Map of key-value string pairs to specify advanced configuration options. Note that the values for these configuration options must be strings (wrapped in quotes) or they may be wrong and cause a perpetual diff, causing Terraform to want to recreate your Elasticsearch domain on every apply."
|
||||
type = map(string)
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "log_publishing_options" {
|
||||
description = "List of maps of options for publishing slow logs to CloudWatch Logs."
|
||||
type = list(map(string))
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "node_to_node_encryption_enabled" {
|
||||
description = "Whether to enable node-to-node encryption."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "enforce_https" {
|
||||
description = "Whether or not to require HTTPS."
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "tls_security_policy" {
|
||||
description = "The name of the TLS security policy that needs to be applied to the HTTPS endpoint. Example values: Policy-Min-TLS-1-0-2019-07 and Policy-Min-TLS-1-2-2019-07. Terraform will only perform drift detection if a configuration value is provided."
|
||||
type = string
|
||||
default = null
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_http
|
||||
//
|
||||
|
||||
// Provider specific configs
|
||||
provider "aws" {
|
||||
access_key = "${var.aws_access_key}"
|
||||
secret_key = "${var.aws_secret_key}"
|
||||
region = "${var.aws_region}"
|
||||
}
|
||||
|
||||
// ELB Resource for Module
|
||||
// A note about instances:
|
||||
// - This module assumes your instances will be made
|
||||
// by an ASG and the ASG will associate them with
|
||||
// the ELB.
|
||||
resource "aws_elb" "elb" {
|
||||
name = "${var.elb_name}"
|
||||
subnets = ["${var.subnet_az1}","${var.subnet_az2}"]
|
||||
internal = "${var.elb_is_internal}"
|
||||
security_groups = ["${var.elb_security_group}"]
|
||||
|
||||
listener {
|
||||
instance_port = "${var.backend_port}"
|
||||
instance_protocol = "${var.backend_protocol}"
|
||||
lb_port = 80
|
||||
lb_protocol = "http"
|
||||
}
|
||||
|
||||
health_check {
|
||||
healthy_threshold = 2
|
||||
unhealthy_threshold = 2
|
||||
timeout = 3
|
||||
target = "${var.health_check_target}"
|
||||
interval = 30
|
||||
}
|
||||
|
||||
cross_zone_load_balancing = true
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_http
|
||||
//
|
||||
|
||||
output "elb_id" {
|
||||
value = "${aws_elb.elb.id}"
|
||||
}
|
||||
|
||||
output "elb_name" {
|
||||
value = "${aws_elb.elb.name}"
|
||||
}
|
||||
|
||||
output "elb_dns_name" {
|
||||
value = "${aws_elb.elb.dns_name}"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_http
|
||||
//
|
||||
|
||||
// Module specific variables
|
||||
|
||||
variable "elb_name" {}
|
||||
|
||||
variable "elb_is_internal" {
|
||||
description = "Determines if the ELB is internal or not"
|
||||
default = false
|
||||
// Defaults to false, which results in an external IP for the ELB
|
||||
}
|
||||
|
||||
variable "elb_security_group" {}
|
||||
|
||||
variable "subnet_az1" {
|
||||
description = "The subnet for AZ1"
|
||||
}
|
||||
|
||||
variable "subnet_az2" {
|
||||
description = "The subnet for AZ2"
|
||||
}
|
||||
|
||||
variable "backend_port" {
|
||||
description = "The port the service on the EC2 instances listens on"
|
||||
}
|
||||
|
||||
variable "backend_protocol" {
|
||||
description = "The protocol the backend service speaks"
|
||||
// Possible options are
|
||||
// - http
|
||||
// - https
|
||||
// - tcp
|
||||
// - ssl (secure tcp)
|
||||
}
|
||||
|
||||
variable "health_check_target" {
|
||||
description = "The URL the ELB should use for health checks"
|
||||
// This is primarily used with `http` or `https` backend protocols
|
||||
// The format is like `HTTPS:443/health`
|
||||
}
|
||||
|
||||
// Variables for providers used in this module
|
||||
variable "aws_access_key" {}
|
||||
variable "aws_secret_key" {}
|
||||
variable "aws_region" {}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_https
|
||||
//
|
||||
|
||||
// Provider specific configs
|
||||
provider "aws" {
|
||||
access_key = "${var.aws_access_key}"
|
||||
secret_key = "${var.aws_secret_key}"
|
||||
region = "${var.aws_region}"
|
||||
}
|
||||
|
||||
// ELB Resource for Module
|
||||
// A note about instances:
|
||||
// - This module assumes your instances will be made
|
||||
// by an ASG and the ASG will associate them with
|
||||
// the ELB.
|
||||
resource "aws_elb" "elb" {
|
||||
name = "${var.elb_name}"
|
||||
subnets = ["${var.subnet_az1}","${var.subnet_az2}"]
|
||||
internal = "${var.elb_is_internal}"
|
||||
security_groups = ["${var.elb_security_group}"]
|
||||
|
||||
listener {
|
||||
instance_port = "${var.backend_port}"
|
||||
instance_protocol = "${var.backend_protocol}"
|
||||
lb_port = 443
|
||||
lb_protocol = "https"
|
||||
ssl_certificate_id = "${var.ssl_certificate_id}"
|
||||
}
|
||||
|
||||
health_check {
|
||||
healthy_threshold = 2
|
||||
unhealthy_threshold = 2
|
||||
timeout = 3
|
||||
target = "${var.health_check_target}"
|
||||
interval = 30
|
||||
}
|
||||
|
||||
cross_zone_load_balancing = true
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_https
|
||||
//
|
||||
|
||||
output "elb_id" {
|
||||
value = "${aws_elb.elb.id}"
|
||||
}
|
||||
|
||||
output "elb_name" {
|
||||
value = "${aws_elb.elb.name}"
|
||||
}
|
||||
|
||||
output "elb_dns_name" {
|
||||
value = "${aws_elb.elb.dns_name}"
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Module: tf_aws_elb/elb_https
|
||||
//
|
||||
|
||||
// Module specific variables
|
||||
|
||||
variable "elb_name" {}
|
||||
|
||||
variable "elb_is_internal" {
|
||||
description = "Determines if the ELB is internal or not"
|
||||
default = false
|
||||
// Defaults to false, which results in an external IP for the ELB
|
||||
}
|
||||
|
||||
variable "elb_security_group" {}
|
||||
|
||||
// See README.md for details on finding the
|
||||
// ARN of an SSL certificate in EC2
|
||||
variable "ssl_certificate_id" {
|
||||
description = "The ARN of the SSL Certificate in EC2"
|
||||
}
|
||||
|
||||
variable "subnet_az1" {
|
||||
description = "The subnet for AZ1"
|
||||
}
|
||||
|
||||
variable "subnet_az2" {
|
||||
description = "The subnet for AZ2"
|
||||
}
|
||||
|
||||
variable "backend_port" {
|
||||
description = "The port the service on the EC2 instances listens on"
|
||||
}
|
||||
|
||||
variable "backend_protocol" {
|
||||
description = "The protocol the backend service speaks"
|
||||
// Possible options are
|
||||
// - http
|
||||
// - https
|
||||
// - tcp
|
||||
// - ssl (secure tcp)
|
||||
}
|
||||
|
||||
variable "health_check_target" {
|
||||
description = "The URL the ELB should use for health checks"
|
||||
// This is primarily used with `http` or `https` backend protocols
|
||||
// The format is like `HTTPS:443/health`
|
||||
}
|
||||
|
||||
// Variables for providers used in this module
|
||||
variable "aws_access_key" {}
|
||||
variable "aws_secret_key" {}
|
||||
variable "aws_region" {}
|
||||
@@ -0,0 +1,14 @@
|
||||
variable "name" { default = "igw" }
|
||||
variable "vpc_id" {}
|
||||
variable "tags" {
|
||||
description = "A map of tags to add to all resources"
|
||||
default = {}
|
||||
}
|
||||
|
||||
resource "aws_internet_gateway" "igw" {
|
||||
vpc_id = "${var.vpc_id}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.name)))}"
|
||||
}
|
||||
|
||||
output "igw_id" { value = "${aws_internet_gateway.igw.id}" }
|
||||
@@ -0,0 +1,65 @@
|
||||
resource "aws_iam_role" "lambda" {
|
||||
name = "${var.lambda_name}"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {
|
||||
"Service": "lambda.amazonaws.com"
|
||||
},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "lambda" {
|
||||
name = "${var.lambda_name}"
|
||||
role = "${aws_iam_role.lambda.name}"
|
||||
|
||||
policy = "${var.iam_policy_document}"
|
||||
}
|
||||
|
||||
resource "aws_lambda_function" "lambda" {
|
||||
memory_size = "${var.memory_size}"
|
||||
runtime = "${var.runtime}"
|
||||
filename = "${var.lambda_zipfile}"
|
||||
function_name = "${var.lambda_name}"
|
||||
role = "${aws_iam_role.lambda.arn}"
|
||||
handler = "${var.handler}"
|
||||
source_code_hash = "${var.source_code_hash}"
|
||||
count = "${var.enabled}"
|
||||
timeout = "${var.timeout}"
|
||||
|
||||
vpc_config {
|
||||
subnet_ids = ["${var.subnet_ids}"]
|
||||
security_group_ids = ["${var.security_group_ids}"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lambda_permission" "cloudwatch" {
|
||||
statement_id = "AllowExecutionFromCloudWatch"
|
||||
action = "lambda:InvokeFunction"
|
||||
function_name = "${aws_lambda_function.lambda.arn}"
|
||||
principal = "events.amazonaws.com"
|
||||
source_arn = "${aws_cloudwatch_event_rule.lambda.arn}"
|
||||
count = "${var.enabled}"
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_event_rule" "lambda" {
|
||||
name = "${var.lambda_name}"
|
||||
schedule_expression = "${var.schedule_expression}"
|
||||
count = "${var.enabled}"
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_event_target" "lambda" {
|
||||
target_id = "${var.lambda_name}"
|
||||
rule = "${aws_cloudwatch_event_rule.lambda.name}"
|
||||
arn = "${aws_lambda_function.lambda.arn}"
|
||||
count = "${var.enabled}"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
output "lambda_arn" {
|
||||
value = "${aws_lambda_function.lambda.arn}"
|
||||
}
|
||||
|
||||
output "role_arn" {
|
||||
value = "${aws_iam_role.lambda.arn}"
|
||||
}
|
||||
|
||||
output "role_name" {
|
||||
value = "${aws_iam_role.lambda.name}"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
variable "lambda_name" {}
|
||||
|
||||
variable "runtime" {}
|
||||
|
||||
variable "memory_size" {
|
||||
default = 128
|
||||
}
|
||||
|
||||
variable "lambda_zipfile" {}
|
||||
|
||||
variable "source_code_hash" {}
|
||||
|
||||
variable "handler" {}
|
||||
|
||||
variable "schedule_expression" {}
|
||||
|
||||
variable "iam_policy_document" {}
|
||||
|
||||
variable "enabled" {
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "timeout" {
|
||||
default = 3
|
||||
}
|
||||
|
||||
variable "subnet_ids" {
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "security_group_ids" {
|
||||
default = []
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
resource "aws_iam_instance_profile" "nat_profile" {
|
||||
name = "${var.name}-nat_ha_profile"
|
||||
role = "${aws_iam_role.role.name}"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "role" {
|
||||
name = "${var.name}-nat_ha_role"
|
||||
path = "/"
|
||||
|
||||
assume_role_policy = <<EOF
|
||||
{
|
||||
"Version": "2008-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": "sts:AssumeRole",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Effect": "Allow",
|
||||
"Sid": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "modify_routes" {
|
||||
name = "nat_ha_modify_routes"
|
||||
role = "${aws_iam_role.role.id}"
|
||||
|
||||
policy = <<EOF
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"ec2:ReplaceRoute",
|
||||
"ec2:CreateRoute",
|
||||
"ec2:DeleteRoute",
|
||||
"ec2:DescribeRouteTables",
|
||||
"ec2:DescribeNetworkInterfaces",
|
||||
"ec2:DescribeInstanceAttribute"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
data "aws_ami" "ami" {
|
||||
most_recent = true
|
||||
|
||||
filter {
|
||||
name = "name"
|
||||
values = ["${var.ami_name_pattern}"]
|
||||
}
|
||||
|
||||
filter {
|
||||
name = "virtualization-type"
|
||||
values = ["hvm"]
|
||||
}
|
||||
|
||||
owners = ["${var.ami_publisher}"]
|
||||
}
|
||||
|
||||
data "aws_subnet" "first" {
|
||||
id = "${var.public_subnet_ids[0]}"
|
||||
}
|
||||
|
||||
data "aws_vpc" "vpc" {
|
||||
id = "${data.aws_subnet.first.vpc_id}"
|
||||
}
|
||||
|
||||
data "aws_region" "current" { }
|
||||
|
||||
data "template_file" "user_data" {
|
||||
template = "${file("${path.module}/nat-user-data.conf.tmpl")}"
|
||||
count = "${var.instance_count}"
|
||||
|
||||
vars = {
|
||||
name = "${var.name}"
|
||||
mysubnet = "${element(var.private_subnet_ids, count.index)}"
|
||||
vpc_cidr = "${data.aws_vpc.vpc.cidr_block}"
|
||||
region = "${data.aws_region.current.name}"
|
||||
awsnycast_deb_url = "${var.awsnycast_deb_url}"
|
||||
identifier = "${var.route_table_identifier}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "nat" {
|
||||
count = "${var.instance_count}"
|
||||
ami = "${data.aws_ami.ami.id}"
|
||||
instance_type = "${var.instance_type}"
|
||||
source_dest_check = false
|
||||
iam_instance_profile = "${aws_iam_instance_profile.nat_profile.id}"
|
||||
key_name = "${var.aws_key_name}"
|
||||
subnet_id = "${element(var.public_subnet_ids, count.index)}"
|
||||
vpc_security_group_ids = "${var.vpc_security_group_ids}"
|
||||
tags = "${merge(var.tags, map("Name", format("%s-nat%d", var.name, count.index+1)))}"
|
||||
user_data = "${element(data.template_file.user_data.*.rendered, count.index)}"
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"while sudo pkill -0 cloud-init; do sleep 2; done",
|
||||
]
|
||||
|
||||
connection {
|
||||
user = "ubuntu"
|
||||
|
||||
# If we are using a bastion host ssh in via the private IP
|
||||
# If we set this to an empty string we get the default behaviour.
|
||||
host = "${var.ssh_bastion_host != "" ? self.private_ip : ""}"
|
||||
|
||||
private_key = "${var.aws_private_key}"
|
||||
bastion_host = "${var.ssh_bastion_host}"
|
||||
bastion_user = "${var.ssh_bastion_user}"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
output "private_ips" {
|
||||
value = ["${aws_instance.nat.*.private_ip}"]
|
||||
}
|
||||
|
||||
output "public_ips" {
|
||||
value = ["${aws_instance.nat.*.public_ip}"]
|
||||
}
|
||||
|
||||
output "instance_ids" {
|
||||
value = ["${aws_instance.nat.*.id}"]
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
variable "name" {}
|
||||
|
||||
variable "tags" {
|
||||
type = "map"
|
||||
default = {}
|
||||
description = "A map of tags to add to all resources"
|
||||
}
|
||||
|
||||
variable "ami_name_pattern" {
|
||||
default = "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-*"
|
||||
description = "The name filter to use in data.aws_ami"
|
||||
}
|
||||
|
||||
variable "ami_publisher" {
|
||||
default = "099720109477" # Canonical
|
||||
description = "The AWS account ID of the AMI publisher"
|
||||
}
|
||||
|
||||
variable "instance_type" {}
|
||||
variable "instance_count" {}
|
||||
|
||||
variable "az_list" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "public_subnet_ids" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "private_subnet_ids" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "subnets_count" {
|
||||
description = "The number of subnets in public_subnet_ids. Required because of hashicorp/terraform#1497"
|
||||
}
|
||||
|
||||
variable "vpc_security_group_ids" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "aws_key_name" {}
|
||||
variable "aws_private_key" {}
|
||||
|
||||
variable "ssh_bastion_host" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "ssh_bastion_user" {
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "awsnycast_deb_url" {
|
||||
default = "https://github.com/bobtfish/AWSnycast/releases/download/v0.1.5/awsnycast_0.1.5-425_amd64.deb"
|
||||
}
|
||||
|
||||
variable "route_table_identifier" {
|
||||
description = "Indentifier used by AWSnycast route table regexp"
|
||||
default = "rt-private"
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
#----------------------------------------------------------------
|
||||
# This module creates all resources necessary for OpenVPN in AWS
|
||||
#----------------------------------------------------------------
|
||||
|
||||
resource "aws_security_group" "openvpn" {
|
||||
name = "${var.name}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
description = "OpenVPN security group"
|
||||
|
||||
tags {
|
||||
Name = "${var.name}"
|
||||
}
|
||||
|
||||
ingress {
|
||||
protocol = -1
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
cidr_blocks = ["${var.vpc_cidr}"]
|
||||
}
|
||||
|
||||
# For OpenVPN Client Web Server & Admin Web UI
|
||||
|
||||
ingress {
|
||||
protocol = "tcp"
|
||||
from_port = 22
|
||||
to_port = 22
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
ingress {
|
||||
protocol = "tcp"
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
ingress {
|
||||
protocol = "udp"
|
||||
from_port = 1194
|
||||
to_port = 1194
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
egress {
|
||||
protocol = -1
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_instance" "openvpn" {
|
||||
ami = "${var.ami}"
|
||||
instance_type = "${var.instance_type}"
|
||||
key_name = "${var.key_name}"
|
||||
subnet_id = "${element(var.public_subnet_ids, count.index)}"
|
||||
|
||||
vpc_security_group_ids = ["${aws_security_group.openvpn.id}"]
|
||||
|
||||
tags {
|
||||
Name = "${var.name}"
|
||||
}
|
||||
|
||||
# `admin_user` and `admin_pw` need to be passed in to the appliance through `user_data`, see docs -->
|
||||
# https://docs.openvpn.net/how-to-tutorialsguides/virtual-platforms/amazon-ec2-appliance-ami-quick-start-guide/
|
||||
user_data = <<USERDATA
|
||||
admin_user=${var.openvpn_admin_user}
|
||||
admin_pw=${var.openvpn_admin_pw}
|
||||
USERDATA
|
||||
|
||||
provisioner "remote-exec" {
|
||||
connection {
|
||||
user = "${var.openvpn_user}"
|
||||
host = "${self.public_ip}"
|
||||
private_key = "${var.private_key}"
|
||||
timeout = "10m"
|
||||
}
|
||||
|
||||
inline = [
|
||||
# Sleep 60 seconds until AMI is ready
|
||||
"sleep 60",
|
||||
|
||||
# Set VPN network info
|
||||
"sudo /usr/local/openvpn_as/scripts/sacli -k vpn.daemon.0.client.network -v ${element(split("/", var.vpn_cidr), 0)} ConfigPut",
|
||||
|
||||
"sudo /usr/local/openvpn_as/scripts/sacli -k vpn.daemon.0.client.netmask_bits -v ${element(split("/", var.vpn_cidr), 1)} ConfigPut",
|
||||
|
||||
# Do a warm restart so the config is picked up
|
||||
"sudo /usr/local/openvpn_as/scripts/sacli start",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_elb" "openvpn" {
|
||||
name = "openvpn-elb"
|
||||
subnets = ["${var.public_subnet_ids}"]
|
||||
internal = false
|
||||
idle_timeout = 30
|
||||
connection_draining = true
|
||||
connection_draining_timeout = 30
|
||||
instances = ["${aws_instance.openvpn.id}"]
|
||||
security_groups = ["${aws_security_group.openvpn.id}"]
|
||||
|
||||
listener {
|
||||
instance_port = 443
|
||||
instance_protocol = "https"
|
||||
lb_port = 443
|
||||
lb_protocol = "https"
|
||||
ssl_certificate_id = "${var.cert_arn}"
|
||||
}
|
||||
|
||||
health_check {
|
||||
healthy_threshold = 2
|
||||
unhealthy_threshold = 2
|
||||
timeout = 5
|
||||
target = "TCP:443"
|
||||
interval = 20
|
||||
}
|
||||
|
||||
tags {
|
||||
Name = "openvpn-elb"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "openvpn-web" {
|
||||
zone_id = "${var.route_zone_id}"
|
||||
name = "vpn-web.${var.domain_name}"
|
||||
type = "A"
|
||||
|
||||
alias {
|
||||
name = "${aws_elb.openvpn.dns_name}"
|
||||
zone_id = "${aws_elb.openvpn.zone_id}"
|
||||
evaluate_target_health = false
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route53_record" "openvpn" {
|
||||
zone_id = "${var.route_zone_id}"
|
||||
name = "vpn.${var.domain_name}"
|
||||
type = "A"
|
||||
ttl = 300
|
||||
records = ["${aws_instance.openvpn.public_ip}"]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
output "private_ip" {
|
||||
value = "${aws_instance.openvpn.private_ip}"
|
||||
}
|
||||
|
||||
output "public_ip" {
|
||||
value = "${aws_instance.openvpn.public_ip}"
|
||||
}
|
||||
|
||||
output "public_web_fqdn" {
|
||||
value = "${aws_route53_record.openvpn-web.fqdn}"
|
||||
}
|
||||
|
||||
output "public_fqdn" {
|
||||
value = "${aws_route53_record.openvpn.fqdn}"
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
variable "name" {
|
||||
default = "openvpn"
|
||||
}
|
||||
|
||||
variable "vpc_id" {}
|
||||
variable "vpc_cidr" {}
|
||||
|
||||
variable "public_subnet_ids" {
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "cert_arn" {}
|
||||
variable "key_name" {}
|
||||
variable "private_key" {}
|
||||
variable "ami" {}
|
||||
variable "instance_type" {}
|
||||
variable "openvpn_user" {}
|
||||
variable "openvpn_admin_user" {}
|
||||
variable "openvpn_admin_pw" {}
|
||||
variable "vpn_cidr" {}
|
||||
variable "domain_name" {}
|
||||
variable "route_zone_id" {}
|
||||
@@ -0,0 +1,93 @@
|
||||
variable "name" {
|
||||
default = "private"
|
||||
}
|
||||
variable "cidrs" {
|
||||
description = "A list of CIDR"
|
||||
default = []
|
||||
}
|
||||
variable "azs" {
|
||||
description = "A list of availability zones"
|
||||
default = []
|
||||
}
|
||||
variable "vpc_id" {
|
||||
}
|
||||
variable "public_subnet_ids" {
|
||||
description = "A list of public subnet ids"
|
||||
default = []
|
||||
}
|
||||
variable "nat_gateways_count" {
|
||||
}
|
||||
variable "map_public_ip_on_launch" {
|
||||
default = true
|
||||
}
|
||||
variable "tags" {
|
||||
description = "A map of tags to add to all resources"
|
||||
default = {}
|
||||
}
|
||||
|
||||
# Subnet
|
||||
resource "aws_subnet" "private" {
|
||||
vpc_id = "${var.vpc_id}"
|
||||
cidr_block = "${element(var.cidrs, count.index)}"
|
||||
availability_zone = "${element(var.azs, count.index)}"
|
||||
count = "${length(var.cidrs)}"
|
||||
map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s.%s", var.name, element(var.azs, count.index))))}"
|
||||
}
|
||||
|
||||
# Routes
|
||||
resource "aws_route_table" "private" {
|
||||
vpc_id = "${var.vpc_id}"
|
||||
count = "${length(var.cidrs)}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s.%s", var.name, element(var.azs, count.index))))}"
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "private" {
|
||||
subnet_id = "${element(aws_subnet.private.*.id, count.index)}"
|
||||
route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
|
||||
count = "${length(var.cidrs)}"
|
||||
}
|
||||
|
||||
resource "aws_route" "nat_gateway" {
|
||||
route_table_id = "${element(aws_route_table.private.*.id, count.index)}"
|
||||
destination_cidr_block = "0.0.0.0/0"
|
||||
nat_gateway_id = "${element(aws_nat_gateway.nat.*.id, count.index)}"
|
||||
count = "${length(var.cidrs)}"
|
||||
|
||||
depends_on = [
|
||||
"aws_route_table.private"
|
||||
]
|
||||
}
|
||||
|
||||
# NAT
|
||||
resource "aws_eip" "nat" {
|
||||
vpc = true
|
||||
count = "${var.nat_gateways_count}"
|
||||
}
|
||||
|
||||
resource "aws_nat_gateway" "nat" {
|
||||
allocation_id = "${element(aws_eip.nat.*.id, count.index)}"
|
||||
subnet_id = "${element(var.public_subnet_ids, count.index)}"
|
||||
count = "${var.nat_gateways_count}"
|
||||
}
|
||||
|
||||
# Output
|
||||
output "subnet_ids" {
|
||||
value = [
|
||||
"${aws_subnet.private.*.id}"
|
||||
]
|
||||
}
|
||||
|
||||
output "private_route_table_ids" {
|
||||
value = [
|
||||
"${aws_route_table.private.*.id}"
|
||||
]
|
||||
}
|
||||
|
||||
output "nat_eips" {
|
||||
value = [
|
||||
"${aws_eip.nat.*.public_ip}"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
variable "name" {
|
||||
default = "public"
|
||||
}
|
||||
variable "cidrs" {
|
||||
default = []
|
||||
}
|
||||
variable "azs" {
|
||||
description = "A list of availability zones"
|
||||
default = []
|
||||
}
|
||||
variable "vpc_id" {
|
||||
}
|
||||
variable "igw_id" {
|
||||
}
|
||||
variable "map_public_ip_on_launch" {
|
||||
default = true
|
||||
}
|
||||
variable "tags" {
|
||||
description = "A map of tags to add to all resources"
|
||||
default = {}
|
||||
}
|
||||
|
||||
# Subnet
|
||||
resource "aws_subnet" "public" {
|
||||
vpc_id = "${var.vpc_id}"
|
||||
cidr_block = "${element(var.cidrs, count.index)}"
|
||||
availability_zone = "${element(var.azs, count.index)}"
|
||||
count = "${length(var.cidrs)}"
|
||||
map_public_ip_on_launch = "${var.map_public_ip_on_launch}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
tags = "${merge(var.tags, map("Name", format("%s.%s", var.name, element(var.azs, count.index))))}"
|
||||
}
|
||||
|
||||
# Routes
|
||||
resource "aws_route_table" "public" {
|
||||
vpc_id = "${var.vpc_id}"
|
||||
count = "${length(var.cidrs)}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s.%s", var.name, element(var.azs, count.index))))}"
|
||||
}
|
||||
|
||||
resource "aws_route_table_association" "public" {
|
||||
subnet_id = "${element(aws_subnet.public.*.id, count.index)}"
|
||||
route_table_id = "${element(aws_route_table.public.*.id, count.index)}"
|
||||
count = "${length(var.cidrs)}"
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_route" "igw" {
|
||||
route_table_id = "${element(aws_route_table.public.*.id, count.index)}"
|
||||
destination_cidr_block = "0.0.0.0/0"
|
||||
gateway_id = "${var.igw_id}"
|
||||
count = "${length(var.cidrs)}"
|
||||
|
||||
depends_on = [
|
||||
"aws_route_table.public"
|
||||
]
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
output "subnet_ids" {
|
||||
value = [
|
||||
"${aws_subnet.public.*.id}"
|
||||
]
|
||||
}
|
||||
|
||||
output "public_route_table_ids" {
|
||||
value = [
|
||||
"${aws_route_table.public.*.id}"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
module "ami" {
|
||||
source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs"
|
||||
region = var.region
|
||||
distribution = "trusty"
|
||||
instance_type = var.instance_type
|
||||
}
|
||||
|
||||
resource "aws_instance" "puppet-client" {
|
||||
ami = module.ami.ami_id
|
||||
instance_type = var.instance_type
|
||||
iam_instance_profile = var.iam_instance_profile
|
||||
tags {
|
||||
Name = "puppet client"
|
||||
puppet_role = var.puppet_role
|
||||
}
|
||||
key_name = var.aws_key_name
|
||||
subnet_id = var.subnet_id
|
||||
security_groups = ["${var.security_group}"]
|
||||
user_data = replace(file("${path.module}/puppetagent.conf"), "__PUPPETMASTER_IP__", "${var.puppetmaster_ip}")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
output "private_ip" {
|
||||
value = "${aws_instance.puppet-client.private_ip}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
variable "region" {}
|
||||
variable "instance_type" {
|
||||
default = "t2.micro"
|
||||
}
|
||||
variable "subnet_id" {}
|
||||
variable "aws_key_name" {}
|
||||
variable "iam_instance_profile" {
|
||||
default = "describe-instances"
|
||||
}
|
||||
variable "security_group" {}
|
||||
variable "puppetmaster_ip" {}
|
||||
variable "puppet_role" {}
|
||||
@@ -0,0 +1,21 @@
|
||||
module "ami" {
|
||||
source = "github.com/terraform-community-modules/tf_aws_ubuntu_ami/ebs"
|
||||
region = "${var.region}"
|
||||
distribution = "trusty"
|
||||
instance_type = "${var.instance_type}"
|
||||
}
|
||||
|
||||
resource "aws_instance" "puppetmaster" {
|
||||
ami = "${module.ami.ami_id}"
|
||||
instance_type = "${var.instance_type}"
|
||||
iam_instance_profile = "${var.iam_instance_profile}"
|
||||
tags {
|
||||
Name = "puppetmaster"
|
||||
puppet_role = "puppetmaster"
|
||||
}
|
||||
key_name = "${var.aws_key_name}"
|
||||
subnet_id = "${var.subnet_id}"
|
||||
security_groups = ["${var.security_group}"]
|
||||
user_data = "${replace(file("${path.module}/puppetmaster.conf"), "__REPOSITORY__", "${var.repository}")}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
output "private_ip" {
|
||||
value = "${aws_instance.puppetmaster.private_ip}"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "region" {}
|
||||
variable "instance_type" {
|
||||
default = "t2.micro"
|
||||
}
|
||||
variable "subnet_id" {}
|
||||
variable "aws_key_name" {}
|
||||
variable "iam_instance_profile" {
|
||||
default = "describe-instances"
|
||||
}
|
||||
variable "security_group" {}
|
||||
variable "repository" {}
|
||||
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// Module: tf_aws_rds
|
||||
//
|
||||
|
||||
// This template creates the following resources
|
||||
// - An RDS instance
|
||||
// - A database subnet group
|
||||
// - You should want your RDS instance in a VPC
|
||||
|
||||
resource "aws_db_instance" "main_rds_instance" {
|
||||
identifier = "${var.rds_instance_identifier}"
|
||||
allocated_storage = "${var.rds_allocated_storage}"
|
||||
engine = "${var.rds_engine_type}"
|
||||
engine_version = "${var.rds_engine_version}"
|
||||
instance_class = "${var.rds_instance_class}"
|
||||
name = "${var.database_name}"
|
||||
username = "${var.database_user}"
|
||||
password = "${var.database_password}"
|
||||
|
||||
port = "${var.database_port}"
|
||||
|
||||
# Because we're assuming a VPC, we use this option, but only one SG id
|
||||
vpc_security_group_ids = ["${aws_security_group.main_db_access.id}"]
|
||||
|
||||
# We're creating a subnet group in the module and passing in the name
|
||||
db_subnet_group_name = "${aws_db_subnet_group.main_db_subnet_group.id}"
|
||||
parameter_group_name = "${var.use_external_parameter_group ? var.parameter_group_name : aws_db_parameter_group.main_rds_instance.id}"
|
||||
|
||||
# We want the multi-az setting to be toggleable, but off by default
|
||||
multi_az = "${var.rds_is_multi_az}"
|
||||
storage_type = "${var.rds_storage_type}"
|
||||
iops = "${var.rds_iops}"
|
||||
publicly_accessible = "${var.publicly_accessible}"
|
||||
|
||||
# Upgrades
|
||||
allow_major_version_upgrade = "${var.allow_major_version_upgrade}"
|
||||
auto_minor_version_upgrade = "${var.auto_minor_version_upgrade}"
|
||||
apply_immediately = "${var.apply_immediately}"
|
||||
maintenance_window = "${var.maintenance_window}"
|
||||
|
||||
# Snapshots and backups
|
||||
skip_final_snapshot = "${var.skip_final_snapshot}"
|
||||
copy_tags_to_snapshot = "${var.copy_tags_to_snapshot}"
|
||||
|
||||
backup_retention_period = "${var.backup_retention_period}"
|
||||
backup_window = "${var.backup_window}"
|
||||
|
||||
# enhanced monitoring
|
||||
monitoring_interval = "${var.monitoring_interval}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.rds_instance_identifier)))}"
|
||||
}
|
||||
|
||||
resource "aws_db_parameter_group" "main_rds_instance" {
|
||||
count = "${var.use_external_parameter_group ? 0 : 1}"
|
||||
|
||||
name = "${var.rds_instance_identifier}-${replace(var.db_parameter_group, ".", "")}-custom-params"
|
||||
family = "${var.db_parameter_group}"
|
||||
|
||||
# Example for MySQL
|
||||
# parameter {
|
||||
# name = "character_set_server"
|
||||
# value = "utf8"
|
||||
# }
|
||||
|
||||
|
||||
# parameter {
|
||||
# name = "character_set_client"
|
||||
# value = "utf8"
|
||||
# }
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.rds_instance_identifier)))}"
|
||||
}
|
||||
|
||||
resource "aws_db_subnet_group" "main_db_subnet_group" {
|
||||
name = "${var.rds_instance_identifier}-subnetgrp"
|
||||
description = "RDS subnet group"
|
||||
subnet_ids = ["${var.subnets}"]
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.rds_instance_identifier)))}"
|
||||
}
|
||||
|
||||
# Security groups
|
||||
resource "aws_security_group" "main_db_access" {
|
||||
name = "${var.rds_instance_identifier}-access"
|
||||
description = "Allow access to the database"
|
||||
vpc_id = "${var.rds_vpc_id}"
|
||||
|
||||
tags = "${merge(var.tags, map("Name", format("%s", var.rds_instance_identifier)))}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "allow_db_access" {
|
||||
type = "ingress"
|
||||
|
||||
from_port = "${var.database_port}"
|
||||
to_port = "${var.database_port}"
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["${var.private_cidr}"]
|
||||
|
||||
security_group_id = "${aws_security_group.main_db_access.id}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "allow_all_outbound" {
|
||||
type = "egress"
|
||||
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
|
||||
security_group_id = "${aws_security_group.main_db_access.id}"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Module: tf_aws_rds
|
||||
#
|
||||
|
||||
# Output the ID of the RDS instance
|
||||
output "rds_instance_id" {
|
||||
value = "${aws_db_instance.main_rds_instance.id}"
|
||||
}
|
||||
|
||||
# Output the address (aka hostname) of the RDS instance
|
||||
output "rds_instance_address" {
|
||||
value = "${aws_db_instance.main_rds_instance.address}"
|
||||
}
|
||||
|
||||
# Output endpoint (hostname:port) of the RDS instance
|
||||
output "rds_instance_endpoint" {
|
||||
value = "${aws_db_instance.main_rds_instance.endpoint}"
|
||||
}
|
||||
|
||||
# Output the ID of the Subnet Group
|
||||
output "subnet_group_id" {
|
||||
value = "${aws_db_subnet_group.main_db_subnet_group.id}"
|
||||
}
|
||||
|
||||
# Output DB security group ID
|
||||
output "security_group_id" {
|
||||
value = "${aws_security_group.main_db_access.id}"
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
#
|
||||
# Module: tf_aws_rds
|
||||
#
|
||||
|
||||
# RDS Instance Variables
|
||||
|
||||
variable "rds_instance_identifier" {
|
||||
description = "Custom name of the instance"
|
||||
}
|
||||
|
||||
variable "rds_is_multi_az" {
|
||||
description = "Set to true on production"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "rds_storage_type" {
|
||||
description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD)."
|
||||
default = "standard"
|
||||
}
|
||||
|
||||
variable "rds_iops" {
|
||||
description = "The amount of provisioned IOPS. Setting this implies a storage_type of 'io1', default is 0 if rds storage type is not io1"
|
||||
default = "0"
|
||||
}
|
||||
|
||||
variable "rds_allocated_storage" {
|
||||
description = "The allocated storage in GBs"
|
||||
|
||||
# You just give it the number, e.g. 10
|
||||
}
|
||||
|
||||
variable "rds_engine_type" {
|
||||
description = "Database engine type"
|
||||
|
||||
# Valid types are
|
||||
# - mysql
|
||||
# - postgres
|
||||
# - oracle-*
|
||||
# - sqlserver-*
|
||||
# See http://docs.aws.amazon.com/cli/latest/reference/rds/create-db-instance.html
|
||||
# --engine
|
||||
}
|
||||
|
||||
variable "rds_engine_version" {
|
||||
description = "Database engine version, depends on engine type"
|
||||
|
||||
# For valid engine versions, see:
|
||||
# See http://docs.aws.amazon.com/cli/latest/reference/rds/create-db-instance.html
|
||||
# --engine-version
|
||||
}
|
||||
|
||||
variable "rds_instance_class" {
|
||||
description = "Class of RDS instance"
|
||||
|
||||
# Valid values
|
||||
# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html
|
||||
}
|
||||
|
||||
variable "auto_minor_version_upgrade" {
|
||||
description = "Allow automated minor version upgrade"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "allow_major_version_upgrade" {
|
||||
description = "Allow major version upgrade"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "apply_immediately" {
|
||||
description = "Specifies whether any database modifications are applied immediately, or during the next maintenance window"
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "maintenance_window" {
|
||||
description = "The window to perform maintenance in. Syntax: 'ddd:hh24:mi-ddd:hh24:mi' UTC "
|
||||
default = "Mon:03:00-Mon:04:00"
|
||||
}
|
||||
|
||||
variable "database_name" {
|
||||
description = "The name of the database to create"
|
||||
}
|
||||
|
||||
# Self-explainatory variables
|
||||
variable "database_user" {}
|
||||
|
||||
variable "database_password" {}
|
||||
variable "database_port" {}
|
||||
|
||||
# This is for a custom parameter to be passed to the DB
|
||||
# We're "cloning" default ones, but we need to specify which should be copied
|
||||
variable "db_parameter_group" {
|
||||
description = "Parameter group, depends on DB engine used"
|
||||
|
||||
# default = "mysql5.6"
|
||||
# default = "postgres9.5"
|
||||
}
|
||||
|
||||
variable "use_external_parameter_group" {
|
||||
description = "Use parameter group specified by `parameter_group_name` instead of built-in one"
|
||||
default = false
|
||||
}
|
||||
|
||||
# Use an external parameter group (i.e. defined in caller of this module)
|
||||
variable "parameter_group_name" {
|
||||
description = "Parameter group to use instead of the default"
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "publicly_accessible" {
|
||||
description = "Determines if database can be publicly available (NOT recommended)"
|
||||
default = false
|
||||
}
|
||||
|
||||
# RDS Subnet Group Variables
|
||||
variable "subnets" {
|
||||
description = "List of subnets DB should be available at. It might be one subnet."
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "private_cidr" {
|
||||
description = "VPC private addressing, used for a security group"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "rds_vpc_id" {
|
||||
description = "VPC to connect to, used for a security group"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "skip_final_snapshot" {
|
||||
description = "If true (default), no snapshot will be made before deleting DB"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "copy_tags_to_snapshot" {
|
||||
description = "Copy tags from DB to a snapshot"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "backup_window" {
|
||||
description = "When AWS can run snapshot, can't overlap with maintenance window"
|
||||
default = "22:00-03:00"
|
||||
}
|
||||
|
||||
variable "backup_retention_period" {
|
||||
type = "string"
|
||||
description = "How long will we retain backups"
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
description = "A map of tags to add to all resources"
|
||||
default = {}
|
||||
}
|
||||
|
||||
variable "monitoring_interval" {
|
||||
description = "To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60."
|
||||
default = "0"
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#
|
||||
# Module: tf_aws_redshift
|
||||
#
|
||||
|
||||
# This template creates the following resources
|
||||
# - An Redshift cluster
|
||||
# - A Redshift subnet group
|
||||
# - You should want your Redshift cluster in a VPC
|
||||
|
||||
resource "aws_redshift_cluster" "main_redshift_cluster" {
|
||||
cluster_identifier = "${var.cluster_identifier}"
|
||||
cluster_version = "${var.cluster_version}"
|
||||
node_type = "${var.cluster_node_type}"
|
||||
number_of_nodes = "${var.cluster_number_of_nodes}"
|
||||
database_name = "${var.cluster_database_name}"
|
||||
master_username = "${var.cluster_master_username}"
|
||||
master_password = "${var.cluster_master_password}"
|
||||
|
||||
port = "${var.cluster_port}"
|
||||
|
||||
# Because we're assuming a VPC, we use this option, but only one SG id
|
||||
vpc_security_group_ids = ["${aws_security_group.main_redshift_access.id}"]
|
||||
|
||||
# We're creating a subnet group in the module and passing in the name
|
||||
cluster_subnet_group_name = "${aws_redshift_subnet_group.main_redshift_subnet_group.name}"
|
||||
cluster_parameter_group_name = "${aws_redshift_parameter_group.main_redshift_cluster.id}"
|
||||
|
||||
publicly_accessible = "${var.publicly_accessible}"
|
||||
|
||||
# Snapshots and backups
|
||||
skip_final_snapshot = "${var.skip_final_snapshot}"
|
||||
automated_snapshot_retention_period = "${var.automated_snapshot_retention_period }"
|
||||
preferred_maintenance_window = "${var.preferred_maintenance_window}"
|
||||
|
||||
# IAM Roles
|
||||
iam_roles = ["${var.cluster_iam_roles}"]
|
||||
|
||||
lifecycle {
|
||||
prevent_destroy = true
|
||||
}
|
||||
|
||||
tags = "${var.default_tags}"
|
||||
|
||||
# Encryption
|
||||
encrypted = "${var.encrypted}"
|
||||
kms_key_id = "${var.kms_key_id}"
|
||||
|
||||
}
|
||||
|
||||
resource "aws_redshift_parameter_group" "main_redshift_cluster" {
|
||||
name = "${var.cluster_identifier}-${replace(var.cluster_parameter_group, ".", "-")}-custom-params"
|
||||
family = "${var.cluster_parameter_group}"
|
||||
|
||||
parameter {
|
||||
name = "wlm_json_configuration"
|
||||
value = "${var.wlm_json_configuration}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_redshift_subnet_group" "main_redshift_subnet_group" {
|
||||
name = "${var.cluster_identifier}-redshift-subnetgrp"
|
||||
description = "Redshift subnet group of ${var.cluster_identifier}"
|
||||
subnet_ids = ["${var.subnets}"]
|
||||
|
||||
tags = "${var.default_tags}"
|
||||
}
|
||||
|
||||
# Security groups
|
||||
resource "aws_security_group" "main_redshift_access" {
|
||||
name = "${var.cluster_identifier}-redshift-access"
|
||||
description = "Allow access to the cluster: ${var.cluster_identifier}"
|
||||
vpc_id = "${var.redshift_vpc_id}"
|
||||
|
||||
tags = "${merge(var.default_tags, map(
|
||||
"Name", "${var.cluster_identifier}-redshift-access"
|
||||
))}"
|
||||
}
|
||||
|
||||
# Keep rules separated to not recreate the cluster when deleting/adding rules
|
||||
resource "aws_security_group_rule" "allow_port_inbound" {
|
||||
type = "ingress"
|
||||
|
||||
from_port = "${var.cluster_port}"
|
||||
to_port = "${var.cluster_port}"
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["${var.private_cidr}"]
|
||||
|
||||
security_group_id = "${aws_security_group.main_redshift_access.id}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "allow_all_outbound" {
|
||||
type = "egress"
|
||||
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
|
||||
security_group_id = "${aws_security_group.main_redshift_access.id}"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Module: tf_aws_redshift
|
||||
#
|
||||
|
||||
# Output the ID of the Redshift cluster
|
||||
output "redshift_cluster_id" {
|
||||
value = "${aws_redshift_cluster.main_redshift_cluster.id}"
|
||||
}
|
||||
|
||||
# Output address (hostname) of the Redshift cluster
|
||||
output "redshift_cluster_address" {
|
||||
value = "${replace(aws_redshift_cluster.main_redshift_cluster.endpoint, format(":%s", aws_redshift_cluster.main_redshift_cluster.port), "")}"
|
||||
}
|
||||
|
||||
# Output endpoint (hostname:port) of the Redshift cluster
|
||||
output "redshift_cluster_endpoint" {
|
||||
value = "${aws_redshift_cluster.main_redshift_cluster.endpoint}"
|
||||
}
|
||||
|
||||
# Output the ID of the Subnet Group
|
||||
output "subnet_group_id" {
|
||||
value = "${aws_redshift_subnet_group.main_redshift_subnet_group.id}"
|
||||
}
|
||||
|
||||
# Output DB security group ID
|
||||
output "security_group_id" {
|
||||
value = "${aws_security_group.main_redshift_access.id}"
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#
|
||||
# Module: tf_aws_redshift
|
||||
#
|
||||
|
||||
# Redshift Cluster Variables
|
||||
|
||||
variable "cluster_identifier" {
|
||||
description = "Custom name of the cluster"
|
||||
}
|
||||
|
||||
variable "cluster_version" {
|
||||
description = "Version of Redshift engine cluster"
|
||||
default = "1.0"
|
||||
|
||||
# Constraints: Only version 1.0 is currently available.
|
||||
# http://docs.aws.amazon.com/cli/latest/reference/redshift/create-cluster.html
|
||||
}
|
||||
|
||||
variable "cluster_node_type" {
|
||||
description = "Node Type of Redshift cluster"
|
||||
|
||||
# Valid Values: ds1.xlarge | ds1.8xlarge | ds2.xlarge | ds2.8xlarge | dc1.large | dc1.8xlarge.
|
||||
# http://docs.aws.amazon.com/cli/latest/reference/redshift/create-cluster.html
|
||||
}
|
||||
|
||||
variable "cluster_number_of_nodes" {
|
||||
description = "Number of Node in the cluster"
|
||||
default = 3
|
||||
}
|
||||
|
||||
variable "cluster_database_name" {
|
||||
description = "The name of the database to create"
|
||||
}
|
||||
|
||||
# Self-explainatory variables
|
||||
variable "cluster_master_username" {}
|
||||
|
||||
variable "cluster_master_password" {}
|
||||
|
||||
variable "cluster_port" {
|
||||
default = 5439
|
||||
}
|
||||
|
||||
# This is for a custom parameter to be passed to the DB
|
||||
# We're "cloning" default ones, but we need to specify which should be copied
|
||||
variable "cluster_parameter_group" {
|
||||
description = "Parameter group, depends on DB engine used"
|
||||
default = "redshift-1.0"
|
||||
}
|
||||
|
||||
variable "cluster_iam_roles" {
|
||||
description = "A list of IAM Role ARNs to associate with the cluster. A Maximum of 10 can be associated to the cluster at any time."
|
||||
type = "list"
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "publicly_accessible" {
|
||||
description = "Determines if Cluster can be publicly available (NOT recommended)"
|
||||
default = false
|
||||
}
|
||||
|
||||
# Redshift Subnet Group Variables
|
||||
variable "subnets" {
|
||||
description = "List of subnets DB should be available at. It might be one subnet."
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "private_cidr" {
|
||||
description = "VPC private addressing, used for a security group"
|
||||
type = "list"
|
||||
}
|
||||
|
||||
variable "redshift_vpc_id" {
|
||||
description = "VPC to connect to, used for a security group"
|
||||
type = "string"
|
||||
}
|
||||
|
||||
variable "skip_final_snapshot" {
|
||||
description = "If true (default), no snapshot will be made before deleting DB"
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "preferred_maintenance_window" {
|
||||
description = "When AWS can run snapshot, can't overlap with maintenance window"
|
||||
default = "sat:10:00-sat:10:30"
|
||||
}
|
||||
|
||||
variable "automated_snapshot_retention_period" {
|
||||
type = "string"
|
||||
description = "How long will we retain backups"
|
||||
default = 0
|
||||
}
|
||||
|
||||
variable "wlm_json_configuration" {
|
||||
default = "[{\"query_concurrency\": 5}]"
|
||||
}
|
||||
|
||||
variable "default_tags" {
|
||||
type = "map"
|
||||
}
|
||||
|
||||
variable "encrypted" {
|
||||
description = "(Optional) If true , the data in the cluster is encrypted at rest."
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "kms_key_id" {
|
||||
description = "(Optional) The ARN for the KMS encryption key. When specifying kms_key_id, encrypted needs to be set to true."
|
||||
default = ""
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Module: tf_aws_sg/sg_carbon-relay-ng
|
||||
//
|
||||
//
|
||||
|
||||
resource "aws_security_group" "main_security_group" {
|
||||
name = "${var.security_group_name}"
|
||||
description = "tf-sg-${var.security_group_name}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
}
|
||||
|
||||
// Allow any internal network flow.
|
||||
resource "aws_security_group_rule" "ingress_any_any_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "-1"
|
||||
self = true
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: TCP:2003 for carbon line-in.
|
||||
resource "aws_security_group_rule" "ingress_tcp_2003_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 2003
|
||||
to_port = 2003
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: UDP:2013 for carbon line-in.
|
||||
resource "aws_security_group_rule" "ingress_udp_2003_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 2003
|
||||
to_port = 2003
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: TCP:2013 for Pickle.
|
||||
resource "aws_security_group_rule" "ingress_tcp_2013_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 2013
|
||||
to_port = 2013
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: UDP:2013 for Pickle.
|
||||
resource "aws_security_group_rule" "ingress_udp_2013_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 2013
|
||||
to_port = 2013
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: TCP:2004 for Admin port.
|
||||
resource "aws_security_group_rule" "ingress_tcp_2004_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 2004
|
||||
to_port = 2004
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow: TCP:8081 for graphical user interface.
|
||||
resource "aws_security_group_rule" "ingress_tcp_8081_cidr" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8081
|
||||
to_port = 8081
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Output ID of sg_carbon-relay-ng SG we made
|
||||
output "security_group_id" {
|
||||
value = "${aws_security_group.main_security_group.id}"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Module specific variables
|
||||
variable "security_group_name" {
|
||||
description = "The name for the security group"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "The VPC this security group will go in"
|
||||
}
|
||||
|
||||
variable "source_cidr_block" {
|
||||
description = "The source CIDR block to allow traffic from"
|
||||
default = ["0.0.0.0/0"]
|
||||
type = "list"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Module: tf_aws_sg/sg_cassandra
|
||||
//
|
||||
//
|
||||
|
||||
resource "aws_security_group" "main_security_group" {
|
||||
name = "${var.security_group_name}"
|
||||
description = "tf-sg-${var.security_group_name}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
}
|
||||
|
||||
// Allow any internal network flow.
|
||||
resource "aws_security_group_rule" "ingress_any_any_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "-1"
|
||||
self = true
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:9042 (Cassandra clients).
|
||||
resource "aws_security_group_rule" "ingress_tcp_9042_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 9042
|
||||
to_port = 9042
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:9160 (Cassandra Thrift clients)
|
||||
resource "aws_security_group_rule" "ingress_tcp_9160_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 9160
|
||||
to_port = 9160
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:7199 (JMX)
|
||||
resource "aws_security_group_rule" "ingress_tcp_7199_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 7199
|
||||
to_port = 7199
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Output ID of sg_cassandra SG we made
|
||||
output "security_group_id" {
|
||||
value = "${aws_security_group.main_security_group.id}"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Module specific variables
|
||||
variable "security_group_name" {
|
||||
description = "The name for the security group"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "The VPC this security group will go in"
|
||||
}
|
||||
|
||||
variable "source_cidr_block" {
|
||||
description = "The source CIDR block to allow traffic from"
|
||||
default = ["0.0.0.0/0"]
|
||||
type = "list"
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// Module: tf_aws_sg/sg_consul
|
||||
//
|
||||
//
|
||||
|
||||
resource "aws_security_group" "main_security_group" {
|
||||
name = "${var.security_group_name}"
|
||||
description = "tf-sg-${var.security_group_name}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
}
|
||||
|
||||
// Allow any internal network flow.
|
||||
resource "aws_security_group_rule" "ingress_any_any_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 0
|
||||
to_port = 65535
|
||||
protocol = "-1"
|
||||
self = true
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:8300 (Server RPC).
|
||||
resource "aws_security_group_rule" "ingress_tcp_8300_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8300
|
||||
to_port = 8300
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:8500 (Consul Web UI).
|
||||
resource "aws_security_group_rule" "ingress_tcp_8500_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8500
|
||||
to_port = 8500
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:8301 (Serf LAN).
|
||||
resource "aws_security_group_rule" "ingress_tcp_8301_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8301
|
||||
to_port = 8301
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow UDP:8301 (Serf LAN).
|
||||
resource "aws_security_group_rule" "ingress_udp_8301_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8301
|
||||
to_port = 8301
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:8302 (Serf WAN).
|
||||
resource "aws_security_group_rule" "ingress_tcp_8302_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8302
|
||||
to_port = 8302
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow UDP:8302 (Serf WAN).
|
||||
resource "aws_security_group_rule" "ingress_udp_8302_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8302
|
||||
to_port = 8302
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow TCP:8600 (Consul DNS).
|
||||
resource "aws_security_group_rule" "ingress_tcp_8600_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8600
|
||||
to_port = 8600
|
||||
protocol = "tcp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
|
||||
// Allow UDP:8600 (Consul DNS).
|
||||
resource "aws_security_group_rule" "ingress_udp_8600_self" {
|
||||
security_group_id = "${aws_security_group.main_security_group.id}"
|
||||
from_port = 8600
|
||||
to_port = 8600
|
||||
protocol = "udp"
|
||||
cidr_blocks = "${var.source_cidr_block}"
|
||||
type = "ingress"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// Output ID of sg_consul SG we made
|
||||
output "security_group_id" {
|
||||
value = "${aws_security_group.main_security_group.id}"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Module specific variables
|
||||
variable "security_group_name" {
|
||||
description = "The name for the security group"
|
||||
}
|
||||
|
||||
variable "vpc_id" {
|
||||
description = "The VPC this security group will go in"
|
||||
}
|
||||
|
||||
variable "source_cidr_block" {
|
||||
description = "The source CIDR block to allow traffic from"
|
||||
default = ["0.0.0.0/0"]
|
||||
type = "list"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
output "sg_id" {
|
||||
value = "${aws_security_group.default_sg.id}"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
resource "aws_security_group" "default_sg" {
|
||||
name = "${var.sg_name}"
|
||||
description = "${var.sg_description}"
|
||||
vpc_id = "${var.vpc_id}"
|
||||
tags = "${var.tags}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "ingress_rule" {
|
||||
count = "${length(var.inbound_rules)}"
|
||||
type = "ingress"
|
||||
cidr_blocks = ["${element(var.inbound_rules[count.index], 0)}"]
|
||||
from_port = "${element(var.inbound_rules[count.index], 1)}"
|
||||
to_port = "${element(var.inbound_rules[count.index], 2)}"
|
||||
protocol = "${element(var.inbound_rules[count.index], 3)}"
|
||||
security_group_id = "${aws_security_group.default_sg.id}"
|
||||
}
|
||||
|
||||
resource "aws_security_group_rule" "egress_rule" {
|
||||
count = "${length(var.outbound_rules)}"
|
||||
type = "egress"
|
||||
cidr_blocks = ["${element(var.outbound_rules[count.index], 0)}"]
|
||||
from_port = "${element(var.outbound_rules[count.index], 1)}"
|
||||
to_port = "${element(var.outbound_rules[count.index], 2)}"
|
||||
protocol = "${element(var.outbound_rules[count.index], 3)}"
|
||||
security_group_id = "${aws_security_group.default_sg.id}"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
variable "vpc_id" {}
|
||||
variable "sg_name" {}
|
||||
|
||||
variable "sg_description" {
|
||||
default = "Security Group managed by Terraform"
|
||||
}
|
||||
|
||||
variable "inbound_rules" {
|
||||
type = "map"
|
||||
}
|
||||
|
||||
variable "outbound_rules" {
|
||||
type = "map"
|
||||
}
|
||||
|
||||
variable "tags" {
|
||||
type = "map"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user