File upload

Preface

Rport allows users to copy files from their local machines to one or many remote clients through the rport server. The most common use case is the distribution of software or configuration files.

As an alternative, users can write a script to download needed files from the Internet, but usually, we don't want the client machine downloading it directly because a virus scan must happen at a central place first.

A recommended solution would be to download the file in some workstation, do the necessary virus scans and checksum checks and then upload the file to the rport server. The latter will distribute it among the clients through the secure SSH connection:

    Browser | Rportcli | curl (you)
        file_xyz
------------------------- HTTP(s)        
           ᐁ
       RPort server 
------------------------- SSH/SFTP  
    ᐁ       ᐁ       ᐁ
   cl_1    cl_2    cl_n  

Data flow

  • The RPort administrator uploads a file to the RPort server by using UPLOAD APIopen in new window. With the file, he provides all required information: target file path on client, list of client IDs or group IDs, desired file mode, owner/group etc.
  • The RPort server copies the file to a temporary folder [server] {data_dir}/filepush/xxx, where [server] data_dir is a configuration option and xxx is a random unique file name generated by the Rport server.
  • The RPort server sends to the provided clients a lightweight JSON request via the established and secured SSH connections. The request contains a temporary file location on the server as well as all other details (target path, checksum, desired file mode and owner etc) needed for the file operations on the client.
  • The RPort client(s) opens an SFTP session on top of the existing SSH connection and downloads the file to a temporary location [client] {data_dir}/filepush/xxx, where [client] {data_dir} is the client configuration option and xxx is a unique file name generated by the Rport server.
  • If the SFTP session succeeds, the client checks the md5 hash of the actual file against the provided checksum, chowns and chmods the file (for Unix only) if needed and finally moves it to the target location.
  • If the file already exists, and force and sync flags are false, rport client will do nothing.
  • If force flag is true, the existing file will be removed and replaced by the provided one
  • If sync flag is true, the rport client will compare md5 hash of the existing file with the new one, and will overwrite it if they don't match. Additionally, it will apply chmod/chown operations if needed.
  • Successes or failures of file operations will be sent to the server via the established SSH connection.
  • The server will track the successes or failures on the clients and will report them to all websocket listeners.
  • Finally, it will remove the temporary file.

Upload API

You can use UPLOAD APIopen in new window to upload a file to a Rport server.

JSON API is not well suited for uploading files, so you need to use the multipart form data formatopen in new window.

The file itself is marked with the required upload key.

Additionally, users should provide the following information as additional key/value parts of the multipart request:

client_id

(string optional)

ID of a client who should receive the file. You can repeat client part to send a file to multiple clients.

group_id

(string optional)

Client group ID where server should place the uploaded file. You can repeat group IDs to indicate multiple client groups.

dest

(string required)

Absolute path with the file name, showing the desired location of the uploaded file on the client(s).

force

(bool, optional, default false)

By default, ff the target file exists, Rport client will skip the upload request. By providing force flag you require rport to overwrite the target file no matter if it exists or not.

sync

(bool, optional, default false)

The sync flag is taken into account only if the target file already exists. The Rport client will do the following:

  • if the md5 of the provided file doesn't match the md5 hash of the existing file, it will be overwritten by the new file
  • if file mode parameter is provided (see below), the file mode of the target file will be changed to this value (for Unix only)
  • if either user or group parameters is provided (see below) and the existing file has a different owner or group, Rport client will apply a chown operation to it to change owner and group attributes (for Unix only)
  • if a destination file doesn't exist, the file will be copied to the destination as mentioned before

mode

(string, optional, default empty, for Unix only)

Indicates the desired file mode of the target file. If no target file exists, rport client will create a temp file with the provided mode. If no mode is provided, the default value will be 0764. When rport moves the temp file to the destination with it's mode. If target file already exists and the sync flag is true, rport client will explicitly change mode of the target file to the provided value.

user/group

(string, optional, default empty, for Unix only)

Indicates the desired file owner and group of the target file. If nothing is given, the current Rport client user and his default group will be used.

If no target file exists, rport will create a temp file with the current user and his default group. Then it will do the chown operation on the temp file. Then rport client will move the temporary file to the target path along with its owner and group attributes.

If target file exists and sync flag is true, rport client will explicitly call chown operation on the target file.

Please note, that on Unix the rport client runs with unprivileged rights. Changing the ownership of a file and moving a file to folders with restricted write access requires sudo rights. The user must create sudo rules for that. This allows a fine-grained control over which folders are accessible for the rport client. Example:

