Skip to content

Commit

Permalink
Merge pull request #367 from Lodestone-Team/safe-mode
Browse files Browse the repository at this point in the history
Update Safe mode to disable global FS reads and writes
  • Loading branch information
CheatCod committed Jun 17, 2024
2 parents 6054010 + 7c8b9a3 commit bd27d5c
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 50 deletions.
29 changes: 27 additions & 2 deletions core/src/auth/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,10 @@ impl User {
}
}

pub fn try_action(&self, action: &UserAction) -> Result<(), Error> {
if self.can_perform_action(action) {
pub fn try_action(&self, action: &UserAction, safe_mode: bool) -> Result<(), Error> {
if (action.is_safe() || (!action.is_safe() && !safe_mode))
&& self.can_perform_action(action)
{
Ok(())
} else {
Err(Error {
Expand Down Expand Up @@ -285,6 +287,29 @@ pub enum UserAction {
ManagePermission,
}

impl UserAction {
pub fn is_safe(&self) -> bool {
match self {
UserAction::ViewInstance(_) => true,
UserAction::StartInstance(_) => true,
UserAction::StopInstance(_) => true,
UserAction::AccessConsole(_) => true,
UserAction::AccessSetting(_) => true,
UserAction::ReadResource(_) => true,
UserAction::WriteResource(_) => true,
UserAction::AccessMacro(_) => true,
UserAction::ReadInstanceFile(_) => true,
UserAction::WriteInstanceFile(_) => true,
UserAction::CreateInstance => true,
UserAction::DeleteInstance => true,
UserAction::ReadGlobalFile => false,
UserAction::WriteGlobalFile => false,
UserAction::ManageUser => false,
UserAction::ManagePermission => false,
}
}
}

#[derive(Serialize, Deserialize, Clone, TS)]
#[ts(export)]
pub struct PublicUser {
Expand Down
20 changes: 10 additions & 10 deletions core/src/handlers/global_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ async fn list_files(
source: eyre!("Token error"),
})?;

requester.try_action(&UserAction::ReadGlobalFile)?;
requester.try_action(&UserAction::ReadGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);
let caused_by = CausedBy::User {
Expand Down Expand Up @@ -158,7 +158,7 @@ async fn read_file(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::ReadGlobalFile)?;
requester.try_action(&UserAction::ReadGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);
let ret = tokio::fs::read_to_string(&path).await.context(
Expand Down Expand Up @@ -195,7 +195,7 @@ async fn write_file(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);

Expand Down Expand Up @@ -231,7 +231,7 @@ async fn make_directory(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);
tokio::fs::create_dir(&path).await.context(format!(
Expand Down Expand Up @@ -271,7 +271,7 @@ async fn move_file(
source: eyre!("Token error"),
})?;

requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

crate::util::fs::rename(&path_source, &path_dest).await?;

Expand Down Expand Up @@ -306,7 +306,7 @@ async fn remove_file(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);

Expand Down Expand Up @@ -341,7 +341,7 @@ async fn remove_dir(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);

Expand Down Expand Up @@ -377,7 +377,7 @@ async fn new_file(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path = PathBuf::from(absolute_path);

Expand Down Expand Up @@ -413,7 +413,7 @@ async fn download_file(
kind: ErrorKind::Unauthorized,
source: eyre!("Token error"),
})?;
requester.try_action(&UserAction::ReadGlobalFile)?;
requester.try_action(&UserAction::ReadGlobalFile, state.global_settings.lock().await.safe_mode())?;
let path = PathBuf::from(absolute_path);
let downloadable_file_path: PathBuf;
let downloadable_file = if fs::metadata(path.clone()).unwrap().is_dir() {
Expand Down Expand Up @@ -468,7 +468,7 @@ async fn upload_file(
source: eyre!("Token error"),
})?;

requester.try_action(&UserAction::WriteGlobalFile)?;
requester.try_action(&UserAction::WriteGlobalFile, state.global_settings.lock().await.safe_mode())?;

let path_to_dir = PathBuf::from(absolute_path);

Expand Down
20 changes: 16 additions & 4 deletions core/src/handlers/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ pub async fn get_instance_info(
source: eyre!("Instance not found"),
})?;

requester.try_action(&UserAction::ViewInstance(uuid.clone()))?;
requester.try_action(
&UserAction::ViewInstance(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
Ok(Json(instance.get_instance_info().await))
}

Expand All @@ -65,7 +68,10 @@ pub async fn create_minecraft_instance(
Json(manifest_value): Json<SetupValue>,
) -> Result<Json<InstanceUuid>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::CreateInstance)?;
requester.try_action(
&UserAction::CreateInstance,
state.global_settings.lock().await.safe_mode(),
)?;
let mut perm = requester.permissions;

let mut instance_uuid = InstanceUuid::default();
Expand Down Expand Up @@ -196,7 +202,10 @@ pub async fn create_generic_instance(
Json(setup_config): Json<GenericSetupConfig>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::CreateInstance)?;
requester.try_action(
&UserAction::CreateInstance,
state.global_settings.lock().await.safe_mode(),
)?;
let mut instance_uuid = InstanceUuid::default();
for entry in state.instances.iter() {
if let Some(uuid) = entry.key().as_ref().get(0..8) {
Expand Down Expand Up @@ -297,7 +306,10 @@ pub async fn delete_instance(
AuthBearer(token): AuthBearer,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::DeleteInstance)?;
requester.try_action(
&UserAction::DeleteInstance,
state.global_settings.lock().await.safe_mode(),
)?;
let caused_by = CausedBy::User {
user_id: requester.uid.clone(),
user_name: requester.username.clone(),
Expand Down
30 changes: 24 additions & 6 deletions core/src/handlers/instance_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ pub async fn get_instance_configurable_manifest(
AuthBearer(token): AuthBearer,
) -> Result<Json<ConfigurableManifest>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand All @@ -37,7 +40,10 @@ pub async fn get_instance_settings(
AuthBearer(token): AuthBearer,
) -> Result<Json<ConfigurableManifest>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand All @@ -52,7 +58,10 @@ pub async fn set_instance_setting(
Json(value): Json<ConfigurableValue>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
let instance = state.instances.get(&uuid).ok_or(Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand All @@ -72,7 +81,10 @@ pub async fn set_instance_name(
Json(new_name): Json<String>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
state
.instances
.get(&uuid)
Expand All @@ -92,7 +104,10 @@ pub async fn set_instance_description(
Json(new_description): Json<String>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
state
.instances
.get(&uuid)
Expand All @@ -111,7 +126,10 @@ pub async fn change_version(
AuthBearer(token): AuthBearer,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::AccessSetting(uuid.clone()))?;
requester.try_action(
&UserAction::AccessSetting(uuid.clone()),
state.global_settings.lock().await.safe_mode(),
)?;
state
.instances
.get(&uuid)
Expand Down
26 changes: 13 additions & 13 deletions core/src/handlers/instance_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async fn list_instance_files(
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;

requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -118,7 +118,7 @@ async fn read_instance_file(
) -> Result<String, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -150,7 +150,7 @@ async fn write_instance_file(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -191,7 +191,7 @@ async fn make_instance_directory(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -231,7 +231,7 @@ async fn copy_instance_files(
}): Json<CopyInstanceFileRequest>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -374,7 +374,7 @@ async fn move_instance_file(
let relative_path_source = decode_base64(&base64_relative_path_source)?;
let relative_path_dest = decode_base64(&base64_relative_path_dest)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -441,7 +441,7 @@ async fn remove_instance_file(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -478,7 +478,7 @@ async fn remove_instance_dir(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -540,7 +540,7 @@ async fn new_instance_file(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -577,7 +577,7 @@ async fn get_instance_file_url(
) -> Result<String, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::ReadInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -659,7 +659,7 @@ async fn upload_instance_file(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let caused_by = CausedBy::User {
user_id: requester.uid.clone(),
user_name: requester.username.clone(),
Expand Down Expand Up @@ -795,7 +795,7 @@ pub async fn unzip_instance_file(
) -> Result<Json<()>, Error> {
let relative_path = decode_base64(&base64_relative_path)?;
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down Expand Up @@ -868,7 +868,7 @@ async fn zip_instance_files(
Json(zip_request): Json<ZipRequest>,
) -> Result<Json<()>, Error> {
let requester = state.users_manager.read().await.try_auth_or_err(&token)?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()))?;
requester.try_action(&UserAction::WriteInstanceFile(uuid.clone()), state.global_settings.lock().await.safe_mode())?;
let instance = state.instances.get(&uuid).ok_or_else(|| Error {
kind: ErrorKind::NotFound,
source: eyre!("Instance not found"),
Expand Down
Loading

0 comments on commit bd27d5c

Please sign in to comment.