OCI Bastion and jump-host build with DRG using terraform code
Overview
BASTION
Provide
restricted and time-limited secure access to resources that don not have public
endpoints and require strict resource access controls. Examples include compute
instances, bare metal and virtual machines, MySQL, ATP, OKE, and any other
resource that allows Secure Shell Protocol (SSH) access. For more details see oci bastion documentation
OCI Bastion removes the need for a public IP for bastion access, eliminating the hassle and potential attack surface from remote access.
See bastion concept using Transit routing in figure 1.0.
Figure1.0:

SESSION
The Bastion service recognizes three types of sessions. The type of session you create, or choose to connect to, depends on the type of target resource. Recommended to use ssh port forwarding session. For more details see: link
Overview of Dynamic Routing Gateways and remote VCN peering
A DRG acts as a virtual router, providing a path for traffic between your on-premises networks and VCNs, and can also be used to route traffic between VCNs. Using different types of attachments, custom network topologies can be constructed using components in different regions and tenancies. Each DRG attachment has an associated route table which is used to route packets entering the DRG to their next hop. In addition to static routes, routes from the attached networks are dynamically imported into DRG route tables using optional import route distributions.
Remote VCN peering is the process of connecting two VCNs in different regions (but the same tenancy ). The peering allows the VCNs' resources to communicate using private IP addresses without routing the traffic over the internet or through your on-premises network. Without peering, a given VCN would need an internet gateway and public IP addresses for the instances that need to communicate with another VCN in a different region.
For more details see: link
Note: the CIDR range would not be overlapping.
See Figure1.1:
Terraform code
#Setup local’s variable that are repeatedly using in code.
locals {
# Jump Host properties
jump_host_compartment_ocid = ""
jump_host_vcn_cidr = "192.168.0.0/29"
jump_host_vcn_name = ""
jump_host_subnet_cidr = "192.168.0.0/29"
jump_host_subnet_name = ""
jump_host_subnet_security_list_name = ""
jump_host_subnet_route_table_name = ""
jump_host_to_service_lpg_name = ""
jump_host_service_gateway_name = ""
jump_nat_gateway_name = ""
#MS service properties
service_ms_compartment_ocid = ""
service_ms_vpn_ocid = ""
service_ms_vcn_cidr = "10.0.0.0/24"
service_ms_vcn_name = ""
service_ms_control_plane_subnet_cidr = "10.0.0.0/24"
service_ms_control_plane_subnet_name = ""
service_ms_control_plane_subnet_security_list_name = ""
service_ms_control_plane_subnet_route_table_name = ""
service_ms_to_jump_host_lpg_name = ""
service_ms_vcn_service_ms_gateway_name = ""
service_ms_nat_gateway_name = ""
# Common Networking properties
TCP = "6"
CIDR_BLOCK = "CIDR_BLOCK"
SERVICE_CIDR_BLOCK = "SERVICE_CIDR_BLOCK"
oci_service_id = data.oci_core_services.oci.services[0].id
oci_service_cidr = data.oci_core_services.oci.services[0].cidr_block
# Common Compute Instance properties
compute_instance_shape = "VM.Standard1.1"
ad = "EU-FRANKFURT-1-AD-1"
image_ocid = ""
boot_volume_size_in_gbs = 75
ssh_public_key = ""
InstanceShape. = ""
# Bastion properties
bastion_name = ""
phone_book_entry = ""
allow_list = ""
#Stage1
#Creation of separate VCN in CIDR range (192.168.0.0/29) that would host OCI bastion and jump-hosts. /29 CIDR range support 8 Ip’s and that will be sufficient for setups bastion and backend jump-hosts.
resource "oci_core_vcn" jump_host_vcn {
compartment_id = local.jump_host_compartment_ocid
cidr_block = local.jump_host_vcn_cidr
display_name = local.jump_host_vcn_name
}
#Stage2
#Creation of DRG for the jump-host VCN network and attach DRG in the same VCN and then initiate remote peering. Inf the below example I am creating a connection from Frankfurt to Ashburn region.
resource oci_core_drg FRA-to-ASH-DRG {
compartment_id = local.jump_host_compartment_ocid
defined_tags = {
}
display_name = "FRA-to-ASH-DRG"
}
resource "oci_core_drg_attachment" "FRA-to-ASH-ATTACH-DRG" {
drg_id = oci_core_drg.FRA-to-ASH-DRG.id
display_name = "FRA-to-ASH-ATTACH-DRG"
vcn_id = oci_core_vcn.jump_host_vcn.id
}
resource oci_core_remote_peering_connection FRA-to-ASH-RPC-DRG {
compartment_id = local.jump_host_compartment_ocid
display_name = "FRA-to-ASH-RPC-DRG"
drg_id = oci_core_drg.FRA-to-ASH-DRG.id
}
#Stage3
#Creation and attachment of DRG in another region (Ashburn) VCN.
resource oci_core_drg MS-ASH-to-JUMP-FRA-DRG-POC {
provider = oci.us-ashburn-1
compartment_id = local.service_ms_compartment_ocid
display_name = "MS-ASH-to-JUMP-FRA-DRG-POC"
}
resource "oci_core_drg_attachment" "MS-ASH-to-JUMP-FRA-ATTACH-DRG-POC" {
provider = oci.us-ashburn-1
drg_id = oci_core_drg.MS-ASH-to-JUMP-FRA-DRG-POC.id
display_name = "MS-ASH-to-JUMP-FRA-ATTACH-DRG-POC"
vcn_id = local.service_ms_vcn_cidr
}
resource oci_core_remote_peering_connection MS-ASH-to-JUMP-FRA-DRG-POC {
provider = oci.us-ashburn-1
compartment_id = local.service_ms_compartment_ocid
display_name = "FRA-to-ASH-RPC-DRG-POC"
drg_id = oci_core_drg.MS-ASH-to-JUMP-FRA-DRG-POC.id
peer_id = oci_core_remote_peering_connection.FRA-to-ASH-RPC-DRG-POC.id
peer_region_name = "eu-frankfurt-1"
}
#Stage4
#Create a Service gateway, NAT gateway, Security list , route table and subnets for Jump-host VCN
#Discover service gateway
data "oci_core_services" oci {
filter {
name = "name"
values = ["All.*Oracle.*Services"]
regex = true
}
}
resource "oci_core_security_list" jump_host_subnet_security_list {
compartment_id = local.jump_host_compartment_ocid
vcn_id = oci_core_vcn.jump_host_vcn.id
display_name = local.jump_host_subnet_security_list_name
#allow egress traffic to flow to service vcn cidr
egress_security_rules {
description = "egress for overlayhost connection"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
protocol = "6"
stateless = false
}
# all ingress traffic from all IP addresses of this subnet to all other IP addresses within the subnet
ingress_security_rules {
source_type = local.CIDR_BLOCK
source = local.jump_host_vcn_cidr
protocol = local.TCP
tcp_options {
min = 22
max = 22
}
description = "From other IP Addresses within subnet via TCP"
}
# all ingress traffic from all IP addresses from MS subnet.
ingress_security_rules {
source_type = local.CIDR_BLOCK
source = local.service_ms_control_plane_subnet_cidr
protocol = local.TCP
tcp_options {
min = 22
max = 22
}
description = "From MS IP Addresses within subnet via TCP"
}
# all egress traffic from all IP addresses of this subnet to all other IP addresses within the subnet
egress_security_rules {
destination_type = local.CIDR_BLOCK
destination = local.jump_host_subnet_cidr
protocol = local.TCP
tcp_options {
min = 22
max = 22
}
description = "To other IP Addresses within subnet via TCP"
}
}
# service gatway
resource "oci_core_service_gateway" jump_host_sgw {
compartment_id = local.jump_host_compartment_ocid
vcn_id = oci_core_vcn.jump_host_vcn.id
display_name = local.jump_host_service_gateway_name
services {
service_id = local.oci_service_id
}
}
# NAT gatway
resource "oci_core_nat_gateway" "test_nat_gateway" {
compartment_id = local.jump_host_compartment_ocid
vcn_id = oci_core_vcn.jump_host_vcn.id
display_name = local.jump_nat_gateway_name
}
# attaching rules to route table
resource "oci_core_route_table" "test_route_table" {
compartment_id = local.jump_host_compartment_ocid
vcn_id = oci_core_vcn.jump_host_vcn.id
display_name = local.jump_host_subnet_route_table_name
route_rules {
description = "Add DRG route to subnet"
destination = local.service_ms_control_plane_subnet_cidr
destination_type = "CIDR_BLOCK"
network_entity_id = oci_core_drg.FRA-to-ASH-DRG.id
}
route_rules {
description = "Add service GW route to subnet"
destination = local.oci_service_cidr
destination_type = "SERVICE_CIDR_BLOCK"
network_entity_id = oci_core_service_gateway.jump_host_sgw.id
}
route_rules {
description = "Add NAT gatway to subnet"
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
network_entity_id = oci_core_nat_gateway.test_nat_gateway.id
}
}
#Creation of subnet at jumphost vcn
resource "oci_core_subnet" jump_host_subnet {
compartment_id = local.jump_host_compartment_ocid
vcn_id = oci_core_vcn.jump_host_vcn.id
cidr_block = local.jump_host_subnet_cidr
prohibit_public_ip_on_vnic = true
prohibit_internet_ingress = "true"
display_name = local.jump_host_subnet_name
route_table_id = oci_core_route_table.test_route_table.id
security_list_ids = [oci_core_security_list.jump_host_subnet_security_list.id]
}
#Stage5
#REPEATE Stage4 AND ADD ROUTING TABLE AND OPEN SECURULES/NSG CONNECTION FOR MANAGED SERVICES IN OTHER REGION.
#Stage6
#Creation a jump-host
Creating jump host
data "oci_identity_availability_domains" "ads" {
compartment_id = local.jump_host_compartment_ocid
}
resource "oci_core_instance" "ms-jumphost01" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
compartment_id = local.jump_host_compartment_ocid
display_name = "ms-jumphost01"
shape = local.InstanceShape
subnet_id = oci_core_subnet.jump_host_subnet.id
preserve_boot_volume = "false"
create_vnic_details {
assign_public_ip = "false"
}
source_details {
source_type = "image"
source_id = local.image_ocid
boot_volume_size_in_gbs = local.boot_volume_size_in_gbs
}
metadata = {
ssh_authorized_keys = local.ssh_public_key
hostclass = local.hostclass
}
# You need to ignore the source details if you don't want to apply any changes to old instances.
lifecycle {
ignore_changes = [
source_details
]
}
}
#Stage7
#Repeat Stage6 for second jump-host creation
#Stage8
#OCI Bastion creation. For more details see link
resource "oci_bastion_bastion" "test_bastion" {
bastion_type = "STANDARD"
client_cidr_block_allow_list = local.allow_list
compartment_id = local.jump_host_compartment_ocid
target_subnet_id = oci_core_subnet.jump_host_subnet.id
name = local.bastion_name
phone_book_entry = local.phone_book_entry
static_jump_host_ip_addresses = [oci_core_instance.ms-jumphost01.private_ip, oci_core_instance.ms-jumphost02.private_ip]
}
#Stage9
#Create a bastion session
resource "oci_bastion_session""test_session"{
bastion_id=oci_bastion_bastion.test_bastion.id
key_details{
public_key_content=var.session_key_details_public_key_content
}
target_resource_details{
session_type=var.session_target_resource_details_session_type
}display_name=var.session_display_name
}
#Stage10
#Outputs
data "oci_bastion_bastion" "test_bastions" {
bastion_id = oci_bastion_bastion.test_bastion.id
}
output bastions {
value = data.bastion_internal_bastion.test_bastions.id
}
data "oci_bastion_sessions""test_sessions"{
bastion_id = oci_bastion_bastion.test_bastion.id }
output sessions
{
value = data.oci_bastion_sessions.test_sessions
}
Comments
Post a Comment