github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/DESIGN.md (about)

     1  # Fleetspeak Design
     2  
     3  Fleetspeak is a client-server framework for communicating with a fleet of
     4  machines. This document summarizes the various components, providing an overview
     5  of what bits serve what purpose.
     6  
     7  ## Identity
     8  
     9  Fleetspeak identifies clients using a fingerprint of a public key, much like
    10  openssl keys. Specifically, client creates a keypair on startup, or when asked
    11  to rekey. The Fleetspeak
    12  [`common.ClientID`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/common#ClientID)
    13  is the first 8 bytes of a sha256 hash of the public part of this key. It is the
    14  [Server Communicator's](#server-communicator) responsibility to verify the
    15  identity of clients. The recommended approach is to communicate over TLS using
    16  the client's Fleetspeak key as TLS client identification. The
    17  [`https.Communicator` source](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/server/https/https.go)
    18  has an example of this.
    19  
    20  ## Messages
    21  
    22  At its core, Fleetspeak forwards
    23  [`fleetspeak.Message`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/common/proto/fleetspeak/common.proto)
    24  protocol buffers. The comments in the `.proto` file should be considered
    25  definitive, but the most important fields to understand are `destination`,
    26  `message_type` and `data`. Essentially, `destination` field tells Fleetspeak
    27  where to forward the message to. The `message_type` and `data` fields are
    28  forwarded verbatim, and when integrating a service a developer should set these
    29  fields according to their needs.
    30  
    31  The `message_type` is meant to be used both for dispatching within a service,
    32  and for reporting. So for example if your integration has three basic types of
    33  messages to pass, you might indicate them with three different message type
    34  strings. By doing this you make it possible to query Fleetspeak for the number
    35  of messages of each type.
    36  
    37  # Server
    38  
    39  A Fleetspeak Server middleware process written in go. To start a server, you
    40  instantiate a
    41  [`server.Server`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server#Server),
    42  providing the components needed for your particular installation.
    43  
    44  ## Miniserver: An Example
    45  
    46  The
    47  [`miniserver`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/demo/miniserver/miniserver.go)
    48  binary from the demo directory defines a Fleetspeak Server in a way suitable for
    49  demonstrations and small installations.
    50  
    51  When run, the miniserver binary binds two ports, and accepts bind addresses for
    52  each from the command line. The `--https_addr` flag determines the interface and
    53  port that clients will connect to. It needs to be open to the internet, or at
    54  least to all Fleetspeak client machines. See
    55  [Server Communicator](#server-communicator), below.
    56  
    57  The `--admin_addr` flag determines the interface and port that the
    58  [Administrative Interface](#administrative-interface) listens on. The miniserver
    59  binary does not perform any authentication of administrative requests. Therefore
    60  access to this port needs to be limited to trusted processes.
    61  
    62  The miniserver process stores all of its state in an SQLite version 3 database.
    63  The location of this database file is set by the flag `--database_path`. This
    64  file will be created if missing. After running miniserver, you can examine the
    65  system state using, e.g., the `sqlite3` command and package on Debian systems.
    66  See [Datastore](#datastore) below.
    67  
    68  ## Administrative Interface
    69  
    70  The Administrative Interface is a [GRPC](https://grpc.io/) server which provides
    71  access to Fleetspeak state for administrative and integration purposes. It is
    72  implemented separately from the Fleetspeak Server and can be run from the same
    73  or a different process, so long as it is connected to the same
    74  [Datastore](#datastore)
    75  
    76  ## Datastore
    77  
    78  The
    79  [`db.Store`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/db#Store)
    80  interface defines the persistent state held by a Fleetspeak Server. If a
    81  Fleetspeak installation has multiple server processes, they should run the same
    82  Datastore implementation providing a view of the same database. Currently we
    83  provide two Datastore implementations.
    84  
    85  At a minimum, any Datastore implementation should pass the tests implemented by
    86  the
    87  [`dbtesting`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/dbtesting)
    88  package.
    89  
    90  ### SQLite
    91  
    92  The
    93  [`sqlite.Datastore`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/sqlite#Datastore)
    94  implements
    95  [`db.Store`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/db#Store)
    96  backed by an SQLite version 3 database. This implementation is used extensively
    97  in our unit tests, and its design choices focus on simplicity, safety and
    98  ease-of-use rather than performance. It is meant for testing, local
    99  demonstrations, and single server installations with a small number of clients.
   100  
   101  It does not support multiple servers processes - the SQLite database file should
   102  only be opened by one instance of `sqlite.Datastore` at a time.
   103  
   104  ### Mysql
   105  
   106  The
   107  [`mysql.Datastore`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/mysql#Datastore)
   108  implements
   109  [`db.Store`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/db#Store)
   110  backed by a mysql database. Using recent versions of the
   111  [`go-sql-driver/mysql`](https://github.com/go-sql-driver/mysql) driver it passes
   112  [`dbtesting`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/dbtesting),
   113  but performance testing and database optimization is still in progress.
   114  
   115  ## Server Communicator
   116  
   117  Every server requires a
   118  [`Communicator`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/comms#Communicator)
   119  component which handles communication with clients. This component defines how
   120  the server communicates with fleetspeak machines and should agree on protocol
   121  with a corresponding [Client Communicator](#client-communicator).
   122  
   123  The quintessential example is
   124  [`https.Communicator`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/https#Communicator)
   125  and at this point it is the expected implementation for essentially all
   126  installations. By adjusting the passed in `net.Listener` parameter, it should be
   127  possible to include any needed additional support for load balancing or other
   128  reverse proxying.
   129  
   130  ## Server Service Factories and Configuration
   131  
   132  When messages arrive on a Fleetspeak server, they must be addressed to a
   133  particular service - the `destination` field as described in
   134  [Messages](#messages). A Fleetspeak server runs one or more Services in order to
   135  handle these messages. By configuring additional independent services a single
   136  Fleetspeak installation can handle messages for independent purposes.
   137  
   138  A service is configured by a
   139  [`fleetspeak.server.ServiceConfig`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/server/proto/fleetspeak_server/services.proto)
   140  protocol buffer. Besides the name, used to address the service, the most
   141  important parameter is `factory`. This string is used to look up a
   142  [`service.Factory`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/service#Factory),
   143  which determines what code to use to process incoming messages.
   144  
   145  ### Message Saver
   146  
   147  As a particularly simple example, the fleetspeak demo directory includes a
   148  [`messagesaver`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/demo/messagesaver/messagesaver.go)
   149  package which defines a service which simply saves all received messages to text
   150  files.
   151  
   152  ### GRPCService
   153  
   154  The
   155  [`grpcservice`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/grpcservice)
   156  package provides a `service.Factory` which makes a [GRPC](https://grpc.io/) call
   157  for each delivered message, in this way handing the message off to another
   158  process.
   159  
   160  It expects configuration parameters to be provided in a
   161  [`fleetspeak.grpcservice.Config`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/server/grpcservice/proto/fleetspeak_grpcservice/grpcservice.proto)
   162  protocol buffer, and the target GRPC server must implement the
   163  `fleetspeak.grpcservice.Processor` GRPC interface.
   164  
   165  In addition to the factory, the grpcservice package also exports a
   166  [concrete type](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/server/grpcservice#GRPCService)
   167  which can be used to derive a GRPC-based service with more control over how and
   168  when it dials a new GRPC target.
   169  
   170  # Client
   171  
   172  The Fleetspeak Client is a small process which runs on an endpoint and
   173  communicates with a Fleetspeak Server. Much like the server, it consists of a
   174  base
   175  [`client.Client`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client#Client)
   176  along with a collection of components, and individual installations may adjust
   177  these components according to specific needs.
   178  
   179  ## Miniclient: An Example
   180  
   181  The
   182  [`miniclient`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/demo/miniclient/miniclient.go)
   183  binary from the demo directory defines a Fleetspeak Client in a general and
   184  flexible way. Individual installations may want to define their own client
   185  binary in order to hardcode security critical parameters (for example, before
   186  signing it as a trusted binary) and otherwise adjust client behavior.
   187  
   188  A Fleetspeak client must be provided with a list of TLS root certificates. The
   189  client will then only communicate with a server if it presents one of these
   190  certs, or a cert chaining to one of these certs. The `--trusted_cert_file` flag
   191  is required by miniclient to set this list.
   192  
   193  A Fleetspeek client must also be provided with the server (host and port) to
   194  connect to. The client will require that the presented TLS server be valid for
   195  this host. The `--server` flag is required by miniclient to set this server.
   196  
   197  In addition, a Fleetspeak client needs a public key that it will use to check
   198  the signature of externally provided service configurations. The implications of
   199  this are discussed in more detail below. The `--deployment_key_file` flag is
   200  required by miniclient to configure this.
   201  
   202  To build a binary that can only be used by a specific Fleetspeak installation,
   203  we recommend creating binary which hardcodes the configuration parameters set by
   204  `--trusted_cert_file`, `--server`, and `--deployment_key_file`. Specifically, we
   205  strongly recommend this if you will sign, whitelist a hash, or otherwise mark
   206  the Fleetspeak client binary as trusted.
   207  
   208  ## Configuration Path
   209  
   210  In addition to the security critical parameters described in the previous
   211  section, a Fleetspeak client normally requires a configuration directory to
   212  store its private key and to look for additional configuration. See the comments
   213  on
   214  [`config.Configuration`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/config#Configuration)
   215  for details.
   216  
   217  ## Client Communicator
   218  
   219  Every client requires a
   220  [`Communicator`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/comms#Communicator)
   221  component which handles communication with the server. This component defines
   222  how the client communicates with the Fleetspeak server and should agree on
   223  protocol with a corresponding [Server Communicator](#server-communicator).
   224  
   225  The quintessential example is
   226  [`https.Communicator`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/https#Communicator)
   227  and at this point it is the expected implementation for essentially all
   228  installations. By adjusting the `DialContext` attribute before starting the
   229  Fleetspeak client, it should be possible to include any needed additional
   230  support for specialized tunneling or proxying.
   231  
   232  ## Client Service Factories and Configuration
   233  
   234  When messages arrive on a Fleetspeak client, they must be addressed to a
   235  particular service - the `destination` field as described in
   236  [Messages](#messages). A Fleetspeak client runs one or more Services in order to
   237  handle these messages, and create message to send to the server. By configuring
   238  additional independent services a single Fleetspeak client process can handle
   239  messages for independent purposes.
   240  
   241  A service is typically configured by dropping a
   242  [`fleetspeak.SignedClientServiceConfig`](https://github.com/google/fleetspeak/blob/master/fleetspeak/src/common/proto/fleetspeak/system.proto)
   243  into `<config_path>/services/`. Besides the name, used to address the service,
   244  the most important parameter is `factory`. This string is used to look up a
   245  [`service.Factory`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/service#Factory),
   246  which determines what code to use to process incoming messages.
   247  
   248  This dropped configuration file must be signed with the deployment key.
   249  Therefore by controlling access to the private part of the deployment key, and
   250  hardcoding the public exponent into the client binary, allows an installation to
   251  maintain strong control over what a particular client binary is capable of.
   252  
   253  ### Stdinservice
   254  
   255  The
   256  [`stdinservice.Factory`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/stdinservice#Factory)
   257  runs a binary with flags and standard input provided by a message, and returns
   258  the output it produces. The service configuration determines what binary to run.
   259  Every message received by the service causes and execution of the binary. The
   260  configuration used in the
   261  [`demo` directory](https://github.com/google/fleetspeak/tree/master/fleetspeak/src/demo)
   262  sets up services based on this for the `ls` and `cat` binaries.
   263  
   264  ### Daemonservice
   265  
   266  The
   267  [`daemonservice.Factory`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/daemonservice#Factory)
   268  handles the use case in which you want Fleetspeak to run a sub-process and
   269  send/receive [messages](#messages) to/from it. This gives full control over what
   270  is sent to the server, but requires more integration. The sub-process should use
   271  the
   272  [`daemonservice` client library](https://github.com/google/fleetspeak/tree/master/fleetspeak/src/client/daemonservice/client)
   273  (currently available for go and python) to communicate through Fleetspeak.
   274  
   275  ### Socketservice
   276  
   277  The
   278  [`socketservice.Factory`](https://godoc.org/github.com/google/fleetspeak/fleetspeak/src/client/socketservice#Factory)
   279  handles the use case in which you want Fleetspeak and some separately running
   280  process to find each other and communicate using a local filesystem path, e.g.
   281  through a UNIX domain socket. Much like [`Daemonservice`](#daemonservice) this
   282  also gives full control over what is sent to the server and requires some
   283  integration. The sister process should use the
   284  [`socketservice` client library](https://github.com/google/fleetspeak/tree/master/fleetspeak/src/client/socketservice/client)
   285  to communicate through Fleetspeak.