Skip to content

Commit 84f7592

Browse files
feat: add SAML options and service type for OpenSearch (#64)
* feat: add SAML options and service type for OpenSearch - Added `aws_service_type` variable to support both Elasticsearch and OpenSearch deployments, with validation and default for backward compatibility. - Introduced `elasticsearch_saml_options` variable and resource to manage SAML authentication for OpenSearch domains. - Updated outputs to be conditional on `local.enabled`. - Added `elasticsearch_log_cleanup_enabled` variable for log cleanup Lambda. - Improved password generation logic for compatibility. * Update src/variables.tf Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * feat(terraform): add SAML options for ES and OpenSearch domains Refactored SAML options resources to support both Elasticsearch and OpenSearch domains. Added conditional logic to create the appropriate resource based on the selected AWS service type. Updated resource names and configuration to ensure compatibility and flexibility for both services. --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 7ccc874 commit 84f7592

File tree

3 files changed

+81
-14
lines changed

3 files changed

+81
-14
lines changed

src/main.tf

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ locals {
99
elasticsearch_domain_endpoint = format(local.elasticsearch_endpoint_format, "elasticsearch_domain_endpoint")
1010
elasticsearch_kibana_endpoint = format(local.elasticsearch_endpoint_format, "elasticsearch_kibana_endpoint")
1111
elasticsearch_admin_password = format(local.elasticsearch_endpoint_format, "password")
12-
}
1312

14-
locals {
1513
create_password = local.enabled && length(var.elasticsearch_password) == 0
16-
elasticsearch_password = local.create_password ? join("", random_password.elasticsearch_password.*.result) : var.elasticsearch_password
14+
elasticsearch_password = local.create_password ? one(random_password.elasticsearch_password[*].result) : var.elasticsearch_password
15+
saml_options_enabled = local.enabled && var.elasticsearch_saml_options.enabled
1716
}
1817

1918
module "elasticsearch" {
@@ -25,6 +24,7 @@ module "elasticsearch" {
2524
subnet_ids = local.vpc_private_subnet_ids
2625
zone_awareness_enabled = length(local.vpc_private_subnet_ids) > 1 ? true : false
2726
elasticsearch_version = var.elasticsearch_version
27+
aws_service_type = var.aws_service_type
2828
instance_type = var.instance_type
2929
instance_count = length(local.vpc_private_subnet_ids)
3030
availability_zone_count = length(local.vpc_private_subnet_ids)
@@ -56,6 +56,32 @@ module "elasticsearch" {
5656
context = module.this.context
5757
}
5858

59+
resource "aws_elasticsearch_domain_saml_options" "elasticsearch" {
60+
count = local.saml_options_enabled && var.aws_service_type == "elasticsearch" ? 1 : 0
61+
62+
domain_name = module.elasticsearch.domain_name
63+
saml_options {
64+
enabled = var.elasticsearch_saml_options.enabled
65+
idp {
66+
entity_id = var.elasticsearch_saml_options.entity_id
67+
metadata_content = var.elasticsearch_saml_options.metadata_content
68+
}
69+
}
70+
}
71+
72+
resource "aws_opensearch_domain_saml_options" "opensearch" {
73+
count = local.saml_options_enabled && var.aws_service_type == "opensearch" ? 1 : 0
74+
75+
domain_name = module.elasticsearch.domain_name
76+
saml_options {
77+
enabled = var.elasticsearch_saml_options.enabled
78+
idp {
79+
entity_id = var.elasticsearch_saml_options.entity_id
80+
metadata_content = var.elasticsearch_saml_options.metadata_content
81+
}
82+
}
83+
}
84+
5985
resource "random_password" "elasticsearch_password" {
6086
count = local.create_password ? 1 : 0
6187
# character length
@@ -104,6 +130,8 @@ module "elasticsearch_log_cleanup" {
104130
source = "cloudposse/lambda-elasticsearch-cleanup/aws"
105131
version = "0.16.1"
106132

133+
enabled = var.elasticsearch_log_cleanup_enabled
134+
107135
es_endpoint = module.elasticsearch.domain_endpoint
108136
es_domain_arn = module.elasticsearch.domain_arn
109137
es_security_group_id = module.elasticsearch.security_group_id

src/outputs.tf

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,54 @@
11
output "security_group_id" {
2-
value = module.elasticsearch.security_group_id
2+
value = local.enabled ? module.elasticsearch.security_group_id : null
33
description = "Security Group ID to control access to the Elasticsearch domain"
44
}
55

66
output "domain_arn" {
7-
value = module.elasticsearch.domain_arn
7+
value = local.enabled ? module.elasticsearch.domain_arn : null
88
description = "ARN of the Elasticsearch domain"
99
}
1010

1111
output "domain_id" {
12-
value = module.elasticsearch.domain_id
12+
value = local.enabled ? module.elasticsearch.domain_id : null
1313
description = "Unique identifier for the Elasticsearch domain"
1414
}
1515

16+
output "domain_name" {
17+
value = local.enabled ? module.elasticsearch.domain_name : null
18+
description = "Name of the Elasticsearch domain"
19+
}
20+
1621
output "domain_endpoint" {
17-
value = module.elasticsearch.domain_endpoint
22+
value = local.enabled ? module.elasticsearch.domain_endpoint : null
1823
description = "Domain-specific endpoint used to submit index, search, and data upload requests"
1924
}
2025

2126
output "kibana_endpoint" {
22-
value = module.elasticsearch.kibana_endpoint
27+
value = local.enabled ? module.elasticsearch.kibana_endpoint : null
2328
description = "Domain-specific endpoint for Kibana without https scheme"
2429
}
2530

2631
output "domain_hostname" {
27-
value = module.elasticsearch.domain_hostname
32+
value = local.enabled ? module.elasticsearch.domain_hostname : null
2833
description = "Elasticsearch domain hostname to submit index, search, and data upload requests"
2934
}
3035

3136
output "kibana_hostname" {
32-
value = module.elasticsearch.kibana_hostname
37+
value = local.enabled ? module.elasticsearch.kibana_hostname : null
3338
description = "Kibana hostname"
3439
}
3540

3641
output "elasticsearch_user_iam_role_name" {
37-
value = module.elasticsearch.elasticsearch_user_iam_role_name
42+
value = local.enabled ? module.elasticsearch.elasticsearch_user_iam_role_name : null
3843
description = "The name of the IAM role to allow access to Elasticsearch cluster"
3944
}
4045

4146
output "elasticsearch_user_iam_role_arn" {
42-
value = module.elasticsearch.elasticsearch_user_iam_role_arn
47+
value = local.enabled ? module.elasticsearch.elasticsearch_user_iam_role_arn : null
4348
description = "The ARN of the IAM role to allow access to Elasticsearch cluster"
4449
}
4550

4651
output "master_password_ssm_key" {
47-
value = local.elasticsearch_admin_password
52+
value = local.enabled ? local.elasticsearch_admin_password : null
4853
description = "SSM key of Elasticsearch master password"
4954
}

src/variables.tf

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,21 @@ variable "instance_type" {
88
description = "The type of the instance"
99
}
1010

11+
variable "aws_service_type" {
12+
type = string
13+
description = "The type of AWS service to deploy (`elasticsearch` or `opensearch`)."
14+
# For backwards compatibility we default to elasticsearch
15+
default = "elasticsearch"
16+
17+
validation {
18+
condition = contains(["elasticsearch", "opensearch"], var.aws_service_type)
19+
error_message = "Value can only be one of `elasticsearch` or `opensearch`."
20+
}
21+
}
22+
1123
variable "elasticsearch_version" {
1224
type = string
13-
description = "Version of Elasticsearch to deploy (_e.g._ `7.1`, `6.8`, `6.7`, `6.5`, `6.4`, `6.3`, `6.2`, `6.0`, `5.6`, `5.5`, `5.3`, `5.1`, `2.3`, `1.5`"
25+
description = "Version of Elasticsearch or Opensearch to deploy (_e.g._ `7.1`, `6.8`, `6.7`, `6.5`, `6.4`, `6.3`, `6.2`, `6.0`, `5.6`, `5.5`, `5.3`, `5.1`, `2.3`, `1.5`"
1426
}
1527

1628
variable "encrypt_at_rest_enabled" {
@@ -100,6 +112,28 @@ variable "elasticsearch_password" {
100112
}
101113
}
102114

115+
variable "elasticsearch_saml_options" {
116+
type = object({
117+
enabled = optional(bool, false)
118+
entity_id = optional(string)
119+
metadata_content = optional(string)
120+
})
121+
description = <<-EOT
122+
Manages SAML authentication options for an AWS OpenSearch Domain
123+
124+
enabled: Whether to enable SAML authentication for the OpenSearch Domain
125+
entity_id: The entity ID of the IdP
126+
metadata_content: The metadata of the IdP
127+
EOT
128+
default = {}
129+
}
130+
131+
variable "elasticsearch_log_cleanup_enabled" {
132+
type = bool
133+
description = "Whether to enable Elasticsearch log cleanup Lambda"
134+
default = true
135+
}
136+
103137
variable "dns_delegated_environment_name" {
104138
type = string
105139
description = "The name of the environment where the `dns-delegated` component is deployed"

0 commit comments

Comments
 (0)