summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--collectors/plugins.d/plugins_d.c2
-rw-r--r--libnetdata/socket/security.c57
-rw-r--r--libnetdata/socket/security.h1
-rw-r--r--streaming/README.md47
-rw-r--r--streaming/rrdpush.c9
-rw-r--r--streaming/stream.conf16
6 files changed, 129 insertions, 3 deletions
diff --git a/collectors/plugins.d/plugins_d.c b/collectors/plugins.d/plugins_d.c
index 0c6010103c..aea2704a35 100644
--- a/collectors/plugins.d/plugins_d.c
+++ b/collectors/plugins.d/plugins_d.c
@@ -251,10 +251,10 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
char tmpbuffer[PLUGINSD_LINE_MAX];
char *readfrom;
#endif
+ char *r = NULL;
while(!ferror(fp)) {
if(unlikely(netdata_exit)) break;
- char *r;
#ifdef ENABLE_HTTPS
int normalread = 1;
if(netdata_srv_ctx) {
diff --git a/libnetdata/socket/security.c b/libnetdata/socket/security.c
index 9eb8e60247..ab324a1691 100644
--- a/libnetdata/socket/security.c
+++ b/libnetdata/socket/security.c
@@ -164,7 +164,7 @@ void security_start_ssl(int selector) {
switch (selector) {
case NETDATA_SSL_CONTEXT_SERVER: {
struct stat statbuf;
- if (stat(security_key,&statbuf) || stat(security_cert,&statbuf)) {
+ if (stat(security_key, &statbuf) || stat(security_cert, &statbuf)) {
info("To use encryption it is necessary to set \"ssl certificate\" and \"ssl key\" in [web] !\n");
return;
}
@@ -186,6 +186,11 @@ void security_start_ssl(int selector) {
}
}
+/**
+ * Clean Open SSL
+ *
+ * Clean all the allocated contexts from netdata.
+ */
void security_clean_openssl() {
if (netdata_srv_ctx)
{
@@ -265,6 +270,15 @@ int security_process_accept(SSL *ssl,int msg) {
return NETDATA_SSL_HANDSHAKE_COMPLETE;
}
+/**
+ * Test Certificate
+ *
+ * Check the certificate of Netdata master
+ *
+ * @param ssl is the connection structure
+ *
+ * @return It returns 0 on success and -1 otherwise
+ */
int security_test_certificate(SSL *ssl) {
X509* cert = SSL_get_peer_certificate(ssl);
int ret;
@@ -283,7 +297,48 @@ int security_test_certificate(SSL *ssl) {
} else {
ret = 0;
}
+
return ret;
}
+/**
+ * Location for context
+ *
+ * Case the user give us a directory with the certificates available and
+ * the Netdata master certificate, we use this function to validate the certificate.
+ *
+ * @param ctx the context where the path will be set.
+ * @param file the file with Netdata master certificate.
+ * @param path the directory where the certificates are stored.
+ *
+ * @return It returns 0 on success and -1 otherwise.
+ */
+int security_location_for_context(SSL_CTX *ctx, char *file, char *path) {
+ struct stat statbuf;
+ if (stat(file, &statbuf)) {
+ info("Netdata does not have a SSL master certificate, so it will use the default OpenSSL configuration to validate certificates!");
+ return 0;
+ }
+
+ ERR_clear_error();
+ u_long err;
+ char buf[256];
+ if(!SSL_CTX_load_verify_locations(ctx, file, path)) {
+ goto slfc;
+ }
+
+ if(!SSL_CTX_set_default_verify_paths(ctx)) {
+ goto slfc;
+ }
+
+ return 0;
+
+slfc:
+ while ((err = ERR_get_error()) != 0) {
+ ERR_error_string_n(err, buf, sizeof(buf));
+ error("Cannot set the directory for the certificates and the master SSL certificate: %s",buf);
+ }
+ return -1;
+}
+
#endif
diff --git a/libnetdata/socket/security.h b/libnetdata/socket/security.h
index cc870ce17b..697e0fda1f 100644
--- a/libnetdata/socket/security.h
+++ b/libnetdata/socket/security.h
@@ -34,6 +34,7 @@ extern SSL_CTX *netdata_srv_ctx;
extern const char *security_key;
extern const char *security_cert;
extern int netdata_validate_server;
+extern int security_location_for_context(SSL_CTX *ctx,char *file,char *path);
void security_openssl_library();
void security_clean_openssl();
diff --git a/streaming/README.md b/streaming/README.md
index ca3edeaecf..1bfbb23626 100644
--- a/streaming/README.md
+++ b/streaming/README.md
@@ -236,6 +236,53 @@ When TLS/SSL is enabled on the slave, the default behavior will be to not connec
ssl skip certificate verification = yes
```
+#### Trusted certificate
+
+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.
+
+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.
+
+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).
+
+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.
+
+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.
+
+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.
+
+```
+# mkdir /usr/share/ca-certificates/netdata
+# cp master_cert.pem /usr/share/ca-certificates/netdata/master_cert.crt
+# chown -R netdata.netdata /usr/share/ca-certificates/netdata/
+```
+
+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.
+
+Next, edit the file `/etc/ca-certificates.conf` and add the following line:
+
+```
+netdata/master_cert.crt
+```
+
+Now you update the list of certificates running the following, again either as `sudo` or `root`:
+
+```
+# update-ca-certificates
+```
+
+!!! note
+ 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).
+
+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:
+
+```
+[stream]
+ CApath = /etc/ssl/certs/
+ CAfile = /etc/ssl/certs/master_cert.pem
+```
+
+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.
+
#### Expected behaviors
With the introduction of TLS/SSL, the master-slave communication behaves as shown in the table below, depending on the following configurations:
diff --git a/streaming/rrdpush.c b/streaming/rrdpush.c
index c798cd1b19..59913c24b5 100644
--- a/streaming/rrdpush.c
+++ b/streaming/rrdpush.c
@@ -50,6 +50,8 @@ char *default_rrdpush_api_key = NULL;
char *default_rrdpush_send_charts_matching = NULL;
#ifdef ENABLE_HTTPS
int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
+char *netdata_ssl_ca_path = NULL;
+char *netdata_ssl_ca_file = NULL;
#endif
static void load_stream_conf() {
@@ -92,13 +94,17 @@ int rrdpush_init() {
}
}
}
+
char *invalid_certificate = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "ssl skip certificate verification", "no");
if ( !strcmp(invalid_certificate,"yes")){
if (netdata_validate_server == NETDATA_SSL_VALID_CERTIFICATE){
- info("The Netdata is configured to accept invalid certificate.");
+ info("Netdata is configured to accept invalid SSL certificate.");
netdata_validate_server = NETDATA_SSL_INVALID_CERTIFICATE;
}
}
+
+ netdata_ssl_ca_path = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CApath", "/etc/ssl/certs/");
+ netdata_ssl_ca_file = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CAfile", "/etc/ssl/certs/certs.pem");
#endif
return default_rrdpush_enabled;
@@ -655,6 +661,7 @@ void *rrdpush_sender_thread(void *ptr) {
#ifdef ENABLE_HTTPS
if (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE ){
security_start_ssl(NETDATA_SSL_CONTEXT_STREAMING);
+ security_location_for_context(netdata_client_ctx, netdata_ssl_ca_file, netdata_ssl_ca_path);
}
#endif
diff --git a/streaming/stream.conf b/streaming/stream.conf
index 0d360cc24f..fdff1f25fc 100644
--- a/streaming/stream.conf
+++ b/streaming/stream.conf
@@ -41,6 +41,22 @@
#
#ssl skip certificate verification = yes
+ # Certificate Authority Path
+ #
+ # OpenSSL has a default directory where the known certificates are stored,
+ # case it is necessary it is possible to change this rule using the variable
+ # "CApath"
+ #
+ #CApath = /etc/ssl/certs/
+
+ # Certificate Authority file
+ #
+ # When the Netdata master has certificate, that is not recognized as valid,
+ # we can add this certificate in the list of known certificates in CApath
+ # and give for Netdata as argument.
+ #
+ #CAfile = /etc/ssl/certs/cert.pem
+
# The API_KEY to use (as the sender)
api key =