opensearch (terraform)
Introduction
Tip: module 'opensearch'.
Terraform resource for managing an AWS OpenSearch.
Resources (AWS OpenSearch Serverless):
aws_opensearchserverless_access_policy awscc_opensearchserverless_access_policy
aws_opensearchserverless_collection awscc_opensearchserverless_collection
aws_opensearchserverless_security_config awscc_opensearchserverless_security_config
aws_opensearchserverless_security_policy awscc_opensearchserverless_security_policy
aws_opensearchserverless_vpc_endpoint awscc_opensearchserverless_vpc_endpoint
Reference
Introduction to OpenSearch
https://opensearch.org/docs/latest/about/
Querying your Amazon OpenSearch Service data with SQL
https://docs.aws.amazon.com/opensearch-service/latest/developerguide/sql-support.html
Sample: Collection of type SEARCH
This is experimental, not yet ready for usage
modules/opensearch/variables.tf
variable "creatable" {
description = "If opensearch will be created"
nullable = false
type = bool
}
variable "vpc_id" {}
variable "subnets_ids" {}
variable "vpc_endpoint_sgs_ids" {
description = "SGs Ids that will use the OSS VPC endpoint (in addition to the OSS SG itself)"
nullable = false
}
modules/opensearch/outputs.tf
output "collection_endpoint" {
value = try(aws_opensearchserverless_collection.example[0].collection_endpoint, null)
}
output "dashboard_endpoint" {
value = try(aws_opensearchserverless_collection.example[0].dashboard_endpoint, null)
}
modules/opensearch/opensearch.tf
#
# EXPERIMENTAL, NOT YET READY FOR USAGE
#
locals {
env = data.aws_default_tags.common.tags.env
ci = data.aws_default_tags.common.tags.ci
collection_keyword = "sample7"
collection_name = "${local.env}-${local.ci}-${local.collection_keyword}"
}
# Get the default tags from the provider
data "aws_default_tags" "common" {}
# An aws_opensearchserverless_collection cannot be created without having an applicable encryption security policy. Use the depends_on meta-argument to define this dependency.
resource "aws_opensearchserverless_security_policy" "example_encryption" {
count = var.creatable ? 1 : 0
# Args required
name = "${local.collection_name}-security"
policy = jsonencode({
Rules = [
{
Resource = [
"collection/${local.collection_name}" #Match the collection name
],
ResourceType = "collection"
}
],
AWSOwnedKey = true
})
type = "encryption"
# Args optional
description = "encryption policy for ${local.collection_name}"
}
# Collection creation
resource "aws_opensearchserverless_collection" "example" {
count = var.creatable ? 1 : 0
depends_on = [aws_opensearchserverless_security_policy.example_encryption]
# Args required
name = local.collection_name
# Args optional
description = "Description of the collection"
tags = {}
type = "SEARCH" # One of SEARCH, TIMESERIES, or VECTORSEARCH
}
# Creates a security group to be associate w/ the opensearch serverless vpc endpoint
resource "aws_security_group" "security_group" {
count = var.creatable ? 1 : 0
description = "OpenSearch Serverless" #Maps to the AWS GroupDescription attribute, for which there is no Update API
name_prefix = "${local.collection_name}-opensearch-"
tags = {
Name = "${local.collection_name} OSS collection"
}
vpc_id = var.vpc_id
}
# Allows all outbound traffic (IPv4)
resource "aws_vpc_security_group_egress_rule" "sg_egress_ipv4" {
count = var.creatable ? 1 : 0
cidr_ipv4 = "0.0.0.0/0"
#cidr_ipv6 = "::/0"
description = "Allow all outbound traffic (IPv4)"
#from_port # Required unless ip_protocol is set to -1 or icmpv6
ip_protocol = "-1"
security_group_id = aws_security_group.security_group[0].id
#to_port # Required unless ip_protocol is set to -1 or icmpv6
}
# Allows all outbound traffic (IPv6)
resource "aws_vpc_security_group_egress_rule" "sg_egress_ipv6" {
count = var.creatable ? 1 : 0
#cidr_ipv4 = "0.0.0.0/0"
cidr_ipv6 = "::/0"
description = "Allow all outbound traffic (IPv6)"
#from_port # Required unless ip_protocol is set to -1 or icmpv6
ip_protocol = "-1"
security_group_id = aws_security_group.security_group[0].id
#to_port # Required unless ip_protocol is set to -1 or icmpv6
}
# Allows inbound traffic from within security group
resource "aws_vpc_security_group_ingress_rule" "sg_ingress_within" {
count = var.creatable ? 1 : 0
#cidr_ipv4 #(Optional) The source IPv4 CIDR range
#cidr_ipv6 #(Optional) The source IPv6 CIDR range
description = "Allows inbound traffic from within security group"
#from_port # Required unless ip_protocol is set to -1 or icmpv6
ip_protocol = "-1"
referenced_security_group_id = aws_security_group.security_group[0].id #(Optional) The source security group that is referenced in the rule
security_group_id = aws_security_group.security_group[0].id
#to_port # Required unless ip_protocol is set to -1 or icmpv6
}
# Creates VPC endpoint to allow a private connection between your VPC and OpenSearch Serverless (seems that only one per vpc allowed)
resource "aws_opensearchserverless_vpc_endpoint" "example_vpc_endpoint" {
count = var.creatable ? 1 : 0
name = "${local.env}-${var.vpc_id}-ep"
vpc_id = var.vpc_id
subnet_ids = var.subnets_ids
# Make sure that the security group rules allow the resources that will use the VPC endpoint to communicate with OpenSearch Serverless to communicate with the endpoint network interface
security_group_ids = setunion([aws_security_group.security_group[0].id], var.vpc_endpoint_sgs_ids)
}
# Creates a network security policy
resource "aws_opensearchserverless_security_policy" "example_network" {
count = var.creatable ? 1 : 0
name = "${local.collection_name}-network"
type = "network"
description = "public access for dashboard, VPC access for collection endpoint"
policy = jsonencode([
{
Description = "OSS VPC access for collection endpoint",
Rules = [
{
ResourceType = "collection",
Resource = [
"collection/${local.collection_name}"
]
}
],
AllowFromPublic = false,
SourceVPCEs = [
aws_opensearchserverless_vpc_endpoint.example_vpc_endpoint[0].id
]
},
{
Description = "Public access for dashboards",
Rules = [
{
ResourceType = "dashboard"
Resource = [
"collection/${local.collection_name}"
]
}
],
AllowFromPublic = true
}
])
}
# Gets access to the effective Account ID, User ID, and ARN in which Terraform is authorized
data "aws_caller_identity" "current" {}
# Creates a data access policy
resource "aws_opensearchserverless_access_policy" "example_access" {
count = var.creatable ? 1 : 0
name = "${local.collection_name}-data"
policy = jsonencode([
{
Rules = [
{
ResourceType = "index",
Resource = [
"index/${local.collection_name}/*"
],
Permission = [
"aoss:*"
]
},
{
ResourceType = "collection",
Resource = [
"collection/${local.collection_name}"
],
Permission = [
"aoss:*"
]
}
],
Principal = [
data.aws_caller_identity.current.arn
]
}
])
type = "data"
# Args optional
description = "Allow index and collection access for ${local.collection_name}"
}