Skip to content

Commit

Permalink
Merge pull request #8 from lgallard/feature/advanced_security_options
Browse files Browse the repository at this point in the history
Feature/advanced security options
  • Loading branch information
lgallard authored Jul 15, 2020
2 parents e552143 + 45eefed commit c50feb8
Show file tree
Hide file tree
Showing 19 changed files with 325 additions and 9 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 0.4.0 (July 15, 2020)

ENHANCEMENTS:

* Add `advanced_security_options` block
* Add examples for `advanced_security_options` block

FIXES:

* Change "false" for the bool value

## 0.3.0 (June 26, 2020)

FIXES:
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,20 @@ module "aws_es" {

| Name | Version |
|------|---------|
| aws | >= 2.60.0 |
| aws | >= 2.69.0 |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| access\_policies | IAM policy document specifying the access policies for the domain | `string` | `""` | no |
| advanced\_options | 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 | `map(string)` | `{}` | no |
| advanced\_security\_options | Options for fine-grained access control | `any` | `{}` | no |
| advanced\_security\_options\_enabled | Whether advanced security is enabled (Forces new resource) | `bool` | `false` | no |
| advanced\_security\_options\_internal\_user\_database\_enabled | Whether the internal user database is enabled. If not set, defaults to false by the AWS API. | `bool` | `false` | no |
| advanced\_security\_options\_master\_user\_arn | ARN for the master user. Only specify if `internal_user_database_enabled` is not set or set to `false`) | `string` | n/a | yes |
| advanced\_security\_options\_master\_user\_password | The master user's password, which is stored in the Amazon Elasticsearch Service domain's internal database. Only specify if `internal_user_database_enabled` is set to `true`. | `string` | n/a | yes |
| advanced\_security\_options\_master\_user\_username | The master user's username, which is stored in the Amazon Elasticsearch Service domain's internal database. Only specify if `internal_user_database_enabled` is set to `true`. | `string` | n/a | yes |
| cluster\_config | Cluster configuration of the domain | `map` | `{}` | no |
| cluster\_config\_availability\_zone\_count | Number of Availability Zones for the domain to use with | `number` | `3` | no |
| cluster\_config\_dedicated\_master\_count | Number of dedicated master nodes in the cluster | `number` | `3` | no |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Use this data source to get the access to the effective Account ID in which
# Terraform is working.
data "aws_caller_identity" "current" {}

# To obtain the name of the AWS region configured on the provider
data "aws_region" "current" {}


