2017-11-09 20:33:09 +01:00
.. highlight :: bash
2017-11-10 13:41:17 +01:00
.. _transport:
2017-11-09 20:33:09 +01:00
Transports
==========
2017-11-10 13:35:09 +01:00
A transport provides an authenticated `io.ReadWriteCloser <https://golang.org/pkg/io/#ReadWriteCloser> `_ to the RPC layer.
(An `` io.ReadWriteCloser `` is essentially a bidirectional reliable communication channel.)
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
Currently, only the `` ssh+stdinserver `` transport is supported.
2017-11-09 20:33:09 +01:00
2017-11-09 21:17:09 +01:00
.. _transport-ssh+stdinserver:
2017-11-10 13:35:09 +01:00
`` ssh+stdinserver `` Transport
-----------------------------
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
The way the `` ssh+stdinserver `` transport works is inspired by `git shell <https://git-scm.com/docs/git-shell> `_ and `Borg Backup <https://borgbackup.readthedocs.io/en/stable/deployment.html> `_ .
It is implemented in the Go package `` github.com/zrepl/zrepl/sshbytestream `` .
The config excerpts are taken from the :ref: `tutorial` which you should complete before reading further.
2017-11-09 20:33:09 +01:00
2017-11-10 12:48:41 +01:00
.. _transport-ssh+stdinserver-serve:
2017-11-10 13:35:09 +01:00
Serve Mode
~~~~~~~~~~
2017-11-09 20:33:09 +01:00
::
jobs:
- name: pull_backup
type: source
serve:
type: stdinserver
client_identity: backup-srv.example.com
...
2017-11-10 13:35:09 +01:00
The serving job opens a UNIX socket named after `` client_identity `` in the runtime directory, e.g. `` /var/run/zrepl/stdinserver/backup-srv.example.com `` .
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
On the same machine, the `` zrepl stdinserver $client_identity `` command connects to that socket.
For example, `` zrepl stdinserver backup-srv.example.com `` connects to the UNIX socket `` /var/run/zrepl/stdinserver/backup-srv.example.com `` .
2017-11-09 20:33:09 +01:00
It then passes its stdin and stdout file descriptors to the zrepl daemon via *cmsg(3)* .
2017-11-10 13:35:09 +01:00
zrepl daemon in turn combines them into an `` io.ReadWriteCloser `` :
a `` Write() `` turns into a write to stdout, a `` Read() `` turns into a read from stdin.
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
Interactive use of the `` stdinserver `` subcommand does not make much sense.
2017-11-09 20:33:09 +01:00
However, we can force its execution when a user with a particular SSH pubkey connects via SSH.
2017-11-10 13:35:09 +01:00
This can be achieved with an entry in the `` authorized_keys `` file of the serving zrepl daemon.
2017-11-09 20:33:09 +01:00
::
# for OpenSSH >= 7.2
command="zrepl stdinserver CLIENT_IDENTITY",restrict CLIENT_SSH_KEY
# for older OpenSSH versions
command="zrepl stdinserver CLIENT_IDENTITY",no-port-forwarding,no-X11-forwarding,no-pty,no-agent-forwarding,no-user-rc CLIENT_SSH_KEY
2017-11-10 13:35:09 +01:00
* CLIENT_IDENTITY is substituted with `` backup-srv.example.com `` in our example
* CLIENT_SSH_KEY is substituted with the public part of the SSH keypair specified in the `` connect `` directive on the connecting host.
2017-11-09 20:33:09 +01:00
.. NOTE ::
2017-11-10 13:35:09 +01:00
You may need to adjust the `` PermitRootLogin `` option in `` /etc/ssh/sshd_config `` to `` forced-commands-only `` or higher for this to work.
2017-11-09 20:33:09 +01:00
Refer to sshd_config(5) for details.
2017-11-10 13:35:09 +01:00
To recap, this is of how client authentication works with the `` ssh+stdinserver `` transport:
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
* Connections to the `` client_identity `` UNIX socket are blindly trusted by zrepl daemon.
2017-11-09 20:33:09 +01:00
* Thus, the runtime directory must be private to the zrepl user (checked by zrepl daemon)
2017-11-10 13:35:09 +01:00
* The admin of the host with the serving zrepl daemon controls the `` authorized_keys `` file.
* Thus, the administrator controls the mapping `` PUBKEY -> CLIENT_IDENTITY `` .
2017-11-09 20:33:09 +01:00
2017-11-10 12:48:41 +01:00
.. _transport-ssh+stdinserver-connect:
2017-11-10 13:35:09 +01:00
Connect Mode
~~~~~~~~~~~~
2017-11-09 20:33:09 +01:00
::
jobs:
- name: pull_app-srv
type: pull
connect:
type: ssh+stdinserver
host: app-srv.example.com
user: root
port: 22
identity_file: /etc/zrepl/ssh/identity
options: # optional
- "Compression=on"
The connecting zrepl daemon
2017-11-10 13:35:09 +01:00
#. Creates a pipe
#. Forks
#. In the forked process
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
#. Replaces forked stdin and stdout with the corresponding pipe ends
#. Executes the `` ssh `` binary found in `` $PATH `` .
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
#. The identity file (`` -i `` ) is set to `` $identity_file `` .
#. The remote user, host and port correspond to those configured.
#. Further options can be specified using the `` options `` field, which appends each entry in the list to the command line using `` -o $entry `` .
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
1. Wraps the pipe ends in an `` io.ReadWriteCloser `` and uses it for RPC.
2017-11-09 20:33:09 +01:00
2017-11-10 13:35:09 +01:00
As discussed in the section above, the connecting zrepl daemon expects that `` zrepl stdinserver $client_identity `` is executed automatically via an `` authorized_keys `` file entry.
2017-11-09 20:33:09 +01:00
.. NOTE ::
2017-11-10 13:35:09 +01:00
The environment variables of the underlying SSH process are cleared. `` $SSH_AUTH_SOCK `` will not be available.
2017-11-09 20:33:09 +01:00
It is suggested to create a separate, unencrypted SSH key solely for that purpose.