########################## Components and their Usage ########################## LN Manager ########## .. _guide/ln_manager/gui: The LN Manager GUI ================== Inspecting topics ----------------- .. _guide/lnm_gui/inspecting/services: Inspecting services ------------------- .. _lnm/re-connecting-to-running-processes: Re-Connecting to running Processes ---------------------------------- .. _guide/components/lnmanager-cli: The LN Manager CLI Interface ============================ The LN Manager Configuration File ================================= Configuring Processes --------------------- Accessing the X Server from a client ...................................... See :doc:`x11_connections` for a dedicated explanation of X11 display selection, authentication cookies, ``xauth``, ``xhost``, and how ln_manager's :ref:`process/forward_x11` support relates to that. .. _guide/lnm_config/python-output-encoding: Setting the default output encoding for Python .................................................. TODO: explain why and when setting the output encoding is necessary .. sourcecode:: lnc add environment: LANG=en_US.UTF-8 add environment: PYTHONIOENCODING=utf-8 output_encoding: utf-8 - user authentication - passing X11 connections - debugging and warnings - networking configuration & options .. _process/default_resource_limits: Setting resource limits ----------------------- .. _lnm/starting_remote_processes: starting processes on remote hosts ---------------------------------- Processes both on remote hosts and on the host which the ln manager is running on (the "localhost") are started using the ln_daemon. Most of the LN daemon operation happens transparently and automatically, so very little configuration is needed. For more details, see section :ref:`guide/ln_daemon`. .. seealso:: For more information on how to configure processes, you can look at the :doc:`config_process` section of the :doc:`configuration reference `. Also, starting process on remote computers uses a special program, called the :term:`LN daemon`. Normally, it starts automatically, but if you have any difficulty, please refer to section :ref:`guide/ln_daemon` in the user guide part. .. _lnm/controlling_the_lnm_via_cli: controlling the LN manager via the command line interface --------------------------------------------------------- .. _guide/state_objects: defining LN state objects and what they are good for ----------------------------------------------------- .. _guide/inspecting_services: inspecting services interactively --------------------------------- .. _guide/defining_setting_using_parameters: Defining, setting and using Parameters --------------------------------------- Network Configuration --------------------- Message communication --------------------- Message Definitions ------------------- .. _guide/hints_on_using_message_definitions: Some hints on how to use topics and messages ............................................ * Message definitions are part of the :term:`interface` of a software :term:`module`. They should not be changed after their release - use versioned names, like ``counter2``, if you should need to change them. * It is a good idea to standardize and document message definitions and re-use them if this makes sense. * Do not forget to document and explain what information topics in your system transport. This is very helpful to understand information exchange and the architecture of a system. .. _guide/message_definitions/nesting: Nested Message definitions .......................... .. _guide/ln-generate_tool: The ln-generate Tool: creating interfaces for the C++ API --------------------------------------------------------- :program:`ln_generate` reads LN :term:`message definition` files and generates a C/C++ header, usually named :file:`ln_messages.h`. C++ clients include that header to get the generated structs, message definition names, message definition hashes, and wrapped service base classes used by the C++ API. For CMake projects that consume LN through Conan, use the ``generate_ln_message_headers()`` helper exported by the ``liblinks_and_nodes`` package instead of writing a custom ``add_custom_command`` for :program:`ln_generate` manually. The helper finds :program:`ln_generate`, forwards the message-definition search path, tracks the message-definition files as build dependencies, and adds an interface target that contributes the generated include directory. The minimal CMake example is in :file:`documentation/examples/guide/cmake_consume_libln/`. Its :file:`CMakeLists.txt` is: .. literalinclude:: examples/guide/cmake_consume_libln/CMakeLists.txt :language: cmake :linenos: The example Conan recipe declares the LN library and message-definition packages as normal requirements, and declares ``links_and_nodes_base_python`` as a tool requirement because that package provides :program:`ln_generate`: .. literalinclude:: examples/guide/cmake_consume_libln/conanfile.py :language: python :linenos: For Makefile-based projects or command-line debugging, :program:`ln_generate` can still be called directly. Pass ``-o`` for the output header and one or more message-definition names. Use ``--md-dir`` for local message-definition directories that are not already provided through :envvar:`LN_MESSAGE_DEFINITION_DIRS`. .. index:: pair: LN daemon; user guide .. _guide/ln_daemon: The LN Daemon ############# .. index:: pair: LN daemon; function The LN daemon is a program component which is used by the LN manager. It has two main functions: 1. to start, stop and control required processes on remote hosts 2. to relay messages for topics and services over a network It is designed to mostly work transparently and without user intervention (and therefore, very little information is needed to cover it). .. index:: single: LN daemon; how to start .. _starting a daemon: Starting LN daemons =================== There are three ways which an LN daemon can be started: 1. Automatically at system boot-up. For this, it needs to be configured as a system service which is started by systemd (or similar). 2. Automatically by the LN manager via a remote :term:`SSH ` connection. For this to work, for a remote machine, the SSH configuration needs to allow for a password-less remote login. In normal cases, this will use the "authorized_keys" feature and the "ssh-agent" program, which allows to unlock a local key, and starts programs such as the LN manager which use it. Note that starting a daemon in this way does not require any root access to a computer - this is intended to make it easy to move between networked computers for program development, and embedded computers which might have looser restrictions, in order to allow for hardware access. 3. If the LN manager cannot start a daemon, one also can start an instance manually, using the :program:`ln_daemon` command. .. note:: Configuring ssh clients and the sshd daemon is outside of the scope of this manual. If you need more information on how to configure an ssh connection, please consult the system man page on `ssh_config`, `ssh-keygen`, `ssh-agent`, and `ssh-add`. The detail setup may vary depending on your local administration policy. .. index:: single: LN daemon; arbiter Daemon instances ================ :term:`LN daemons ` start with an initial process, which is also called the *arbiter*, and fork from that into child processes which perform communication and management of LN processes on a specific host. Each child process or daemon instance is owned by exactly **one** user. After a user has connected to it, it will only carry out commands for that user, and reject commands from other users. When the user stops all processes on a specific :term:`node` via the LN manager, his daemon instance will also be ended. The arbiter instance will not be stopped. .. index:: single: LN daemon; authentication .. index:: triple: LN daemon; public-key authentication; configuration .. _guide/daemon_authentication: Daemon Authentication ===================== .. index:: single: LN daemon; why authentication is needed triple: LN daemon access; safety; security pair: authentication; starting processes Normally, daemons run as user processes, which means their privileges are restricted to that of the corresponding user. Because daemons can start arbitrary commands and processes, there are two potential issues related to security and safety: 1. The daemon instance can read any data from the user that it belongs to (both local data and data that might, for example, be accessible via NFS), which can affect security-relevant data such as for example mail passwords, or github keys. This means that exposing confidential data from that user to other users must be prevented. 2. Because the daemon forwards any messages from that user to LN clients, it can also send unrestricted commands to robots which are controlled by that user. However, robotic systems are normally designed in a way that important control components, such as goal-planning modules or GUI displays, mirror the state of controlled low-level components, such as motors, using a local copy of that state. As a consequence, **simultaneous sending of commands from other users, which might be physically unsafe or even hazardous, must be prevented**. To secure the daemon connection, daemons require some basic :term:`authentication`: any daemon which starts to accept commands from one user therefore becomes `locked` to this user, meaning that it will not accept connections from any different user. .. index:: single: LN daemon; public key authentication This is achieved in the following way: First, the daemon gets passed a so-called *public key*. This can be carried out by starting the daemon with the path to a key file, from which the daemon will read this key. If a daemon is not locked at start-up, and is first contacted, the LN manager will send it a key. The daemon will then register this key. The alternative is sometimes more practical, but in general it is less preferable than locking the daemon at start-up. .. index:: single: LN daemon; default location of DSA keys .. note:: If no key is already available, the LN manager will generate and store a pair of keys, which by default will have the names :file:`$HOME/.ssh/id_dsa_ln_daemons.pub` for the public key, and :file:`$HOME/.ssh/id_dsa_ln_daemons` for the corresponding private key [#note-key-pairs]_. Second, whenever an LN manager creates a new connection to an already running LN daemon, the daemon will request the LN manager to authenticate itself. This is done by so-called :term:`public-key cryptography`. Basically, the LN daemon sends to the LN manager a random message, and the LN manager signs that massage by using the *private key* corresponding to the daemons public key. This key is owned by the user, and which nobody else knows. Then, it sends the message back to the LN daemon. The daemon can now use the public key mentioned before to check that it matches the private key, and, if succeeding, will grant the LN manager access. In specific situations where the LN daemon can neither access private data from the user, nor trigger any potentially unsafe robotic actions, the authentication can be switched off. .. warning:: Do not switch off authentication without a good grasp of the security implications! .. note:: The authentication described here does **not** encrypt communication between LN manager and LN clients, because that would be very costly in terms of CPU time, but also, complexity. In certain circumstances, this could be exploited. For example, if the LN manager updates device firmware by sending a firmware image and a password which is needed for flashing the firmware, the password would be visible to any attacker who manages to sniff the network traffic. In this case, the password would need to be protected by other means. The normal way of authentication, which is by using a file with the public key which is passed at start-up of the daemon, requires that this file is present and visible at the host where the daemon runs, and at the time when it starts. If it is a robotic system which e.g. has no NFS access, the public key file consequently needs to be copied manually from :file:`$HOME/.ssh/id_dsa_ln_daemons.pub` to the user home of that file system. It can simply be copied to that computer by whatever tool is available, for example using the :program:`scp` command (which is always available if ssh access is configured). .. index:: single: LN daemon; possible causes for failure to start Common Problems and Failure Modes --------------------------------- The authentication has the effect that the communication is much safer, and many errors caused by misunderstandings will be avoided. For example, if two users try to run the same robot from several LN instances, this will not work: The second LN manager instance which is started will report that it cannot connect to the host that controls the hardware. On the other hand, there are a few failure modes which users should check for when things do not work as expected: 1. If an LN daemon or a :term:`node` does not respond to LN commands, it should be checked that the LN daemon belongs to the user which wants to run the command. 2. If several users share the same user identity on a mobile robot, this can easily cause problems, which can only be avoided by planning for exclusive access at the same time to the robot or system. Generally, users (that means, people) should not share identities (multi-user systems, version control software like git, and also systems such as Conan are simply not designed for it). 3. If a user changes or resets his/her public key, it must stop and re-start any LN daemon which uses the old key. As long as the LN manager which started a daemon is running, this can be done by stopping all processes. Otherwise, it is necessary to stop the daemon manually, by logging in into the remote computer, and using the Unix :program:`kill` or :program:`pkill` command, and then start it again. 4. If a user works on a robot system and wants to stop so that another user can continue to work on it, he or she has to stop all processes, so that there is not daemon left around which will be still locked to him. .. index:: single: LN daemon; configuration of keys LN Daemon configuration ======================= * The :program:`ln_daemon` program can be configured to receive its public key from a specific file file. This is explained in sections :ref:`hosts/daemon_private_key_file` and :ref:`hosts/daemon_private_key_file` of the "hosts" section of the configuration reference. * Also, the path of the ssh binary can be configured via the option :ref:`hosts/ssh_binary`. * Finally, the user that the LN daemon expects to connect to can be configured, see :ref:`hosts/expected_user` for more details. Otherwise, the LN daemon has very little configuration options, because it was designed with the goal to work transparently (i.e., in an "invisible" manner), and require as little configuration as possible. .. _guide/network-config: .. rubric:: Footnotes .. [#note-key-pairs] In the public-key cryptographic scheme used here, keys are always generated in pairs, one public key and one private key. The public key can be shared, the private key must remain secret; it can be used for both *signing* a message to prove its authenticity, or for *decrypting* a message which was encrypted with the public key. .. seealso:: * `Wikipedia: Public-key cryptography `_.