59 changes: 59 additions & 0 deletions examples/advanced_security_options/master_user_arn/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module "aws_es" {

source = "lgallard/elasticsearch/aws"

domain_name = var.es_domain_name
elasticsearch_version = var.es_version

cluster_config = {
dedicated_master_enabled = "true"
instance_count = "3"
instance_type = "r5.large.elasticsearch"
zone_awareness_enabled = "true"
availability_zone_count = "3"
}

advanced_security_options = {
enabled = true
internal_user_database_enabled = true
master_user_options = {
master_user_arn = "arn:aws:iam::123456789101:user/lgallard"
}
}

ebs_options = {
ebs_enabled = "true"
volume_size = "25"
}

encrypt_at_rest = {
enabled = "true"
kms_key_id = "alias/aws/es"
}


log_publishing_options = {
enabled = "true"
}

advanced_options = {
"rest.action.multi.allow_explicit_index" = "true"
}

access_policies = templatefile("${path.module}/whitelits.tpl", {
region = data.aws_region.current.name,
account = data.aws_caller_identity.current.account_id,
domain_name = var.es_domain_name,
whitelist = "${jsonencode(var.whitelist)}"
})

node_to_node_encryption_enabled = "true"
snapshot_options_automated_snapshot_start_hour = "23"

#timeouts_update = "90m"

tags = {
Owner = "sysops"
env = "dev"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provider "aws" {
region = var.region
profile = var.profile
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
region = "us-east-1"
profile = "default"
es_domain_name = "elasticsearch-public"
es_version = "7.1"
whitelist = ["1.1.1.1", "2.2.2.2"]
15 changes: 15 additions & 0 deletions examples/advanced_security_options/master_user_arn/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Provider
variable "region" {}
variable "profile" {}


# AWS Elasticsearch
variable "es_domain_name" {}
variable "es_version" {}


# Whitelist (allow public IPs)
variable "whitelist" {
default = []
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

terraform {
required_version = ">= 0.12"
}
19 changes: 19 additions & 0 deletions examples/advanced_security_options/master_user_arn/whitelits.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:${region}:${account}:domain/${domain_name}/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": ${whitelist}
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Use this data source to get the access to the effective Account ID in which
# Terraform is working.
data "aws_caller_identity" "current" {}

# To obtain the name of the AWS region configured on the provider
data "aws_region" "current" {}


Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module "aws_es" {

source = "lgallard/elasticsearch/aws"

domain_name = var.es_domain_name
elasticsearch_version = var.es_version

cluster_config = {
dedicated_master_enabled = "true"
instance_count = "3"
instance_type = "r5.large.elasticsearch"
zone_awareness_enabled = "true"
availability_zone_count = "3"
}

advanced_security_options = {
enabled = true
internal_user_database_enabled = true
master_user_options = {
master_user_name = "username"
master_user_password = "topsecret"
}
}

ebs_options = {
ebs_enabled = "true"
volume_size = "25"
}

encrypt_at_rest = {
enabled = "true"
kms_key_id = "alias/aws/es"
}


log_publishing_options = {
enabled = "true"
}

advanced_options = {
"rest.action.multi.allow_explicit_index" = "true"
}

access_policies = templatefile("${path.module}/whitelits.tpl", {
region = data.aws_region.current.name,
account = data.aws_caller_identity.current.account_id,
domain_name = var.es_domain_name,
whitelist = "${jsonencode(var.whitelist)}"
})

node_to_node_encryption_enabled = "true"
snapshot_options_automated_snapshot_start_hour = "23"

#timeouts_update = "90m"

tags = {
Owner = "sysops"
env = "dev"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provider "aws" {
region = var.region
profile = var.profile
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
region = "us-east-1"
profile = "default"
es_domain_name = "elasticsearch-public"
es_version = "7.1"
whitelist = ["1.1.1.1", "2.2.2.2"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Provider
variable "region" {}
variable "profile" {}


# AWS Elasticsearch
variable "es_domain_name" {}
variable "es_version" {}


# Whitelist (allow public IPs)
variable "whitelist" {
default = []
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

terraform {
required_version = ">= 0.12"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "es:*",
"Resource": "arn:aws:es:${region}:${account}:domain/${domain_name}/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": ${whitelist}
}
}
}
]
}
45 changes: 38 additions & 7 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ resource "aws_elasticsearch_domain" "es_domain" {
# advanced_options
advanced_options = var.advanced_options == null ? {} : var.advanced_options

# advanced_security_options
dynamic "advanced_security_options" {
for_each = local.advanced_security_options
content {
enabled = lookup(advanced_security_options.value, "enabled")
internal_user_database_enabled = lookup(advanced_security_options.value, "internal_user_database_enabled")

master_user_options {
master_user_arn = lookup(lookup(advanced_security_options.value, "master_user_options"), "master_user_arn", null)
master_user_name = lookup(lookup(advanced_security_options.value, "master_user_options"), "master_user_name", null)
master_user_password = lookup(lookup(advanced_security_options.value, "master_user_options"), "master_user_name", null)
}
}
}

# ebs_options
dynamic "ebs_options" {
for_each = local.ebs_options
Expand Down Expand Up @@ -52,7 +67,7 @@ resource "aws_elasticsearch_domain" "es_domain" {

dynamic "zone_awareness_config" {
# cluster_availability_zone_count valid values: 2 or 3.
for_each = lookup(cluster_config.value, "zone_awareness_enabled", "false") == "false" || ! contains(["2", "3"], lookup(cluster_config.value, "availability_zone_count", "1")) ? [] : [1]
for_each = lookup(cluster_config.value, "zone_awareness_enabled", false) == false || ! contains(["2", "3"], lookup(cluster_config.value, "availability_zone_count", "1")) ? [] : [1]
content {
availability_zone_count = lookup(cluster_config.value, "availability_zone_count")
}
Expand Down Expand Up @@ -117,17 +132,33 @@ resource "aws_elasticsearch_domain" "es_domain" {
}

locals {
# advanced_security_options
# Create subblock master_user_options
master_user_options = lookup(var.advanced_security_options, "master_user_options", null) != null ? lookup(var.advanced_security_options, "master_user_options") : {
master_user_arn = var.advanced_security_options_internal_user_database_enabled == false ? var.advanced_security_options_master_user_arn : null
master_user_username = var.advanced_security_options_internal_user_database_enabled == true ? var.advanced_security_options_master_user_username : null
master_user_password = var.advanced_security_options_internal_user_database_enabled == true ? var.advanced_security_options_master_user_password : null
}

# If advanced_security_options is provided, build a advanced_security_options using the default values
advanced_security_options_default = {
enabled = lookup(var.advanced_security_options, "enabled", null) == null ? var.advanced_security_options_enabled : lookup(var.advanced_security_options, "enabled")
internal_user_database_enabled = lookup(var.advanced_security_options, "internal_user_database_enabled", null) == null ? var.advanced_security_options_internal_user_database_enabled : lookup(var.advanced_security_options, "internal_user_database_enabled")
master_user_options = local.master_user_options
}

advanced_security_options = lookup(local.advanced_security_options_default, "enabled", false) == false ? [] : [local.advanced_security_options_default]

# ebs_options
# If no ebs_options is provided, build a ebs_options using the default values
# If no ebs_options is provided, build an ebs_options using the default values
ebs_option_default = {
ebs_enabled = lookup(var.ebs_options, "ebs_enabled", null) == null ? var.ebs_enabled : lookup(var.ebs_options, "ebs_enabled")
volume_type = lookup(var.ebs_options, "volume_type", null) == null ? var.ebs_options_volume_type : lookup(var.ebs_options, "volume_type")
volume_size = lookup(var.ebs_options, "volume_size", null) == null ? var.ebs_options_volume_size : lookup(var.ebs_options, "volume_size")
iops = lookup(var.ebs_options, "iops", null) == null ? var.ebs_options_iops : lookup(var.ebs_options, "iops")
}

ebs_options = var.ebs_enabled == false || lookup(local.ebs_option_default, "ebs_enabled", "false") == "false" ? [] : [local.ebs_option_default]
ebs_options = var.ebs_enabled == false || lookup(local.ebs_option_default, "ebs_enabled", false) == false ? [] : [local.ebs_option_default]

# encrypt_at_rest
# If no encrypt_at_rest list is provided, build a encrypt_at_rest using the default values
Expand All @@ -137,15 +168,15 @@ locals {
kms_key_id = lookup(var.encrypt_at_rest, "kms_key_id", null) == null ? data.aws_kms_key.aws_es.arn : lookup(var.encrypt_at_rest, "kms_key_id")
}

encrypt_at_rest = var.encrypt_at_rest_enabled == false || lookup(local.encrypt_at_rest_default, "enabled", "false") == "false" ? [] : [local.encrypt_at_rest_default]
encrypt_at_rest = var.encrypt_at_rest_enabled == false || lookup(local.encrypt_at_rest_default, "enabled", false) == false ? [] : [local.encrypt_at_rest_default]

# node_to_node_encryption
# If no node_to_node_encryption list is provided, build a node_to_node_encryption using the default values
node_to_node_encryption_default = {
enabled = lookup(var.node_to_node_encryption, "enabled", null) == null ? var.node_to_node_encryption_enabled : lookup(var.node_to_node_encryption, "enabled")
}

node_to_node_encryption = var.node_to_node_encryption_enabled == false || lookup(local.node_to_node_encryption_default, "enabled", "false") == "false" ? [] : [local.node_to_node_encryption_default]
node_to_node_encryption = var.node_to_node_encryption_enabled == false || lookup(local.node_to_node_encryption_default, "enabled", false) == false ? [] : [local.node_to_node_encryption_default]

# cluster_config
# If no cluster_config list is provided, build a cluster_config using the default values
Expand Down Expand Up @@ -186,7 +217,7 @@ locals {
enabled = lookup(var.log_publishing_options, "enabled", null) == null ? var.log_publishing_options_enabled : lookup(var.log_publishing_options, "enabled")
}

log_publishing_options = var.log_publishing_options_enabled == false || lookup(local.log_publishing_options_default, "enabled") == "false" ? [] : [local.log_publishing_options_default]
log_publishing_options = var.log_publishing_options_enabled == false || lookup(local.log_publishing_options_default, "enabled") == false ? [] : [local.log_publishing_options_default]

# cognito_options
# If no cognito_options list is provided, build a cognito_options using the default values
Expand All @@ -197,7 +228,7 @@ locals {
role_arn = lookup(var.cognito_options, "role_arn", null) == null ? var.cognito_options_role_arn : lookup(var.cognito_options, "role_arn")
}

cognito_options = var.cognito_options_enabled == false || lookup(local.cognito_options_default, "enabled", "false") == "false" ? [] : [local.cognito_options_default]
cognito_options = var.cognito_options_enabled == false || lookup(local.cognito_options_default, "enabled", false) == false ? [] : [local.cognito_options_default]

# Timeouts
# If timeouts block is provided, build one using the default values
Expand Down
Loading

0 comments on commit c50feb8

Please sign in to comment.