securise the connecions between the leader and followers + forbid joining the cluster without the right master key

This commit is contained in:
Tamo 2023-03-23 12:28:36 +01:00
parent 7ad14373e9
commit 38100d5c05
3 changed files with 53 additions and 12 deletions

View File

@ -6,7 +6,7 @@ use std::time::Duration;
use bus::{Bus, BusReader}; use bus::{Bus, BusReader};
use crossbeam::channel::{unbounded, Receiver, Sender}; use crossbeam::channel::{unbounded, Receiver, Sender};
use ductile::{ChannelReceiver, ChannelSender, ChannelServer}; use ductile::{ChannelReceiver, ChannelSender, ChannelServer};
use log::info; use log::{info, warn};
use meilisearch_types::keys::Key; use meilisearch_types::keys::Key;
use meilisearch_types::tasks::Task; use meilisearch_types::tasks::Task;
use synchronoise::SignalEvent; use synchronoise::SignalEvent;
@ -31,7 +31,10 @@ pub struct Leader {
} }
impl Leader { impl Leader {
pub fn new(listen_on: impl ToSocketAddrs + Send + 'static) -> Leader { pub fn new(
listen_on: impl ToSocketAddrs + Send + 'static,
master_key: Option<String>,
) -> Leader {
let new_followers = Arc::new(AtomicUsize::new(0)); let new_followers = Arc::new(AtomicUsize::new(0));
let active_followers = Arc::new(AtomicUsize::new(1)); let active_followers = Arc::new(AtomicUsize::new(1));
let wake_up = Arc::new(SignalEvent::auto(true)); let wake_up = Arc::new(SignalEvent::auto(true));
@ -43,7 +46,15 @@ impl Leader {
let af = active_followers.clone(); let af = active_followers.clone();
let wu = wake_up.clone(); let wu = wake_up.clone();
std::thread::spawn(move || { std::thread::spawn(move || {
Self::listener(listen_on, nf, af, wu, process_batch_receiver, task_finished_sender) Self::listener(
listen_on,
master_key,
nf,
af,
wu,
process_batch_receiver,
task_finished_sender,
)
}); });
Leader { Leader {
@ -68,14 +79,29 @@ impl Leader {
/// to each new followers /// to each new followers
fn listener( fn listener(
listen_on: impl ToSocketAddrs, listen_on: impl ToSocketAddrs,
master_key: Option<String>,
new_followers: Arc<AtomicUsize>, new_followers: Arc<AtomicUsize>,
active_followers: Arc<AtomicUsize>, active_followers: Arc<AtomicUsize>,
wake_up: Arc<SignalEvent>, wake_up: Arc<SignalEvent>,
broadcast_to_follower: Receiver<LeaderMsg>, broadcast_to_follower: Receiver<LeaderMsg>,
task_finished: Sender<u32>, task_finished: Sender<u32>,
) { ) {
let listener: ChannelServer<LeaderMsg, FollowerMsg> = let listener: ChannelServer<LeaderMsg, FollowerMsg> = if let Some(ref master_key) =
ChannelServer::bind(listen_on).unwrap(); master_key
{
let mut enc = [0; 32];
let master_key = master_key.as_bytes();
if master_key.len() < 32 {
warn!("Master key is not secure, use a longer master key (at least 32 bytes long)");
}
enc.iter_mut().zip(master_key).for_each(|(enc, mk)| *enc = *mk);
info!("Listening with encryption enabled");
ChannelServer::bind_with_enc(listen_on, enc).unwrap()
} else {
ChannelServer::bind(listen_on).unwrap()
};
info!("Ready to the receive connections");
// We're going to broadcast all the batches to all our follower // We're going to broadcast all the batches to all our follower
let bus: Bus<LeaderMsg> = Bus::new(10); let bus: Bus<LeaderMsg> = Bus::new(10);

View File

@ -4,8 +4,8 @@ use std::sync::{Arc, RwLock};
use batch::Batch; use batch::Batch;
use crossbeam::channel::{unbounded, Receiver, Sender}; use crossbeam::channel::{unbounded, Receiver, Sender};
use ductile::{connect_channel, ChannelReceiver, ChannelSender}; use ductile::{connect_channel, connect_channel_with_enc, ChannelReceiver, ChannelSender};
use log::info; use log::{info, warn};
use meilisearch_types::keys::Key; use meilisearch_types::keys::Key;
use meilisearch_types::tasks::{KindWithContent, Task}; use meilisearch_types::tasks::{KindWithContent, Task};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -109,8 +109,19 @@ pub struct Follower {
} }
impl Follower { impl Follower {
pub fn join(leader: impl ToSocketAddrs) -> (Follower, Vec<u8>) { pub fn join(leader: impl ToSocketAddrs, master_key: Option<String>) -> (Follower, Vec<u8>) {
let (sender, receiver) = connect_channel(leader).unwrap(); let (sender, receiver) = if let Some(master_key) = master_key {
let mut enc = [0; 32];
let master_key = master_key.as_bytes();
if master_key.len() < 32 {
warn!("Master key is not secure, use a longer master key (at least 32 bytes long)");
}
enc.iter_mut().zip(master_key).for_each(|(enc, mk)| *enc = *mk);
info!("Connecting with encryption enabled");
connect_channel_with_enc(leader, &enc).unwrap()
} else {
connect_channel(leader).unwrap()
};
info!("Connection to the leader established"); info!("Connection to the leader established");
@ -160,7 +171,7 @@ impl Follower {
loop { loop {
match receiver.recv().expect("Lost connection to the leader") { match receiver.recv().expect("Lost connection to the leader") {
LeaderMsg::JoinFromDump(_) => { LeaderMsg::JoinFromDump(_) => {
panic!("Received a join from dump msg but Im already running") warn!("Received a join from dump msg but Im already running : ignoring the message")
} }
LeaderMsg::StartBatch { id, batch } => { LeaderMsg::StartBatch { id, batch } => {
info!("Starting to process a new batch"); info!("Starting to process a new batch");

View File

@ -197,7 +197,11 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc<IndexScheduler>, Auth
info!("Starting as a leader"); info!("Starting as a leader");
let mut addr = opt.http_addr.to_socket_addrs().unwrap().next().unwrap(); let mut addr = opt.http_addr.to_socket_addrs().unwrap().next().unwrap();
addr.set_port(6666); addr.set_port(6666);
open_or_create_database(opt, empty_db, Some(Cluster::Leader(Leader::new(addr))))? open_or_create_database(
opt,
empty_db,
Some(Cluster::Leader(Leader::new(addr, opt.master_key.clone()))),
)?
} }
"follower" => { "follower" => {
info!("Starting as a follower"); info!("Starting as a follower");
@ -215,7 +219,7 @@ pub fn setup_meilisearch(opt: &Opt) -> anyhow::Result<(Arc<IndexScheduler>, Auth
.unwrap(); .unwrap();
addr.set_port(6666); addr.set_port(6666);
let (follower, dump) = Follower::join(addr); let (follower, dump) = Follower::join(addr, opt.master_key.clone());
let mut dump_file = tempfile::NamedTempFile::new().unwrap(); let mut dump_file = tempfile::NamedTempFile::new().unwrap();
dump_file.write_all(&dump).unwrap(); dump_file.write_all(&dump).unwrap();