]> git.ipfire.org Git - thirdparty/collectd.git/commitdiff
open_telemetry plugin: Add SSL options for the exporter.
authorFlorian Forster <octo@collectd.org>
Fri, 2 Feb 2024 15:15:51 +0000 (16:15 +0100)
committerFlorian Forster <octo@collectd.org>
Tue, 20 Feb 2024 14:28:50 +0000 (15:28 +0100)
src/collectd.conf.in
src/collectd.conf.pod
src/open_telemetry_exporter.cc

index 86dcbb5a1b3c76fac0d3e469a54e62d0b74231a4..33e9bc4e1fadec5530f97bf418042754e61759b4 100644 (file)
 #    SSLCACertificateFile "/path/to/root.pem"
 #    SSLCertificateFile "/path/to/client.pem"
 #    SSLCertificateKeyFile "/path/to/client.key"
-#    VerifyPeer false
+#    VerifyPeer true
 #  </Receiver>
-#  Exporter "localhost" "4317"
+#  <Exporter "localhost" "4317">
+#    EnableSSL false
+#    SSLCACertificateFile "/path/to/root.pem"
+#    SSLCertificateFile "/path/to/client.pem"
+#    SSLCertificateKeyFile "/path/to/client.key"
+#  </Exporter>
 #</Plugin>
 
 #<Plugin oracle>
index 285a0ca1eb59b9e5faa05c4c22a46fc9c7d982cf..0aadd0e74c156cd2482b6a86797c85d8a8c7c18a 100644 (file)
@@ -7192,7 +7192,7 @@ Optionally, B<Receiver> blocks support the following options:
 
 =item B<EnableSSL> I<false>|I<true>
 
-Whether to enable SSL for incoming connections. Default: false.
+Whether to enable SSL for incoming connections. Default: I<false>.
 
 =item B<SSLCACertificateFile> I<Filename>
 
@@ -7222,6 +7222,25 @@ The argument I<Host> may be a hostname, an IPv4 address, or an IPv6 address.
 The I<Port> argument may be omitted. In that case the default C<"4317"> is
 used.
 
+Optionally, B<Exporter> blocks support the following options:
+
+=over 4
+
+=item B<EnableSSL> I<false>|I<true>
+
+Whether to require SSL when connecting. Default: I<false>.
+
+=item B<SSLCACertificateFile> I<Filename>
+
+=item B<SSLCertificateFile> I<Filename>
+
+=item B<SSLCertificateKeyFile> I<Filename>
+
+Filenames specifying SSL certificate and key material to be used with SSL
+connections.
+
+=back
+
 =back
 
 =head2 Plugin C<oracle>
index 3b736c3ae922d386df47343f870c1b955799aa31..de62e74b8d31e33385facc3a75ce740453c01515 100644 (file)
@@ -37,6 +37,8 @@ extern "C" {
 #include <netdb.h>
 }
 
+#include <fstream>
+
 #include <grpc++/grpc++.h>
 
 #include "opentelemetry/proto/collector/metrics/v1/metrics_service.grpc.pb.h"
@@ -51,7 +53,7 @@ using opentelemetry::proto::collector::metrics::v1::
 using opentelemetry::proto::collector::metrics::v1::MetricsService;
 
 /*
- * Private variables
+ * Private types
  */
 typedef struct {
   int reference_count;
@@ -59,6 +61,9 @@ typedef struct {
   char *host;
   char *port;
 
+  bool use_ssl;
+  grpc::SslCredentialsOptions *ssl_opts;
+
   resource_metrics_set_t resource_metrics;
   cdtime_t staged_time;
 
@@ -69,14 +74,15 @@ typedef struct {
 
 static int export_metrics(ot_callback_t *cb) {
   if (cb->stub == NULL) {
-    strbuf_t buf = STRBUF_CREATE;
-    strbuf_printf(&buf, "%s:%s", cb->host, cb->port);
+    grpc::string addr = grpc::string(cb->host) + ":" + grpc::string(cb->port);
 
-    auto chan =
-        grpc::CreateChannel(buf.ptr, grpc::InsecureChannelCredentials());
-    cb->stub = MetricsService::NewStub(chan);
+    auto creds = grpc::InsecureChannelCredentials();
+    if (cb->use_ssl) {
+      creds = grpc::SslCredentials(*cb->ssl_opts);
+    }
 
-    STRBUF_DESTROY(buf);
+    auto chan = grpc::CreateChannel(addr, creds);
+    cb->stub = MetricsService::NewStub(chan);
   }
 
   auto req = format_open_telemetry_export_metrics_service_request(
@@ -142,6 +148,8 @@ static void ot_callback_decref(void *data) {
   sfree(cb->host);
   sfree(cb->port);
 
+  delete cb->ssl_opts;
+
   pthread_mutex_unlock(&cb->mu);
   pthread_mutex_destroy(&cb->mu);
 
@@ -178,6 +186,29 @@ static int ot_write(metric_family_t const *fam, user_data_t *user_data) {
   return 0;
 }
 
+static int config_get_file(oconfig_item_t const *ci, grpc::string *out) {
+  char *path = NULL;
+  int err = cf_util_get_string(ci, &path);
+  if (err) {
+    return err;
+  }
+
+  std::ifstream f;
+  f.open(path);
+  if (!f.is_open()) {
+    ERROR("open_telemetry plugin: Failed to open \"%s\"", path);
+    return EPERM;
+  }
+
+  grpc::string line;
+  while (std::getline(f, line)) {
+    out->append(line);
+    out->push_back('\n');
+  }
+  f.close();
+  return 0;
+} /* config_get_file */
+
 int exporter_config(oconfig_item_t *ci) {
   if (ci->values_num < 1 || ci->values_num > 2 ||
       ci->values[0].type != OCONFIG_TYPE_STRING ||
@@ -194,17 +225,40 @@ int exporter_config(oconfig_item_t *ci) {
     return -1;
   }
 
-  *cb = (ot_callback_t){
-      .reference_count = 1,
-      .host = strdup(ci->values[0].value.string),
-  };
+  cb->reference_count = 1;
+  cb->host = strdup(ci->values[0].value.string);
   if (ci->values_num >= 2) {
     cb->port = strdup(ci->values[1].value.string);
   } else {
     cb->port = strdup(OT_DEFAULT_PORT);
   }
+  cb->ssl_opts = new grpc::SslCredentialsOptions;
   pthread_mutex_init(&cb->mu, /* attr = */ NULL);
 
+  for (int i = 0; i < ci->children_num; i++) {
+    oconfig_item_t *child = ci->children + i;
+
+    int err = 0;
+    if (!strcasecmp("EnableSSL", child->key)) {
+      err = cf_util_get_boolean(child, &cb->use_ssl);
+    } else if (!strcasecmp("SSLCACertificateFile", child->key)) {
+      err = config_get_file(child, &cb->ssl_opts->pem_root_certs);
+    } else if (!strcasecmp("SSLCertificateKeyFile", child->key)) {
+      err = config_get_file(child, &cb->ssl_opts->pem_private_key);
+    } else if (!strcasecmp("SSLCertificateFile", child->key)) {
+      err = config_get_file(child, &cb->ssl_opts->pem_cert_chain);
+    } else {
+      ERROR("open_telemetry plugin: Option \"%s\" is not allowed inside a "
+            "\"%s\" block.",
+            child->key, ci->key);
+      err = EINVAL;
+    }
+
+    if (err) {
+      return err;
+    }
+  }
+
   strbuf_t callback_name = STRBUF_CREATE;
   strbuf_printf(&callback_name, "open_telemetry/[%s]:%s", cb->host, cb->port);