To improve the security of the Secretless Broker when opening connections to a database backend, the connection opened between the broker and the target service should happen over SSL.
- Extract sslmode params from credentials into backend connection options
- sslmode: Provide different levels of protection.
- sslrootcert: The Certificate Authority (CA) certificate file. This option, if used, must specify the same certificate used by the server
- sslcert: The client public key certificate file.
- sslkey: The client private key file.
- sslcrl: The certificates revoked by certificate authorities.
- Dial backend to get net.Conn
- Default to secure connection if TLS supported
- Ensure client TLS requirements match server requirements and support, FAIL if not.
- Default to required secured connection, regardless of support
- Upgrade net.Conn to tls.Conn and use appropriate strategy for sslmode
Given DB container services with TLS support and without:
- each sslmode works or errors as intended
- happy path to secretless via unix socket, and tcp
https://dev.mysql.com/doc/internals/en/connection-phase.html
Note that throughout the handshake a sequenceID is maintained which is incremented at every step. This means a handshake with TLS-encryption will have a final sequenceID higher than a plain handshake.
- Upon initial Dial the server responds to client with capabilities
- Client creates HandshakeResponse with capabilities in common .e.g TLS
- To initiate an TLS-encrypted connection the client sends an SSLRequest, a truncated version of HandshakeResponse. See https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::SSLRequest
- Finally, client sends HandshakeResponse which contains authentication information. See https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
- Deal with Authentication Method Mismatch. See https://dev.mysql.com/doc/internals/en/authentication-method-mismatch.html
NOTE: MySQL can CREATE users required to use SSL
support for "sslmode" = ( disable allow prefer require verify-ca verify-full )
** NOTE - as a mysql user you might be used to the following notation but we only support the notation above **
support for "ssl-mode" = ( DISABLED PREFFERED REQUIRED VERIFY_CA VERIFY_IDENTITY )
https://www.postgresql.org/docs/9.1/libpq-ssl.html#LIBPQ-SSL-PROTECTION
https://www.postgresql.org/docs/9.3/protocol-flow.html
- Upon initial Dial the server waits for the client to issue a StartupMessage; This message includes the names of the user and of the database the user wants to connect to; it also identifies the particular protocol version to be used.
- To initiate an TLS-encrypted connection, the frontend initially sends an SSLRequest message rather than a StartupMessage
- The client sends the StartupMessage
- The server then sends an appropriate authentication request message, to which the client must reply with an appropriate authentication response message.
support for "sslmode" = ( disable allow prefer require verify-ca verify-full )
- https://github.com/lib/pq/blob/master/ssl.go
- https://github.com/CrunchyData/crunchy-proxy/tree/master/connect
Each handler should have a corresponding story
-
handler documentation provides example and descriptions of sslmode params in credentials (see example)
-
handler supports TLS defaulting to sslmode=require
A.C
- When a connection is made to a server:
- FAIL, if the server does not support TLS
- DO NOT VERIFY server certificate, otherwise
- test cases exist for each of the scenarios above
- When a connection is made to a server:
-
handler supports sslrootcert and sslmode up to verify-ca
A.C
- handler credentials accepts sslmode and sslrootcert
- [default] When a connection is made to a server:
- FAIL, if the server does not support TLS
- DO NOT VERIFY, if no root CA is present
- VERIFY the server certificate (same as verify-ca), if a root CA file is present
- When a connection is made to a server:
- FAIL, if client requires TLS and server does not support it
- DO NOT USE TLS, if sslmode=disable
- ONLY USE TLS, if sslmode=prefer and server supports TLS
- test cases exist for each of the scenarios above
-
handler supports sslmode=verify-full
A.C
- When a connection is made to a server:
- FAIL, if the server cannot verify cert and hostnea
- SUCCESS, otherwise
- test cases exist for each of the scenarios above
- When a connection is made to a server:
-
handler supports private-key pair as sslkey and sslcert
A.C
- handler credentials accepts
sslkey
andsslcert
- When a connection is made to a server:
- FAIL, if the server cannot verify private-key pair
- SUCCESS, otherwise
- test cases exist for each of the scenarios above
- handler credentials accepts
The PostgreSQL handler authenticates and brokers connections to a postgres database.
To secure connections, we support all the postgres SSL options you're familar
with. See the sslmode
option below for details.
Note that, unlike most clients, the default sslmode
for Secretless is
required
, since nearly all use cases require TLS. If you do need to turn it
off, however, and know you can do so safely, you can.
You tell Secretless where to find your database connection details in the yaml
file's credentials
section.
There you specify where to find your database's address, your username and password,
as well as the sslmode
details, including the location of any relevant certificates
and revocation lists, if applicable.
The options are as follows:
-
address
RequiredConnection string of the form
host[:port][/dbname]
-
username
RequiredUsername of the PostgreSQL account you are connecting as.
-
password
RequiredPassword of the PostgreSQL account you are connecting as.
-
sslmode
OptionalThis option determines if the connection between Secretless and your database will be protected by SSL.
NOTE: As mentioned above, the default is
require
as opposed toprefer
, forcing SSL unless you explicitly turn it off.The Postgres documentation website provides detail on the levels of protection provided by different values for the sslmode parameter.
There are six modes:
-
disable
only try a non-SSL connection -
allow
first try a non-SSL connection; if that fails, try an SSL connection -
prefer
first try an SSL connection; if that fails, try a non-SSL connection -
require
(default) only try an SSL connection. If a root CA file is present, verify the certificate in the same way as if verify-ca was specified -
verify-ca
only try an SSL connection, and verify that the server certificate is issued by a trusted certificate authority (CA). -
verify-full
only try an SSL connection, verify that the server certificate is issued by a trusted CA and that the server host name matches that in the certificate
-
NOTE: If sslmode
is set to require
, verify-ca
, or verify-full
, it may
be necessary to set some of the values below. The particular values needed
depend on your use case.
-
sslcert
OptionalThe content of this parameter specifies the client SSL certificate, replacing the default ~/.postgresql/postgresql.crt. This parameter is ignored if an SSL connection is not made.
-
sslkey
OptionalThe content of this parameter specifies the secret key used for the client certificate, replacing the default ~/.postgresql/postgresql.key. This parameter is ignored if an SSL connection is not made.
-
sslrootcert
OptionalThe content of this parameter specifies the SSL certificate authority (CA) certificate(s), replacing the default ~/.postgresql/root.crt. If present, the server's certificate will be verified to be signed by one of these authorities.
-
sslcrl
OptionalThis content of this parameter specifies the SSL certificate revocation list (CRL), replacing the default ~/.postgresql/root.crl. Certificates listed, if present, will be rejected while attempting to authenticate the server's certificate.
version: "2"
services:
pg_connector:
connector: pg
listenOn: tcp://0.0.0.0:5432
credentials:
host: postgres.my-service.internal
username: myservice
password:
from: env
get: PG_PASSWORD
version: "2"
services:
pg_connector:
connector: pg
listenOn: tcp://0.0.0.0:5432
credentials:
host: postgres.my-service.internal
username: myservice
password:
from: env
get: PG_PASSWORD
sslmode: verify-full
# NOTE: if your CA is stored in the environment
# or a secret store, rather than a file, you can
# use the appropriate provider
sslrootcert:
from: file
get: /etc/pg/root.crt
sslcert:
from: file
get: /etc/pg/client.crt
sslkey:
from: file
get: /etc/pg/client.key
sslcrl:
from: file
get: /etc/pg/root.crl
version: "2"
services:
pg_connector:
connector: pg
listenOn: unix:///sock/.s.PGSQL.5432
credentials:
host: postgres.my-service.internal
username: myservice
password:
from: env
get: PG_PASSWORD