mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-04 16:09:05 +00:00
feat: introduce rbac for logs patterns, logs insights and cache refresh (#10662)
This commit is contained in:
@@ -31,7 +31,10 @@ use o2_openfga::{
|
||||
add_tuple_for_pipeline, get_add_user_to_org_tuples, get_org_creation_tuples,
|
||||
get_ownership_all_org_tuple, get_ownership_tuple, update_tuples,
|
||||
},
|
||||
meta::mapping::{NON_OWNING_ORG, OFGA_MODELS, OFGAModel},
|
||||
meta::mapping::{
|
||||
LOGS_INSIGHTS_KEY, LOGS_PATTERN_KEY, NON_OWNING_ORG, OFGA_MODELS, OFGAModel,
|
||||
RESULT_LOGS_CACHE_KEY,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -62,6 +65,7 @@ pub async fn init() -> Result<(), anyhow::Error> {
|
||||
let mut need_ai_chat_permissions_migration = false;
|
||||
let mut need_re_pattern_permission_migration = false;
|
||||
let mut need_license_permission_migration = false;
|
||||
let mut need_logs_pattern_insights_migration = false;
|
||||
|
||||
let existing_meta: Option<o2_openfga::meta::mapping::OFGAModel> =
|
||||
match db::ofga::get_ofga_model().await {
|
||||
@@ -236,6 +240,7 @@ pub async fn init() -> Result<(), anyhow::Error> {
|
||||
let v0_0_18 = version_compare::Version::from("0.0.18").unwrap();
|
||||
let v0_0_20 = version_compare::Version::from("0.0.20").unwrap();
|
||||
let v0_0_21 = version_compare::Version::from("0.0.21").unwrap();
|
||||
let v0_0_25 = version_compare::Version::from("0.0.25").unwrap();
|
||||
|
||||
if meta_version > v0_0_5 && existing_model_version < v0_0_6 {
|
||||
need_pipeline_migration = true;
|
||||
@@ -269,6 +274,13 @@ pub async fn init() -> Result<(), anyhow::Error> {
|
||||
log::info!("[OFGA:Local] license permissions migration needed");
|
||||
need_license_permission_migration = true;
|
||||
}
|
||||
|
||||
if existing_model_version < v0_0_25 {
|
||||
log::info!(
|
||||
"[OFGA:Local] logs patterns, insights, cache delete permissions migration needed"
|
||||
);
|
||||
need_logs_pattern_insights_migration = true;
|
||||
}
|
||||
}
|
||||
|
||||
let mut tuples = vec![];
|
||||
@@ -368,6 +380,11 @@ pub async fn init() -> Result<(), anyhow::Error> {
|
||||
if need_license_permission_migration {
|
||||
get_ownership_all_org_tuple(org_name, "license", &mut tuples);
|
||||
}
|
||||
if need_logs_pattern_insights_migration {
|
||||
get_ownership_all_org_tuple(org_name, LOGS_INSIGHTS_KEY, &mut tuples);
|
||||
get_ownership_all_org_tuple(org_name, LOGS_PATTERN_KEY, &mut tuples);
|
||||
get_ownership_all_org_tuple(org_name, RESULT_LOGS_CACHE_KEY, &mut tuples);
|
||||
}
|
||||
}
|
||||
if need_alert_folders_migration {
|
||||
match migrations::migrate_alert_folders().await {
|
||||
|
||||
@@ -1042,6 +1042,7 @@ where
|
||||
// service_streams APIs are org-level, not stream-specific
|
||||
|| path.contains("/service_streams/_analytics")
|
||||
|| path.contains("/service_streams/_correlate")
|
||||
|| (url_len == 5 && path.ends_with("/patterns/extract"))
|
||||
{
|
||||
return Ok(AuthExtractor {
|
||||
auth: auth_str.to_owned(),
|
||||
|
||||
@@ -953,6 +953,7 @@ pub enum SearchEventType {
|
||||
DerivedStream,
|
||||
SearchJob,
|
||||
Download,
|
||||
Insights,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for SearchEventType {
|
||||
@@ -994,6 +995,7 @@ impl std::fmt::Display for SearchEventType {
|
||||
Self::DerivedStream => write!(f, "derived_stream"),
|
||||
Self::SearchJob => write!(f, "search_job"),
|
||||
Self::Download => write!(f, "download"),
|
||||
Self::Insights => write!(f, "insights"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1012,8 +1014,9 @@ impl TryFrom<&str> for SearchEventType {
|
||||
"derived_stream" | "derivedstream" => Ok(Self::DerivedStream),
|
||||
"search_job" | "searchjob" => Ok(Self::SearchJob),
|
||||
"download" => Ok(Self::Download),
|
||||
"insights" => Ok(Self::Insights),
|
||||
_ => Err(format!(
|
||||
"invalid SearchEventType `{s}`, expected one of `ui`, `dashboards`, `reports`, `alerts`, `values`, `other`, `rum`, `derived_stream`, `search_job`"
|
||||
"invalid SearchEventType `{s}`, expected one of `ui`, `dashboards`, `reports`, `alerts`, `values`, `other`, `rum`, `derived_stream`, `search_job`, `insights`"
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,6 +384,7 @@ pub enum SearchEventType {
|
||||
DerivedStream,
|
||||
SearchJob,
|
||||
Download,
|
||||
Insights,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize, ToSchema, Hash)]
|
||||
@@ -568,6 +569,7 @@ impl From<meta_search::SearchEventType> for SearchEventType {
|
||||
meta_search::SearchEventType::DerivedStream => Self::DerivedStream,
|
||||
meta_search::SearchEventType::SearchJob => Self::SearchJob,
|
||||
meta_search::SearchEventType::Download => Self::Download,
|
||||
meta_search::SearchEventType::Insights => Self::Insights,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -748,6 +750,7 @@ impl From<SearchEventType> for meta_search::SearchEventType {
|
||||
SearchEventType::DerivedStream => Self::DerivedStream,
|
||||
SearchEventType::SearchJob => Self::SearchJob,
|
||||
SearchEventType::Download => Self::Download,
|
||||
SearchEventType::Insights => Self::Insights,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@ use svix_ksuid::Ksuid;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use {
|
||||
crate::common::utils::auth::check_permissions,
|
||||
crate::handler::http::request::search::utils::check_stream_permissions,
|
||||
crate::handler::http::request::search::utils::{
|
||||
StreamPermissionResourceType, check_stream_permissions,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -748,6 +750,7 @@ pub async fn generate_sql(
|
||||
&org_id,
|
||||
&user_email.user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
@@ -981,7 +981,7 @@ pub async fn get_group_details(Path(_path): Path<(String, String)>) -> Response
|
||||
pub async fn get_resources(Path(_org_id): Path<String>) -> Response {
|
||||
#[cfg(feature = "cloud")]
|
||||
use o2_openfga::meta::mapping::NON_CLOUD_RESOURCE_KEYS;
|
||||
use o2_openfga::meta::mapping::Resource;
|
||||
use o2_openfga::meta::mapping::{Resource, remove_resource_keys};
|
||||
let resources = o2_openfga::meta::mapping::OFGA_MODELS
|
||||
.values()
|
||||
.collect::<Vec<&Resource>>();
|
||||
@@ -990,6 +990,12 @@ pub async fn get_resources(Path(_org_id): Path<String>) -> Response {
|
||||
.into_iter()
|
||||
.filter(|r| !NON_CLOUD_RESOURCE_KEYS.contains(&r.key))
|
||||
.collect::<Vec<&Resource>>();
|
||||
|
||||
let remove_keys = remove_resource_keys();
|
||||
let resources = resources
|
||||
.into_iter()
|
||||
.filter(|r| !remove_keys.contains(&r.key))
|
||||
.collect::<Vec<&Resource>>();
|
||||
Json(resources).into_response()
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ use axum::{
|
||||
use o2_enterprise::enterprise::common::config::get_config as get_o2_config;
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::handler::http::request::search::utils::check_stream_permissions;
|
||||
use crate::handler::http::request::search::utils::{
|
||||
StreamPermissionResourceType, check_stream_permissions,
|
||||
};
|
||||
use crate::{
|
||||
common::{meta::http::HttpResponse as MetaHttpResponse, utils::auth::UserEmail},
|
||||
handler::http::extractors::Headers,
|
||||
@@ -159,6 +161,7 @@ pub async fn extract_patterns(
|
||||
&org_id,
|
||||
&user_id,
|
||||
&config::meta::stream::StreamType::Logs,
|
||||
StreamPermissionResourceType::PatternExtract,
|
||||
)
|
||||
.await
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ use hashbrown::HashMap;
|
||||
use http::HeaderMap;
|
||||
use tracing::{Instrument, Span};
|
||||
#[cfg(feature = "enterprise")]
|
||||
use utils::check_stream_permissions;
|
||||
use utils::{StreamPermissionResourceType, check_stream_permissions};
|
||||
|
||||
#[cfg(feature = "cloud")]
|
||||
use crate::service::organization::is_org_in_free_trial_period;
|
||||
@@ -387,8 +387,14 @@ pub async fn search(
|
||||
|
||||
// Check permissions on stream
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Some(res) =
|
||||
check_stream_permissions(&stream_name, &org_id, user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
&stream_name,
|
||||
&org_id,
|
||||
user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@@ -1884,8 +1890,14 @@ pub async fn result_schema(
|
||||
|
||||
// Check permissions on stream
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Some(res) =
|
||||
check_stream_permissions(&stream_name, &org_id, user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
&stream_name,
|
||||
&org_id,
|
||||
user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ use serde_json;
|
||||
use tracing::{Instrument, Span};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::handler::http::request::search::utils::check_stream_permissions;
|
||||
use crate::handler::http::request::search::utils::{
|
||||
StreamPermissionResourceType, check_stream_permissions,
|
||||
};
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::service::search::sql::visitor::cipher_key::get_cipher_key_names;
|
||||
use crate::{
|
||||
@@ -189,7 +191,14 @@ pub async fn get_search_profile(
|
||||
|
||||
// Check permissions on stream
|
||||
#[cfg(feature = "enterprise")]
|
||||
if let Some(res) = check_stream_permissions(&stream_name, org_id, &user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
&stream_name,
|
||||
org_id,
|
||||
&user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ use config::meta::search::Request;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use {
|
||||
crate::handler::http::request::search::{
|
||||
query_manager::cancel_query_inner, utils::check_stream_permissions,
|
||||
query_manager::cancel_query_inner,
|
||||
utils::{StreamPermissionResourceType, check_stream_permissions},
|
||||
},
|
||||
crate::service::search_jobs::{get_result, merge_response},
|
||||
crate::{
|
||||
@@ -181,8 +182,14 @@ pub async fn submit_job(
|
||||
|
||||
// Check permissions on stream
|
||||
for stream_name in stream_names.iter() {
|
||||
if let Some(res) =
|
||||
check_stream_permissions(stream_name, &org_id, &user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
stream_name,
|
||||
&org_id,
|
||||
&user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
return res;
|
||||
}
|
||||
@@ -714,8 +721,14 @@ async fn check_permissions(job: &JobModel, org_id: &str, user_id: &str) -> Optio
|
||||
let stream_type = StreamType::from(job.stream_type.as_str());
|
||||
let stream_names: Vec<String> = json::from_str(&job.stream_names).unwrap();
|
||||
for stream_name in stream_names.iter() {
|
||||
if let Some(res) =
|
||||
check_stream_permissions(stream_name, org_id, user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
stream_name,
|
||||
org_id,
|
||||
user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
@@ -45,8 +45,11 @@ use tracing::Span;
|
||||
use crate::common::utils::http::get_extract_patterns_from_request;
|
||||
#[cfg(feature = "enterprise")]
|
||||
use crate::{
|
||||
common::meta::search::AuditContext, common::utils::auth::check_permissions,
|
||||
handler::http::request::search::utils::check_stream_permissions,
|
||||
common::meta::search::AuditContext,
|
||||
common::utils::auth::check_permissions,
|
||||
handler::http::request::search::utils::{
|
||||
StreamPermissionResourceType, check_stream_permissions,
|
||||
},
|
||||
service::self_reporting::audit,
|
||||
};
|
||||
use crate::{
|
||||
@@ -364,16 +367,28 @@ pub async fn search_http2_stream(
|
||||
}
|
||||
}
|
||||
|
||||
req.clear_cache = get_clear_cache_from_request(&query);
|
||||
|
||||
// Check if user has edit permissions when clear_cache is requested
|
||||
#[cfg(feature = "enterprise")]
|
||||
if get_clear_cache_from_request(&query) {
|
||||
if req.clear_cache {
|
||||
use o2_openfga::meta::mapping::{RESULT_LOGS_CACHE_KEY, is_cache_rbac_enabled};
|
||||
|
||||
// We only check DELETE cache rbac for logs stream type
|
||||
let (permission_type, method) =
|
||||
if stream_type.eq(&StreamType::Logs) && is_cache_rbac_enabled() {
|
||||
// check if cache rbac is enabled
|
||||
(RESULT_LOGS_CACHE_KEY, "DELETE")
|
||||
} else {
|
||||
(stream_type.as_str(), "PUT")
|
||||
};
|
||||
for stream_name in stream_names.iter() {
|
||||
if !check_permissions(
|
||||
stream_name,
|
||||
&org_id,
|
||||
&user_id,
|
||||
stream_type.as_str(),
|
||||
"PUT",
|
||||
permission_type,
|
||||
method,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
@@ -403,7 +418,6 @@ pub async fn search_http2_stream(
|
||||
}
|
||||
|
||||
// Set use_cache from query params
|
||||
req.clear_cache = get_clear_cache_from_request(&query);
|
||||
req.use_cache = get_use_cache_from_request(&query) && !req.clear_cache;
|
||||
|
||||
// Set search type if not set
|
||||
@@ -451,11 +465,25 @@ pub async fn search_http2_stream(
|
||||
.and_then(|event_type| get_search_event_context_from_request(event_type, &query));
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
// Check permissions for each stream
|
||||
let permission_resource_type =
|
||||
if req.search_type == Some(config::meta::search::SearchEventType::Insights) {
|
||||
StreamPermissionResourceType::Insights
|
||||
} else {
|
||||
StreamPermissionResourceType::Search
|
||||
};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
for stream_name in stream_names.iter() {
|
||||
if let Some(res) =
|
||||
check_stream_permissions(stream_name, &org_id, &user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
stream_name,
|
||||
&org_id,
|
||||
&user_id,
|
||||
&stream_type,
|
||||
permission_resource_type,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// Add audit before closing
|
||||
#[cfg(feature = "enterprise")]
|
||||
@@ -843,8 +871,14 @@ pub async fn values_http2_stream(
|
||||
// Check permissions for each stream
|
||||
#[cfg(feature = "enterprise")]
|
||||
for stream_name in stream_names.iter() {
|
||||
if let Some(res) =
|
||||
check_stream_permissions(stream_name, &org_id, &user_id, &stream_type).await
|
||||
if let Some(res) = check_stream_permissions(
|
||||
stream_name,
|
||||
&org_id,
|
||||
&user_id,
|
||||
&stream_type,
|
||||
StreamPermissionResourceType::Search,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// Add audit before closing
|
||||
#[cfg(feature = "enterprise")]
|
||||
|
||||
@@ -33,11 +33,22 @@ use {
|
||||
service::users::get_user,
|
||||
},
|
||||
config::meta::user::User,
|
||||
o2_openfga::meta::mapping::OFGA_MODELS,
|
||||
o2_openfga::{
|
||||
config::get_config,
|
||||
meta::mapping::{LOGS_INSIGHTS_KEY, LOGS_PATTERN_KEY, OFGA_MODELS},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::service::search::sql::Sql;
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum StreamPermissionResourceType {
|
||||
Search,
|
||||
PatternExtract,
|
||||
Insights,
|
||||
}
|
||||
|
||||
// Check permissions on stream
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn check_stream_permissions(
|
||||
@@ -45,23 +56,43 @@ pub async fn check_stream_permissions(
|
||||
org_id: &str,
|
||||
user_id: &str,
|
||||
stream_type: &StreamType,
|
||||
permission_resource_type: StreamPermissionResourceType,
|
||||
) -> Option<Response> {
|
||||
if !is_root_user(user_id) {
|
||||
let user: User = get_user(Some(org_id), user_id).await.unwrap();
|
||||
let stream_type_str = stream_type.as_str();
|
||||
|
||||
let config = get_config();
|
||||
|
||||
let mut o2_model_type = "";
|
||||
// If rbac for logs pattern and logs insights is enabled, use those resources for permission
|
||||
// check
|
||||
match permission_resource_type {
|
||||
StreamPermissionResourceType::PatternExtract => {
|
||||
if config.logs_pattern_rbac_enabled {
|
||||
o2_model_type = LOGS_PATTERN_KEY;
|
||||
}
|
||||
}
|
||||
StreamPermissionResourceType::Insights => {
|
||||
if config.logs_pattern_rbac_enabled {
|
||||
o2_model_type = LOGS_INSIGHTS_KEY;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
if o2_model_type.is_empty() {
|
||||
o2_model_type = OFGA_MODELS
|
||||
.get(stream_type_str)
|
||||
.map_or(stream_type_str, |model| model.key);
|
||||
}
|
||||
|
||||
if !crate::handler::http::auth::validator::check_permissions(
|
||||
user_id,
|
||||
AuthExtractor {
|
||||
auth: "".to_string(),
|
||||
method: "GET".to_string(),
|
||||
o2_type: format!(
|
||||
"{}:{}",
|
||||
OFGA_MODELS
|
||||
.get(stream_type_str)
|
||||
.map_or(stream_type_str, |model| model.key),
|
||||
stream_name
|
||||
),
|
||||
o2_type: format!("{o2_model_type}:{stream_name}"),
|
||||
org_id: org_id.to_string(),
|
||||
bypass_check: false,
|
||||
parent_id: "".to_string(),
|
||||
|
||||
@@ -441,6 +441,7 @@ pub enum QuerySearchEventType {
|
||||
DerivedStream,
|
||||
SearchJob,
|
||||
Download,
|
||||
Insights,
|
||||
}
|
||||
|
||||
impl QuerySearchEventType {
|
||||
@@ -454,6 +455,7 @@ impl QuerySearchEventType {
|
||||
const DERIVED_STREAM: i16 = 7;
|
||||
const SEARCH_JOB: i16 = 8;
|
||||
const DOWNLOAD: i16 = 9;
|
||||
const INSIGHTS: i16 = 10;
|
||||
}
|
||||
|
||||
// Implementation for translating from intermediate representation into DB
|
||||
@@ -471,6 +473,7 @@ impl From<QuerySearchEventType> for i16 {
|
||||
QuerySearchEventType::DerivedStream => QuerySearchEventType::DERIVED_STREAM,
|
||||
QuerySearchEventType::SearchJob => QuerySearchEventType::SEARCH_JOB,
|
||||
QuerySearchEventType::Download => QuerySearchEventType::DOWNLOAD,
|
||||
QuerySearchEventType::Insights => QuerySearchEventType::INSIGHTS,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,6 +495,7 @@ impl TryFrom<i16> for QuerySearchEventType {
|
||||
Self::DERIVED_STREAM => Ok(QuerySearchEventType::DerivedStream),
|
||||
Self::SEARCH_JOB => Ok(QuerySearchEventType::SearchJob),
|
||||
Self::DOWNLOAD => Ok(QuerySearchEventType::Download),
|
||||
Self::INSIGHTS => Ok(QuerySearchEventType::Insights),
|
||||
_ => Err(FromI16Error {
|
||||
value,
|
||||
ty: "SearchEventType".to_owned(),
|
||||
@@ -513,6 +517,7 @@ impl From<MetaSearchEventType> for QuerySearchEventType {
|
||||
MetaSearchEventType::DerivedStream => Self::DerivedStream,
|
||||
MetaSearchEventType::SearchJob => Self::SearchJob,
|
||||
MetaSearchEventType::Download => Self::Download,
|
||||
MetaSearchEventType::Insights => Self::Insights,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,6 +535,7 @@ impl From<QuerySearchEventType> for MetaSearchEventType {
|
||||
QuerySearchEventType::DerivedStream => Self::DerivedStream,
|
||||
QuerySearchEventType::SearchJob => Self::SearchJob,
|
||||
QuerySearchEventType::Download => Self::Download,
|
||||
QuerySearchEventType::Insights => Self::Insights,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,6 +635,21 @@ const modifyResourcePermissions = (resource: Resource) => {
|
||||
resource.permission.AllowDelete.show = false;
|
||||
resource.permission.AllowPost.show = false;
|
||||
}
|
||||
if (
|
||||
resource.resourceName === "logs_pattern" ||
|
||||
resource.resourceName === "logs_insights"
|
||||
) {
|
||||
resource.permission.AllowList.show = false;
|
||||
resource.permission.AllowDelete.show = false;
|
||||
resource.permission.AllowPost.show = false;
|
||||
resource.permission.AllowPut.show = false;
|
||||
}
|
||||
if (resource.resourceName === "logs_cache") {
|
||||
resource.permission.AllowList.show = false;
|
||||
resource.permission.AllowGet.show = false;
|
||||
resource.permission.AllowPost.show = false;
|
||||
resource.permission.AllowPut.show = false;
|
||||
}
|
||||
};
|
||||
|
||||
const getResourcePermissions = () => {
|
||||
@@ -1388,6 +1403,9 @@ const getResourceEntities = (resource: Resource | Entity) => {
|
||||
cipher_keys: getCipherKeys,
|
||||
afolder: getAlertFolders,
|
||||
re_patterns: getRePatterns,
|
||||
logs_pattern: getLogsPatternStreams,
|
||||
logs_insights: getLogsInsightsStreams,
|
||||
logs_cache: getLogsCacheStreams,
|
||||
};
|
||||
|
||||
return new Promise(async (resolve, reject) => {
|
||||
@@ -1639,6 +1657,36 @@ const getLogs = async (resource: Resource | Entity) => {
|
||||
});
|
||||
};
|
||||
|
||||
const getLogsPatternStreams = async (resource: Resource | Entity) => {
|
||||
const logs: any = await getStreams("logs", false);
|
||||
|
||||
updateResourceEntities("logs_pattern", ["name"], logs.list);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
resolve(true);
|
||||
});
|
||||
};
|
||||
|
||||
const getLogsInsightsStreams = async (resource: Resource | Entity) => {
|
||||
const logs: any = await getStreams("logs", false);
|
||||
|
||||
updateResourceEntities("logs_insights", ["name"], logs.list);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
resolve(true);
|
||||
});
|
||||
};
|
||||
|
||||
const getLogsCacheStreams = async (resource: Resource | Entity) => {
|
||||
const logs: any = await getStreams("logs", false);
|
||||
|
||||
updateResourceEntities("logs_cache", ["name"], logs.list);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
resolve(true);
|
||||
});
|
||||
};
|
||||
|
||||
const getIndexStreams = async (resource: Resource | Entity) => {
|
||||
const indices: any = await getStreams("index", false);
|
||||
|
||||
@@ -1963,6 +2011,25 @@ const updateResourceEntities = (
|
||||
top_level: !!resource.childs.find((child) => child.name === childName)
|
||||
?.top_level,
|
||||
});
|
||||
// Hide non-applicable permissions for logs_pattern and logs_insights entities
|
||||
if (
|
||||
resourceName === "logs_pattern" ||
|
||||
resourceName === "logs_insights"
|
||||
) {
|
||||
const entity = resource.entities[resource.entities.length - 1];
|
||||
entity.permission.AllowList.show = false;
|
||||
entity.permission.AllowDelete.show = false;
|
||||
entity.permission.AllowPost.show = false;
|
||||
entity.permission.AllowPut.show = false;
|
||||
}
|
||||
// Hide non-applicable permissions for logs_cache entities (only All and Delete)
|
||||
if (resourceName === "logs_cache") {
|
||||
const entity = resource.entities[resource.entities.length - 1];
|
||||
entity.permission.AllowList.show = false;
|
||||
entity.permission.AllowGet.show = false;
|
||||
entity.permission.AllowPost.show = false;
|
||||
entity.permission.AllowPut.show = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
:viewOnly="false"
|
||||
:allowAlertCreation="false"
|
||||
:simplifiedPanelView="true"
|
||||
searchType="dashboards"
|
||||
:searchType="props.streamType === 'logs' ? 'insights' : 'dashboards'"
|
||||
@variablesManagerReady="onVariablesManagerReady"
|
||||
@onDeletePanel="handlePanelDelete"
|
||||
class="tw:p-[0.4rem] trace-analysis-dashboards"
|
||||
|
||||
Reference in New Issue
Block a user