Setting the Service mode to SSH
enables it to operate in the application-layer aware SSH mode. This mode enables you to provide secret-less access for Users to the protected upstream SSH server without having to share the upstream's password or private key. This mode also provides you with clear application-layer aware visibility where your SSH sessions are logged and audited in real-time.
You can also check out the embedded SSH mode where you can seamlessly provide secret-less SSH access via SSH servers that are embedded from within connected octelium
clients to serve directly SSH to Users without the need of SSH servers running on the client's host.
Secret-less Access
Password
Here is an example where the upstream SSH server is accessed through a password.
1kind: Service2metadata:3name: ssh14spec:5mode: SSH6port: 20227config:8upstream:9url: ssh://address-to-host10ssh:11user: root12auth:13password:14fromSecret: <SECRET_NAME>15upstreamHostKey:16key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+G/MMcPZTKlWX...
If you want to accept any host key from the upstream, which is NOT recommended, you can use the insecureIgnoreHostKey
option as follows:
1kind: Service2metadata:3name: ssh14spec:5mode: SSH6port: 20227config:8upstream:9url: ssh://address-to-host10ssh:11user: root12auth:13password:14fromSecret: <SECRET_NAME>15upstreamHostKey:16insecureIgnoreHostKey: true
Private Key
Here is an example where the upstream SSH server is accessed through a private key.
1kind: Service2metadata:3name: ssh14spec:5mode: SSH6port: 227config:8upstream:9url: ssh://address-to-host10ssh:11user: root12auth:13privateKey:14fromSecret: <SECRET_NAME>15upstreamHostKey:16key: ssh-rsa AAA...
Access Control
You can control access based on the SSH request information. Such information are stored in ctx.request.ssh
where it contains the requested SSH user. Here is an example:
1kind: Service2metadata:3name: svc14spec:5mode: SSH6port: 20227config:8upstream:9url: ssh://address-to-host10# rest of config...11authorization:12inlinePolicies:13- spec:14rules:15- effect: ALLOW16condition:17match: ctx.request.ssh.connect.user != "root"
You do not actually need to control access by checking against the SSH user (e.g. root
) since you already can override the SSH user in the Service configuration as illustrated above regardless of the SSH user value provided by the User. You can also use dynamic configuration in order to map different Users to different credentials and/or different SSH users. You can read more about dynamic configuration here
Dynamic Configuration
You can use dynamic configuration in order to, for example, route to different upstreams and/or set different users/passwords depending on the request's context (read more about dynamic configuration here). Here is a simple example where Users belonging to the ops
Group are logged in as root
SSH users, while the rest are logged in as some unprivileged usr
SSH user.
1kind: Service2metadata:3name: ssh14spec:5mode: SSH6dynamicConfig:7configs:8- name: root9upstream:10url: ssh://address-to-host11ssh:12user: root13auth:14password:15fromSecret: root-password16upstreamHostKey:17key: ssh-rsa AAA....18- name: usr19upstream:20url: ssh://address-to-host21ssh:22user: usr23auth:24password:25fromSecret: usr-password26upstreamHostKey:27key: ssh-rsa AAA....28rules:29- condition:30match: '"ops" in ctx.user.spec.groups'31configName: root32- condition:33matchAny: true34configName: usr
Visibility
The Service emits access logs in real time to the audit collector. Each log provides SSH application-layer aware information about the request such as the request path, method, etc... as well as the response code and body size. Here is an example:
1{2"apiVersion": "core/v1",3"entry": {4"common": {5"connectionID": "muxv-ofat-eta1fervm8z5vairkw6jysiy-090t-nn63",6"endedAt": "2025-03-21T20:28:05.611245268Z",7"isAuthenticated": true,8"isAuthorized": true,9"namespaceRef": {10"apiVersion": "core/v1",11"kind": "Namespace",12"name": "default",13"resourceVersion": "0195b81d-43ec-7ba7-81f7-9b77202b3612",14"uid": "bff0768e-eec8-4044-a972-9f7af81b79d8"15},16"regionRef": {17"apiVersion": "core/v1",18"kind": "Region",19"name": "default",20"uid": "6e233d12-2fd6-4670-a82d-8c712e1f7374"21},22"sequence": "18",23"serviceRef": {24"apiVersion": "core/v1",25"kind": "Service",26"name": "essh1.default",27"resourceVersion": "0195ba63-6c77-7b4c-93f6-0da38b0d5107",28"uid": "b800371e-9521-42a0-8665-5ef1937a8a07"29},30"sessionID": "muxv-ofat-eta1fervm8z5vairkw6jysiy-090t-nn63-q7r1lr",31"sessionRef": {32"apiVersion": "core/v1",33"kind": "Session",34"name": "usr1-3pt93j",35"resourceVersion": "0195ba62-a468-7ca8-bf8b-2cd998c5ae23",36"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"37},38"startedAt": "2025-03-21T20:28:01.580119846Z",39"userRef": {40"apiVersion": "core/v1",41"kind": "User",42"name": "usr1",43"resourceVersion": "0195b821-228d-79b2-92f3-4bb458944f97",44"uid": "e0f251b2-6952-4a46-a771-2712a45c47f5"45}46},47"info": {48"ssh": {49"sessionRecording": {50"data": "G1...aA==",51"type": "STDOUT"52},53"type": "SESSION_RECORDING"54}55}56},57"kind": "AccessLog",58"metadata": {59"actorRef": {60"apiVersion": "core/v1",61"kind": "Session",62"name": "usr1-3pt93j",63"resourceVersion": "0195ba62-a468-7ca8-bf8b-2cd998c5ae23",64"uid": "e8bea7be-b858-4457-a8ee-a0cb7f6c91da"65},66"createdAt": "2025-03-21T20:28:05.611236444Z",67"id": "vj3p-rbwf-wyz5tum1jtmyb394y7yoh8cn-yjlg-ilh1",68"targetRef": {69"apiVersion": "core/v1",70"kind": "Service",71"name": "essh1.default",72"resourceVersion": "0195ba63-6c77-7b4c-93f6-0da38b0d5107",73"uid": "b800371e-9521-42a0-8665-5ef1937a8a07"74}75}76}
As you can see in the above example, the type of this SSH
access Log is a SESSION_RECORDING
. The SSH
mode has currently 10 Log types: START
, END
, DIRECT_TCPIP_START
, DIRECT_TCPIP_END
, SESSION_START
, SESSION_END
, SESSION_RECORDING
, SESSION_REQUEST_SHELL
, SESSION_REQUEST_EXEC
, SESSION_REQUEST_SUBSYSTEM
and some of these types include different detailed information according to their type. You can read more in the API reference.