Skip to content

Commit 71a7adc

Browse files
Merge pull request #57 from gdbranco/feat/ocm-13090
OCM-13090 | feat: include bastion host module
2 parents 035ecf7 + b7cb476 commit 71a7adc

File tree

12 files changed

+374
-29
lines changed

12 files changed

+374
-29
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,9 @@ terraform.rc
4141

4242
# Ignore IDE directories
4343
.idea/
44+
45+
# Cert files
46+
*.pem
47+
48+
# PID file generated by sshuttle daemon bastion connnect script
49+
*sshuttle-pid-file

assets/bastion-host-user-data.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#cloud-config
2+
#package_update: true
3+
#package_upgrade: true
4+
runcmd:
5+
- curl -L https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/4.1.15/openshift-client-linux-4.1.15.tar.gz | tar -C /usr/bin/ -xzf -

assets/bastion_connect.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/bin/sh
2+
set -eux
3+
4+
# Check for dependencies
5+
if ! command -v sshuttle >/dev/null; then
6+
echo "Please install sshuttle"
7+
exit 1
8+
fi
9+
if ! command -v jq >/dev/null; then
10+
echo "Please install jq"
11+
exit 1
12+
fi
13+
14+
TERRAFORM_JSON=$(terraform output -json)
15+
# Assigns public IP of bastion host to variables
16+
BASTION_HOST_PUB_IP=$(jq '.bastion_host_public_ip.value[0]' -r <<< $TERRAFORM_JSON)
17+
# Sest bastion host ssh .pem filename to variable
18+
ROSA_KEY=$(find . | grep '.pem')
19+
# Get API url of Rosa Cluster
20+
API=$(jq '.cluster_api_url.value' -r <<< $TERRAFORM_JSON)
21+
PW=$(jq '.password.value.result' -r <<< $TERRAFORM_JSON)
22+
23+
if [ -z "$API" ]; then
24+
echo "Could not find the API URL"
25+
exit 4
26+
fi
27+
if [ -z "$ROSA_KEY" ]; then
28+
echo "Could not find the SSH key"
29+
exit 4
30+
fi
31+
if [ -z "$BASTION_HOST_PUB_IP" ]; then
32+
echo "Could not find the SSH bastion host IP address"
33+
exit 4
34+
fi
35+
if [ -z "$PW" ]; then
36+
echo "Could not find the cluster idp password"
37+
exit 4
38+
fi
39+
40+
# Connect to the SSH bastion
41+
# Note that the user depends on AMI and might require to be changed
42+
sshuttle --daemon --pidfile="${TF_DIR:-.}/sshuttle-pid-file" --ssh-cmd "ssh -i ${TF_DIR:-.}/${ROSA_KEY}" --dns -NHr "ec2-user@${BASTION_HOST_PUB_IP}" 10.0.0.0/16
43+
oc login $API --username admin --password "${PW}"

assets/bastion_disconnect.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
PID=$(cat ${TF_DIR:-.}/sshuttle-pid-file)
3+
kill $PID

examples/rosa-hcp-private/README.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# ROSA HCP Private
1+
# Private ROSA HCP
22

33
## Introduction
44

@@ -7,6 +7,7 @@ This is a Terraform manifest example for creating a Red Hat OpenShift Service on
77
This example includes:
88
- A ROSA cluster with private access.
99
- All AWS resources (IAM and networking) that are created as part of the ROSA cluster module execution.
10+
- A bastion host EC2 instance that allows to reach the private cluster.
1011

1112
## Example Usage
1213

