@cryptotaxi247 / netdata-1 / commits / 6b091fafd

OpenTSDB and TLS (#9068)

Brings TLS to OpenTSDB connector and InfluxDB

thiagoftsm committed May 26, 2020 at 17:05 UTC 6b091fafd9c3b0197325b3ef751dbdb317048e2b
6 files changed +171 -3
exporting/exporting_engine.h
+2
@@ -25,6 +25,7 @@ typedef enum exporting_options {
25
26 EXPORTING_OPTION_SEND_CONFIGURED_LABELS = (1 << 3),
27 EXPORTING_OPTION_SEND_AUTOMATIC_LABELS = (1 << 4),
28 + EXPORTING_OPTION_USE_TLS = (1 << 5),
29
30 EXPORTING_OPTION_SEND_NAMES = (1 << 16)
31 } EXPORTING_OPTIONS;
@@ -252,6 +253,7 @@ static inline void disable_instance(struct instance *instance)
253 }
254
255 #include "exporting/prometheus/prometheus.h"
256 +#include "exporting/opentsdb/opentsdb.h"
257 #if ENABLE_PROMETHEUS_REMOTE_WRITE
258 #include "exporting/prometheus/remote_write/remote_write.h"
259 #endif
exporting/opentsdb/opentsdb.c
+10
@@ -59,6 +59,16 @@ int init_opentsdb_http_instance(struct instance *instance)
59 instance->config.connector_specific_config = (void *)connector_specific_config;
60 connector_specific_config->default_port = 4242;
61
62 +#ifdef ENABLE_HTTPS
63 + struct opentsdb_specific_data *connector_specific_data = callocz(1, sizeof(struct opentsdb_specific_data));
64 + connector_specific_data->flags = NETDATA_SSL_START;
65 + connector_specific_data->conn = NULL;
66 + if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
67 + security_start_ssl(NETDATA_SSL_CONTEXT_OPENTSDB);
68 + }
69 + instance->connector_specific_data = connector_specific_data;
70 +#endif
71 +
72 instance->start_batch_formatting = NULL;
73 instance->start_host_formatting = format_host_labels_opentsdb_http;
74 instance->start_chart_formatting = NULL;
exporting/opentsdb/opentsdb.h
+7
@@ -18,4 +18,11 @@ int format_dimension_stored_opentsdb_telnet(struct instance *instance, RRDDIM *r
18 int format_dimension_collected_opentsdb_http(struct instance *instance, RRDDIM *rd);
19 int format_dimension_stored_opentsdb_http(struct instance *instance, RRDDIM *rd);
20
21 +#ifdef ENABLE_HTTPS
22 +struct opentsdb_specific_data {
23 + SSL *conn; //SSL connection
24 + int flags; //The flags for SSL connection
25 +};
26 +#endif
27 +
28 #endif //NETDATA_EXPORTING_OPENTSDB_H
exporting/read_config.c
+6
@@ -430,6 +430,12 @@ struct engine *read_exporting_config()
430
431 tmp_instance->config.destination = strdupz(exporter_get(instance_name, "destination", default_destination));
432
433 +#ifdef ENABLE_HTTPS
434 + if (tmp_instance->config.type == EXPORTING_CONNECTOR_TYPE_OPENTSDB_USING_HTTP && !strncmp(tmp_ci_list->local_ci.connector_name, "opentsdb:https", 14)) {
435 + tmp_instance->config.options |= EXPORTING_OPTION_USE_TLS;
436 + }
437 +#endif
438 +
439 #ifdef NETDATA_INTERNAL_CHECKS
440 info(
441 " Dest=[%s], upd=[%d], buffer=[%d] timeout=[%ld] options=[%u]",
exporting/send_data.c
+129 -1
@@ -45,6 +45,13 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
45 response = buffer_create(1);
46
47 struct stats *stats = &instance->stats;
48 +#ifdef ENABLE_HTTPS
49 + uint32_t options = (uint32_t)instance->config.options;
50 + struct opentsdb_specific_data *connector_specific_data = instance->connector_specific_data;
51 +
52 + if (options & EXPORTING_OPTION_USE_TLS)
53 + ERR_clear_error();
54 +#endif
55
56 errno = 0;
57
@@ -53,7 +60,41 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
60 buffer_need_bytes(response, 4096);
61
62 ssize_t r;
63 +#ifdef ENABLE_HTTPS
64 + if (options & EXPORTING_OPTION_USE_TLS &&
65 + connector_specific_data->conn &&
66 + connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
67 + r = (ssize_t)SSL_read(connector_specific_data->conn,
68 + &response->buffer[response->len],
69 + (int) (response->size - response->len));
70 +
71 + if (likely(r > 0)) {
72 + // we received some data
73 + response->len += r;
74 + stats->received_bytes += r;
75 + stats->receptions++;
76 + continue;
77 + } else {
78 + int sslerrno = SSL_get_error(connector_specific_data->conn, (int) r);
79 + u_long sslerr = ERR_get_error();
80 + char buf[256];
81 + switch (sslerrno) {
82 + case SSL_ERROR_WANT_READ:
83 + case SSL_ERROR_WANT_WRITE:
84 + goto endloop;
85 + default:
86 + ERR_error_string_n(sslerr, buf, sizeof(buf));
87 + error("SSL error (%s)",
88 + ERR_error_string((long)SSL_get_error(connector_specific_data->conn, (int)r), NULL));
89 + goto endloop;
90 + }
91 + }
92 + } else {
93 + r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
94 + }
95 +#else
96 r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
97 +#endif
98 if (likely(r > 0)) {
99 // we received some data
100 response->len += r;
@@ -69,10 +110,14 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
110 error("EXPORTING: cannot receive data from '%s'.", instance->config.destination);
111 }
112 }
113 +
114 #ifdef UNIT_TESTING
115 break;
116 #endif
117 }
118 +#ifdef ENABLE_HTTPS
119 +endloop:
120 +#endif
121
122 // if we received data, process them
123 if (buffer_strlen(response))
@@ -96,6 +141,14 @@ void simple_connector_send_buffer(int *sock, int *failures, struct instance *ins
141 flags += MSG_NOSIGNAL;
142 #endif
143
144 +#ifdef ENABLE_HTTPS
145 + uint32_t options = (uint32_t)instance->config.options;
146 + struct opentsdb_specific_data *connector_specific_data = instance->connector_specific_data;
147 +
148 + if (options & EXPORTING_OPTION_USE_TLS)
149 + ERR_clear_error();
150 +#endif
151 +
152 struct stats *stats = &instance->stats;
153
154 int ret = 0;
@@ -104,8 +157,19 @@ void simple_connector_send_buffer(int *sock, int *failures, struct instance *ins
157
158 ssize_t written = -1;
159
107 - if (!ret)
160 + if (!ret) {
161 +#ifdef ENABLE_HTTPS
162 + if (options & EXPORTING_OPTION_USE_TLS &&
163 + connector_specific_data->conn &&
164 + connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
165 + written = (ssize_t)SSL_write(connector_specific_data->conn, buffer_tostring(buffer), len);
166 + } else {
167 + written = send(*sock, buffer_tostring(buffer), len, flags);
168 + }
169 +#else
170 written = send(*sock, buffer_tostring(buffer), len, flags);
171 +#endif
172 + }
173
174 if(written != -1 && (size_t)written == len) {
175 // we sent the data successfully
@@ -167,6 +231,13 @@ void simple_connector_worker(void *instance_p)
231 {
232 struct instance *instance = (struct instance*)instance_p;
233
234 +#ifdef ENABLE_HTTPS
235 + uint32_t options = (uint32_t)instance->config.options;
236 + struct opentsdb_specific_data *connector_specific_data = instance->connector_specific_data;
237 +
238 + if (options & EXPORTING_OPTION_USE_TLS)
239 + ERR_clear_error();
240 +#endif
241 struct simple_connector_config *connector_specific_config = instance->config.connector_specific_config;
242 struct stats *stats = &instance->stats;
243
@@ -208,6 +279,56 @@ void simple_connector_worker(void *instance_p)
279 &reconnects,
280 NULL,
281 0);
282 +#ifdef ENABLE_HTTPS
283 + if(sock != -1) {
284 + if (netdata_opentsdb_ctx) {
285 + if ( sock_delnonblock(sock) < 0 )
286 + error("Exporting cannot remove the non-blocking flag from socket %d", sock);
287 +
288 + if (connector_specific_data->conn == NULL) {
289 + connector_specific_data->conn = SSL_new(netdata_opentsdb_ctx);
290 + if (connector_specific_data->conn == NULL) {
291 + error("Failed to allocate SSL structure to socket %d.", sock);
292 + connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
293 + }
294 + } else {
295 + SSL_clear(connector_specific_data->conn);
296 + }
297 +
298 + if (connector_specific_data->conn) {
299 + if (SSL_set_fd(connector_specific_data->conn, sock) != 1) {
300 + error("Failed to set the socket to the SSL on socket fd %d.", sock);
301 + connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
302 + } else {
303 + connector_specific_data->flags = NETDATA_SSL_HANDSHAKE_COMPLETE;
304 + SSL_set_connect_state(connector_specific_data->conn);
305 + int err = SSL_connect(connector_specific_data->conn);
306 + if (err != 1) {
307 + err = SSL_get_error(connector_specific_data->conn, err);
308 + error("SSL cannot connect with the server: %s ",
309 + ERR_error_string((long)SSL_get_error(connector_specific_data->conn, err), NULL));
310 + connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
311 + } else {
312 + info("Exporting established a SSL connection.");
313 +
314 + struct timeval tv;
315 + tv.tv_sec = timeout.tv_sec /4;
316 + tv.tv_usec = 0;
317 +
318 + if (!tv.tv_sec)
319 + tv.tv_sec = 2;
320 +
321 + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)))
322 + error("Cannot set timeout to socket %d, this can block communication", sock);
323 +
324 + }
325 + }
326 + }
327 + }
328 +
329 + }
330 +#endif
331 +
332 stats->reconnects += reconnects;
333 }
334
@@ -265,5 +386,12 @@ void simple_connector_worker(void *instance_p)
386 clean_prometheus_remote_write(instance);
387 #endif
388
389 +#ifdef ENABLE_HTTPS
390 + if (options & EXPORTING_OPTION_USE_TLS) {
391 + SSL_free(connector_specific_data->conn);
392 + freez(instance->connector_specific_data);
393 + }
394 +#endif
395 +
396 simple_connector_cleanup(instance);
397 }
libnetdata/socket/security.c
+17 -2
@@ -66,12 +66,16 @@ int tls_select_version(const char *lversion) {
66 return TLS1_1_VERSION;
67 else if (!strcmp(lversion, "1.2"))
68 return TLS1_2_VERSION;
69 -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_111
69 +#if defined(TLS1_3_VERSION)
70 else if (!strcmp(lversion, "1.3"))
71 return TLS1_3_VERSION;
72 #endif
73
74 +#if defined(TLS_MAX_VERSION)
75 return TLS_MAX_VERSION;
76 +#else
77 + return TLS1_2_VERSION;
78 +#endif
79 }
80 #endif
81
@@ -120,7 +124,18 @@ SSL_CTX * security_initialize_openssl_client() {
124 ctx = SSL_CTX_new(TLS_client_method());
125 #endif
126 if(ctx) {
123 - security_openssl_common_options(ctx, 1);
127 +#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
128 + SSL_CTX_set_options (ctx,SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
129 +#else
130 + SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
131 +# if defined(TLS_MAX_VERSION)
132 + SSL_CTX_set_max_proto_version(ctx, TLS_MAX_VERSION);
133 +# elif defined(TLS1_3_VERSION)
134 + SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION);
135 +# elif defined(TLS1_2_VERSION)
136 + SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION);
137 +# endif
138 +#endif
139 }
140
141 return ctx;