implement transparent mode

This commit is contained in:
mbecker20
2024-05-23 02:19:42 -07:00
parent ec47bb11ee
commit e8cfc13342
16 changed files with 75 additions and 135 deletions
+2 -3
View File
@@ -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,
+2 -4
View File
@@ -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(
+10 -30
View File
@@ -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")?
+1 -1
View File
@@ -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(
+10 -31
View File
@@ -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 {
+1
View File
@@ -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,
})
}
}
+7 -30
View File
@@ -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();
+5 -28
View File
@@ -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();
+2 -2
View File
@@ -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,
};
+3 -2
View File
@@ -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 {
+4
View File
@@ -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);
+7 -2
View File
@@ -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 {
+6 -2
View File
@@ -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?
+2
View File
@@ -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,
+3
View File
@@ -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