Skip to content

Commit b38ac3e

Browse files
committed
Add a new TF module that create a custom VPC (minimal-vpc)
1 parent dcddc1c commit b38ac3e

File tree

14 files changed

+385
-0
lines changed

14 files changed

+385
-0
lines changed

minimal-vpc/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Terraform Elasticsearch Single Node on AWS
2+
3+
Example of the creation of an AWS Elasticsearch single node with Terraform
4+
5+
## Includes
6+
7+
- Create an AWS Elasticsearch Service instance (managed by AWS)
8+
- Deploy the Elasticsearch instance under a custom VPC
9+
- Encryption with a KMS custom key (let you manage the usage of the KMS key)
10+
- Accessible only from your office/home public IP
11+
12+
## Improvements
13+
14+
This project is just a minimal example of how to deploy an AWS Elasticsearch service instance with a single node with the minimum of security.
15+
16+
This Terraform module can also be improved by adding this changes:
17+
18+
- Support for multiple environments (distinct name and tags between environment)
19+
- Support for Route 53 (by adding an alias to an existing Route 53 zone)
20+
21+
```bash
22+
module "es-single-node" {
23+
source = "git::https://github.com/timoa/terraform-elastic-single-node/minimal-vpc"
24+
25+
name = "es-single-node-example"
26+
27+
# Need to be greater than t2 since it doesn't support encryption
28+
instance_type = "m4.large.elasticsearch"
29+
30+
}
31+
```