@@ -61,9 +62,46 @@ resource "random_password" "password" {
6162
module "vpc" {
6263
source = "terraform-redhat/rosa-hcp/rhcs//modules/vpc"
6364
64-
name_prefix = "my-cluster"
65+
name_prefix = "my-vpc"
6566
availability_zones_count = 3
6667
}
68+
69+
############################
70+
# Bastion instance for connection to the cluster
71+
############################
72+
data "aws_ami" "rhel9" {
73+
most_recent = true
74+
75+
filter {
76+
name = "platform-details"
77+
values = ["Red Hat Enterprise Linux"]
78+
}
79+
80+
filter {
81+
name = "architecture"
82+
values = ["x86_64"]
83+
}
84+
85+
filter {
86+
name = "root-device-type"
87+
values = ["ebs"]
88+
}
89+
90+
filter {
91+
name = "manifest-location"
92+
values = ["amazon/RHEL-9.*_HVM-*-x86_64-*-Hourly2-GP2"]
93+
}
94+
95+
owners = ["309956199498"] # Amazon's "Official Red Hat" account
96+
}
97+
module "bastion_host" {
98+
source = "../../modules/bastion-host"
99+
prefix = "my-host"
100+
vpc_id = module.vpc.vpc_id
101+
subnet_ids = [module.vpc.public_subnets[0]]
102+
ami_id = aws_ami.rhel9.id
103+
user_data_file = file("bastion-host-user-data.yaml")
104+
}
67105
```
68106

69107

@@ -81,21 +119,23 @@ module "vpc" {
81119

82120
| Name | Version |
83121
|------|---------|
122+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.35.0 |
84123
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |
85124

86125
## Modules
87126

88127
| Name | Source | Version |
89128
|------|--------|---------|
129+
| <a name="module_bastion_host"></a> [bastion\_host](#module\_bastion\_host) | ../../modules/bastion-host | n/a |
90130
| <a name="module_hcp"></a> [hcp](#module\_hcp) | ../../ | n/a |
91-
| <a name="module_htpasswd_idp"></a> [htpasswd\_idp](#module\_htpasswd\_idp) | ../../modules/idp | n/a |
92131
| <a name="module_vpc"></a> [vpc](#module\_vpc) | ../../modules/vpc | n/a |
93132

94133
## Resources
95134

96135
| Name | Type |
97136
|------|------|
98137
| [random_password.password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
138+
| [aws_ami.rhel9](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
99139

100140
## Inputs
101141

@@ -110,6 +150,9 @@ module "vpc" {
110150
|------|-------------|
111151
| <a name="output_account_role_prefix"></a> [account\_role\_prefix](#output\_account\_role\_prefix) | The prefix used for all generated AWS resources. |
112152
| <a name="output_account_roles_arn"></a> [account\_roles\_arn](#output\_account\_roles\_arn) | A map of Amazon Resource Names (ARNs) associated with the AWS IAM roles created. The key in the map represents the name of an AWS IAM role, while the corresponding value represents the associated Amazon Resource Name (ARN) of that role. |
153+
| <a name="output_bastion_host_public_ip"></a> [bastion\_host\_public\_ip](#output\_bastion\_host\_public\_ip) | Bastion Host Public IP |
154+
| <a name="output_cluster_api_url"></a> [cluster\_api\_url](#output\_cluster\_api\_url) | The URL of the API server. |
155+
| <a name="output_cluster_console_url"></a> [cluster\_console\_url](#output\_cluster\_console\_url) | The URL of the console. |
113156
| <a name="output_cluster_id"></a> [cluster\_id](#output\_cluster\_id) | Unique identifier of the cluster. |
114157
| <a name="output_oidc_config_id"></a> [oidc\_config\_id](#output\_oidc\_config\_id) | The unique identifier associated with users authenticated through OpenID Connect (OIDC) generated by this OIDC config. |
115158
| <a name="output_oidc_endpoint_url"></a> [oidc\_endpoint\_url](#output\_oidc\_endpoint\_url) | Registered OIDC configuration issuer URL, generated by this OIDC config. |

examples/rosa-hcp-private/main.tf

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ locals {
99
module "hcp" {
1010
source = "../../"
1111

12-
cluster_name = var.cluster_name
13-
openshift_version = var.openshift_version
14-
machine_cidr = module.vpc.cidr_block
15-
aws_subnet_ids = module.vpc.private_subnets
16-
aws_availability_zones = module.vpc.availability_zones
17-
replicas = length(module.vpc.availability_zones)
18-
private = true
19-
create_admin_user = true
20-
ec2_metadata_http_tokens = "required"
12+
cluster_name = var.cluster_name
13+
openshift_version = var.openshift_version
14+
machine_cidr = module.vpc.cidr_block
15+
aws_subnet_ids = module.vpc.private_subnets
16+
replicas = 2
17+
private = true
18+
create_admin_user = true
19+
admin_credentials_username = "admin"
20+
admin_credentials_password = random_password.password.result
21+
ec2_metadata_http_tokens = "required"
2122

2223
// STS configuration
2324
create_account_roles = true
@@ -27,25 +28,13 @@ module "hcp" {
2728
operator_role_prefix = local.operator_role_prefix
2829
}
2930

30-
############################
31-
# HTPASSWD IDP
32-
############################
33-
module "htpasswd_idp" {
34-
source = "../../modules/idp"
35-
36-
cluster_id = module.hcp.cluster_id
37-
name = "htpasswd-idp"
38-
idp_type = "htpasswd"
39-
htpasswd_idp_users = [{ username = "test-user", password = random_password.password.result }]
40-
}
41-
4231
resource "random_password" "password" {
43-
length = 14
44-
special = true
45-
min_lower = 1
32+
length = 14
33+
special = true
34+
min_lower = 1
4635
min_numeric = 1
4736
min_special = 1
48-
min_upper = 1
37+
min_upper = 1
4938
}
5039

5140
############################
@@ -55,5 +44,42 @@ module "vpc" {
5544
source = "../../modules/vpc"
5645

5746
name_prefix = var.cluster_name
58-
availability_zones_count = 3
47+
availability_zones_count = 1
48+
}
49+
50+
############################
51+
# Bastion instance for connection to the cluster
52+
############################
53+
data "aws_ami" "rhel9" {
54+
most_recent = true
55+
56+
filter {
57+
name = "platform-details"
58+
values = ["Red Hat Enterprise Linux"]
59+
}
60+
61+
filter {
62+
name = "architecture"
63+
values = ["x86_64"]
64+
}
65+
66+
filter {
67+
name = "root-device-type"
68+
values = ["ebs"]
69+
}
70+
71+
filter {
72+
name = "manifest-location"
73+
values = ["amazon/RHEL-9.*_HVM-*-x86_64-*-Hourly2-GP2"]
74+
}
75+
76+
owners = ["309956199498"] # Amazon's "Official Red Hat" account
77+
}
78+
module "bastion_host" {
79+
source = "../../modules/bastion-host"
80+
prefix = var.cluster_name
81+
vpc_id = module.vpc.vpc_id
82+
subnet_ids = [module.vpc.public_subnets[0]]
83+
ami_id = data.aws_ami.rhel9.id
84+
user_data_file = file("../../assets/bastion-host-user-data.yaml")
5985
}

examples/rosa-hcp-private/outputs.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
1+
output "bastion_host_public_ip" {
2+
value = module.bastion_host.bastion_host_public_ip
3+
description = "Bastion Host Public IP"
4+
}
5+
16
output "cluster_id" {
27
value = module.hcp.cluster_id
38
description = "Unique identifier of the cluster."
49
}
510

11+
output "cluster_api_url" {
12+
value = module.hcp.cluster_api_url
13+
description = "The URL of the API server."
14+
}
15+
16+
output "cluster_console_url" {
17+
value = module.hcp.cluster_console_url
18+
description = "The URL of the console."
19+
}
20+
621
output "account_role_prefix" {
722
value = module.hcp.account_role_prefix
823
description = "The prefix used for all generated AWS resources."

modules/bastion-host/README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Bastion Host
2+
3+
## Introduction
4+
5+
This is a Terraform manifest example for creating a bastion host aws ec2 instance. This example provides a structured configuration template that demonstrates how to deploy vpc and bastion host to your AWS environment by using Terraform.
6+
7+
This example includes:
8+
- A VPC with both public and private subnets.
9+
- An EC2 instance attached to the public subnet of the vpc that allows connection to it so it may access the private network from within it.
10+
11+
## Example Usage
12+
13+
```
14+
############################
15+
# VPC
16+
############################
17+
module "vpc" {
18+
source = "terraform-redhat/rosa-hcp/rhcs//modules/vpc"
19+
20+
name_prefix = "my-vpc"
21+
availability_zones_count = 1
22+
}
23+
24+
############################
25+
# Bastion instance for connection to the cluster
26+
############################
27+
module "bastion_host" {
28+
source = "../../modules/bastion-host"
29+
prefix = "my-host"
30+
vpc_id = module.vpc.vpc_id
31+
subnet_ids = [module.vpc.public_subnets[0]]
32+
ami_id = aws_ami.rhel9.id
33+
user_data_file = file("bastion-host-user-data.yaml")
34+
}
35+
```
36+
37+
38+
<!-- BEGIN_AUTOMATED_TF_DOCS_BLOCK -->
39+
## Requirements
40+
41+
| Name | Version |
42+
|------|---------|
43+
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
44+
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.35.0 |
45+
46+
## Providers
47+
48+
| Name | Version |
49+
|------|---------|
50+
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.35.0 |
51+
| <a name="provider_http"></a> [http](#provider\_http) | n/a |
52+
| <a name="provider_local"></a> [local](#provider\_local) | n/a |
53+
| <a name="provider_time"></a> [time](#provider\_time) | n/a |
54+
| <a name="provider_tls"></a> [tls](#provider\_tls) | n/a |
55+
56+
## Modules
57+
58+
No modules.
59+
60+
## Resources
61+
62+
| Name | Type |
63+
|------|------|
64+
| [aws_instance.bastion_host](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource |
65+
| [aws_key_pair.bastion_ssh_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource |
66+
| [aws_security_group.bastion_host_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
67+
| [local_file.bastion_private_ssh_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
68+
| [time_sleep.bastion_resources_wait](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
69+
| [tls_private_key.pk](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
70+
| [http_http.myip](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |
71+
72+
## Inputs
73+
74+
| Name | Description | Type | Default | Required |
75+
|------|-------------|------|---------|:--------:|
76+
| <a name="input_ami_id"></a> [ami\_id](#input\_ami\_id) | Amazon Machine Image to run the bastion host with | `string` | `null` | no |
77+
| <a name="input_cidr_blocks"></a> [cidr\_blocks](#input\_cidr\_blocks) | CIDR ranges to include as ingress allowed ranges | `list(string)` | `null` | no |
78+
| <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | Instance type of the bastion hosts | `string` | `"t2.micro"` | no |
79+
| <a name="input_prefix"></a> [prefix](#input\_prefix) | Prefix for the name of each AWS resource | `string` | n/a | yes |
80+
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | Set of subnet IDs to instantiate a bastion host against | `list(string)` | n/a | yes |
81+
| <a name="input_user_data_file"></a> [user\_data\_file](#input\_user\_data\_file) | User data for proxy configuration | `string` | `null` | no |
82+
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | ID of the AWS VPC resource | `string` | n/a | yes |
83+
84+
## Outputs
85+
86+
| Name | Description |
87+
|------|-------------|
88+
| <a name="output_bastion_host_public_ip"></a> [bastion\_host\_public\_ip](#output\_bastion\_host\_public\_ip) | Bastion Host Public IP |
89+
<!-- END_AUTOMATED_TF_DOCS_BLOCK -->

0 commit comments

Comments
 (0)