@cryptotaxi247 / netdata-1 / commits / 551617bd3

Add configurable default locations for trusted CA certificates (#6549)

* sslcertificate: Trust certificate The netdata could not allow invalid certificate or certificate with invalid chain this commit fixes this! * sslcertificate: Changing name We are binging the same names used by the OpenSSL library to simplify the understand of the parameters * sslcertificate: Name changes and explicity directory This commit fix the problem with Streams and rename correctly the files in the option, it also uses stat to define the existence of a file * sslcertificate: Documentation Fix grammar for the newest section in the documentation * sslcertificate: Rename variables The old variables did not represent well what they are doing, so it was renamed

thiagoftsm committed Jul 29, 2019 at 12:27 UTC 551617bd322e2b855ccf19375650348fda77938a
6 files changed +129 -3
collectors/plugins.d/plugins_d.c
+1 -1
@@ -251,10 +251,10 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
251 char tmpbuffer[PLUGINSD_LINE_MAX];
252 char *readfrom;
253 #endif
254 + char *r = NULL;
255 while(!ferror(fp)) {
256 if(unlikely(netdata_exit)) break;
257
257 - char *r;
258 #ifdef ENABLE_HTTPS
259 int normalread = 1;
260 if(netdata_srv_ctx) {
libnetdata/socket/security.c
+56 -1
@@ -164,7 +164,7 @@ void security_start_ssl(int selector) {
164 switch (selector) {
165 case NETDATA_SSL_CONTEXT_SERVER: {
166 struct stat statbuf;
167 - if (stat(security_key,&statbuf) || stat(security_cert,&statbuf)) {
167 + if (stat(security_key, &statbuf) || stat(security_cert, &statbuf)) {
168 info("To use encryption it is necessary to set \"ssl certificate\" and \"ssl key\" in [web] !\n");
169 return;
170 }
@@ -186,6 +186,11 @@ void security_start_ssl(int selector) {
186 }
187 }
188
189 +/**
190 + * Clean Open SSL
191 + *
192 + * Clean all the allocated contexts from netdata.
193 + */
194 void security_clean_openssl() {
195 if (netdata_srv_ctx)
196 {
@@ -265,6 +270,15 @@ int security_process_accept(SSL *ssl,int msg) {
270 return NETDATA_SSL_HANDSHAKE_COMPLETE;
271 }
272
273 +/**
274 + * Test Certificate
275 + *
276 + * Check the certificate of Netdata master
277 + *
278 + * @param ssl is the connection structure
279 + *
280 + * @return It returns 0 on success and -1 otherwise
281 + */
282 int security_test_certificate(SSL *ssl) {
283 X509* cert = SSL_get_peer_certificate(ssl);
284 int ret;
@@ -283,7 +297,48 @@ int security_test_certificate(SSL *ssl) {
297 } else {
298 ret = 0;
299 }
300 +
301 return ret;
302 }
303
304 +/**
305 + * Location for context
306 + *
307 + * Case the user give us a directory with the certificates available and
308 + * the Netdata master certificate, we use this function to validate the certificate.
309 + *
310 + * @param ctx the context where the path will be set.
311 + * @param file the file with Netdata master certificate.
312 + * @param path the directory where the certificates are stored.
313 + *
314 + * @return It returns 0 on success and -1 otherwise.
315 + */
316 +int security_location_for_context(SSL_CTX *ctx, char *file, char *path) {
317 + struct stat statbuf;
318 + if (stat(file, &statbuf)) {
319 + info("Netdata does not have a SSL master certificate, so it will use the default OpenSSL configuration to validate certificates!");
320 + return 0;
321 + }
322 +
323 + ERR_clear_error();
324 + u_long err;
325 + char buf[256];
326 + if(!SSL_CTX_load_verify_locations(ctx, file, path)) {
327 + goto slfc;
328 + }
329 +
330 + if(!SSL_CTX_set_default_verify_paths(ctx)) {
331 + goto slfc;
332 + }
333 +
334 + return 0;
335 +
336 +slfc:
337 + while ((err = ERR_get_error()) != 0) {
338 + ERR_error_string_n(err, buf, sizeof(buf));
339 + error("Cannot set the directory for the certificates and the master SSL certificate: %s",buf);
340 + }
341 + return -1;
342 +}
343 +
344 #endif
libnetdata/socket/security.h
+1
@@ -34,6 +34,7 @@ extern SSL_CTX *netdata_srv_ctx;
34 extern const char *security_key;
35 extern const char *security_cert;
36 extern int netdata_validate_server;
37 +extern int security_location_for_context(SSL_CTX *ctx,char *file,char *path);
38
39 void security_openssl_library();
40 void security_clean_openssl();
streaming/README.md
+47
@@ -236,6 +236,53 @@ When TLS/SSL is enabled on the slave, the default behavior will be to not connec
236 ssl skip certificate verification = yes
237 ```
238
239 +#### Trusted certificate
240 +
241 +If you've enabled [certificate verification](#certificate-verification), you might see errors from the OpenSSL library when there's a problem with checking the certificate chain (`X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY`). More importantly, OpenSSL will reject self-signed certificates.
242 +
243 +Given these known issues, you have two options. If you trust your certificate, you can set the options `CApath` and `CAfile` to inform Netdata where your certificates, and the certificate trusted file, are stored.
244 +
245 +For more details about these options, you can read about [verify locations](https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_load_verify_locations.html).
246 +
247 +Before you changed your streaming configuration, you need to copy your trusted certificate to your slave system and add the certificate to OpenSSL's list.
248 +
249 +On most Linux distributions, the `update-ca-certificates` command searches inside the `/usr/share/ca-certificates` directory for certificates. You should double-check by reading the `update-ca-certificate` manual (`man update-ca-certificate`), and then change the directory in the below commands if needed.
250 +
251 +If you have `sudo` configured on your slave system, you can use that to run the following commands. If not, you'll have to log in as `root` to complete them.
252 +
253 +```
254 +# mkdir /usr/share/ca-certificates/netdata
255 +# cp master_cert.pem /usr/share/ca-certificates/netdata/master_cert.crt
256 +# chown -R netdata.netdata /usr/share/ca-certificates/netdata/
257 +```
258 +
259 +First, you create a new directory to store your certificates for Netdata. Next, you need to change the extension on your certificate from `.pem` to `.crt` so it's compatible with `update-ca-certificate`. Finally, you need to change permissions so the user that runs Netdata can access the directory where you copied in your certificate.
260 +
261 +Next, edit the file `/etc/ca-certificates.conf` and add the following line:
262 +
263 +```
264 +netdata/master_cert.crt
265 +```
266 +
267 +Now you update the list of certificates running the following, again either as `sudo` or `root`:
268 +
269 +```
270 +# update-ca-certificates
271 +```
272 +
273 +!!! note
274 + Some Linux distributions have different methods of updating the certificate list. For more details, please read this guide on [addding trusted root certificates](https://github.com/Busindre/How-to-Add-trusted-root-certificates).
275 +
276 +Once you update your certificate list, you can set the stream parameters for Netdata to trust the master certificate. Open `stream.conf` for editing and change the following lines:
277 +
278 +```
279 +[stream]
280 + CApath = /etc/ssl/certs/
281 + CAfile = /etc/ssl/certs/master_cert.pem
282 +```
283 +
284 +With this configuration, the `CApath` option tells Netdata to search for trusted certificates inside `/etc/ssl/certs`. The `CAfile` option specifies the Netdata master certificate is located at `/etc/ssl/certs/master_cert.pem`. With this configuration, you can skip using the system's entire list of certificates and use Netdata's master certificate instead.
285 +
286 #### Expected behaviors
287
288 With the introduction of TLS/SSL, the master-slave communication behaves as shown in the table below, depending on the following configurations:
streaming/rrdpush.c
+8 -1
@@ -50,6 +50,8 @@ char *default_rrdpush_api_key = NULL;
50 char *default_rrdpush_send_charts_matching = NULL;
51 #ifdef ENABLE_HTTPS
52 int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
53 +char *netdata_ssl_ca_path = NULL;
54 +char *netdata_ssl_ca_file = NULL;
55 #endif
56
57 static void load_stream_conf() {
@@ -92,13 +94,17 @@ int rrdpush_init() {
94 }
95 }
96 }
97 +
98 char *invalid_certificate = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "ssl skip certificate verification", "no");
99 if ( !strcmp(invalid_certificate,"yes")){
100 if (netdata_validate_server == NETDATA_SSL_VALID_CERTIFICATE){
98 - info("The Netdata is configured to accept invalid certificate.");
101 + info("Netdata is configured to accept invalid SSL certificate.");
102 netdata_validate_server = NETDATA_SSL_INVALID_CERTIFICATE;
103 }
104 }
105 +
106 + netdata_ssl_ca_path = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CApath", "/etc/ssl/certs/");
107 + netdata_ssl_ca_file = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CAfile", "/etc/ssl/certs/certs.pem");
108 #endif
109
110 return default_rrdpush_enabled;
@@ -655,6 +661,7 @@ void *rrdpush_sender_thread(void *ptr) {
661 #ifdef ENABLE_HTTPS
662 if (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE ){
663 security_start_ssl(NETDATA_SSL_CONTEXT_STREAMING);
664 + security_location_for_context(netdata_client_ctx, netdata_ssl_ca_file, netdata_ssl_ca_path);
665 }
666 #endif
667
streaming/stream.conf
+16
@@ -41,6 +41,22 @@
41 #
42 #ssl skip certificate verification = yes
43
44 + # Certificate Authority Path
45 + #
46 + # OpenSSL has a default directory where the known certificates are stored,
47 + # case it is necessary it is possible to change this rule using the variable
48 + # "CApath"
49 + #
50 + #CApath = /etc/ssl/certs/
51 +
52 + # Certificate Authority file
53 + #
54 + # When the Netdata master has certificate, that is not recognized as valid,
55 + # we can add this certificate in the list of known certificates in CApath
56 + # and give for Netdata as argument.
57 + #
58 + #CAfile = /etc/ssl/certs/cert.pem
59 +
60 # The API_KEY to use (as the sender)
61 api key =
62