src/tls/README.md
cockpit-tls is a TLS terminating HTTP proxy for cockpit-ws. TLS termination
should not be done directly in cockpit-ws, as that is hard to audit and trust:
This code is subject to external attacks through HTTP, does a lot of
interpretation of data streams, uses a lot of external dependencies, and
multiplexes sessions of different users in one process. Thus any vulnerability
can easily lead to complete privilege escalation across all running and future
sessions.
By isolating the TLS termination and certificate checking from the http
processing, and isolating http processing for each client certificate, Cockpit
can do certificate based client authentication (smart cards, browser-imported
certificates, and similar) in a sufficiently robust manner. Any tampering with
a cockpit-ws process is then unable to affect other sessions and the
certificate attestation.
+---------+ http://machine:9090 +------------------------+
|Browser A|+----------------------+ +-->|cockpit-ws http instance|
+---------+ | | +------------------------+
| |
| + (plain HTTP over Unix socket)
| |
+---------+ https://machine:9090 | +------------+ | +------------------------------------+
|Browser B|+----------------------+--->| cockpit-tls|--+-->|cockpit-ws https instance for cert B|
+---------+ client cert B | +------------+ + +------------------------------------+
| |
| |
+---------+ https://machine:9090 | | +------------------------------------+
|Browser C|+----------------------+ +-->|cockpit-ws https instance for cert C|
+---------+ client cert C +------------------------------------+
The startup of these instances and isolating them from one another makes heavy use of systemd features.
cockpit-tls, usually
as user cockpit-ws (for historical reasons, to avoid having to change the
ownership of /etc/cockpit/ws-certs.d/* on upgrades).cockpit-wsinstance-factory that
reads the fingerprint from stdin, and asks systemd to start a new
[email protected]
and .service pair.cockpit-wsinstance-socket./run/cockpit/tls/<fingerprint>
while there is at least one open connection with that certificate, i. e. as
long as there is an active Cockpit session.This must be explicitly enabled in cockpit.conf with ClientCertAuthentication = yes,
see the guide and
manpage. Then cockpit-tls will ask the
browser for a client certificate.
Commonly this is provided by a smart card, but it's equally possible to import certificates directly into the web browser.
This requires the host to be in an Identity Management domain like FreeIPA or Active Directory, which can associate certificates to users. See the FreeIPA User Certificates documentation for details.
The sssd-dbus package must be installed for this to work.
If the web browser presents a client certificate, cockpit-tls will write this
certificate to /run/cockpit/tls. If cockpit-ws sees that cockpit-tls
exports a certificate for its connection (by checking its cgroup instance name,
which is the certificate fingerprint, and checking /run/cockpit/tls for it),
then it will request the tls-cert authentication schema from cockpit-session,
instead of the usual basic or gssapi. cockpit-session then uses the content
of this file to ask sssd to map the certificate to a username. If the mapping
is successful, cockpit-session sets the user name and opens the PAM session
without further authentication.
A Connection (in connection.[hc]) object represents a single TCP
connection from a client (browser) towards cockpit-tls. Each connection is
handled in its own thread, so that blocked connections cannot starve others.
It has the code for launching ws instances and shoveling data back and forth
between the browser and the ws instance.
A Server (in server.[hc]) object represents the cockpit-tls logic. It is
a singleton (not instantiated), and mostly split out into a separate object
so that it can be properly unit tested. It maintains some global
configuration, listens to the port, and coordinates the connection threads.
and WsInstance objects according to incoming requests.
certfile.[hc] deals with exporting current certificates to
/run/cockpit/tls/, and the refcounting from all Connections that belong to a
particular certificate.
The other files are helpers or unit tests.