-
Notifications
You must be signed in to change notification settings - Fork 2
SolarSSH API
The SolarSSH server acts as an intermediary between SolarNodes and an administrator, allowing an administrator access to nodes that are not directly accessible over the internet because of network configuration details (such as firewalls). It exposes two main features for a given SolarNode:
- a URL for accessing the node web server (and thus, the setup GUI)
- a websocket connection to a SSH terminal shell on the node
To provide these features, SolarSSH exposes a RESTful API that a browser can use to control the entire process of authenticating the administrator, getting SolarNode to SSH to SolarSSH, and exposing the features listed above to the browser.
The general process of using SolarSSH follows these steps:
- Create a new SolarSSH session, which contains a unique session ID and other details needed in subsequent steps. A SolarNet security token is required to authenticate the administrator.
- Enqueue a StartRemoteSsh instruction with SolarNet, passing in details from the session details returned in step 1. The ID of the instruction is added to the session details for use in subsequent steps.
- Using the instruction ID returned in step 2, wait for the instruction to reach the
Completed
state, which signals that the SolarNode has established the SSH connection with SolarSSH. - At this stage, feature #1 from above is available, and the browser can access the node web server via a URL on the SolarSSH server.
- To access the node via SSH, the browser can open a websocket connection to the SolarSSH server and then pass SSH credentials to SolarSSH. SolarSSH will then establish a SSH terminal shell on the node, and connect the shell to the websocket.
- At this stage, all text sent over the websocket will be passed to the node's terminal shell, and any text emitted by the shell will be passed back over the websocket to the browser. By using a JavaScript terminal emulator like xterm.js (with that project's attach addon) a full interactive shell can be created right in the browser.
Many of the REST API methods require a SNWSv2 header value be passed on
a X-SN-PreSignedAuthorization
HTTP header that SolarSSH can use to
make requests to specific API methods on SolarNetwork. Passing pre-computed
authorization serves a few purposes:
- The security token secret is never passed to SolarSSH, so SolarSSH never has any knowledge of it.
- SolarSSH can only make the specific requests to SolarNetwork that are explicitly encoded in the pre-computed authorization. As the authorization is unique to each request and includes the details of the request, SolarSSH cannot access anything other than what the authorization allows.
- SolarSSH can authenticate the API request when it invokes the HTTP request on SolarNetwork using the pre-computed authorization. If the request is authorized by SolarNetwork, then SolarSSH knows the API request is valid.
The solarnetwork-d3 project has a helper class for computing authorization
header values that can be used as an example. SolarSSH issues
all requests using HTTPS URLs to the data.solarnetwork.net
host.
All REST responses are encoded as a JSON object, with a minimum of a success
boolean property. For example:
{ "success": true }
If there is additional information, it will be provided on a data
property,
for example:
{ "success": true, "data": { "foo": "bar" } }
If an error occurs, a message and error code will be included, for example:
{ "success": true, "code": 5000, "message": "Bad credentials." }
This method will create a new SolarSSH session and is the required first step for interacting with SolarSSH. See the webterminal source for an example of invoking this endpoint.
GET | /api/v1/ssh/session/new |
---|---|
nodeId |
A query parameter containing the ID of the SolarNode to use the session with. |
X-SN-PreSignedAuthorization |
A HTTP header containing a SNWSv2 authorization header value for making
a GET request to the SolarUser view
pending instructions API for the given nodeId . |
X-SN-Date |
A HTTP header containing the the date used in the X-SN-PreSignedAuthorization
value. |
The response includes a session object. A typical response looks like this:
{
"success": true,
"code": null,
"message": null,
"data": {
"sessionId": "8d0b329c-4845-49df-a7d9-c952fb395a8a",
"created": 1498590980179,
"nodeId": 246,
"host": "ssh.solarnetwork.net",
"port": 8022,
"reversePort": 43332,
"startInstructionId": null,
"stopInstructionId": null,
"established": false
}
}
A session object contains the following properties:
sessionId |
A unique ID for the session, as a string. This is also the username the node must use when connecting to SolarSSH. |
---|---|
created |
The date the session was created, as milliseconds since the epoch. |
nodeId |
The SolarNode ID associated with the session. |
host |
The SSH hostname for the SolarNode to connect to. Typically this will be the same hostname SolarSSH is running on, but it could differ. |
port |
The SSH port for the SolarNode to connect to (on host ). |
reversePort |
A reverse listen port for the SolarNode to establish when it connects
via SSH, for forwarding to port 22 on localhost ,
for tunneling SSH traffic back to the node. This would be like the node passing
-R 127.0.0.1:reversePort:localhost:22 via OpenSSH. The node
is then expected to also request reversePort + 1 for reverse
forwarding to port 8080 on localhost , for
tunneling HTTP traffic back tothe node. This would be like the node
passing -R 127.0.0.1:reversePort+1:localhost:8080 via OpenSSH. |
startInstructionId |
The SolarNetwork instruction ID for the StartRemoteSsh
instruction queued for the node. This ID can be used to query on the
status of this instruction, and know if the node successfully connected
to SolarSSH or not. |
stopInstructionId |
The SolarNetwork instruction ID for the StopRemoteSsh
instruction queued for the node. This ID can be used to query on the
status of this instruction, and know if the node successfully disconnected
to SolarSSH or not. |
established |
A boolean that gets set to true when the node
successfully connects and authenticates to SolarSSH. |
This method will enqueue a StartRemoteSsh
instruction for the session's node.
See the webterminal source for an example of invoking this
endpoint.
After this method returns, clients can invoke the View
instruction endpoint on SolarNetwork directly
to find out if the instruction has been handled correctly by the node. Once the
instruction state
reaches the Completed
state, the SSH connection will be ready for
use and the HTTP proxy and websocket
shell can be used. See the webterminal
source for an example of polling for the Completed
instruction
state.
GET | /api/v1/ssh/session/{sessionId} /start |
---|---|
sessionId |
A path variable containing the ID of the session (originally returned from the Create session endpoint). |
X-SN-PreSignedAuthorization |
A HTTP header containing a SNWSv2 authorization header value for making
a POST request to the SolarUser Queue
instruction API. The nodeId in the authorized request must be the
same node ID value in the session. The topic in the authorized
request must be StartRemoteSsh .
|
X-SN-Date |
A HTTP header containing the the date used in the X-SN-PreSignedAuthorization
value. |
For the X-SN-PreSignedAuthorization
authorization, the order of the
instruction parameters in the authorized request must be:
-
host
- thehost
from the session -
user
- thesessionId
from the session -
port
- theport
from the session -
rport
- thereversePort
from the session
The response includes a session object.
This method will enqueue a StopRemoteSsh
instruction for the session's node.
See the webterminal source for an example of invoking this
endpoint. Once this method is invoked, the session is invalidated and subsequent
use of the session will fail.
GET | /api/v1/ssh/session/{sessionId} /stop |
---|---|
sessionId |
A path variable containing the ID of the session (originally returned from the Create session endpoint). |
X-SN-PreSignedAuthorization |
A HTTP header containing a SNWSv2 authorization header value for making
a POST request to the SolarUser Queue
instruction API. The nodeId in the authorized request must be the
same node ID value in the session. The topic in the authorized
request must be StopRemoteSsh . |
X-SN-Date |
A HTTP header containing the the date used in the X-SN-PreSignedAuthorization
value. |
For the X-SN-PreSignedAuthorization
authorization, the order of the
instruction parameters in the authorized request must be:
-
host
- thehost
from the session -
user
- thesessionId
from the session -
port
- theport
from the session -
rport
- thereversePort
from the session
The response includes a session object.
Once a session has been started, then SolarSSH will expose a HTTP reverse proxy
at /nodeproxy/:sessionId/
that forwards all requests to the node's HTTP
server. That URL is publicly available and does not require any
authentication itself. However the node HTTP server by default shows the setup
GUI, which requires authentication to access. The proxy URL can thus be shared
with other administrators freely, and they can administer the node as long as
they have credentials to access the node setup GUI.
The HTTP proxy is valid as long as the session is valid. Once the session is stopped the HTTP proxy will be closed.
See the webterminal source for an example of exposing the HTTP proxy to the browser.
Once a session has been started, then SolarSSH will expose a websocket
connection at /ssh?sessionId=:sessionId
. The session ID must be passed as the
sessionId
query parameter of the connect URL and a protocol of
solarssh
. See the webterminal source for an
example of opening a remote shell websocket connection.
Once the websocket is connected, then the browser must first send a text message with a JSON payload containing an object with the following properties outlined below. See the webterminal source for an example of authenticating the remote shell websocket connection.
An example JSON payload looks like this:
{
"cmd": "attach-ssh",
"data": {
"authorization": "SNWS2 Credential=0934jLKdjd09d7809djd,SignedHeaders=host;x-sn-date,Signature=910d03505e32dd96a6e1ba60f43a1455335701347249c03c5c93dc495d244ee8",
"authorization-date": 1498685326942,
"cols": 100,
"lines": 24,
"password": "solar",
"term": "xterm",
"username": "solar"
}
}
cmd |
The literal string attach-ssh . |
---|---|
data |
A nested object with authentication details and optional terminal settings. |
The data
authentication object must contain the following
properties:
authorization |
A string containing a SNWSv2 authorization HTTP header value for making
a GET request to the SolarUser Get
node metadata endpoint. The nodeId in the authorized request must be the
same node ID value in the session. |
---|---|
authorization-date |
The date used in authorization as a number, as milliseconds since the epoch. |
username |
A string node SSH username to use when attaching the remote shell terminal. |
password |
A string node SSH password to use when attaching the remote shell terminal. |
In addition, the following optional properties may be provided:
term |
A string value to pass as the remote shell terminal type. Defaults to xterm . |
---|---|
cols |
A number for the number of columns to use for the remote shell terminal. Defaults to 80 . |
lines |
The number of lines to use for the remote shell terminal. Defaults to 24 . |
width |
A number width in pixels to use for the remote shell terminal. Defaults to 640 . |
height |
>A number height in pixels to use for the remote shell terminal. Defaults to 480 . |
environment |
An object whose key/value pairs will be passed as environment variables on the remote shell. |