df_consul/
lib.rs

1pub mod catalog;
2mod kv;
3pub mod locking;
4mod with_index;
5
6use std::fs::File;
7use std::io::Read;
8
9use anyhow::{bail, Result};
10
11pub use with_index::WithIndex;
12
13/// Configuration parameters to talk to a Consul server
14pub struct Config {
15    /// HTTP address of the Consul server, with `http://` or `https://` prefix
16    pub addr: String,
17    /// CA certificate of the Consul CA, when using TLS
18    pub ca_cert: Option<String>,
19    /// Client certificate for client auth when using TLS
20    pub client_cert: Option<String>,
21    /// Client key for client auth when using TLS
22    pub client_key: Option<String>,
23    /// Skip verification of consul server TLS certificates
24    pub tls_skip_verify: bool,
25}
26
27/// Client used to talk to a Consul server.
28/// All calls to the key/value API are automatically prefixed with an arbitrary string
29/// that is constructed at client creation.
30#[derive(Clone)]
31pub struct Consul {
32    client: reqwest::Client,
33
34    url: String,
35    kv_prefix: String,
36}
37
38impl Consul {
39    pub fn new(config: Config, kv_prefix: &str) -> Result<Self> {
40        let client = match (&config.client_cert, &config.client_key) {
41            (Some(client_cert), Some(client_key)) => {
42                let mut client_cert_buf = vec![];
43                File::open(client_cert)?.read_to_end(&mut client_cert_buf)?;
44
45                let mut client_key_buf = vec![];
46                File::open(client_key)?.read_to_end(&mut client_key_buf)?;
47
48                let identity = reqwest::Identity::from_pem(
49                    &[&client_cert_buf[..], &client_key_buf[..]].concat()[..],
50                )?;
51
52                if config.tls_skip_verify {
53                    reqwest::Client::builder()
54                        .use_rustls_tls()
55                        .danger_accept_invalid_certs(true)
56                        .identity(identity)
57                        .build()?
58                } else if let Some(ca_cert) = &config.ca_cert {
59                    let mut ca_cert_buf = vec![];
60                    File::open(ca_cert)?.read_to_end(&mut ca_cert_buf)?;
61
62                    reqwest::Client::builder()
63                        .use_rustls_tls()
64                        .add_root_certificate(reqwest::Certificate::from_pem(&ca_cert_buf[..])?)
65                        .identity(identity)
66                        .build()?
67                } else {
68                    reqwest::Client::builder()
69                        .use_rustls_tls()
70                        .identity(identity)
71                        .build()?
72                }
73            }
74            (None, None) => reqwest::Client::new(),
75            _ => bail!("Incomplete Consul TLS configuration parameters"),
76        };
77
78        Ok(Self {
79            client,
80            url: config.addr.trim_end_matches('/').to_string(),
81            kv_prefix: kv_prefix.to_string(),
82        })
83    }
84}