# /etc/sudoers.d/rport-filepush
# The following rule allows the rport cliebr to change the ownership of any file retrieved from the rport server
rport ALL=NOPASSWD: /usr/bin/chown * /var/lib/rport/filepush/*_rport_filepush

# The following rules allows the rport client to move copied files to any folder
rport ALL=NOPASSWD: /usr/bin/mv /var/lib/rport/filepush/*_rport_filepush *

Example for a file upload via curl with all parameters provided:

curl -XPOST \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFwIiwic2NvcGVzIjpbeyJ1cmkiOiIqIiwibWV0aG9kIjoiKiJ9LHsidXJpIjoiL2FwaS92MS92ZXJpZnktMmZhIiwibWV0aG9kIjoiKiIsImV4Y2x1ZGUiOnRydWV9XSwianRpIjoiMTMxNDEzNTcxNTgxNjk5Njk3MDAifQ.az3I9cod3CAuUOi1UF7c9iECIH__RLELYTPO7_V04wk' \ 
-F 'upload=@/home/myuser/some-file.txt' \
-F 'client_id=89C4AB76-D90A-555C-85BF-9F8770A3036F' \
-F 'client_id=b4f795ef-718f-4f69-8f6f-b304b38a904f' \
-F 'dest=/Users/hero/Projects/rport/dist/data/client/some-file.txt' \
-F 'force=true' \
-F 'sync=true' \
-F 'mode=0744' \
-F 'user=hero' \ 
-F 'group=staff' \ 
http://localhost:3000/api/v1/files

Tracking upload results

Sending a file to the rport server is performed as a synchronous atomic operation. It means if the transfer has failed, the whole operation will be rejected. Similarly, if the server cannot perform some file operations e.g. because of insufficient permissions, the whole file will be discarded.

However, distribution of a large file among multiple clients might take a while so there is no reason for the user to wait for it. Therefore, the Rport server will respond with success information once the upload operation completes. This doesn't mean, that the distribution to the given clients was successful too.

If you want to track upload process in real time, you can use a websocket API our testing API for Websocketsopen in new window similar to commands websocket API.

You can also use our sandbox interface to play with the upload websocket API. First, enable testing endpoints by setting enable_ws_test_endpoints flag to true in the [server] section of the configuration file:

[server]
...
  enable_ws_test_endpoints = true

Restart Rport server and go to: {YOUR_RPORT_ADDRESS}/api/v1/test/uploads/ui

Put an access token in the corresponding field.

Click Open to start websocket connection.

The websocket API will give you information about all uploads happening after you open a ws connection.

Here is an example payload you're usually getting through the ws upload API:

{
  "client_id": "89C4AB76-D90A-555C-85BF-9F8770A3036F",
  "uuid": "482ae29e-d372-4d21-8cb4-58d75482b7e1",
  "filepath": "/target/file.txt",
  "size": 17118,
  "message": "file successfully copied to destination",
  "status": "success"
}

This message says that the client 89C4AB76-D90A-555C-85BF-9F8770A3036F downloaded the 17118 bytes of a file and placed it to the destination path /target/file.txt. The uuid parameter indicates a unique request id, that you also received once file was uploaded to the server.

Similarly, errors or warnings will be reported in the same format, e.g.:

{
  "client_id": "89C4AB76-D90A-555C-85BF-9F8770A3036F",
  "uuid": "2ea7863b-94ae-4a91-87de-a85bc105ad4e",
  "filepath": "",
  "size": 0,
  "message": "rename /data/filepush/2ea7863b-94ae-4a91-87de-a85bc105ad4e_rport_filepush /etc/lala.txt: permission denied",
  "status": "error"
}

This message tells about the failure of a rename/move operation because of permission denied error.

The websocket API will deliver upload results at real time but only those which happened after the websocket connection was opened as rport server doesn't store upload results for this use case. If you need this information, use audit logs for that.

Uploads for all clients and all requests will be delivered to the same websocket. Server won't close the ws connection like it happens with the commands websockets.

Upload restrictions

By default, Rport client can place files anywhere in the file system where the rport OS user is allowed to write files.

That means, that running rport as sudo user, will give write access to the whole filesystem on the client (for Unix only).

However, by default rport won't allow uploading files to the following folders ['/bin', '/sbin', '/boot', '/usr/bin', '/usr/sbin', '/dev', '/lib*', '/run'] for Unix and ['C:\Windows\', 'C:\ProgramData'] for Windows

The denied folders list are defined as a list of glob patternsopen in new window in the [file-reception] protected configuration section of an rport client.

The restriction is applied for both target directory or target file path. Here is the list of examples to demonstrate this:

  • /bin rejects the target paths like /bin/yourfile.txt, /bin/somefile.csv but not /etc/bin/yourfile.txt
  • C:\Windows\*.exe rejects the target paths like C:\Windows\myfancy_program.exe, C:\Windows\notepad.exe but not C:\Windows\myfancy_program.txt or C:\Windows\notepad.md

File size limit

you can limit the size of uploaded files in bytes by setting max_filepush_size parameter in [server] section of rport server configuration. By default, this limit is 10485760 bytes (ca 10,5 MB).

Disabling uploads on the client

file uploads are enabled on the client by default. If you want to disable it, set [file-reception] enabled flag to false in the client config.

Last Updated:
Contributors: Andrey