In part II, and after demonstrating how to use OCI Bastion Service using the Console (see part I), we will cover how to create Bastion Service using automation tools like OCI CLI and Terraform as I didn’t want all these approaches to be lumped in one post.
A quick table of contents
– Create Bastion Service using OCI CLI
– Create Bastion Service using Terraform
As described in part I the Bastion Service is linked to the target subnet and a Bastion Session will define the port forwarding to the target instance.
 Our environment:
  – VCN vcnterra has the private subnet db-sub with a CIDR of 192.168.78.0/24
  – DB instance IP is 192.168.78.10
OCI CLI is perfect for quickly automating Bastion Service creation with many sessions/ports.
By specifying the compartment and subnet ids from the previous example
$ export comp_id=ocid1.compartment.oc1..a***q 
$ export subnet_id=ocid1.subnet.oc1.ca-toronto-1.a**q
-- Create the Bastion -- 
$ oci bastion bastion create --bastion-type Standard --compartment-id $comp_id --target-subnet-id $subnet_id --client-cidr-list '["0.0.0.0/0"]'
-- describe the Bastion Service -- 
$ export bastion_id=$(oci bastion bastion list --compartment-id  $comp_id --all --query "data[0].id" --raw-output)
$ oci bastion bastion get --bastion-id $bastion_id  --query "data.{Name:name,bastion_type:\"bastion-type\",state:\"lifecycle-state\",allow_list:\"client-cidr-block-allow-list\",jump_ip:\"private-endpoint-ip-address\",timeout:\"max-session-ttl-in-seconds\"}"   --output table
+-----------+-------------+-------------+---------------+--------+---------+
| Name | allow_list |bastion_type | jump_ip | state | timeout |
+-----------+-------------+-------------+---------------+--------+---------+
| bastion2* |['0.0.0.0/0']| STANDARD |192.168.78.127 | ACTIVE | 10800 |
+-----------+-------------+-------------+---------------+--------+---------+ 
We will use $bastion_id and other required attributes we inserted in the console earlier
$ oci bastion session create-port-forwarding  --display-name bastiontoDBSession --bastion-id $bastion_id --key-type PUB --ssh-public-key-file id_rsa_oci.pub --target-port 22 --target-private-ip 192.168.78.10 --wait-for-state SUCCEEDED  
$ session_id=$(oci bastion session list --bastion-id $bastion_id --session-lifecycle-state ACTIVE --sort-order asc --all --query "data[0].id" --raw-output)  
$ oci bastion session get --session-id $session_id --query "data.\"ssh-metadata\".command" --raw-output
ssh -i 
   
     -N -L 
    
     :192.168.78.10:22 -p 22 ocid1.bastionsession.oc1.ca-toronto-1.ama**@host.bastion.ca-toronto-1.oci.oraclecloud.com
    
    
This is also super cool to have, especially when deploying a full stack and needing to connect to private resources right away
The SSH Command can even be extracted from the output (we’ll use the same environment)
3 x Configuration files
$ vi bastion.tf
resource "oci_bastion_bastion" "mybastion" {
 #Required
 bastion_type = "standard"
 compartment_id = var.compartment_ocid
 target_subnet_id = oci_core_subnet.terraDB.id #CHANGE ME
 name = var.bastion_name
 client_cidr_block_allow_list = [var.bastion_cidr_block_allow_list]
}
##################################
# Bastion Session
##################################
resource "oci_bastion_session" "mybastion_session" {
 #Required
 bastion_id = oci_bastion_bastion.mybastion.id
 key_details {
 public_key_content = var.ssh_public_key
 }
 target_resource_details {
 session_type = var.bastion_session_type
 target_resource_port = "22" 
 target_resource_private_ip_address = "192.168.78.10" 
 }
 display_name = var.bastion_session_name 
 key_type = "PUB"
 session_ttl_in_seconds = "10800" 
}
 
$ vi variable.tf
variable "bastion_cidr_block_allow_list" { default= "0.0.0.0/0"}
variable "bastion_name" { default = "BastionMyDB"}
variable "bastion_session_type" {default = "PORT_FORWARDING"}
variable "bastion_session_name" {default = "Session-Mybastion" } 
 
$ vi output.tf
 output "bastion_session_state" {
 value = oci_bastion_session.mybastion_session.state}
output "bastion_session_target_resource_details" {
 value = oci_bastion_session.mybastion_session.target_resource_details}
output "bastion_session_ssh_connection" {
 value = oci_bastion_session.mybastion_session.ssh_metadata.command} 
 
# ssh -i ~/.ssh/id_rsa_oci -N -L 22:192.168.78.10:22 -p 22 ocid1.bastionsession.oc1.ca-toronto-1.amaaaaaavr**a@host.bastion.ca-toronto-1.oci.oraclecloud.com & 
# ssh -i  ~/.ssh/id_rsa_dbcs opc@localhost
[opc@hopsdb-oci ~]$ cat /etc/redhat-release --- target instance
Red Hat Enterprise Linux Server release 7.9 (Maipo)
[opc@hopsdb-oci ~]$ ifconfig  ens3
ens3: flags=4163
    
       mtu 9000
     
inet 192.168.78.10  netmask 255.255.255.0  broadcast 192.168.78.255
     
     
In this article, we learned