Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/riemann mtls #103

Merged
merged 3 commits into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions docs_src/references/exporter-riemann.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,67 @@ USAGE:

FLAGS:
-h, --help Prints help information
--mtls Connect to a Riemann server using mTLS. Parameters address, ca, cert and key must be defined.
-q, --qemu Instruct that scaphandre is running on an hypervisor
-V, --version Prints version information

OPTIONS:
-a, --address <address> Riemann ipv6 or ipv4 address [default: localhost]
-a, --address <address> Riemann ipv6 or ipv4 address. If mTLS is used then server fqdn must be
provided [default: localhost]
-d, --dispatch <dispatch_duration> Duration between metrics dispatch [default: 5]
-p, --port <port> Riemann TCP port number [default: 5555]

--ca <cafile> CA certificate file (.pem format)
--cert <certfile> Client certificate file (.pem format)
--key <keyfile> Client RSA key
```
With default options values, the metrics are sent to http://localhost:5555 every 5 seconds

Use -q or --qemu option if you are running scaphandre on a hypervisor. In that case a label with the vm name will be added to all `qemu-system*` processes.
Use `--mtls` option to connect to a Riemann server using mTLS. In such case, you must provide the following parameters:
* `--address` to specify the **fqdn** of the Riemann server.
* `--ca` to specify the CA that authenticate the Riemann server.
* `--cert` to specify the client certificate.
* `--key` to specify the **RSA** key to be used by the client certificate.

Use `-q` or `--qemu` option if you are running scaphandre on a hypervisor. In that case a label with the vm name will be added to all `qemu-system*` processes.
This will allow to easily create charts consumption for each vm and defined which one is the top contributor.

## Metrics exposed
*Troubleshooting note:* run Scaphandre using `-vv` parameter. If Scaphandre is stuck on the `Send data` log event, ensure you are connecting the Riemann server using a TLS port (5554 in the below example).
As a reference here is a Riemann configuration:
```
; -*- mode: clojure; -*-
; vim: filetype=clojure

(logging/init {:file "riemann.log"})

; Listen on the local interface over TCP (5555), UDP (5555), TLS/TCP (5554) and websockets
; (5556)
(let [host "0.0.0.0"]
(tcp-server {:host host})
(tcp-server {:host host
:port 5554
:tls? true
:key "/client.key.pkcs8"
:cert "/client.pem"
:ca-cert "/CA.pem"})
(udp-server {:host host})
(ws-server {:host host}))

; Expire old events from the index every 5 seconds.
(periodically-expire 5)

(let [index (index)]
; Inbound events will be passed to these streams:
(streams
(default :ttl 60
; Index all events immediately.
index

; Log expired events.
(expired
(fn [event] (info "expired" event))))))
```

## Metrics exposed
Typically the Riemann exporter is working in the same way as the prometheus exporter regarding metrics. Please look at details in [Prometheus exporter](exporter-prometheus.md) documentations.

There is only one exception about `process_power_consumption_microwatts` each process has a service name `process_power_consumption_microwatts_pid_exe`.
Expand Down
66 changes: 56 additions & 10 deletions src/exporters/riemann.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,25 @@ struct RiemannClient {
}

impl RiemannClient {
/// Instanciate the Riemann client.
fn new(address: &str, port: &str) -> RiemannClient {
let address = String::from(address);
let port = port.parse::<u16>().expect("Fail parsing port number");
let client = Client::connect(&(address, port)).expect("Fail to connect to Riemann server");
/// Instanciate the Riemann client either with mTLS or using raw TCP.
fn new(parameters: &ArgMatches) -> RiemannClient {
let address = String::from(parameters.value_of("address").unwrap());
let port = parameters
.value_of("port")
.unwrap()
.parse::<u16>()
.expect("Fail parsing port number");
let client: Client;
if parameters.is_present("mtls") {
let cafile = parameters.value_of("cafile").unwrap();
let certfile = parameters.value_of("certfile").unwrap();
let keyfile = parameters.value_of("keyfile").unwrap();
client = Client::connect_tls(&address, port, cafile, certfile, keyfile)
.expect("Fail to connect to Riemann server using mTLS");
} else {
client = Client::connect(&(address, port))
.expect("Fail to connect to Riemann server using raw TCP");
}
RiemannClient { client }
}

Expand Down Expand Up @@ -116,10 +130,7 @@ impl Exporter for RiemannExporter {

let hostname = get_hostname();

let mut rclient = RiemannClient::new(
parameters.value_of("address").unwrap(),
parameters.value_of("port").unwrap(),
);
let mut rclient = RiemannClient::new(&parameters);

info!(
"{}: Starting Riemann exporter",
Expand Down Expand Up @@ -215,7 +226,7 @@ impl Exporter for RiemannExporter {
let mut options = Vec::new();
let arg = Arg::with_name("address")
.default_value(DEFAULT_IP_ADDRESS)
.help("Riemann ipv6 or ipv4 address")
.help("Riemann ipv6 or ipv4 address. If mTLS is used then server fqdn must be provided")
.long("address")
.short("a")
.required(false)
Expand Down Expand Up @@ -248,6 +259,41 @@ impl Exporter for RiemannExporter {
.takes_value(false);
options.push(arg);

let arg = Arg::with_name("mtls")
.help("Connect to a Riemann server using mTLS. Parameters address, ca, cert and key must be defined.")
.long("mtls")
.required(false)
.takes_value(false)
.requires_all(&["address","cafile", "certfile", "keyfile"]);
options.push(arg);

let arg = Arg::with_name("cafile")
.help("CA certificate file (.pem format)")
.long("ca")
.required(false)
.takes_value(true)
.display_order(1000)
.requires("mtls");
options.push(arg);

let arg = Arg::with_name("certfile")
.help("Client certificate file (.pem format)")
.long("cert")
.required(false)
.takes_value(true)
.display_order(1001)
.requires("mtls");
options.push(arg);

let arg = Arg::with_name("keyfile")
.help("Client RSA key")
.long("key")
.required(false)
.takes_value(true)
.display_order(1001)
.requires("mtls");
options.push(arg);

options
}
}
Expand Down