minimal-vpc/main.tf

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
terraform {
2+
required_version = ">= 0.12.8"
3+
}
4+
5+
module "network" {
6+
source = "./modules/network"
7+
8+
# Global
9+
aws_region = var.aws_region
10+
11+
# VPC
12+
vpc_cidr = var.vpc_cidr
13+
public_subnet = var.public_subnet
14+
15+
# Security
16+
my_public_ip = var.my_public_ip
17+
18+
# Tags
19+
tags = var.tags
20+
21+
}
22+
23+
module "security" {
24+
source = "./modules/security"
25+
26+
# Tags
27+
tags = var.tags
28+
}
29+
30+
module "elasticsearch" {
31+
source = "./modules/elasticsearch"
32+
33+
# Network
34+
vpc_id = module.network.vpc_id
35+
security_group = module.network.elasticsearch_sg_id
36+
public_subnet = module.network.public_subnets[0]
37+
38+
# Security
39+
my_public_ip = var.my_public_ip
40+
encryption_kms_key_id = module.security.elasticsearch_kms_key_id
41+
42+
# Elasticsearch
43+
domain_name = var.domain_name
44+
elasticsearch_version = var.elasticsearch_version
45+
instance_type = var.instance_type
46+
volume_size = var.volume_size
47+
48+
# Tags
49+
tags = var.tags
50+
51+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
resource "aws_elasticsearch_domain" "elasticsearch" {
2+
domain_name = var.domain_name
3+
elasticsearch_version = var.elasticsearch_version
4+
5+
encrypt_at_rest {
6+
enabled = "true"
7+
kms_key_id = var.encryption_kms_key_id
8+
}
9+
10+
cluster_config {
11+
instance_type = var.instance_type
12+
instance_count = "1"
13+
dedicated_master_enabled = "false"
14+
dedicated_master_count = "0"
15+
zone_awareness_enabled = "false"
16+
}
17+
18+
access_policies = <<CONFIG
19+
{
20+
"Version": "2012-10-17",
21+
"Statement": [
22+
{
23+
"Effect": "Allow",
24+
"Principal": {
25+
"AWS": "*"
26+
},
27+
"Action": "es:*",
28+
"Resource": "${var.my_public_ip}/32"
29+
}
30+
]
31+
}
32+
CONFIG
33+
34+
vpc_options {
35+
security_group_ids = [var.security_group]
36+
subnet_ids = var.public_subnet
37+
}
38+
39+
advanced_options = {
40+
"rest.action.multi.allow_explicit_index" = "true"
41+
"indices.query.bool.max_clause_count" = "1024"
42+
}
43+
44+
ebs_options {
45+
ebs_enabled = true
46+
volume_type = "gp2"
47+
volume_size = var.volume_size
48+
}
49+
50+
snapshot_options {
51+
automated_snapshot_start_hour = "0"
52+
}
53+
54+
# Tags
55+
tags = "${merge(var.tags, map(
56+
"Name", "elasticsearch-es",
57+
"Domain", var.domain_name
58+
))}"
59+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
output "elasticsearch_endpoint" {
2+
value = aws_elasticsearch_domain.elasticsearch.endpoint
3+
}
4+
5+
output "elasticsearch_arn" {
6+
value = aws_elasticsearch_domain.elasticsearch.arn
7+
}
8+
9+
output "elasticsearch_domain_id" {
10+
value = aws_elasticsearch_domain.elasticsearch.domain_id
11+
}
12+
13+
output "elasticsearch_kibana_endpoint" {
14+
value = aws_elasticsearch_domain.elasticsearch.kibana_endpoint
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Network
2+
variable "vpc_id" {}
3+
variable "security_group" {}
4+
variable "public_subnet" {}
5+
6+
#Security
7+
variable "my_public_ip" {}
8+
variable "encryption_kms_key_id" {}
9+
10+
# Elasticsearch
11+
variable "domain_name" {}
12+
variable "elasticsearch_version" {}
13+
variable "instance_type" {}
14+
variable "volume_size" {}
15+
16+
variable tags {
17+
type = "map"
18+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Usage:
3+
*
4+
* module "network" {
5+
* source = "./modules/network"
6+
*
7+
* # Global
8+
* aws_region = var.aws_region
9+
*
10+
* # VPC
11+
* vpc_cidr = var.vpc_cidr
12+
* public_subnet = var.public_subnet
13+
*
14+
* }
15+
*/
16+
17+
module "vpc" {
18+
source = "terraform-aws-modules/vpc/aws"
19+
20+
name = "elasticsearch-vpc"
21+
cidr = var.vpc_cidr
22+
23+
azs = ["${var.aws_region}a"]
24+
public_subnets = [var.public_subnet]
25+
26+
enable_dns_hostnames = true
27+
enable_nat_gateway = false
28+
single_nat_gateway = false
29+
enable_vpn_gateway = false
30+
31+
# Tags
32+
tags = merge(var.tags, map(
33+
"Name", "elasticsearch-vpc"
34+
))
35+
36+
}
37+
38+
module "elasticsearch_sg" {
39+
source = "terraform-aws-modules/security-group/aws"
40+
41+
name = "elasticsearch-sg"
42+
description = "Security group that allows access to Elasticsearch only from your IP and all egress traffic"
43+
vpc_id = module.vpc.vpc_id
44+
45+
ingress_with_cidr_blocks = [
46+
{
47+
rule = "https-443-tcp"
48+
description = "Elasticsearch/Kibana"
49+
cidr_blocks = "${var.my_public_ip}/32"
50+
},
51+
]
52+
53+
egress_with_cidr_blocks = [
54+
{
55+
rule = "all-all"
56+
description = "Internet"
57+
cidr_blocks = "0.0.0.0/0"
58+
},
59+
]
60+
61+
# Tags
62+
tags = merge(var.tags, map(
63+
"Name", "elasticsearch-sg"
64+
))
65+
66+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
output "vpc_id" {
2+
description = "ID of the VPC"
3+
value = module.vpc.vpc_id
4+
}
5+
6+
output "public_subnets" {
7+
description = "ID of the VPC public subnet"
8+
value = [module.vpc.public_subnets]
9+
}
10+
11+
output "elasticsearch_sg_id" {
12+
description = "Elasticsearch security group ID"
13+
value = module.elasticsearch_sg.this_security_group_id
14+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
variable "aws_region" {}
2+
3+
variable "vpc_cidr" {}
4+
variable "public_subnet" {}
5+
6+
variable "my_public_ip" {}
7+
8+
variable tags {
9+
type = "map"
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
resource "aws_kms_key" "elasticsearch_kms_key" {
2+
description = "KMS key to encrypt the Elasticsearch volume"
3+
4+
# Tags
5+
tags = merge(var.tags, map(
6+
"Name", "elasticsearch-kms"
7+
))
8+
9+
}
10+
11+
resource "aws_kms_alias" "key" {
12+
name = "alias/elasticsearch-kms"
13+
target_key_id = aws_kms_key.elasticsearch_kms_key.key_id
14+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
output "elasticsearch_kms_key_id" {
2+
description = "Elasticsearch KMS Key ID"
3+
value = aws_kms_key.elasticsearch_kms_key.key_id
4+
}

0 commit comments

Comments
 (0)