Oracle Cloud Infrastructure Bastion service provides restricted and time-limited access to target resources that don’t have public endpoints. Through the configuration of a bastion, you can let authorized users connect from specific IP addresses to target resources by way of Secure Shell (SSH) sessions hosted on the bastion.

Typically you have ticketing solutions and security mechanisms that gives users ephemeral access to resources. That capability can be easily built using several OCI services and APIs as we depict a little bit in this post.
Bastion Service: Provides access to private resources via sessions created against it. Each bastion has properties such as CIDR’s ranges of origin IP’s that are allowed to connect to OCI resources.

Bastion Sessions: are ephemeral connections. Can be two types: ssh and port forward ssh. When you create a session the following must be provided:
- Type: two options available, ssh or port forwarding
- Target IP, you probably have it in an inventory or it can be query with the OCI SDK
- Target OCID of the resource, same comments as previous parameter
- A public key corresponding to a private key created for the session
- Timeout of the session
- Username, is the operating system user name which are already configured on the target instance (opc for Oracle Linux instances, ubuntu for Ubuntu, etc)

This is an example on how to create session using the OCI CLI. First create a JSON file with the following:
{ "bastion-id": "ocid1.bastion.oc1....ta", "display-name": "S00000111", "key-type": "PUB", "session-ttl-in-seconds": 10800, "target-resource-details": { "session-type": "MANAGED_SSH", "target-resource-id": "ocid1.instance.oc1....ha", "target-resource-operating-system-user-name": "opc", "target-resource-port": 22, "target-resource-private-ip-address": "10.0.2.94" } }
Create a pair of openssh files:
openssl genrsa -out keyfile.pem 2048 openssl rsa -pubout -in keyfile.pem -out keyfile_public.pem
And now execute:
oci bastion session create --from-json file://mysession.json --ssh-public-key-file keyfile_public.pem { "data": { "bastion-id": "ocid1.bastion.oc1.eu-frankfurt-1.ama...ta", "bastion-name": "Bastion202105312247", "bastion-public-host-key-info": null, "bastion-user-name": null, "display-name": "S00000111", "id": "ocid1.bastionsession.oc1.eu-frankfurt-1.ama...tq", "key-details": { "public-key-content": "ssh-rsa AAAA...04-20\n" }, "key-type": "PUB", "lifecycle-details": null, "lifecycle-state": "CREATING", "session-ttl-in-seconds": 10800, "ssh-metadata": null, "target-resource-details": { "session-type": "MANAGED_SSH", "target-resource-display-name": "bastion-priv", "target-resource-id": "ocid1.instance.oc1.eu-frankfurt-1.ant...ha", "target-resource-operating-system-user-name": "opc", "target-resource-port": 22, "target-resource-private-ip-address": "10.0.2.94" }, "time-created": "2021-06-01T22:21:06.269000+00:00", "time-updated": "2021-06-01T22:21:06.269000+00:00" }, "opc-work-request-id": "ocid1.bastionworkrequest.oc1.eu-frankfurt-1.amaaa...
A few seconds later the session will be active for the period configured:

Now, get the id of the bastionsession created, execute the following and notice the command key in the returned json:
oci bastion session get --session-id ocid1.bastionsession.oc1.eu-frankfurt-1.amaa...4tq { "data": { "bastion-id": "ocid1.bastion.oc1.eu-frankfurt-1.amaaata", "bastion-name": "Bastion202105312247", "bastion-public-host-key-info": null, "bastion-user-name": "ocid1.bastionsession.oc1.eu-frankfurt-1.amaaa4tq", "display-name": "S00000111", "id": "ocid1.bastionsession.oc1.eu-frankfurt-1.amaaa4tq", "key-details": { "public-key-content": "ssh-rsa AAA...04-20\n" }, "key-type": "PUB", "lifecycle-details": null, "lifecycle-state": "ACTIVE", "session-ttl-in-seconds": 10800, "ssh-metadata": { "command": "ssh -i <privateKey> -o ProxyCommand=\"ssh -i <privateKey> -W %h:%p -p 22 ocid1.bastionsession.oc1.eu-frankfurt-1.amaaaaaaxwhvexyamziinma5hshi6kquzrabgru2gxu2iybuz67elnyoq4tq@host.bastion.eu-frankfurt-1.oci.oraclecloud.com\" -p 22 opc@10.0.2.94" }, "target-resource-details": { "session-type": "MANAGED_SSH", "target-resource-display-name": "bastion-priv", "target-resource-id": "ocid1.instance.oc1.eu-frankfurt-1.an...ha", "target-resource-operating-system-user-name": "opc", "target-resource-port": 22, "target-resource-private-ip-address": "10.0.2.94" }, "time-created": "2021-06-01T22:21:06.269000+00:00", "time-updated": "2021-06-01T22:21:13.394000+00:00" }, "etag": "9a5ed8...c42d--gzip" }
Now, test the session using the value of the private key created for the session, execute the provided command and see what happens.

So far so good. How can we automate this stuff? Let’s create a web app that provides the capability for the user to upload its public key and function that does the following:
- Gets the publickey of the grantee from the database
- Creates a bastion session with the needed parameters mentioned above, including the public key file
- Grab the ssh access command for the session
- Send the ssh command to the granted user via email
For the OCI Email notification setup follow this post.
Here a diagram of the solution:

In future post we’ll provide the steps and artefacts to implement the solution as an OCI Function.
That’s all for now, hope it helps! š