mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-09 16:02:44 +00:00
implement transparent mode
This commit is contained in:
@@ -13,8 +13,7 @@ use mungos::{
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
state::{db_client, State},
|
||||
config::core_config, helpers::query::get_resource_ids_for_non_admin, state::{db_client, State}
|
||||
};
|
||||
|
||||
const NUM_ALERTS_PER_PAGE: u64 = 100;
|
||||
@@ -26,7 +25,7 @@ impl Resolve<ListAlerts, User> for State {
|
||||
user: User,
|
||||
) -> anyhow::Result<ListAlertsResponse> {
|
||||
let mut query = query.unwrap_or_default();
|
||||
if !user.admin {
|
||||
if !user.admin && !core_config().transparent_mode {
|
||||
let server_ids = get_resource_ids_for_non_admin(
|
||||
&user.id,
|
||||
ResourceTargetVariant::Server,
|
||||
|
||||
@@ -14,9 +14,7 @@ use mungos::mongodb::bson::{doc, oid::ObjectId};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
resource,
|
||||
state::{db_client, State},
|
||||
config::core_config, helpers::query::get_resource_ids_for_non_admin, resource, state::{db_client, State}
|
||||
};
|
||||
|
||||
impl Resolve<GetAlerter, User> for State {
|
||||
@@ -50,7 +48,7 @@ impl Resolve<GetAlertersSummary, User> for State {
|
||||
GetAlertersSummary {}: GetAlertersSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetAlertersSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
let query = if user.admin || core_config().transparent_mode {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
str::FromStr,
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
@@ -12,23 +11,19 @@ use monitor_client::{
|
||||
entities::{
|
||||
build::{Build, BuildActionState, BuildListItem, BuildState},
|
||||
permission::PermissionLevel,
|
||||
update::{ResourceTargetVariant, UpdateStatus},
|
||||
update::UpdateStatus,
|
||||
user::User,
|
||||
Operation,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
find::find_collect,
|
||||
mongodb::{
|
||||
bson::{doc, oid::ObjectId},
|
||||
options::FindOptions,
|
||||
},
|
||||
mongodb::{bson::doc, options::FindOptions},
|
||||
};
|
||||
use resolver_api::{Resolve, ResolveToString};
|
||||
|
||||
use crate::{
|
||||
config::core_config,
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
resource,
|
||||
state::{action_states, build_state_cache, db_client, State},
|
||||
};
|
||||
@@ -86,31 +81,18 @@ impl Resolve<GetBuildsSummary, User> for State {
|
||||
GetBuildsSummary {}: GetBuildsSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetBuildsSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
&user.id,
|
||||
ResourceTargetVariant::Build,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flat_map(|id| ObjectId::from_str(&id))
|
||||
.collect::<Vec<_>>();
|
||||
let query = doc! {
|
||||
"_id": { "$in": ids }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
let builds = resource::list_full_for_user::<Build>(
|
||||
Default::default(),
|
||||
&user,
|
||||
)
|
||||
.await
|
||||
.context("failed to get all builds")?;
|
||||
|
||||
let builds = find_collect(&db_client().await.builds, query, None)
|
||||
.await
|
||||
.context("failed to find all build documents")?;
|
||||
let mut res = GetBuildsSummaryResponse::default();
|
||||
|
||||
let cache = build_state_cache();
|
||||
let action_states = action_states();
|
||||
|
||||
|
||||
for build in builds {
|
||||
res.total += 1;
|
||||
|
||||
@@ -241,9 +223,7 @@ impl Resolve<GetBuildVersions, User> for State {
|
||||
let versions = find_collect(
|
||||
&db_client().await.updates,
|
||||
filter,
|
||||
FindOptions::builder()
|
||||
.sort(doc! { "_id": -1 })
|
||||
.build(),
|
||||
FindOptions::builder().sort(doc! { "_id": -1 }).build(),
|
||||
)
|
||||
.await
|
||||
.context("failed to pull versions from mongo")?
|
||||
|
||||
@@ -51,7 +51,7 @@ impl Resolve<GetBuildersSummary, User> for State {
|
||||
GetBuildersSummary {}: GetBuildersSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetBuildersSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
let query = if user.admin || core_config().transparent_mode {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{cmp, collections::HashSet, str::FromStr};
|
||||
use std::{cmp, collections::HashSet};
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
use monitor_client::{
|
||||
@@ -10,23 +10,17 @@ use monitor_client::{
|
||||
},
|
||||
permission::PermissionLevel,
|
||||
server::Server,
|
||||
update::{Log, ResourceTargetVariant},
|
||||
update::Log,
|
||||
user::User,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
find::find_collect,
|
||||
mongodb::bson::{doc, oid::ObjectId},
|
||||
};
|
||||
use periphery_client::api;
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::{
|
||||
periphery_client, query::get_resource_ids_for_non_admin,
|
||||
},
|
||||
helpers::periphery_client,
|
||||
resource,
|
||||
state::{action_states, db_client, deployment_status_cache, State},
|
||||
state::{action_states, deployment_status_cache, State},
|
||||
};
|
||||
|
||||
impl Resolve<GetDeployment, User> for State {
|
||||
@@ -200,27 +194,12 @@ impl Resolve<GetDeploymentsSummary, User> for State {
|
||||
GetDeploymentsSummary {}: GetDeploymentsSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetDeploymentsSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
&user.id,
|
||||
ResourceTargetVariant::Deployment,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flat_map(|id| ObjectId::from_str(&id))
|
||||
.collect::<Vec<_>>();
|
||||
let query = doc! {
|
||||
"_id": { "$in": ids }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
|
||||
let deployments =
|
||||
find_collect(&db_client().await.deployments, query, None)
|
||||
.await
|
||||
.context("failed to find all deployment documents")?;
|
||||
let deployments = resource::list_full_for_user::<Deployment>(
|
||||
Default::default(),
|
||||
&user,
|
||||
)
|
||||
.await
|
||||
.context("failed to get deployments from db")?;
|
||||
let mut res = GetDeploymentsSummaryResponse::default();
|
||||
let status_cache = deployment_status_cache();
|
||||
for deployment in deployments {
|
||||
|
||||
@@ -211,6 +211,7 @@ impl Resolve<GetCoreInfo, User> for State {
|
||||
.github_webhook_base_url
|
||||
.clone()
|
||||
.unwrap_or_else(|| config.host.clone()),
|
||||
transparent_mode: config.transparent_mode,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Context;
|
||||
use monitor_client::{
|
||||
api::read::{
|
||||
@@ -11,20 +9,14 @@ use monitor_client::{
|
||||
entities::{
|
||||
permission::PermissionLevel,
|
||||
procedure::{Procedure, ProcedureState},
|
||||
update::ResourceTargetVariant,
|
||||
user::User,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
find::find_collect,
|
||||
mongodb::bson::{doc, oid::ObjectId},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
resource,
|
||||
state::{action_states, db_client, procedure_state_cache, State},
|
||||
state::{action_states, procedure_state_cache, State},
|
||||
};
|
||||
|
||||
impl Resolve<GetProcedure, User> for State {
|
||||
@@ -58,27 +50,12 @@ impl Resolve<GetProceduresSummary, User> for State {
|
||||
GetProceduresSummary {}: GetProceduresSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetProceduresSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
&user.id,
|
||||
ResourceTargetVariant::Procedure,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flat_map(|id| ObjectId::from_str(&id))
|
||||
.collect::<Vec<_>>();
|
||||
let query = doc! {
|
||||
"_id": { "$in": ids }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
|
||||
let procedures =
|
||||
find_collect(&db_client().await.procedures, query, None)
|
||||
.await
|
||||
.context("failed to find all procedure documents")?;
|
||||
let procedures = resource::list_full_for_user::<Procedure>(
|
||||
Default::default(),
|
||||
&user,
|
||||
)
|
||||
.await
|
||||
.context("failed to get procedures from db")?;
|
||||
|
||||
let mut res = GetProceduresSummaryResponse::default();
|
||||
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Context;
|
||||
use monitor_client::{
|
||||
api::read::*,
|
||||
entities::{
|
||||
permission::PermissionLevel,
|
||||
repo::{Repo, RepoActionState, RepoListItem, RepoState},
|
||||
update::ResourceTargetVariant,
|
||||
user::User,
|
||||
},
|
||||
};
|
||||
use mungos::{
|
||||
find::find_collect,
|
||||
mongodb::bson::{doc, oid::ObjectId},
|
||||
};
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
resource,
|
||||
state::{action_states, db_client, repo_state_cache, State},
|
||||
state::{action_states, repo_state_cache, State},
|
||||
};
|
||||
|
||||
impl Resolve<GetRepo, User> for State {
|
||||
@@ -75,26 +67,11 @@ impl Resolve<GetReposSummary, User> for State {
|
||||
GetReposSummary {}: GetReposSummary,
|
||||
user: User,
|
||||
) -> anyhow::Result<GetReposSummaryResponse> {
|
||||
let query = if user.admin {
|
||||
None
|
||||
} else {
|
||||
let ids = get_resource_ids_for_non_admin(
|
||||
&user.id,
|
||||
ResourceTargetVariant::Alerter,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.flat_map(|id| ObjectId::from_str(&id))
|
||||
.collect::<Vec<_>>();
|
||||
let query = doc! {
|
||||
"_id": { "$in": ids }
|
||||
};
|
||||
Some(query)
|
||||
};
|
||||
let repos =
|
||||
resource::list_full_for_user::<Repo>(Default::default(), &user)
|
||||
.await
|
||||
.context("failed to get repos from db")?;
|
||||
|
||||
let repos = find_collect(&db_client().await.repos, query, None)
|
||||
.await
|
||||
.context("failed to find all repo documents")?;
|
||||
let mut res = GetReposSummaryResponse::default();
|
||||
|
||||
let cache = repo_state_cache();
|
||||
|
||||
@@ -68,10 +68,10 @@ impl Resolve<GetServerTemplatesSummary, User> for State {
|
||||
};
|
||||
let total = db_client()
|
||||
.await
|
||||
.builders
|
||||
.server_templates
|
||||
.count_documents(query, None)
|
||||
.await
|
||||
.context("failed to count all builder documents")?;
|
||||
.context("failed to count all server template documents")?;
|
||||
let res = GetServerTemplatesSummaryResponse {
|
||||
total: total as u32,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ use mungos::{
|
||||
use resolver_api::Resolve;
|
||||
|
||||
use crate::{
|
||||
config::core_config,
|
||||
helpers::query::get_resource_ids_for_non_admin,
|
||||
resource,
|
||||
state::{db_client, State},
|
||||
@@ -40,7 +41,7 @@ impl Resolve<ListUpdates, User> for State {
|
||||
ListUpdates { query, page }: ListUpdates,
|
||||
user: User,
|
||||
) -> anyhow::Result<ListUpdatesResponse> {
|
||||
let query = if user.admin {
|
||||
let query = if user.admin || core_config().transparent_mode {
|
||||
query
|
||||
} else {
|
||||
let server_ids = get_resource_ids_for_non_admin(
|
||||
@@ -163,7 +164,7 @@ impl Resolve<GetUpdate, User> for State {
|
||||
.await
|
||||
.context("failed to query to db")?
|
||||
.context("no update exists with given id")?;
|
||||
if user.admin {
|
||||
if user.admin || core_config().transparent_mode {
|
||||
return Ok(update);
|
||||
}
|
||||
match &update.target {
|
||||
|
||||
@@ -77,6 +77,10 @@ pub fn core_config() -> &'static CoreConfig {
|
||||
.monitor_logging_opentelemetry_service_name
|
||||
.unwrap_or(config.logging.opentelemetry_service_name);
|
||||
|
||||
config.transparent_mode = env
|
||||
.monitor_transparent_mode
|
||||
.unwrap_or(config.transparent_mode);
|
||||
|
||||
config.local_auth =
|
||||
env.monitor_local_auth.unwrap_or(config.local_auth);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use mungos::{
|
||||
mongodb::bson::{doc, oid::ObjectId, Document},
|
||||
};
|
||||
|
||||
use crate::{resource, state::db_client};
|
||||
use crate::{config::core_config, resource, state::db_client};
|
||||
|
||||
#[instrument(level = "debug")]
|
||||
pub async fn get_user(user_id: &str) -> anyhow::Result<User> {
|
||||
@@ -150,6 +150,11 @@ pub async fn get_user_permission_on_resource(
|
||||
resource_variant: ResourceTargetVariant,
|
||||
resource_id: &str,
|
||||
) -> anyhow::Result<PermissionLevel> {
|
||||
let lowest_permission = if core_config().transparent_mode {
|
||||
PermissionLevel::Read
|
||||
} else {
|
||||
PermissionLevel::None
|
||||
};
|
||||
let permission = find_collect(
|
||||
&db_client().await.permissions,
|
||||
doc! {
|
||||
@@ -163,7 +168,7 @@ pub async fn get_user_permission_on_resource(
|
||||
.context("failed to query db for permissions")?
|
||||
.into_iter()
|
||||
// get the max permission user has between personal / any user groups
|
||||
.fold(PermissionLevel::None, |level, permission| {
|
||||
.fold(lowest_permission, |level, permission| {
|
||||
if permission.level > level {
|
||||
permission.level
|
||||
} else {
|
||||
|
||||
@@ -28,6 +28,7 @@ use serde::{de::DeserializeOwned, Serialize};
|
||||
use serror::serialize_error_pretty;
|
||||
|
||||
use crate::{
|
||||
config::core_config,
|
||||
helpers::{
|
||||
create_permission,
|
||||
query::{
|
||||
@@ -191,7 +192,10 @@ pub async fn get_check_permissions<T: MonitorResource>(
|
||||
permission_level: PermissionLevel,
|
||||
) -> anyhow::Result<Resource<T::Config, T::Info>> {
|
||||
let resource = get::<T>(id_or_name).await?;
|
||||
if user.admin {
|
||||
if user.admin
|
||||
|| (permission_level <= PermissionLevel::Read
|
||||
&& core_config().transparent_mode)
|
||||
{
|
||||
return Ok(resource);
|
||||
}
|
||||
let permissions = get_user_permission_on_resource(
|
||||
@@ -249,7 +253,7 @@ async fn list_full_for_user_using_document<T: MonitorResource>(
|
||||
mut filters: Document,
|
||||
user: &User,
|
||||
) -> anyhow::Result<Vec<Resource<T::Config, T::Info>>> {
|
||||
if !user.admin {
|
||||
if !user.admin && !core_config().transparent_mode {
|
||||
let ids =
|
||||
get_resource_ids_for_non_admin(&user.id, T::resource_type())
|
||||
.await?
|
||||
|
||||
@@ -85,4 +85,6 @@ pub struct GetCoreInfoResponse {
|
||||
pub monitoring_interval: Timelength,
|
||||
/// The github webhook base url to use with github webhooks.
|
||||
pub github_webhook_base_url: String,
|
||||
/// Whether transparent mode is enabled, which gives all users read access to all resources.
|
||||
pub transparent_mode: bool
|
||||
}
|
||||
|
||||
@@ -67,6 +67,9 @@ pub struct Env {
|
||||
/// Override `logging.opentelemetry_service_name`
|
||||
pub monitor_logging_opentelemetry_service_name: Option<String>,
|
||||
|
||||
/// Override `transparent_mode`
|
||||
pub monitor_transparent_mode: Option<bool>,
|
||||
|
||||
/// Override `local_auth`
|
||||
pub monitor_local_auth: Option<bool>,
|
||||
|
||||
@@ -185,6 +188,9 @@ fn default_config_path() -> String {
|
||||
/// ## if empty, the "docker organization" config option will not be shown.
|
||||
/// ## default: empty
|
||||
/// # docker_organizations = ["your_docker_org1", "your_docker_org_2"]
|
||||
///
|
||||
/// ## allows all users to have read access on all resources
|
||||
/// # transparent_mode = true
|
||||
///
|
||||
/// ## allow or deny user login with username / password
|
||||
/// ## default: false
|
||||
@@ -296,6 +302,10 @@ pub struct CoreConfig {
|
||||
#[serde(default)]
|
||||
pub logging: LogConfig,
|
||||
|
||||
/// Enable transparent mode, which gives all (enabled) users read access to all resources.
|
||||
#[serde(default)]
|
||||
pub transparent_mode: bool,
|
||||
|
||||
/// enable login with local auth
|
||||
#[serde(default)]
|
||||
pub local_auth: bool,
|
||||
|
||||
@@ -63,6 +63,9 @@ passkey = "a_random_passkey"
|
||||
## default: empty
|
||||
# docker_organizations = ["your_docker_org1", "your_docker_org_2"]
|
||||
|
||||
## allows all users to have read access on all resources
|
||||
# transparent_mode = true
|
||||
|
||||
## allow or deny user login with username / password
|
||||
## default: false
|
||||
# local_auth = true
|
||||
|
||||
Reference in New Issue
Block a user