mirror of https://github.com/hashicorp/boundary
Add TLS security page (#602)
parent
ce40b69ffa
commit
5505d9a9ea
@ -0,0 +1,135 @@
|
||||
---
|
||||
layout: docs
|
||||
page_title: TLS
|
||||
sidebar_title: TLS
|
||||
description: |-
|
||||
How Boundary secures its connections
|
||||
---
|
||||
|
||||
# TLS in Boundary
|
||||
|
||||
As a security product, Boundary has been designed from the ground up to ensure
|
||||
its connections are secure. There are three types of connections in Boundary;
|
||||
this page will describe how TLS works with each of them.
|
||||
|
||||
Some of the ways that Boundary uses TLS, e.g. for client-to-worker connections,
|
||||
are different from most other products. It may not be readily apparent that user
|
||||
configuration of TLS on the listening port of Workers is not only not required,
|
||||
but more secure; however, when it comes to TLS, Boundary tries to provide high
|
||||
security by default with simplicity of operation.
|
||||
|
||||
Details are in the individual sections below.
|
||||
|
||||
## Client-to-Controller TLS
|
||||
|
||||
Boundary's API access (that is, the Controller server defaulting to port 9200)
|
||||
uses standard PKI. TLS is configured by providing a valid certificate (and
|
||||
optionally CA certificate or chain) and clients must trust that CA chain. This
|
||||
provides broad compatibility with a wide array of clients.
|
||||
|
||||
## Worker-to-Controller TLS
|
||||
|
||||
The service exposed by the a Controller to handle Worker requests takes
|
||||
advantage of the KMS key designated for `worker-auth` within Boundary's
|
||||
configuration file, which must point to the same key on the KMS for both the
|
||||
Controller and the Worker. Security of the connection relies on secure
|
||||
transmission of a single set of allowed TLS parameters, which forms the entire
|
||||
allowable CA chain for the connection.
|
||||
|
||||
TLS establishment is performed as follows:
|
||||
|
||||
1. The Worker generates a TLS certificate acting as a self-contained chain, as
|
||||
well as a nonce. The generated key type is currently Ed25519. The certificate is
|
||||
valid for a total of 2.5 minutes: thirty seconds before the current time (to
|
||||
allow for some minor clock drift) and two minutes after (to allow time to
|
||||
establish the connection).
|
||||
|
||||
2. The Worker marshals the TLS chain and nonce and encrypts the resulting bytes
|
||||
via the shared KMS. This value is marshaled and split into chunks.
|
||||
|
||||
3. The Worker establishes a TLS 1.3 connection to the Controller. The encrypted
|
||||
value is transmitted to the Controller via the TLS ALPN field as numbered
|
||||
chunks.
|
||||
|
||||
4. The Controller reads the chunks and reassembles them into the original
|
||||
encrypted value.
|
||||
|
||||
5. The Controller decrypts this value via the shared KMS. If successful, the
|
||||
Controller validates that the nonce is not known, to ensure that this is not a
|
||||
replay.
|
||||
|
||||
6. The Controller uses the decrypted parameters to configures its TLS stack with
|
||||
the same certificate and key.
|
||||
|
||||
7. The connection is mutually authenticated; on each end, only the single
|
||||
self-signed CA certificate that was securely transmitted is configured as a
|
||||
valid root CA for validation checking.
|
||||
|
||||
8. If successful, the nonce is stored in the database along with an expiration
|
||||
time set several minutes past the actual expiration time of the certificate
|
||||
itself. This ensures that any replay attempt that occurs is detected and
|
||||
rejected until after the certificate is otherwise invalid.
|
||||
|
||||
## Client-to-Worker TLS
|
||||
|
||||
Workers do not require any configuration for their client-facing listeners to
|
||||
support a high degree of security. Instead, the TLS configuration to use is
|
||||
determined dynamically via SNI, and the session is then mutually authenticated.
|
||||
Here's how it works:
|
||||
|
||||
TLS establishment is performed as follows:
|
||||
|
||||
1. When the session is authorized, the Controller generates a TLS certificate
|
||||
acting as a self-contained chain. This is similar to the Worker-to-Controller
|
||||
flow above, but in this case the key is an Ed25519 key generated via derivation
|
||||
from a base key within the Controller, which itself is protected at rest via the
|
||||
controller's "root" KMS. The derivation uses HKDF-SHA256 with the user ID and
|
||||
the session ID as inputs. The lifetime of the certificate is tied to the
|
||||
lifetime of the session.
|
||||
|
||||
2. The certificate and private key (along with other session authorization data,
|
||||
notably the session ID) are returned to the client as part of the output of an
|
||||
`authorize-session` action against a target, in the form of a marshaled object.
|
||||
The controller persists the certificate in the database, but not the private
|
||||
key.
|
||||
|
||||
3. The client (that is, the `boundary connect` command) parses this session
|
||||
authorization data and uses the certificate and private key to construct a TLS
|
||||
stack. It then makes a TLS 1.3 connection to a Worker, passing the session ID as
|
||||
the SNI value.
|
||||
|
||||
4. The worker sees the SNI value and makes a call to the Controller to fetch
|
||||
session authorization information, keyed by the session ID.
|
||||
|
||||
5. The Controller looks for a session with the given ID and fetches the
|
||||
information. Using the session ID and the user ID tied to the session, it
|
||||
re-derives the private key and passes all of the information back to the Worker.
|
||||
Notably, this may include a TOFU (Trust On First Use) token.
|
||||
|
||||
6. The Worker uses the given data to construct a TLS stack with the same
|
||||
certificate and key.
|
||||
|
||||
7. The connection is mutually authenticated; on each end, only the single
|
||||
self-signed CA certificate that was securely transmitted is configured as a
|
||||
valid root CA for validation checking.
|
||||
|
||||
8. If successful, the client and Worker perform a handshake, where the client
|
||||
passes a TOFU (Trust On First Use) value to the Worker. This value is derived
|
||||
when the client is created; that is, when `boundary connect` is run. This allows
|
||||
for a single client to make multiple connections within a session, without the
|
||||
credentials being usable via a different client:
|
||||
|
||||
* If the worker was not given a TOFU token in step 5, the worker submits the
|
||||
value to the Controller. The Controller verifies (via a database transaction)
|
||||
that the session has not had a different TOFU token submitted prior and stores
|
||||
it. Otherwise it's rejected, and so is the connection, as a possible replay
|
||||
attack.
|
||||
|
||||
* If the Worker was given a TOFU token in step 5, it checks to see whether the
|
||||
token values match. If not, the connection is rejected as a possible replay
|
||||
attack.
|
||||
|
||||
In the future, to support other client paradigms, we may support user
|
||||
configuration of the Worker's client-facing TLS. In this model, the shared
|
||||
certificate/private key would instead act as credentials for the session,
|
||||
similar to a username/password.
|
||||
Loading…
Reference in new issue