#include <amqp_framing.h>
#ifdef HAVE_AMQP_TCP_SOCKET_H
+#include <amqp_ssl_socket.h>
#include <amqp_tcp_socket.h>
#endif
#ifdef HAVE_AMQP_SOCKET_H
char *user;
char *password;
+ bool tls_enabled;
+ bool tls_verify_peer;
+ bool tls_verify_hostname;
+ char *tls_cacert;
+ char *tls_client_cert;
+ char *tls_client_key;
+
char *exchange;
char *routing_key;
sfree(conf->vhost);
sfree(conf->user);
sfree(conf->password);
+ sfree(conf->tls_cacert);
+ sfree(conf->tls_client_cert);
+ sfree(conf->tls_client_key);
sfree(conf->exchange);
sfree(conf->exchange_type);
sfree(conf->queue);
#ifdef HAVE_AMQP_TCP_SOCKET
#define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us \
*/
- /* TODO: add support for SSL using amqp_ssl_socket_new
- * and related functions */
- socket = amqp_tcp_socket_new(conf->connection);
- if (!socket) {
- ERROR("amqp plugin: amqp_tcp_socket_new failed.");
- amqp_destroy_connection(conf->connection);
- conf->connection = NULL;
- return ENOMEM;
+
+ if (conf->tls_enabled) {
+ socket = amqp_ssl_socket_new(conf->connection);
+ if (!socket) {
+ ERROR("amqp plugin: amqp_ssl_socket_new failed.");
+ amqp_destroy_connection(conf->connection);
+ conf->connection = NULL;
+ return ENOMEM;
+ }
+
+#if AMQP_VERSION >= 0x00080000
+ amqp_ssl_socket_set_verify_peer(socket, conf->tls_verify_peer);
+ amqp_ssl_socket_set_verify_hostname(socket, conf->tls_verify_hostname);
+#endif
+
+ if (conf->tls_cacert) {
+ status = amqp_ssl_socket_set_cacert(socket, conf->tls_cacert);
+ if (status < 0) {
+ ERROR("amqp plugin: amqp_ssl_socket_set_cacert failed: %s",
+ amqp_error_string2(status));
+ amqp_destroy_connection(conf->connection);
+ conf->connection = NULL;
+ return status;
+ }
+ }
+ if (conf->tls_client_cert && conf->tls_client_key) {
+ status = amqp_ssl_socket_set_key(socket, conf->tls_client_cert,
+ conf->tls_client_key);
+ if (status < 0) {
+ ERROR("amqp plugin: amqp_ssl_socket_set_key failed: %s",
+ amqp_error_string2(status));
+ amqp_destroy_connection(conf->connection);
+ conf->connection = NULL;
+ return status;
+ }
+ }
+ } else {
+ socket = amqp_tcp_socket_new(conf->connection);
+ if (!socket) {
+ ERROR("amqp plugin: amqp_tcp_socket_new failed.");
+ amqp_destroy_connection(conf->connection);
+ conf->connection = NULL;
+ return ENOMEM;
+ }
}
status = amqp_socket_open(socket, CONF(conf, host), conf->port);
if (status < 0) {
- status *= -1;
- ERROR("amqp plugin: amqp_socket_open failed: %s", STRERROR(status));
+ ERROR("amqp plugin: amqp_socket_open failed: %s",
+ amqp_error_string2(status));
amqp_destroy_connection(conf->connection);
conf->connection = NULL;
return status;
conf->vhost = NULL;
conf->user = NULL;
conf->password = NULL;
+ conf->tls_enabled = false;
+ conf->tls_verify_peer = true;
+ conf->tls_verify_hostname = true;
+ conf->tls_cacert = NULL;
+ conf->tls_client_cert = NULL;
+ conf->tls_client_key = NULL;
conf->exchange = NULL;
conf->routing_key = NULL;
conf->connection_retry_delay = 0;
status = cf_util_get_string(child, &conf->user);
else if (strcasecmp("Password", child->key) == 0)
status = cf_util_get_string(child, &conf->password);
+ else if (strcasecmp("TLSEnabled", child->key) == 0)
+ status = cf_util_get_boolean(child, &conf->tls_enabled);
+ else if (strcasecmp("TLSVerifyPeer", child->key) == 0)
+ status = cf_util_get_boolean(child, &conf->tls_verify_peer);
+ else if (strcasecmp("TLSVerifyHostName", child->key) == 0)
+ status = cf_util_get_boolean(child, &conf->tls_verify_hostname);
+ else if (strcasecmp("TLSCACert", child->key) == 0)
+ status = cf_util_get_string(child, &conf->tls_cacert);
+ else if (strcasecmp("TLSClientCert", child->key) == 0)
+ status = cf_util_get_string(child, &conf->tls_client_cert);
+ else if (strcasecmp("TLSClientKey", child->key) == 0)
+ status = cf_util_get_string(child, &conf->tls_client_key);
else if (strcasecmp("Exchange", child->key) == 0)
status = cf_util_get_string(child, &conf->exchange);
else if (strcasecmp("ExchangeType", child->key) == 0)
"without the \"Exchange\" option. It will be ignored.");
}
+#if !defined(AMQP_VERSION) || AMQP_VERSION < 0x00040000
+ if (status == 0 && conf->tls_enabled) {
+ ERROR("amqp plugin: TLSEnabled is set but not supported. "
+ "rebuild collectd with rabbitmq-c >= 0.4");
+ status = 1;
+ }
+#endif
+#if !defined(AMQP_VERSION) || AMQP_VERSION < 0x00080000
+ if (status == 0 && (!conf->tls_verify_peer || !conf->tls_verify_hostname)) {
+ ERROR("amqp plugin: disabling TLSVerify* is not supported. "
+ "rebuild collectd with rabbitmq-c >= 0.8");
+ status = 1;
+ }
+#endif
+ if (status == 0 &&
+ (conf->tls_client_cert != NULL || conf->tls_client_key != NULL)) {
+ if (conf->tls_client_cert == NULL || conf->tls_client_key == NULL) {
+ ERROR("amqp plugin: only one of TLSClientCert/TLSClientKey is "
+ "configured. need both or neither.");
+ status = 1;
+ }
+ }
+
if (status != 0) {
camqp_config_free(conf);
return status;
# ConnectionRetryDelay 0
# Format "command"
# StoreRates false
+ # TLSEnabled false
+ # TLSVerifyPeer true
+ # TLSVerifyHostName true
+ # TLSCACert "/path/to/ca.pem"
+ # TLSClientCert "/path/to/client-cert.pem"
+ # TLSClientKey "/path/to/client-key.pem"
# GraphitePrefix "collectd."
# GraphiteEscapeChar "_"
# GraphiteSeparateInstances false
# QueueAutoDelete true
# RoutingKey "collectd.#"
# ConnectionRetryDelay 0
+ # TLSEnabled false
+ # TLSVerifyPeer true
+ # TLSVerifyHostName true
+ # TLSCACert "/path/to/ca.pem"
+ # TLSClientCert "/path/to/client-cert.pem"
+ # TLSClientKey "/path/to/client-key.pem"
</Subscribe>
</Plugin>
I<GraphiteEscapeChar>. Otherwise, if set to B<true>, the C<.> (dot) character
is preserved, i.e. passed through.
+=item B<TLSEnabled> B<true>|B<false>
+
+If set to B<true> then connect to the broker using a TLS connection.
+If set to B<false> (the default), then a plain text connection is used.
+
+Requires rabbitmq-c >= 0.4.
+
+=item B<TLSVerifyPeer> B<true>|B<false>
+
+If set to B<true> (the default) then the server certificate chain is verified.
+Setting this to B<false> will skip verification (insecure).
+
+Requires rabbitmq-c >= 0.8.
+
+=item B<TLSVerifyHostName> B<true>|B<false>
+
+If set to B<true> (the default) then the server host name is verified.
+Setting this to B<false> will skip verification (insecure).
+
+Requires rabbitmq-c >= 0.8.
+
+=item B<TLSCACert> I<Path>
+
+Path to the CA cert file in PEM format.
+
+=item B<TLSClientCert> I<Path>
+
+Path to the client certificate in PEM format.
+If this is set, then B<TLSClientKey> must be set as well.
+
+=item B<TLSClientKey> I<Path>
+
+Path to the client key in PEM format.
+If this is set, then B<TLSClientCert> must be set as well.
+
=back
=head2 Plugin C<amqp1>