Monday, March 21, 2022

OCI Bastion Service Part II: Create Bastion service using OCI CLI & Terraform

This image has an empty alt attribute; its file name is image-6.pngIntro

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. 

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
DB instance IP is

I. Create Bastion Service from OCI CLI

     OCI CLI is perfect for quickly automate bastion service creation with many sessions/ports,.

  • Install and configure OCI CLI as described here . Assuming your default profile will be the target tenancy

1. Create the Bastion  

by specifying the compartment and subnet ids from the previous example.

$ export comp_id=ocid1.compartment.oc1..a***q 
$ export**q

-- Create the Bastion --
$ oci bastion bastion create --bastion-type Standard --compartment-id $comp_id --target-subnet-id $subnet_id --client-cidr-list '[""]'

-- 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* |['']| STANDARD | | ACTIVE | 10800 | +-----------+-------------+-------------+---------------+--------+---------+


2. Create Port forwarding Bastion Session

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 --target-port 22 --target-private-ip --wait-for-state SUCCEEDED 
  • export the bastion session OCID 
$ session_id=$(oci bastion session list --bastion-id $bastion_id --session-lifecycle-state ACTIVE --sort-order asc --all --query "data[0].id" --raw-output) 
  • Display the ssh proxy command details from the bastion session resource 
$ oci bastion session get --session-id $session_id --query "data.\"ssh-metadata\".command" --raw-output

ssh -i <privateKey> -N -L <localPort>: -p 22**

II. Create Bastion Service From terraform

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

  • for both Bastion and Bastion session
$ vi

resource "oci_bastion_bastion" "mybastion" { #Required bastion_type = "standard" compartment_id = var.compartment_ocid target_subnet_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 = 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 = ""
} display_name = var.bastion_session_name key_type = "PUB" session_ttl_in_seconds = "10800" }

$ vi
variable "bastion_cidr_block_allow_list" { default= ""} variable "bastion_name" { default = "BastionMyDB"} variable "bastion_session_type" {default = "PORT_FORWARDING"} variable "bastion_session_name" {default = "Session-Mybastion" }
variable "ssh_public_key" { default = "~/"}

  • to extract all necessary information including the ssh command
$ vi
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}

  • After setting the subnet/compartment ids, terraform apply will create the bastion & display something like the below

This image has an empty alt attribute; its file name is image-13.png

    SSH connection Usage

  • Final result will  looks like this, notice I added & to run it in the background, so I won’t have to open another session to login to the private DB instance. 
    # ssh -i ~/.ssh/id_rsa_oci -N -L 22: -p 22** &
  • Run the final ssh command to access the target resource using a sort of loopback where localhost is forwarded into the target instance IP through the opened proxy tunnel. 

    # 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<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9000
    inet  netmask  broadcast

     Warning:  Beware as It’s important to distinguish between :
    • ssh key pair used to used to build the Bastion session
    • ssh key pair used in the target vm (our db instance) upon creation
  • The first is used when we run the bastion command , the second is used when connecting as opc@locahost .


           In this article we learned

    • How to create OCI Bastion service using  OCI CLI , and finally Terraform.
    • With the above there is no excuse not to try this super cool feature that is absolutely FREE.
    • Thanks for reading

    No comments:

    Post a Comment