Fix the tasks with the new patterns

This commit is contained in:
Kerollmops 2023-02-01 18:21:45 +01:00
parent d563ed8a39
commit a36b1dbd70
No known key found for this signature in database
GPG Key ID: 92ADA4E935E71FA4
8 changed files with 41 additions and 26 deletions

View File

@ -181,10 +181,8 @@ impl CompatV5ToV6 {
.indexes .indexes
.into_iter() .into_iter()
.map(|index| match index { .map(|index| match index {
v5::StarOr::Star => v6::StarOr::Star, v5::StarOr::Star => v6::IndexUidPattern::all(),
v5::StarOr::Other(uid) => { v5::StarOr::Other(uid) => v6::IndexUidPattern::new_unchecked(uid.as_str()),
v6::StarOr::Other(v6::IndexUidPattern::new_unchecked(uid.as_str()))
}
}) })
.collect(), .collect(),
expires_at: key.expires_at, expires_at: key.expires_at,

View File

@ -34,7 +34,6 @@ pub type PaginationSettings = meilisearch_types::settings::PaginationSettings;
// everything related to the api keys // everything related to the api keys
pub type Action = meilisearch_types::keys::Action; pub type Action = meilisearch_types::keys::Action;
pub type StarOr<T> = meilisearch_types::star_or::StarOr<T>;
pub type IndexUidPattern = meilisearch_types::index_uid_pattern::IndexUidPattern; pub type IndexUidPattern = meilisearch_types::index_uid_pattern::IndexUidPattern;
// everything related to the errors // everything related to the errors

View File

@ -43,6 +43,7 @@ use file_store::FileStore;
use meilisearch_types::error::ResponseError; use meilisearch_types::error::ResponseError;
use meilisearch_types::heed::types::{OwnedType, SerdeBincode, SerdeJson, Str}; use meilisearch_types::heed::types::{OwnedType, SerdeBincode, SerdeJson, Str};
use meilisearch_types::heed::{self, Database, Env, RoTxn}; use meilisearch_types::heed::{self, Database, Env, RoTxn};
use meilisearch_types::index_uid_pattern::IndexUidPattern;
use meilisearch_types::milli; use meilisearch_types::milli;
use meilisearch_types::milli::documents::DocumentsBatchBuilder; use meilisearch_types::milli::documents::DocumentsBatchBuilder;
use meilisearch_types::milli::update::IndexerConfig; use meilisearch_types::milli::update::IndexerConfig;
@ -617,7 +618,7 @@ impl IndexScheduler {
&self, &self,
rtxn: &RoTxn, rtxn: &RoTxn,
query: &Query, query: &Query,
authorized_indexes: &Option<Vec<String>>, authorized_indexes: &Option<Vec<IndexUidPattern>>,
) -> Result<RoaringBitmap> { ) -> Result<RoaringBitmap> {
let mut tasks = self.get_task_ids(rtxn, query)?; let mut tasks = self.get_task_ids(rtxn, query)?;
@ -635,7 +636,7 @@ impl IndexScheduler {
let all_indexes_iter = self.index_tasks.iter(rtxn)?; let all_indexes_iter = self.index_tasks.iter(rtxn)?;
for result in all_indexes_iter { for result in all_indexes_iter {
let (index, index_tasks) = result?; let (index, index_tasks) = result?;
if !authorized_indexes.contains(&index.to_owned()) { if !authorized_indexes.iter().any(|p| p.matches_str(index)) {
tasks -= index_tasks; tasks -= index_tasks;
} }
} }
@ -655,7 +656,7 @@ impl IndexScheduler {
pub fn get_tasks_from_authorized_indexes( pub fn get_tasks_from_authorized_indexes(
&self, &self,
query: Query, query: Query,
authorized_indexes: Option<Vec<String>>, authorized_indexes: Option<Vec<IndexUidPattern>>,
) -> Result<Vec<Task>> { ) -> Result<Vec<Task>> {
let rtxn = self.env.read_txn()?; let rtxn = self.env.read_txn()?;
@ -2503,7 +2504,11 @@ mod tests {
let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() }; let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() };
let tasks = index_scheduler let tasks = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &Some(vec!["doggo".to_owned()])) .get_task_ids_from_authorized_indexes(
&rtxn,
&query,
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
)
.unwrap(); .unwrap();
// we have asked for only the tasks associated with catto, but are only authorized to retrieve the tasks // we have asked for only the tasks associated with catto, but are only authorized to retrieve the tasks
// associated with doggo -> empty result // associated with doggo -> empty result
@ -2511,7 +2516,11 @@ mod tests {
let query = Query::default(); let query = Query::default();
let tasks = index_scheduler let tasks = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &Some(vec!["doggo".to_owned()])) .get_task_ids_from_authorized_indexes(
&rtxn,
&query,
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
)
.unwrap(); .unwrap();
// we asked for all the tasks, but we are only authorized to retrieve the doggo tasks // we asked for all the tasks, but we are only authorized to retrieve the doggo tasks
// -> only the index creation of doggo should be returned // -> only the index creation of doggo should be returned
@ -2522,7 +2531,10 @@ mod tests {
.get_task_ids_from_authorized_indexes( .get_task_ids_from_authorized_indexes(
&rtxn, &rtxn,
&query, &query,
&Some(vec!["catto".to_owned(), "doggo".to_owned()]), &Some(vec![
IndexUidPattern::new_unchecked("catto"),
IndexUidPattern::new_unchecked("doggo"),
]),
) )
.unwrap(); .unwrap();
// we asked for all the tasks, but we are only authorized to retrieve the doggo and catto tasks // we asked for all the tasks, but we are only authorized to retrieve the doggo and catto tasks
@ -2570,7 +2582,11 @@ mod tests {
let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() }; let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() };
let tasks = index_scheduler let tasks = index_scheduler
.get_task_ids_from_authorized_indexes(&rtxn, &query, &Some(vec!["doggo".to_string()])) .get_task_ids_from_authorized_indexes(
&rtxn,
&query,
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
)
.unwrap(); .unwrap();
// Return only 1 because the user is not authorized to see task 2 // Return only 1 because the user is not authorized to see task 2
snapshot!(snapshot_bitmap(&tasks), @"[1,]"); snapshot!(snapshot_bitmap(&tasks), @"[1,]");

View File

@ -3,7 +3,6 @@ pub mod error;
mod store; mod store;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::ops::Deref;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
@ -11,7 +10,6 @@ use error::{AuthControllerError, Result};
use maplit::hashset; use maplit::hashset;
use meilisearch_types::index_uid_pattern::IndexUidPattern; use meilisearch_types::index_uid_pattern::IndexUidPattern;
use meilisearch_types::keys::{Action, CreateApiKey, Key, PatchApiKey}; use meilisearch_types::keys::{Action, CreateApiKey, Key, PatchApiKey};
use meilisearch_types::star_or::StarOr;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub use store::open_auth_store_env; pub use store::open_auth_store_env;
use store::{generate_key_as_hexa, HeedAuthStore}; use store::{generate_key_as_hexa, HeedAuthStore};
@ -192,7 +190,7 @@ impl SearchRules {
pub fn get_index_search_rules(&self, index: &str) -> Option<IndexSearchRules> { pub fn get_index_search_rules(&self, index: &str) -> Option<IndexSearchRules> {
match self { match self {
Self::Set(set) => { Self::Set(_) => {
if self.is_index_authorized(index) { if self.is_index_authorized(index) {
Some(IndexSearchRules::default()) Some(IndexSearchRules::default())
} else { } else {

View File

@ -14,7 +14,6 @@ use meilisearch_types::keys::KeyId;
use meilisearch_types::milli; use meilisearch_types::milli;
use meilisearch_types::milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson}; use meilisearch_types::milli::heed::types::{ByteSlice, DecodeIgnore, SerdeJson};
use meilisearch_types::milli::heed::{Database, Env, EnvOpenOptions, RwTxn}; use meilisearch_types::milli::heed::{Database, Env, EnvOpenOptions, RwTxn};
use meilisearch_types::star_or::StarOr;
use sha2::Sha256; use sha2::Sha256;
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::fmt::Hyphenated; use uuid::fmt::Hyphenated;
@ -126,7 +125,7 @@ impl HeedAuthStore {
} }
} }
let no_index_restriction = key.indexes.contains(&StarOr::Star); let no_index_restriction = key.indexes.iter().any(|p| p.matches_all());
for action in actions { for action in actions {
if no_index_restriction { if no_index_restriction {
// If there is no index restriction we put None. // If there is no index restriction we put None.

View File

@ -26,6 +26,11 @@ impl IndexUidPattern {
IndexUidPattern::from_str("*").unwrap() IndexUidPattern::from_str("*").unwrap()
} }
/// Returns `true` if it matches any index.
pub fn matches_all(&self) -> bool {
self.0 == "*"
}
/// Returns `true` if the pattern matches a specific index name. /// Returns `true` if the pattern matches a specific index name.
pub fn is_exact(&self) -> bool { pub fn is_exact(&self) -> bool {
!self.0.ends_with('*') !self.0.ends_with('*')

View File

@ -13,7 +13,6 @@ use uuid::Uuid;
use crate::error::deserr_codes::*; use crate::error::deserr_codes::*;
use crate::error::{unwrap_any, Code, DeserrError, ErrorCode, TakeErrorMessage}; use crate::error::{unwrap_any, Code, DeserrError, ErrorCode, TakeErrorMessage};
use crate::index_uid_pattern::{IndexUidPattern, IndexUidPatternFormatError}; use crate::index_uid_pattern::{IndexUidPattern, IndexUidPatternFormatError};
use crate::star_or::StarOr;
pub type KeyId = Uuid; pub type KeyId = Uuid;

View File

@ -199,6 +199,9 @@ pub mod policies {
token: &str, token: &str,
index: Option<&str>, index: Option<&str>,
) -> Option<AuthFilter> { ) -> Option<AuthFilter> {
// Tenant token will always define an index.
let index = index?;
// Only search action can be accessed by a tenant token. // Only search action can be accessed by a tenant token.
if A != actions::SEARCH { if A != actions::SEARCH {
return None; return None;
@ -206,7 +209,7 @@ pub mod policies {
let uid = extract_key_id(token)?; let uid = extract_key_id(token)?;
// check if parent key is authorized to do the action. // check if parent key is authorized to do the action.
if auth.is_key_authorized(uid, Action::Search, index).ok()? { if auth.is_key_authorized(uid, Action::Search, Some(index)).ok()? {
// Check if tenant token is valid. // Check if tenant token is valid.
let key = auth.generate_key(uid)?; let key = auth.generate_key(uid)?;
let data = decode::<Claims>( let data = decode::<Claims>(
@ -217,11 +220,9 @@ pub mod policies {
.ok()?; .ok()?;
// Check index access if an index restriction is provided. // Check index access if an index restriction is provided.
if let Some(index) = index {
if !data.claims.search_rules.is_index_authorized(index) { if !data.claims.search_rules.is_index_authorized(index) {
return None; return None;
} }
}
// Check if token is expired. // Check if token is expired.
if let Some(exp) = data.claims.exp { if let Some(exp) = data.claims.exp {
@ -230,10 +231,10 @@ pub mod policies {
} }
} }
match auth.get_key_filters(uid, Some(data.claims.search_rules)) { return match auth.get_key_filters(uid, Some(data.claims.search_rules)) {
Ok(auth) if auth.search_rules.is_index_authorized() => Some(auth), Ok(auth) if auth.search_rules.is_index_authorized(index) => Some(auth),
_ => None, _ => None,
} };
} }
None None