Skip to content

Commit

Permalink
Added terraform-aws-bastion module (#93)
Browse files Browse the repository at this point in the history
Signed-off-by: dennaloh <dennaloh@hotmail.com>
  • Loading branch information
dennaloh authored Jan 20, 2025
1 parent d0ab17a commit a5ae9b8
Show file tree
Hide file tree
Showing 16 changed files with 716 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This repository contains a number of Terraform modules for creation of the pre-r
| [terraform-aws-permissions](modules/terraform-aws-permissions/README.md) | Module for creation of the AWS IAM permissions required by the (CDP) Public Cloud environment and datalake deployment. Note that this module is called from the terraform-cdp-aws-prereqs module. |
| [terraform-aws-vpc](modules/terraform-aws-vpc/README.md) | Module for creation of the VPC networking resources on AWS suitable. Can be used to create the CDP VPC and Subnets. Note that this module is called from the terraform-cdp-aws-prereqs module. |
| [terraform-aws-tgw](modules/terraform-aws-tgw/README.md) | Module for creation of AWS Transity Gateway (TGW) and attaching a specified list of VPCs via the TGW. This module can be used to assist in deploying Cloudera Data Platform (CDP) Public Cloud in a fully private networking configuration where a CDP VPC and Networking VPC are connected using the Transit Gateway. |
| [terraform-aws-bastion](modules/terraform-aws-bastion/README.md) | Module to create a Bastion EC2 instance on AWS. This module can be used to assist in deploying Cloudera Data Platform (CDP) Public Cloud in a secure environment, where the CDP Environment requires a Bastion host. |
| [terraform-aws-proxy](modules/terraform-aws-proxy/README.md) | Module to create and configure and EC2 Auto-Scaling Group for a highly available Squid Proxy service with Network Load Balancer (NLB) to forward traffic to the proxy instances. This module can be used to assist in deploying Cloudera Data Platform (CDP) Public Cloud in a fully private networking configuration where a the CDP Environments uses a proxy config via the NLB. |
| [terraform-azure-nfs](modules/terraform-azure-nfs/README.md) | Module for creation of Azure NFS File Share required for Cloudera Machine Learning (CML) Public Cloud. Also optionally creates a Virtual Machine which can be used to mount and set the required ownership for CML workspace's projects folder.|
| [terraform-azure-cdw-permissions](modules/terraform-azure-cdw-permissions/README.md) | Module for creation of the Azure Kubernetes Service (AKS) managed identity required for the Cloudera Data Warehouse (CDW) service.|
Expand Down
21 changes: 21 additions & 0 deletions modules/terraform-aws-bastion/.terraform-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
formatter: markdown
header-from: doc_fragments/header.md
settings:
anchor: true
color: true
default: true
escape: true
html: true
indent: 2
required: true
sensitive: true
type: true


sort:
enabled: true
by: required

output:
file: README.md
mode: replace
83 changes: 83 additions & 0 deletions modules/terraform-aws-bastion/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<!-- BEGIN_TF_DOCS -->
# Terraform Module for AWS Bastion

This module contains resource files and example variable definition files to create a Bastion EC2 instance on AWS. This module can be used to assist in deploying Cloudera Data Platform (CDP) Public Cloud in a secure environment, where the CDP Environment requires a Bastion host.

## Usage

The [examples](./examples) directory has example of using this module:

* `ex01-minimal_inputs` demonstrates how this module can be used to create a Bastion instance in a networking VPC. The [terraform-aws-vpc](../../../terraform-aws-vpc/README.md) module is also used as part of this example.

The sample `terraform.tfvars.sample` describes the required inputs for the example.

## Requirements

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

## Providers

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

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_eip.bastion_eip](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource |
| [aws_eip_association.bastion_eip_assoc](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip_association) | resource |
| [aws_instance.bastion](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource |
| [aws_security_group.bastion_sg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group_rule.bastion_egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.bastion_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_ami.bastion_default_ami](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_bastion_aws_keypair_name"></a> [bastion\_aws\_keypair\_name](#input\_bastion\_aws\_keypair\_name) | SSH Keypair name for the bastion VM. | `string` | n/a | yes |
| <a name="input_bastion_subnet_id"></a> [bastion\_subnet\_id](#input\_bastion\_subnet\_id) | The ID of the subnet where the bastion VM will run. | `string` | n/a | yes |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID for where the bastion VM will run. | `string` | n/a | yes |
| <a name="input_bastion_aws_ami"></a> [bastion\_aws\_ami](#input\_bastion\_aws\_ami) | The AWS AMI to use for the bastion VM. | `string` | `null` | no |
| <a name="input_bastion_aws_instance_type"></a> [bastion\_aws\_instance\_type](#input\_bastion\_aws\_instance\_type) | The EC2 instance type to use for the bastion VM. | `string` | `"t3.medium"` | no |
| <a name="input_bastion_az"></a> [bastion\_az](#input\_bastion\_az) | The availability zone where the bastion instance will be created. | `string` | `null` | no |
| <a name="input_bastion_cpu_options"></a> [bastion\_cpu\_options](#input\_bastion\_cpu\_options) | The CPU options for the bastion instance (e.g., number of cores and threads per core) | <pre>object({<br/> core_count = number<br/> threads_per_core = number<br/> })</pre> | `null` | no |
| <a name="input_bastion_host_name"></a> [bastion\_host\_name](#input\_bastion\_host\_name) | Name of bastion host. | `string` | `null` | no |
| <a name="input_bastion_inst_profile"></a> [bastion\_inst\_profile](#input\_bastion\_inst\_profile) | The IAM instance profile for the bastion instance. | `string` | `null` | no |
| <a name="input_bastion_monitoring"></a> [bastion\_monitoring](#input\_bastion\_monitoring) | Whether to enable detailed monitoring for the bastion instance | `bool` | `null` | no |
| <a name="input_bastion_placement_grp"></a> [bastion\_placement\_grp](#input\_bastion\_placement\_grp) | The placement group to associate with the bastion instance | `string` | `null` | no |
| <a name="input_bastion_private_ip"></a> [bastion\_private\_ip](#input\_bastion\_private\_ip) | The private IP address for the bastion instance | `string` | `null` | no |
| <a name="input_bastion_security_group_id"></a> [bastion\_security\_group\_id](#input\_bastion\_security\_group\_id) | ID for existing Security Group to be used for the bastion VM. Required when create\_bastion\_sg is false. | `string` | `null` | no |
| <a name="input_bastion_security_group_name"></a> [bastion\_security\_group\_name](#input\_bastion\_security\_group\_name) | Name of bastion Security Group for CDP environment. Used only if create\_bastion\_sg is true. | `string` | `null` | no |
| <a name="input_bastion_shutdown_behaviour"></a> [bastion\_shutdown\_behaviour](#input\_bastion\_shutdown\_behaviour) | The instance initiated shutdown behavior (e.g., stop or terminate) | `string` | `null` | no |
| <a name="input_bastion_src_dest_check"></a> [bastion\_src\_dest\_check](#input\_bastion\_src\_dest\_check) | Whether to disable source/destination checks for the bastion instance | `bool` | `null` | no |
| <a name="input_bastion_tenancy"></a> [bastion\_tenancy](#input\_bastion\_tenancy) | The tenancy option for the bastion instance (e.g., default or dedicated) | `string` | `null` | no |
| <a name="input_bastion_user_data"></a> [bastion\_user\_data](#input\_bastion\_user\_data) | Base64-encoded user data for the bastion instance. | `string` | `null` | no |
| <a name="input_create_bastion_sg"></a> [create\_bastion\_sg](#input\_create\_bastion\_sg) | Flag to specify if the Security Group for the bastion should be created. | `bool` | `true` | no |
| <a name="input_create_eip"></a> [create\_eip](#input\_create\_eip) | Flag to specify if an Elastic IP for the bastion should be created and assigned. | `bool` | `false` | no |
| <a name="input_disable_api_termination"></a> [disable\_api\_termination](#input\_disable\_api\_termination) | Whether to disable API termination for the bastion instance | `bool` | `null` | no |
| <a name="input_egress_rules"></a> [egress\_rules](#input\_egress\_rules) | List of egress rules to create. Used only if create\_bastion\_sg is true. | <pre>list(object({<br/> cidrs = list(string)<br/> from_port = number<br/> to_port = optional(number)<br/> protocol = string<br/> }))</pre> | <pre>[<br/> {<br/> "cidrs": [<br/> "0.0.0.0/0"<br/> ],<br/> "from_port": 0,<br/> "protocol": "all",<br/> "to_port": 0<br/> }<br/>]</pre> | no |
| <a name="input_eip_name"></a> [eip\_name](#input\_eip\_name) | Name of Elastic IP. | `string` | `null` | no |
| <a name="input_enable_bastion_public_ip"></a> [enable\_bastion\_public\_ip](#input\_enable\_bastion\_public\_ip) | Whether to create and assign an public IP to the bastion host. | `bool` | `null` | no |
| <a name="input_env_tags"></a> [env\_tags](#input\_env\_tags) | Tags applied to provisioned resources. | `map(any)` | `{}` | no |
| <a name="input_ingress_rules"></a> [ingress\_rules](#input\_ingress\_rules) | List of ingress rules to create. Used only if create\_bastion\_sg is true. | <pre>list(object({<br/> cidrs = list(string)<br/> from_port = number<br/> to_port = optional(number)<br/> protocol = string<br/> }))</pre> | `[]` | no |
| <a name="input_replace_on_user_data_change"></a> [replace\_on\_user\_data\_change](#input\_replace\_on\_user\_data\_change) | Trigger a destroy and recreate of the EC2 instance when user\_data changes. Defaults to false if not set. | `bool` | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_bastion_instance_details"></a> [bastion\_instance\_details](#output\_bastion\_instance\_details) | The details of the Bastion instance. |
| <a name="output_bastion_instance_id"></a> [bastion\_instance\_id](#output\_bastion\_instance\_id) | The ID of the Bastion instance. |
| <a name="output_bastion_instance_private_ip"></a> [bastion\_instance\_private\_ip](#output\_bastion\_instance\_private\_ip) | The private IP address of the Bastion instance. |
| <a name="output_bastion_instance_public_ip"></a> [bastion\_instance\_public\_ip](#output\_bastion\_instance\_public\_ip) | The public IP address of the Bastion instance. |
<!-- END_TF_DOCS -->
26 changes: 26 additions & 0 deletions modules/terraform-aws-bastion/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Find AMI for default bastion VM
data "aws_ami" "bastion_default_ami" {

most_recent = true

filter {
name = "name"
values = ["al2023-ami-2023*-x86_64"]
}

owners = ["amazon"]
}
24 changes: 24 additions & 0 deletions modules/terraform-aws-bastion/defaults.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

locals {

# Security Groups
bastion_security_group_id = (var.create_bastion_sg ?
aws_security_group.bastion_sg[0].id : var.bastion_security_group_id)

# Bastion VM
bastion_aws_ami = coalesce(var.bastion_aws_ami, data.aws_ami.bastion_default_ami.id)

}
11 changes: 11 additions & 0 deletions modules/terraform-aws-bastion/doc_fragments/header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Terraform Module for AWS Bastion

This module contains resource files and example variable definition files to create a Bastion EC2 instance on AWS. This module can be used to assist in deploying Cloudera Data Platform (CDP) Public Cloud in a secure environment, where the CDP Environment requires a Bastion host.

## Usage

The [examples](./examples) directory has example of using this module:

* `ex01-minimal_inputs` demonstrates how this module can be used to create a Bastion instance in a networking VPC. The [terraform-aws-vpc](../../../terraform-aws-vpc/README.md) module is also used as part of this example.

The sample `terraform.tfvars.sample` describes the required inputs for the example.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#cloud-config
hostname: test-host
runcmd:
- echo "Hello from cloud-init file!" > /tmp/hello.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
echo "Bash script executed successfully!" > /home/ec2-user/bash_test.txt
58 changes: 58 additions & 0 deletions modules/terraform-aws-bastion/examples/ex01-minimal_inputs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

provider "aws" {
region = var.aws_region
}

module "ex01_network_vpc" {
source = "../../../terraform-aws-vpc"

cdp_vpc = false
vpc_name = "${var.name_prefix}-network-vpc"
vpc_cidr = "10.11.0.0/16"
enable_nat_gateway = false

private_cidr_range = 26
public_cidr_range = 26
}

module "ex01_bastion" {
source = "../.."

vpc_id = module.ex01_network_vpc.vpc_id
bastion_subnet_id = module.ex01_network_vpc.public_subnets[0]
bastion_aws_keypair_name = var.aws_key_pair

bastion_user_data = base64encode(file("./files/ex-bash.sh"))
replace_on_user_data_change = true

bastion_host_name = "${var.name_prefix}-bastion"
eip_name = "${var.name_prefix}-eip"
bastion_security_group_name = "${var.name_prefix}-sg"
ingress_rules = [
{
cidrs = module.ex01_network_vpc.vpc_cidr_blocks
from_port = 0
to_port = 65535
protocol = "tcp"
},
{
cidrs = var.ingress_extra_cidrs
from_port = 22
to_port = 22
protocol = "tcp"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Copyright 2023 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Bastion public IP
output "bastion_instance_public_ip" {
value = module.ex01_bastion.bastion_instance_public_ip

description = "The public IP assigned to the Bastion host."
}

output "bastion_instance_private_ip" {
value = module.ex01_bastion.bastion_instance_private_ip

description = "The private IP assigned to the Bastion host."
}

output "bastion_instance_details" {
value = module.ex01_bastion.bastion_instance_details

description = "The details of the Bastion host."
}

output "bastion_instance_id" {
value = module.ex01_bastion.bastion_instance_id

description = "The instance ID assigned to the Bastion host."
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ------- Global Settings -------
name_prefix = "<ENTER_VALUE>"

# ------- Cloud Settings -------
aws_region = "<ENTER_VALUE>" # Change this to specify Cloud Provider region, e.g. eu-west-1
aws_key_pair = "<ENTER_VALUE>" # Change this with the name of a pre-existing AWS keypair, e.g. my-keypair

# ------- Bastion settings -------
ingress_extra_cidrs = ["<ENTER_CIDR>", "<ENTER_CIDR>"] # Any additional CIDRs the Proxy Security Groups for SSH access
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2025 Cloudera, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ------- Global settings -------
variable "name_prefix" {
type = string
description = "Shorthand name to use when naming resources."
}

# ------- Cloud Settings -------
variable "aws_region" {
type = string
description = "Region which Cloud resources will be created"
}

variable "aws_key_pair" {
type = string
description = "Name of the Public SSH key for the CDP environment"
}

# ------- Bastion settings -------
variable "ingress_extra_cidrs" {
type = list(string)
description = "List of extra ingress rules to create."

default = []
}
Loading

0 comments on commit a5ae9b8

Please sign in to comment.