zrepl/docs/configuration/transports.rst
2018-04-01 14:58:04 +02:00

117 lines
4.5 KiB
ReStructuredText

.. highlight:: bash
.. _transport:
Transports
==========
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.)
Currently, only the ``ssh+stdinserver`` transport is supported.
.. _transport-ssh+stdinserver:
``ssh+stdinserver`` Transport
-----------------------------
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 provided by the Go package ``github.com/problame/go-netssh``.
The config excerpts are taken from the :ref:`tutorial` which you should complete before reading further.
.. _transport-ssh+stdinserver-serve:
Serve Mode
~~~~~~~~~~
::
jobs:
- name: pull_backup
type: source
serve:
type: stdinserver
client_identity: backup-srv.example.com
...
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``.
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``.
It then passes its stdin and stdout file descriptors to the zrepl daemon via *cmsg(3)*.
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.
Interactive use of the ``stdinserver`` subcommand does not make much sense.
However, we can force its execution when a user with a particular SSH pubkey connects via SSH.
This can be achieved with an entry in the ``authorized_keys`` file of the serving zrepl daemon.
::
# 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
* 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.
.. NOTE::
You may need to adjust the ``PermitRootLogin`` option in ``/etc/ssh/sshd_config`` to ``forced-commands-only`` or higher for this to work.
Refer to sshd_config(5) for details.
To recap, this is of how client authentication works with the ``ssh+stdinserver`` transport:
* Connections to the ``client_identity`` UNIX socket are blindly trusted by zrepl daemon.
* Thus, the runtime directory must be private to the zrepl user (checked by zrepl daemon)
* The admin of the host with the serving zrepl daemon controls the ``authorized_keys`` file.
* Thus, the administrator controls the mapping ``PUBKEY -> CLIENT_IDENTITY``.
.. _transport-ssh+stdinserver-connect:
Connect Mode
~~~~~~~~~~~~
::
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, default [], `-o` arguments passed to ssh
- "Compression=on"
dial_timeout: # optional, default 10s, max time.Duration until initial handshake is completed
The connecting zrepl daemon
#. Creates a pipe
#. Forks
#. In the forked process
#. Replaces forked stdin and stdout with the corresponding pipe ends
#. Executes the ``ssh`` binary found in ``$PATH``.
#. 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``.
#. Wraps the pipe ends in an ``io.ReadWriteCloser`` and uses it for RPC.
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.
The ``known_hosts`` file used by the ssh command must contain an entry for the serving host, e.g., ``app-srv.example.com`` in the example above.
.. NOTE::
The environment variables of the underlying SSH process are cleared. ``$SSH_AUTH_SOCK`` will not be available.
It is suggested to create a separate, unencrypted SSH key solely for that purpose.