Develop MongoDB Locally With TLS
Avalie esse Tutorial
MongoDB hosted on Atlas is fine for development and presents fully valid TLS certificates. I use it alongside two Community Edition local installations. But a free Atlas development account has limits. Even with a paid account, you do not have complete control of a vendor cloud deployment, so if your end goal is on-premises deployment, you can't experiment on Atlas with many deployment details. Therefore, developers may choose to model deployment on their home turf using Community Edition or Enterprise Advanced.
If you are going to model on-premises or intranet cloud deployment, enabling TLS makes the environment more realistic.
In a word, simplicity. To use a worldwide-recognized certificate authority signed certificate, you have to register a domain name. If your enterprise IT maintains a local private certificate authority (such as open source EJBCA or PKI-as-a-service TinyCert), you're done here and only need contact your IT department. Otherwise, a self-signed certificate chain is an easy choice. This is a local-development-only choice. Remember that no production installation should ever present a self-signed certificate chain.
If you're ready to register your domain name, you can reach for Let's Encrypt as a low-impact choice for registering with a genuine certificate authority. We'll discuss Let's Encrypt later in this article. In the meantime, we will take the easy way out and implement a self-signed certificate chain.
Note that this article is the author's opinion only. It does not represent official MongoDB guidance!
You may have seen the hook, "We're professionals—don't try this at home!" Here we have the contrapositive: "Only try this at home!" A self-signed certificate chain presents extra vulnerabilities, even in seemingly low-risk contexts, provided there is the chance of "the enemy within." If your development setup will involve transmitting sensitive data to MongoDB, even inside the enterprise, a self-signed certificate may be a poor choice.
For years, I created a self-signed server certificate without a signing certificate authority and assigned it to a MongoDB Community Edition instance.
Security concerns changed all that. One minor version update of MongoDB which was pushed without prior notice yanked the rug out from under my development setup. The issue that documents the precipitous MongoDB change is SERVER-72839, Server skips peer certificate validation if neither CAFile nor clusterCAFile is provided, which you can read for the details.
Nowadays, instead of creating a self-signed certificate, if we are going the self-signed route, we must create a self-signed certificate authority certificate and sign the server certificate with that certificate authority certificate.
You can skip this section if you're well-briefed on SSL/TLS certificates. Here, we present an abbreviated view of server certificates and skip many important details which a security expert understands.
- A server certificate is meant to prove that a server to which we are connecting is really the server we mean to connect to.
- A server certificate is typically signed by a certificate authority which is looked up during connection to validate the server certificate. The certificate authority certificate may be root, or it may be intermediate signed yet again by a higher-level intermediate, or by the root itself.
- If the full chain is found to be signed all throughout in a cryptographically valid manner, then the server certificate is accepted.
- The reason the root (and often the intermediate) certificates are accepted by the client attempting to connect to the server is that they are present in the client's local trust store, with the root pointing back to its ultimate authority on the Internet site maintained by the authority issuing the certificate, which is the only place the private key for the root certificate resides.
In our self-signed chain, the server will have:
- A self-signed certificate authority certificate.
- The private key of the self-signed certificate authority certificate.
- A server certificate signed by the self-signed certificate authority certificate.
- The private key for this server certificate.
We will then indicate the location of these entities in the MongoDB Community Edition configuration. We will also provide to our client connection:
- The server certificate and its private key.
- We would never, with respect to an authentically signed server certificate, be in possession of the private key for the server certificate!
- The self-signed root certificate authority certificate (without its private key).
Thereafter, our client connects to the server in the manner indicated by this object-oriented PHP snippet:
1 $mongodb_client = new MongoDB\Client($mongodb_uri, 2 [ 3 'tls' => true, 4 'tlsCAFile' => $mongodb_ca_cert_path, 5 'tlsCertificateKeyFile' => $mongodb_cert_path 6 ] 7 );
In the above snippet:
- The tlsCertificateKeyFile pointed to by the path is a combined .pem of the server certificate and its private key.
- The tlsCAFile pointed to by the path is the self-signed root certificate authority certificate (without its private key).
The open source openssl command is present on most reasonable platforms. We'll use it to manufacture our self-signed certificate chain.
1 # Creating self-signed CA cert and SAN cert for localhost 2 # aka mdbinstance.mydevelopment.net 3 #===================================================================================== 4 openssl req -x509 -nodes -sha256 -days 1825 -newkey rsa:4096 \ 5 -keyout rootCA.key -out rootCA.crt -subj="/CN=ca.mydevelopment.net" 6 openssl req -newkey rsa:4096 -keyout server.key -nodes \ 7 -out domain.csr -subj "/CN=server.mydevelopment.net" 8 openssl req -x509 -nodes -CA rootCA.crt -CAkey rootCA.key -in domain.csr \ 9 -out mdbinstance.mydevelopment.net.crt -days 3560 -nodes \ 10 -subj '/CN=<mdbinstance_mydevelopment_net>' -extensions san -config <( \ 11 echo '[req]'; \ 12 echo 'distinguished\_name=req'; \ 13 echo '[san]'; \ 14 echo 'subjectAltName=DNS:localhost,DNS:mdbinstance.mydevelopment.net') 15 cat rootCA.key rootCA.crt >rootCAcombined.pem 16 cat server.key mdbinstance.mydevelopment.net.crt >serverCert.pem
The MongoDB server will need the path to:
- rootCAcombined.pem (the combined CA certificate + private key).
- serverCert.pem (the combined server certificate + private key).
Your application will need the path to:
- rootCA.crt (the CA certificate).
- serverCert.pem (the combined server certificate + private key).
Here is the net key from mongod.conf. Our example assumes you're using port 27017 and a bindIp of 0.0.0.0. This example is for a development installation on a very private stretch of network, since we’ve left the MongoDB server accepting connection from anywhere at all.
1 # network interfaces 2 net: 3 port: 27017 4 bindIp: 0.0.0.0 5 tls: 6 mode: requireTLS 7 certificateKeyFile: /path/to/serverCert.pem 8 CAFile: /path/to/rootCAcombined.pem
We've already shown above the PHP connection strategy.
1 mongosh --tls --tlsCAFile /path/to/rootCA.crt --tlsCertificateKeyFile /path/to/serverCert.pem 'mongodb://userid:password@hostname.domain'
Wherein again:
- The tlsCertificateKeyFile pointed to by the path is a combined .pem of the server certificate and its private key.
- The tlsCAFile pointed to by the path is the self-signed root certificate authority certificate (without its private key).
Note that when formulating a Compass connection string, paths must be URL encoded. In this example, the forward-slashes ( / ) of the paths to the certificate files stored locally on the client must be converted to %2F.
1 mongodb://userid:password@hostname.domain/?directConnection=true&tls=true&tlsCAFile=%2Fpath%2Fto%2FrootCA.crt&tlsCertificateKeyFile=%2Fpath%2Fto%2Fserver_certificate.pem
Wherein again:
- The tlsCertificateKeyFile pointed to by the path is a combined .pem of the server certificate and its private key.
- The tlsCAFile pointed to by the path is the self-signed root certificate authority certificate (without its private key).
If you do have a registered domain name and want to work with a genuine certificate authority, a free-of-charge choice is Let's Encrypt. Visit that website and follow the instructions to obtain a server certificate for your installation.
Make sure the Let's Encrypt root and intermediate CA certificates are part of the operating system trust store for the server and for any client.
Get the complete instructions for enabling TLS and read more about how to configure mongod and mongos for TLS/SSL. The short answer in this article's context is that the TLS subkey of the net key in the mongod.conf file should look something like this:
1 net: 2 tls: 3 mode: requireTLS 4 certificateKeyFile: /etc/ssl/mongodb.pem
Where mongodb.pem is the combined server certificate + key.
Remember when we mentioned simplicity earlier in this article? Let's Encrypt automated certificate issuance involves the ACME protocol. This Automatic Certificate Management Environment has several implementations from among which you must choose. ACME implementations have been the subject of a few CVEs, e.g. [1,2,3]. You can see why some choose to defer this complexity until production.
- A self-signed certificate chain is a sensible choice for a realistic local development installation in a reasonably "safe" environment.
- A self-signed certificate chain should never be deployed in production.
- A self-signed certificate chain should never be deployed in development if development or testing exercises sensitive data.
- An enterprise local certificate authority represents an important alternative to a hand-rolled, self-signed certificate chain such as we have presented here.
- If you have a DNS name and are ready for a genuine certificate authority, Let's Encrypt is a good entré.
- MongoDB Community Edition presents flexible configuration options for modeling deployment scenarios, as we have seen in this article.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.