-
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.
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
|
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
|
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.
TODO
See the webterminal source for an example of opening a remote shell websocket connection.
See the webterminal source for an example of authenticating the remote shell websocket connection.