2696: Add the new `metrics.get` and `metrics.all` actions rights r=Kerollmops a=Kerollmops

Follow the specification and add the new `metrics.get` and `metrics.all` actions, making the `/metrics` route only accessible with those rights.

Co-authored-by: Clément Renault <clement@meilisearch.com>
This commit is contained in:
bors[bot] 2022-08-24 15:08:53 +00:00 committed by GitHub
commit a1bb49c351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 69 additions and 81 deletions

View File

@ -6,59 +6,63 @@ use std::hash::Hash;
#[repr(u8)] #[repr(u8)]
pub enum Action { pub enum Action {
#[serde(rename = "*")] #[serde(rename = "*")]
All = actions::ALL, All = 0,
#[serde(rename = "search")] #[serde(rename = "search")]
Search = actions::SEARCH, Search,
#[serde(rename = "documents.*")] #[serde(rename = "documents.*")]
DocumentsAll = actions::DOCUMENTS_ALL, DocumentsAll,
#[serde(rename = "documents.add")] #[serde(rename = "documents.add")]
DocumentsAdd = actions::DOCUMENTS_ADD, DocumentsAdd,
#[serde(rename = "documents.get")] #[serde(rename = "documents.get")]
DocumentsGet = actions::DOCUMENTS_GET, DocumentsGet,
#[serde(rename = "documents.delete")] #[serde(rename = "documents.delete")]
DocumentsDelete = actions::DOCUMENTS_DELETE, DocumentsDelete,
#[serde(rename = "indexes.*")] #[serde(rename = "indexes.*")]
IndexesAll = actions::INDEXES_ALL, IndexesAll,
#[serde(rename = "indexes.create")] #[serde(rename = "indexes.create")]
IndexesAdd = actions::INDEXES_CREATE, IndexesAdd,
#[serde(rename = "indexes.get")] #[serde(rename = "indexes.get")]
IndexesGet = actions::INDEXES_GET, IndexesGet,
#[serde(rename = "indexes.update")] #[serde(rename = "indexes.update")]
IndexesUpdate = actions::INDEXES_UPDATE, IndexesUpdate,
#[serde(rename = "indexes.delete")] #[serde(rename = "indexes.delete")]
IndexesDelete = actions::INDEXES_DELETE, IndexesDelete,
#[serde(rename = "tasks.*")] #[serde(rename = "tasks.*")]
TasksAll = actions::TASKS_ALL, TasksAll,
#[serde(rename = "tasks.get")] #[serde(rename = "tasks.get")]
TasksGet = actions::TASKS_GET, TasksGet,
#[serde(rename = "settings.*")] #[serde(rename = "settings.*")]
SettingsAll = actions::SETTINGS_ALL, SettingsAll,
#[serde(rename = "settings.get")] #[serde(rename = "settings.get")]
SettingsGet = actions::SETTINGS_GET, SettingsGet,
#[serde(rename = "settings.update")] #[serde(rename = "settings.update")]
SettingsUpdate = actions::SETTINGS_UPDATE, SettingsUpdate,
#[serde(rename = "stats.*")] #[serde(rename = "stats.*")]
StatsAll = actions::STATS_ALL, StatsAll,
#[serde(rename = "stats.get")] #[serde(rename = "stats.get")]
StatsGet = actions::STATS_GET, StatsGet,
#[serde(rename = "metrics.*")]
MetricsAll,
#[serde(rename = "metrics.get")]
MetricsGet,
#[serde(rename = "dumps.*")] #[serde(rename = "dumps.*")]
DumpsAll = actions::DUMPS_ALL, DumpsAll,
#[serde(rename = "dumps.create")] #[serde(rename = "dumps.create")]
DumpsCreate = actions::DUMPS_CREATE, DumpsCreate,
#[serde(rename = "version")] #[serde(rename = "version")]
Version = actions::VERSION, Version,
#[serde(rename = "keys.create")] #[serde(rename = "keys.create")]
KeysAdd = actions::KEYS_CREATE, KeysAdd,
#[serde(rename = "keys.get")] #[serde(rename = "keys.get")]
KeysGet = actions::KEYS_GET, KeysGet,
#[serde(rename = "keys.update")] #[serde(rename = "keys.update")]
KeysUpdate = actions::KEYS_UPDATE, KeysUpdate,
#[serde(rename = "keys.delete")] #[serde(rename = "keys.delete")]
KeysDelete = actions::KEYS_DELETE, KeysDelete,
} }
impl Action { impl Action {
pub fn from_repr(repr: u8) -> Option<Self> { pub const fn from_repr(repr: u8) -> Option<Self> {
use actions::*; use actions::*;
match repr { match repr {
ALL => Some(Self::All), ALL => Some(Self::All),
@ -79,6 +83,8 @@ impl Action {
SETTINGS_UPDATE => Some(Self::SettingsUpdate), SETTINGS_UPDATE => Some(Self::SettingsUpdate),
STATS_ALL => Some(Self::StatsAll), STATS_ALL => Some(Self::StatsAll),
STATS_GET => Some(Self::StatsGet), STATS_GET => Some(Self::StatsGet),
METRICS_ALL => Some(Self::MetricsAll),
METRICS_GET => Some(Self::MetricsGet),
DUMPS_ALL => Some(Self::DumpsAll), DUMPS_ALL => Some(Self::DumpsAll),
DUMPS_CREATE => Some(Self::DumpsCreate), DUMPS_CREATE => Some(Self::DumpsCreate),
VERSION => Some(Self::Version), VERSION => Some(Self::Version),
@ -90,62 +96,39 @@ impl Action {
} }
} }
pub fn repr(&self) -> u8 { pub const fn repr(&self) -> u8 {
use actions::*; *self as u8
match self {
Self::All => ALL,
Self::Search => SEARCH,
Self::DocumentsAll => DOCUMENTS_ALL,
Self::DocumentsAdd => DOCUMENTS_ADD,
Self::DocumentsGet => DOCUMENTS_GET,
Self::DocumentsDelete => DOCUMENTS_DELETE,
Self::IndexesAll => INDEXES_ALL,
Self::IndexesAdd => INDEXES_CREATE,
Self::IndexesGet => INDEXES_GET,
Self::IndexesUpdate => INDEXES_UPDATE,
Self::IndexesDelete => INDEXES_DELETE,
Self::TasksAll => TASKS_ALL,
Self::TasksGet => TASKS_GET,
Self::SettingsAll => SETTINGS_ALL,
Self::SettingsGet => SETTINGS_GET,
Self::SettingsUpdate => SETTINGS_UPDATE,
Self::StatsAll => STATS_ALL,
Self::StatsGet => STATS_GET,
Self::DumpsAll => DUMPS_ALL,
Self::DumpsCreate => DUMPS_CREATE,
Self::Version => VERSION,
Self::KeysAdd => KEYS_CREATE,
Self::KeysGet => KEYS_GET,
Self::KeysUpdate => KEYS_UPDATE,
Self::KeysDelete => KEYS_DELETE,
}
} }
} }
pub mod actions { pub mod actions {
pub(crate) const ALL: u8 = 0; use super::Action::*;
pub const SEARCH: u8 = 1;
pub const DOCUMENTS_ALL: u8 = 2; pub(crate) const ALL: u8 = All.repr();
pub const DOCUMENTS_ADD: u8 = 3; pub const SEARCH: u8 = Search.repr();
pub const DOCUMENTS_GET: u8 = 4; pub const DOCUMENTS_ALL: u8 = DocumentsAll.repr();
pub const DOCUMENTS_DELETE: u8 = 5; pub const DOCUMENTS_ADD: u8 = DocumentsAdd.repr();
pub const INDEXES_ALL: u8 = 6; pub const DOCUMENTS_GET: u8 = DocumentsGet.repr();
pub const INDEXES_CREATE: u8 = 7; pub const DOCUMENTS_DELETE: u8 = DocumentsDelete.repr();
pub const INDEXES_GET: u8 = 8; pub const INDEXES_ALL: u8 = IndexesAll.repr();
pub const INDEXES_UPDATE: u8 = 9; pub const INDEXES_CREATE: u8 = IndexesAdd.repr();
pub const INDEXES_DELETE: u8 = 10; pub const INDEXES_GET: u8 = IndexesGet.repr();
pub const TASKS_ALL: u8 = 11; pub const INDEXES_UPDATE: u8 = IndexesUpdate.repr();
pub const TASKS_GET: u8 = 12; pub const INDEXES_DELETE: u8 = IndexesDelete.repr();
pub const SETTINGS_ALL: u8 = 13; pub const TASKS_ALL: u8 = TasksAll.repr();
pub const SETTINGS_GET: u8 = 14; pub const TASKS_GET: u8 = TasksGet.repr();
pub const SETTINGS_UPDATE: u8 = 15; pub const SETTINGS_ALL: u8 = SettingsAll.repr();
pub const STATS_ALL: u8 = 16; pub const SETTINGS_GET: u8 = SettingsGet.repr();
pub const STATS_GET: u8 = 17; pub const SETTINGS_UPDATE: u8 = SettingsUpdate.repr();
pub const DUMPS_ALL: u8 = 18; pub const STATS_ALL: u8 = StatsAll.repr();
pub const DUMPS_CREATE: u8 = 19; pub const STATS_GET: u8 = StatsGet.repr();
pub const VERSION: u8 = 20; pub const METRICS_ALL: u8 = MetricsAll.repr();
pub const KEYS_CREATE: u8 = 21; pub const METRICS_GET: u8 = MetricsGet.repr();
pub const KEYS_GET: u8 = 22; pub const DUMPS_ALL: u8 = DumpsAll.repr();
pub const KEYS_UPDATE: u8 = 23; pub const DUMPS_CREATE: u8 = DumpsCreate.repr();
pub const KEYS_DELETE: u8 = 24; pub const VERSION: u8 = Version.repr();
pub const KEYS_CREATE: u8 = KeysAdd.repr();
pub const KEYS_GET: u8 = KeysGet.repr();
pub const KEYS_UPDATE: u8 = KeysUpdate.repr();
pub const KEYS_DELETE: u8 = KeysDelete.repr();
} }

View File

@ -126,6 +126,9 @@ impl HeedAuthStore {
Action::StatsAll => { Action::StatsAll => {
actions.insert(Action::StatsGet); actions.insert(Action::StatsGet);
} }
Action::MetricsAll => {
actions.insert(Action::MetricsGet);
}
other => { other => {
actions.insert(*other); actions.insert(*other);
} }

View File

@ -282,7 +282,7 @@ pub async fn get_health() -> Result<HttpResponse, ResponseError> {
} }
pub async fn get_metrics( pub async fn get_metrics(
meilisearch: GuardedData<ActionPolicy<{ actions::STATS_GET }>, MeiliSearch>, meilisearch: GuardedData<ActionPolicy<{ actions::METRICS_GET }>, MeiliSearch>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
let search_rules = &meilisearch.filters().search_rules; let search_rules = &meilisearch.filters().search_rules;
let response = meilisearch.get_all_stats(search_rules).await?; let response = meilisearch.get_all_stats(search_rules).await?;

View File

@ -45,6 +45,7 @@ pub static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'
("PUT", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "settings.*", "*"}, ("PUT", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "settings.*", "*"},
("GET", "/indexes/products/stats") => hashset!{"stats.get", "stats.*", "*"}, ("GET", "/indexes/products/stats") => hashset!{"stats.get", "stats.*", "*"},
("GET", "/stats") => hashset!{"stats.get", "stats.*", "*"}, ("GET", "/stats") => hashset!{"stats.get", "stats.*", "*"},
("GET", "/metrics") => hashset!{"metrics.get", "metrics.*", "*"},
("POST", "/dumps") => hashset!{"dumps.create", "dumps.*", "*"}, ("POST", "/dumps") => hashset!{"dumps.create", "dumps.*", "*"},
("GET", "/version") => hashset!{"version", "*"}, ("GET", "/version") => hashset!{"version", "*"},
("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"}, ("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"},

View File

@ -162,6 +162,7 @@ pub fn default_settings(dir: impl AsRef<Path>) -> Opt {
max_indexing_memory: MaxMemory::unlimited(), max_indexing_memory: MaxMemory::unlimited(),
..Parser::parse_from(None as Option<&str>) ..Parser::parse_from(None as Option<&str>)
}, },
enable_metrics_route: true,
..Parser::parse_from(None as Option<&str>) ..Parser::parse_from(None as Option<&str>)
} }
} }