From 070d831d7546b431b050b3d89d66986507072e47 Mon Sep 17 00:00:00 2001 From: Fabio Santos Date: Mon, 25 Mar 2024 10:06:20 +0000 Subject: [PATCH] feat: Add support to create VPCE security group --- README.md | 35 +++++++++++++++++++++++++++++++++++ examples/complete/README.md | 3 +++ examples/complete/main.tf | 10 ++++++++++ examples/complete/outputs.tf | 18 ++++++++++++++---- locals.tf | 2 ++ main.tf | 26 ++++++++++++++++++++++++++ outputs.tf | 12 ++++++++++++ variables.tf | 30 ++++++++++++++++++++++++++++++ 8 files changed, 132 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c61cfb4..1bdf28b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Dynamic Terraform module, which creates a Opensearch Serverless Collection and r + [Encryption Policy](#encryption-policy) + [Network Policy](#network-policy) - [VPC Access](#vpc-access) + - [Security Group](#security-group) + [Data Access Policy](#data-access-policy) + [Data Lifecycle Policy](#data-lifecycle-policy) + [Security Config](#security-config) @@ -95,6 +96,33 @@ To change the network policy use variable `network_policy_type`. The supported v If the variable `network_policy_type` is different from "AllPublic", the module will create Opensearch Serverless Endpoint to private access. In this case it's necessary configure the following variables: `vpce_subnet_ids` and `vpce_vpc_id`. `vpce_security_group_ids` is optional. +##### Security Group + +* To add existing security group, please use the variable `vpce_security_group_ids`. +* By Default, module creates a new security group. To disable this put the variable `vpce_create_security_group = false`. +* To choose the allowed sources for the created security group, you should use the variable `vpce_security_group_sources`. + * This variable supports two fields: + +| Field | Allowed Values | +|---------|---------------------------------------------------------------------------------------------| +| type | IPv4, IPv6, PrefixLists, SGs | +| sources | List of sources to be allowed. For example: To type IPv4 should be list of IPv4 CIDR blocks | + +* Example: + +```hcl +vpce_security_group_sources = [ + { + type = "IPv4" + sources = ["0.0.0.0/0"] + }, + { + type = "IPv6" + sources = ["::/0"] + } +] +``` + ### Data Access Policy To configure data access policy use variable `access_policy_rules`. This variable is a list of data access rules. @@ -175,6 +203,7 @@ No modules. | [aws_opensearchserverless_security_policy.encryption](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/opensearchserverless_security_policy) | resource | | [aws_opensearchserverless_security_policy.network](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/opensearchserverless_security_policy) | resource | | [aws_opensearchserverless_vpc_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/opensearchserverless_vpc_endpoint) | resource | +| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | ## Inputs @@ -208,8 +237,12 @@ No modules. | [tags](#input\_tags) | A map of tags to assign to the collection. If configured with a provider default\_tags configuration block present, tags with matching keys will overwrite those defined at the provider-level. | `map(string)` | `{}` | no | | [type](#input\_type) | Type of collection. One of SEARCH, TIMESERIES, or VECTORSEARCH. Defaults to TIMESERIES. | `string` | `"TIMESERIES"` | no | | [use\_standby\_replicas](#input\_use\_standby\_replicas) | Indicates whether standby replicas should be used for a collection. | `bool` | `true` | no | +| [vpce\_create\_security\_group](#input\_vpce\_create\_security\_group) | Creates a security group for VPCE. | `bool` | `true` | no | | [vpce\_name](#input\_vpce\_name) | Name of the interface endpoint. | `string` | `null` | no | +| [vpce\_security\_group\_description](#input\_vpce\_security\_group\_description) | Security Group description for VPCE. | `string` | `null` | no | | [vpce\_security\_group\_ids](#input\_vpce\_security\_group\_ids) | One or more security groups that define the ports, protocols, and sources for inbound traffic that you are authorizing into your endpoint. Up to 5 security groups can be provided. | `list(string)` | `null` | no | +| [vpce\_security\_group\_name](#input\_vpce\_security\_group\_name) | Security Group name for VPCE. | `string` | `null` | no | +| [vpce\_security\_group\_sources](#input\_vpce\_security\_group\_sources) | Sources for inbound traffic to Opensearch Serverless |
list(object({
type = string
sources = list(string)
}))
| `[]` | no | | [vpce\_subnet\_ids](#input\_vpce\_subnet\_ids) | One or more subnet IDs from which you'll access OpenSearch Serverless. Up to 6 subnets can be provided. | `list(string)` | `[]` | no | | [vpce\_vpc\_id](#input\_vpce\_vpc\_id) | ID of the VPC from which you'll access OpenSearch Serverless. | `string` | `null` | no | @@ -232,6 +265,8 @@ No modules. | [network\_policy\_version](#output\_network\_policy\_version) | Version of the network policy. | | [security\_config\_name](#output\_security\_config\_name) | Name of the security config. | | [security\_config\_version](#output\_security\_config\_version) | Version of the security config. | +| [security\_group\_id](#output\_security\_group\_id) | Id of the security group. | +| [security\_group\_name](#output\_security\_group\_name) | Name of the security group. | | [vpce\_id](#output\_vpce\_id) | Id of the vpce. | | [vpce\_name](#output\_vpce\_name) | Name of the interface endpoint. | diff --git a/examples/complete/README.md b/examples/complete/README.md index abb885c..5074045 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -63,4 +63,7 @@ Note that this example may create resources which cost money. Run `terraform des | [data\_lifecycle\_policy\_version](#output\_data\_lifecycle\_policy\_version) | Data Lifecycle policy version. | | [encrypt\_policy\_version](#output\_encrypt\_policy\_version) | Encryption policy version. | | [network\_policy\_version](#output\_network\_policy\_version) | Network policy version. | +| [security\_config\_version](#output\_security\_config\_version) | Security Config version. | +| [security\_group\_id](#output\_security\_group\_id) | Id of the security group. | +| [security\_group\_name](#output\_security\_group\_name) | Name of the security group. | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 94d0b9f..b5ed553 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -15,6 +15,16 @@ module "opensearch_serverless" { network_policy_type = "PublicCollectionPrivateDashboard" vpce_vpc_id = module.vpc.vpc_id vpce_subnet_ids = [module.vpc.private_subnets[0]] + vpce_security_group_sources = [ + { + type = "IPv4" + sources = ["0.0.0.0/0"] + }, + { + type = "IPv6" + sources = ["::/0"] + } + ] access_policy_rules = [ { type = "collection" diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 7c32207..e822c49 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -38,7 +38,17 @@ output "data_lifecycle_policy_version" { value = module.opensearch_serverless.data_lifecycle_policy_version } -#output "security_config_version" { -# description = "Security Config version." -# value = module.opensearch_serverless.security_config_version -#} +output "security_config_version" { + description = "Security Config version." + value = module.opensearch_serverless.security_config_version +} + +output "security_group_id" { + description = "Id of the security group." + value = module.opensearch_serverless.security_group_id +} + +output "security_group_name" { + description = "Name of the security group." + value = module.opensearch_serverless.security_group_name +} diff --git a/locals.tf b/locals.tf index 6d2cf5d..3cdc73b 100644 --- a/locals.tf +++ b/locals.tf @@ -1,5 +1,7 @@ locals { create_vpce = var.create_network_policy && var.network_policy_type != "AllPublic" ? true : false + crate_sg = local.create_vpce && var.vpce_create_security_group + sg_name = coalesce(var.vpce_security_group_name, "${var.name}-sg") network_policy_vpces = local.create_vpce ? [aws_opensearchserverless_vpc_endpoint.this[0].id] : null network_policies = { AllPublic = [{ diff --git a/main.tf b/main.tf index 27d734d..ca32ae3 100644 --- a/main.tf +++ b/main.tf @@ -72,3 +72,29 @@ resource "aws_opensearchserverless_security_config" "this" { session_timeout = var.saml_session_timeout } } + +################## +# Security Group +################## +resource "aws_security_group" "this" { + count = local.crate_sg ? 1 : 0 + name = local.sg_name + description = var.vpce_security_group_description + vpc_id = var.vpce_vpc_id + ingress { + from_port = 443 + to_port = 443 + protocol = "tcp" + cidr_blocks = flatten([for i, item in var.vpce_security_group_sources : [for k, source in item.sources : source] if item.type == "IPv4"]) + ipv6_cidr_blocks = flatten([for i, item in var.vpce_security_group_sources : [for k, source in item.sources : source] if item.type == "IPv6"]) + prefix_list_ids = flatten([for i, item in var.vpce_security_group_sources : [for k, source in item.sources : source] if item.type == "PrefixLists"]) + security_groups = flatten([for i, item in var.vpce_security_group_sources : [for k, source in item.sources : source] if item.type == "SGs"]) + description = "Allow Inbound HTTPS Traffic" + } + tags = merge( + var.tags, + { + Name : local.sg_name + } + ) +} diff --git a/outputs.tf b/outputs.tf index 93b4a00..a4e7014 100644 --- a/outputs.tf +++ b/outputs.tf @@ -64,6 +64,18 @@ output "vpce_id" { value = local.create_vpce ? aws_opensearchserverless_vpc_endpoint.this[0].id : null } +####### +## Security Group +####### +output "security_group_id" { + description = "Id of the security group." + value = local.crate_sg ? aws_security_group.this[0].id : null +} + +output "security_group_name" { + description = "Name of the security group." + value = local.crate_sg ? aws_security_group.this[0].name : null +} ####### ## Data Access Policy ####### diff --git a/variables.tf b/variables.tf index 4851804..972494f 100644 --- a/variables.tf +++ b/variables.tf @@ -119,6 +119,36 @@ variable "vpce_security_group_ids" { default = null } +###### +# VPCE Security Group +###### +variable "vpce_create_security_group" { + description = "Creates a security group for VPCE." + type = bool + default = true +} + +variable "vpce_security_group_name" { + description = "Security Group name for VPCE." + type = string + default = null +} + +variable "vpce_security_group_description" { + description = "Security Group description for VPCE." + type = string + default = null +} + +variable "vpce_security_group_sources" { + description = "Sources for inbound traffic to Opensearch Serverless" + type = list(object({ + type = string + sources = list(string) + })) + default = [] +} + ###### # Data Access Policy ######