@@ -196,7 +196,7 @@ resource "aws_lambda_function" "es_indexer" {
196196 MORESLEEP_API_URL = var.moresleep_url
197197 MORESLEEP_USERNAME = var.moresleep_username
198198 MORESLEEP_PASSWORD = var.moresleep_password
199- ELASTICSEARCH_URL = var.elasticsearch_url
199+ ELASTICSEARCH_URL = " https:// ${ aws_opensearch_domain . javazone . endpoint } "
200200 ELASTICSEARCH_USERNAME = var.elasticsearch_username
201201 ELASTICSEARCH_PASSWORD = var.elasticsearch_password
202202 ELASTICSEARCH_INDEX = var.elasticsearch_index
@@ -213,28 +213,21 @@ resource "aws_lambda_event_source_mapping" "sqs_trigger" {
213213}
214214
215215# ###############################################################################
216- # Elasticsearch on Fargate
216+ # OpenSearch Domain
217217# ###############################################################################
218218
219- # SSM Parameter for ES password
220- resource "aws_ssm_parameter" "elasticsearch_password_ssm" {
221- name = " /javazone/elasticsearch/password"
222- type = " SecureString"
223- value = var. elasticsearch_password
224- }
225-
226- # Security Group for Elasticsearch
227- resource "aws_security_group" "elasticsearch" {
228- name = " elasticsearch-javazone"
229- description = " Elasticsearch for JavaZone"
219+ # Security Group for OpenSearch
220+ resource "aws_security_group" "opensearch" {
221+ name = " opensearch-javazone"
222+ description = " OpenSearch for JavaZone"
230223 vpc_id = var. vpc_id
231224
232225 ingress {
233- from_port = 9200
234- to_port = 9200
226+ from_port = 443
227+ to_port = 443
235228 protocol = " tcp"
236229 cidr_blocks = var. allowed_cidr_blocks
237- description = " Elasticsearch HTTP "
230+ description = " HTTPS for OpenSearch "
238231 }
239232
240233 egress {
@@ -245,193 +238,64 @@ resource "aws_security_group" "elasticsearch" {
245238 }
246239}
247240
248- # IAM Role for ECS Task Execution
249- resource "aws_iam_role" "es_execution_role" {
250- name = " elasticsearch-javazone-execution"
251-
252- assume_role_policy = jsonencode ({
253- Version = " 2012-10-17"
254- Statement = [{
255- Action = " sts:AssumeRole"
256- Effect = " Allow"
257- Principal = {
258- Service = " ecs-tasks.amazonaws.com"
259- }
260- }]
261- })
262- }
263-
264- resource "aws_iam_role_policy_attachment" "es_execution_role_policy" {
265- role = aws_iam_role. es_execution_role . name
266- policy_arn = " arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
267- }
268-
269- resource "aws_iam_role_policy" "es_execution_ssm_policy" {
270- name = " ssm-access"
271- role = aws_iam_role. es_execution_role . id
241+ # OpenSearch Domain
242+ resource "aws_opensearch_domain" "javazone" {
243+ domain_name = " javazone-talks"
244+ engine_version = " OpenSearch_2.11"
272245
273- policy = jsonencode ({
274- Version = " 2012-10-17"
275- Statement = [{
276- Effect = " Allow"
277- Action = [" ssm:GetParameters" , " ssm:GetParameter" ]
278- Resource = aws_ssm_parameter.elasticsearch_password_ssm.arn
279- }]
280- })
281- }
282-
283- # IAM Role for ECS Task
284- resource "aws_iam_role" "es_task_role" {
285- name = " elasticsearch-javazone-task"
286-
287- assume_role_policy = jsonencode ({
288- Version = " 2012-10-17"
289- Statement = [{
290- Action = " sts:AssumeRole"
291- Effect = " Allow"
292- Principal = {
293- Service = " ecs-tasks.amazonaws.com"
294- }
295- }]
296- })
297- }
298-
299- # EFS for persistent storage
300- resource "aws_efs_file_system" "elasticsearch_data" {
301- creation_token = " elasticsearch-javazone-data"
302- encrypted = true
303-
304- lifecycle_policy {
305- transition_to_ia = " AFTER_30_DAYS"
246+ cluster_config {
247+ instance_type = " t3.small.search" # ~$0.036/hour = ~$26/month
248+ instance_count = 1
249+ zone_awareness_enabled = false
306250 }
307- }
308-
309- resource "aws_efs_mount_target" "elasticsearch_data" {
310- for_each = toset (var. es_subnet_ids )
311251
312- file_system_id = aws_efs_file_system. elasticsearch_data . id
313- subnet_id = each. value
314- security_groups = [aws_security_group . efs . id ]
315- }
316-
317- resource "aws_security_group" "efs" {
318- name = " elasticsearch-efs"
319- description = " EFS for Elasticsearch data"
320- vpc_id = var. vpc_id
321-
322- ingress {
323- from_port = 2049
324- to_port = 2049
325- protocol = " tcp"
326- security_groups = [aws_security_group . elasticsearch . id ]
327- description = " NFS from ES tasks"
252+ ebs_options {
253+ ebs_enabled = true
254+ volume_size = 10 # GB - plenty for 10K talks
255+ volume_type = " gp3"
328256 }
329257
330- egress {
331- from_port = 0
332- to_port = 0
333- protocol = " -1"
334- cidr_blocks = [" 0.0.0.0/0" ]
258+ vpc_options {
259+ subnet_ids = [var . es_subnet_ids [0 ]] # Single AZ for cost savings
260+ security_group_ids = [aws_security_group . opensearch . id ]
335261 }
336- }
337-
338- # ECS Cluster
339- resource "aws_ecs_cluster" "es_cluster" {
340- name = " elasticsearch-javazone"
341- }
342262
343- # ECS Task Definition
344- resource "aws_ecs_task_definition" "elasticsearch" {
345- family = " elasticsearch-javazone"
346- requires_compatibilities = [" FARGATE" ]
347- network_mode = " awsvpc"
348- cpu = var. task_cpu
349- memory = var. task_memory
350- execution_role_arn = aws_iam_role. es_execution_role . arn
351- task_role_arn = aws_iam_role. es_task_role . arn
352-
353- volume {
354- name = " elasticsearch-data"
355- efs_volume_configuration {
356- file_system_id = aws_efs_file_system. elasticsearch_data . id
357- transit_encryption = " ENABLED"
263+ advanced_security_options {
264+ enabled = true
265+ internal_user_database_enabled = true
266+ master_user_options {
267+ master_user_name = var. elasticsearch_username
268+ master_user_password = var. elasticsearch_password
358269 }
359270 }
360271
361- container_definitions = jsonencode ([{
362- name = " elasticsearch"
363- image = " docker.elastic.co/elasticsearch/elasticsearch:8.11.0"
364-
365- portMappings = [{
366- containerPort = 9200
367- protocol = " tcp"
368- }]
369-
370- mountPoints = [{
371- sourceVolume = " elasticsearch-data"
372- containerPath = " /usr/share/elasticsearch/data"
373- }]
374-
375- environment = [
376- { name = " discovery.type" , value = " single-node" },
377- { name = " xpack.security.enabled" , value = " true" },
378- { name = " ES_JAVA_OPTS" , value = " -Xms${ var . heap_size } m -Xmx${ var . heap_size } m" },
379- { name = " cluster.name" , value = " javazone-cluster" }
380- ]
381-
382- secrets = [{
383- name = " ELASTIC_PASSWORD"
384- valueFrom = aws_ssm_parameter.elasticsearch_password_ssm.arn
385- }]
386-
387- healthCheck = {
388- command = [" CMD-SHELL" , " curl -f http://localhost:9200/_cluster/health || exit 1" ]
389- interval = 30
390- timeout = 5
391- retries = 3
392- startPeriod = 120
393- }
394- }])
395- }
396-
397- # ECS Service
398- resource "aws_ecs_service" "elasticsearch" {
399- name = " elasticsearch-javazone"
400- cluster = aws_ecs_cluster. es_cluster . id
401- task_definition = aws_ecs_task_definition. elasticsearch . arn
402- desired_count = 1
403- launch_type = " FARGATE"
404- platform_version = " 1.4.0"
405-
406- network_configuration {
407- subnets = var. es_subnet_ids
408- security_groups = [aws_security_group . elasticsearch . id ]
409- assign_public_ip = var. assign_public_ip
272+ encrypt_at_rest {
273+ enabled = true
410274 }
411275
412- service_registries {
413- registry_arn = aws_service_discovery_service . elasticsearch . arn
276+ node_to_node_encryption {
277+ enabled = true
414278 }
415- }
416-
417- # Service Discovery
418- resource "aws_service_discovery_private_dns_namespace" "main" {
419- name = " javazone.internal"
420- vpc = var. vpc_id
421- }
422279
423- resource "aws_service_discovery_service" "elasticsearch" {
424- name = " elasticsearch"
425-
426- dns_config {
427- namespace_id = aws_service_discovery_private_dns_namespace. main . id
428- dns_records {
429- ttl = 10
430- type = " A"
431- }
280+ domain_endpoint_options {
281+ enforce_https = true
282+ tls_security_policy = " Policy-Min-TLS-1-2-2019-07"
432283 }
433284
434- health_check_custom_config {
435- failure_threshold = 1
285+ access_policies = jsonencode ({
286+ Version = " 2012-10-17"
287+ Statement = [{
288+ Effect = " Allow"
289+ Principal = {
290+ AWS = " *"
291+ }
292+ Action = " es:*"
293+ Resource = " arn:aws:es:${ var . aws_region } :*:domain/javazone-talks/*"
294+ }]
295+ })
296+
297+ tags = {
298+ Name = " javazone-talks"
436299 }
437300}
301+
0 commit comments