Skip to content

Commit

Permalink
feat(aws): add private link module (#92)
Browse files Browse the repository at this point in the history
### Motivation

For support Customer setup private link to connect the private Pulsar
Cluster endpoint.

### Modifications
- Add module `aws/private-link`
- Change the folder structure to keep consist with GPC/Azure, moved to
module `aws/vendor-access`

### Verification

Applied locally.

```hcl
module "aws_private_link" {
  source = "github.com/streamnative/terraform-managed-cloud//modules/aws/private-link?ref=max/aws-private-link"

  region       = "region"
  vpc_id       = "vpc-id"
  subnet_ids   = ["subnet-id"]
  service_name = "com.amazonaws.vpce.region.vpce-svc-name"
}
```

### ⚠️ Caveats

After this PR, AWS user need change to use
`github.com/streamnative/terraform-managed-cloud//modules/aws/vendor-access`
for vendor access source.
  • Loading branch information
maxsxu authored Jul 19, 2024
1 parent 7514c41 commit b99a234
Show file tree
Hide file tree
Showing 16 changed files with 402 additions and 1,561 deletions.
1,561 changes: 0 additions & 1,561 deletions modules/aws/README.md

This file was deleted.

67 changes: 67 additions & 0 deletions modules/aws/private-link/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# StreamNative Cloud - Managed AWS Private Link

This Terraform module configures your AWS network to access private StreamNative BYOC pulsar service.

# QuickStart
Run the following terraform file with AWS Configuration:

```hcl
module "aws_private_link" {
source = "github.com/streamnative/terraform-managed-cloud//modules/aws/private-link?ref=main"
region = "region"
vpc_id = "vpc-id"
subnet_ids = ["subnet-id"]
service_name = "com.amazonaws.vpce.region.vpce-svc-name"
}
```

1. Run `terraform init`
2. Run `terraform plan`
3. Run `terraform apply`

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.30 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.30 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_vpc_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_endpoint) | resource |
| [aws_vpc.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/vpc) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_name"></a> [name](#input\_name) | The endpoint name | `string` | `""` | no |
| <a name="input_region"></a> [region](#input\_region) | The region of vpc endpoint service. The VPC Endpoint must be the same region as Endpoint Service | `string` | n/a | yes |
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | The ID of one or more security groups to associate with the network interface. If unspecified, will auto-create one | `list(string)` | `null` | no |
| <a name="input_service_name"></a> [service\_name](#input\_service\_name) | The vpc endpoint service name | `string` | n/a | yes |
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | The ID of one or more subnets in which to create a network interface for the endpoint. Must be the same AZ as Endpoint Service. | `list(string)` | n/a | yes |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | The ID of the VPC in which the endpoint will be used | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_vpc_endpoint_arn"></a> [vpc\_endpoint\_arn](#output\_vpc\_endpoint\_arn) | n/a |
| <a name="output_vpc_endpoint_state"></a> [vpc\_endpoint\_state](#output\_vpc\_endpoint\_state) | n/a |
<!-- END_TF_DOCS -->
121 changes: 121 additions & 0 deletions modules/aws/private-link/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
provider "aws" {
region = var.region
}

data "aws_vpc" "this" {
id = var.vpc_id
}

locals {
security_group_ids = coalescelist(var.security_group_ids, aws_security_group.this[*].id)

security_group_rules = {
ingress_https = {
type = "ingress"
protocol = "tcp"
from_port = 0
to_port = 65535
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "Allow access from VPC"
}
egress_http = {
type = "egress"
protocol = "tcp"
from_port = 80
to_port = 80
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "HTTP to VPC"
}
egress_https = {
type = "egress"
protocol = "tcp"
from_port = 443
to_port = 443
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "HTTPS to VPC"
}
egress_broker_tls = {
type = "egress"
protocol = "tcp"
from_port = 6651
to_port = 6651
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "Broker TLS to VPC"
}
egress_kafka_tls = {
type = "egress"
protocol = "tcp"
from_port = 9093
to_port = 9093
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "Kafka TLS to VPC"
}
egress_amqp_tls = {
type = "egress"
protocol = "tcp"
from_port = 5671
to_port = 5671
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "AMQP TLS to VPC"
}
egress_mqtt_tls = {
type = "egress"
protocol = "tcp"
from_port = 8883
to_port = 8883
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "MQTT TLS to VPC"
}
egress_status = {
type = "egress"
protocol = "tcp"
from_port = 15021
to_port = 15021
cidr_blocks = data.aws_vpc.this.cidr_block_associations.*.cidr_block
description = "Status to VPC"
}
}
}

resource "aws_vpc_endpoint" "this" {
vpc_id = var.vpc_id
subnet_ids = var.subnet_ids
service_name = var.service_name
security_group_ids = local.security_group_ids

vpc_endpoint_type = "Interface"
private_dns_enabled = true
auto_accept = true

tags = {
"Name" = coalesce(var.name, var.service_name)
}
}

resource "aws_security_group" "this" {
count = var.security_group_ids == null ? 1 : 0

name_prefix = var.service_name
vpc_id = var.vpc_id
description = "For access vpc endpoint service ${var.service_name}"

tags = {
"Name" = var.service_name
}

lifecycle {
create_before_destroy = true
}
}

resource "aws_security_group_rule" "this" {
for_each = { for k, v in local.security_group_rules : k => v if var.security_group_ids == null }

security_group_id = aws_security_group.this[0].id
type = each.value.type
protocol = each.value.protocol
from_port = each.value.from_port
to_port = each.value.to_port
cidr_blocks = each.value.cidr_blocks
description = each.value.description
}
7 changes: 7 additions & 0 deletions modules/aws/private-link/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "vpc_endpoint_arn" {
value = aws_vpc_endpoint.this.arn
}

output "vpc_endpoint_state" {
value = aws_vpc_endpoint.this.state
}
31 changes: 31 additions & 0 deletions modules/aws/private-link/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
variable "region" {
type = string
description = "The region of vpc endpoint service. The VPC Endpoint must be the same region as Endpoint Service"
}

variable "vpc_id" {
type = string
description = "The ID of the VPC in which the endpoint will be used"
}

variable "subnet_ids" {
type = list(string)
description = "The ID of one or more subnets in which to create a network interface for the endpoint. Must be the same AZ as Endpoint Service."
}

variable "service_name" {
type = string
description = "The vpc endpoint service name"
}

variable "security_group_ids" {
type = list(string)
default = null
description = "The ID of one or more security groups to associate with the network interface. If unspecified, will auto-create one"
}

variable "name" {
type = string
default = ""
description = "The endpoint name"
}
10 changes: 10 additions & 0 deletions modules/aws/private-link/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
terraform {
required_version = ">= 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.30"
}
}
}
Loading

0 comments on commit b99a234

Please sign in to comment.