mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-26 03:55:07 +08:00
securise the connecions between the leader and followers + forbid joining the cluster without the right master key
This commit is contained in:
parent
7ad14373e9
commit
38100d5c05
@ -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);
|
||||||
|
@ -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 I’m already running")
|
warn!("Received a join from dump msg but I’m 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");
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user