mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-22 21:04:27 +01:00
Merge #3406
3406: Master Key: Implements errors and warnings from the specification r=irevoire a=dureuill <sub>Now in technicolor</sub> # Pull Request ## What does this PR do? - Uses `atty` and `termcolor` as dependency - Use these dependencies to print colored background for warning messages - Update messages to match https://github.com/meilisearch/specifications/pull/209 ## PR checklist Please check if your PR fulfills the following requirements: - [ ] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [ ] Have you read the contributing guidelines? - [ ] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: Louis Dureuil <louis@meilisearch.com>
This commit is contained in:
commit
217504fff3
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2285,6 +2285,7 @@ dependencies = [
|
|||||||
"assert-json-diff",
|
"assert-json-diff",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"atty",
|
||||||
"brotli",
|
"brotli",
|
||||||
"bstr 1.1.0",
|
"bstr 1.1.0",
|
||||||
"byte-unit",
|
"byte-unit",
|
||||||
@ -2344,6 +2345,7 @@ dependencies = [
|
|||||||
"tar",
|
"tar",
|
||||||
"temp-env",
|
"temp-env",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"termcolor",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -73,6 +73,8 @@ walkdir = "2.3.2"
|
|||||||
yaup = "0.2.0"
|
yaup = "0.2.0"
|
||||||
serde_urlencoded = "0.7.1"
|
serde_urlencoded = "0.7.1"
|
||||||
actix-utils = "3.0.1"
|
actix-utils = "3.0.1"
|
||||||
|
atty = "0.2.14"
|
||||||
|
termcolor = "1.1.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
actix-rt = "2.7.0"
|
actix-rt = "2.7.0"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ use index_scheduler::IndexScheduler;
|
|||||||
use meilisearch::analytics::Analytics;
|
use meilisearch::analytics::Analytics;
|
||||||
use meilisearch::{analytics, create_app, setup_meilisearch, Opt};
|
use meilisearch::{analytics, create_app, setup_meilisearch, Opt};
|
||||||
use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE};
|
use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE};
|
||||||
|
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||||
@ -32,24 +34,19 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
match (opt.env.as_ref(), &opt.master_key) {
|
match (opt.env.as_ref(), &opt.master_key) {
|
||||||
("production", Some(master_key)) if master_key.len() < MASTER_KEY_MIN_SIZE => {
|
("production", Some(master_key)) if master_key.len() < MASTER_KEY_MIN_SIZE => {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"In production mode, the master key must be of at least {MASTER_KEY_MIN_SIZE} bytes, but the provided key is only {} bytes long
|
"The master key must be at least {MASTER_KEY_MIN_SIZE} bytes in a production environment. The provided key is only {} bytes.
|
||||||
|
|
||||||
We generated a secure master key for you (you can safely copy this token):
|
{}",
|
||||||
|
|
||||||
>> export MEILI_MASTER_KEY={} <<",
|
|
||||||
master_key.len(),
|
master_key.len(),
|
||||||
generate_master_key(),
|
generated_master_key_message(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
("production", None) => {
|
("production", None) => {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"In production mode, you must provide a master key to secure your instance. It can be specified via the MEILI_MASTER_KEY environment variable or the --master-key launch option.
|
"You must provide a master key to secure your instance in a production environment. It can be specified via the MEILI_MASTER_KEY environment variable or the --master-key launch option.
|
||||||
|
|
||||||
We generated a secure master key for you (you can safely copy this token):
|
{}",
|
||||||
|
generated_master_key_message()
|
||||||
>> export MEILI_MASTER_KEY={} <<
|
|
||||||
",
|
|
||||||
generate_master_key()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// No error; continue
|
// No error; continue
|
||||||
@ -147,7 +144,7 @@ pub fn print_launch_resume(
|
|||||||
"
|
"
|
||||||
Thank you for using Meilisearch!
|
Thank you for using Meilisearch!
|
||||||
|
|
||||||
We collect anonymized analytics to improve our product and your experience. To learn more, including how to turn off analytics, visit our dedicated documentation page: https://docs.meilisearch.com/learn/what_is_meilisearch/telemetry.html
|
\nWe collect anonymized analytics to improve our product and your experience. To learn more, including how to turn off analytics, visit our dedicated documentation page: https://docs.meilisearch.com/learn/what_is_meilisearch/telemetry.html
|
||||||
|
|
||||||
Anonymous telemetry:\t\"Enabled\""
|
Anonymous telemetry:\t\"Enabled\""
|
||||||
);
|
);
|
||||||
@ -170,16 +167,10 @@ Anonymous telemetry:\t\"Enabled\""
|
|||||||
eprintln!("A master key has been set. Requests to Meilisearch won't be authorized unless you provide an authentication key.");
|
eprintln!("A master key has been set. Requests to Meilisearch won't be authorized unless you provide an authentication key.");
|
||||||
|
|
||||||
if master_key.len() < MASTER_KEY_MIN_SIZE {
|
if master_key.len() < MASTER_KEY_MIN_SIZE {
|
||||||
eprintln!();
|
print_master_key_too_short_warning()
|
||||||
log::warn!("The provided master key is too short (< {MASTER_KEY_MIN_SIZE} bytes)");
|
|
||||||
eprintln!("A master key of at least {MASTER_KEY_MIN_SIZE} bytes will be required when switching to the production environment.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
("development", None) => {
|
("development", None) => print_missing_master_key_warning(),
|
||||||
log::warn!("No master key found; The server will accept unidentified requests");
|
|
||||||
eprintln!("If you need some protection in development mode, please export a key:\n\nexport MEILI_MASTER_KEY={}", generate_master_key());
|
|
||||||
eprintln!("\nA master key of at least {MASTER_KEY_MIN_SIZE} bytes will be required when switching to the production environment.");
|
|
||||||
}
|
|
||||||
// unreachable because Opt::try_build above would have failed already if any other value had been produced
|
// unreachable because Opt::try_build above would have failed already if any other value had been produced
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -190,3 +181,67 @@ Anonymous telemetry:\t\"Enabled\""
|
|||||||
eprintln!("Contact:\t\thttps://docs.meilisearch.com/resources/contact.html");
|
eprintln!("Contact:\t\thttps://docs.meilisearch.com/resources/contact.html");
|
||||||
eprintln!();
|
eprintln!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const WARNING_BG_COLOR: Option<Color> = Some(Color::Ansi256(178));
|
||||||
|
const WARNING_FG_COLOR: Option<Color> = Some(Color::Ansi256(0));
|
||||||
|
|
||||||
|
fn print_master_key_too_short_warning() {
|
||||||
|
let choice =
|
||||||
|
if atty::is(atty::Stream::Stderr) { ColorChoice::Auto } else { ColorChoice::Never };
|
||||||
|
let mut stderr = StandardStream::stderr(choice);
|
||||||
|
stderr
|
||||||
|
.set_color(
|
||||||
|
ColorSpec::new().set_bg(WARNING_BG_COLOR).set_fg(WARNING_FG_COLOR).set_bold(true),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
writeln!(stderr, "\n").unwrap();
|
||||||
|
writeln!(
|
||||||
|
stderr,
|
||||||
|
" Meilisearch started with a master key considered unsafe for use in a production environment.
|
||||||
|
|
||||||
|
A master key of at least {MASTER_KEY_MIN_SIZE} bytes will be required when switching to a production environment."
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
stderr.reset().unwrap();
|
||||||
|
writeln!(stderr).unwrap();
|
||||||
|
|
||||||
|
eprintln!("\n{}", generated_master_key_message());
|
||||||
|
eprintln!(
|
||||||
|
"\nRestart Meilisearch with the argument above to use this new and secure master key."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_missing_master_key_warning() {
|
||||||
|
let choice =
|
||||||
|
if atty::is(atty::Stream::Stderr) { ColorChoice::Auto } else { ColorChoice::Never };
|
||||||
|
let mut stderr = StandardStream::stderr(choice);
|
||||||
|
stderr
|
||||||
|
.set_color(
|
||||||
|
ColorSpec::new().set_bg(WARNING_BG_COLOR).set_fg(WARNING_FG_COLOR).set_bold(true),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
writeln!(stderr, "\n").unwrap();
|
||||||
|
writeln!(
|
||||||
|
stderr,
|
||||||
|
" No master key was found. The server will accept unidentified requests.
|
||||||
|
|
||||||
|
A master key of at least {MASTER_KEY_MIN_SIZE} bytes will be required when switching to a production environment."
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
stderr.reset().unwrap();
|
||||||
|
writeln!(stderr).unwrap();
|
||||||
|
|
||||||
|
eprintln!("\n{}", generated_master_key_message());
|
||||||
|
eprintln!(
|
||||||
|
"\nRestart Meilisearch with the argument above to use this new and secure master key."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generated_master_key_message() -> String {
|
||||||
|
format!(
|
||||||
|
"We generated a new secure master key for you (you can safely use this token):
|
||||||
|
|
||||||
|
>> --master-key {} <<",
|
||||||
|
generate_master_key()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user