mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Feature/sdk improvements (#2879)
* sdk improvements * subcontainer fixes, disable wifi on migration if not in use, filterable interfaces
This commit is contained in:
13
core/Cargo.lock
generated
13
core/Cargo.lock
generated
@@ -5510,6 +5510,18 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-crypt"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88e79009728d8311d42d754f2f319a975f9e38f156fd5e422d2451486c78b286"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.10.8",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
@@ -6091,6 +6103,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"serde_with",
|
||||
"serde_yml",
|
||||
"sha-crypt",
|
||||
"sha2 0.10.8",
|
||||
"shell-words",
|
||||
"signal-hook",
|
||||
|
||||
@@ -183,6 +183,7 @@ serde_toml = { package = "toml", version = "0.8.2" }
|
||||
serde_urlencoded = "0.7"
|
||||
serde_with = { version = "3.4.0", features = ["macros", "json"] }
|
||||
serde_yaml = { package = "serde_yml", version = "0.0.10" }
|
||||
sha-crypt = "0.5.0"
|
||||
sha2 = "0.10.2"
|
||||
shell-words = "1"
|
||||
signal-hook = "0.3.17"
|
||||
|
||||
@@ -9,6 +9,7 @@ use josekit::jwk::Jwk;
|
||||
use rpc_toolkit::yajrc::RpcError;
|
||||
use rpc_toolkit::{from_fn_async, Context, HandlerArgs, HandlerExt, ParentHandler};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tracing::instrument;
|
||||
use ts_rs::TS;
|
||||
|
||||
@@ -19,6 +20,7 @@ use crate::middleware::auth::{
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::util::crypto::EncryptedWire;
|
||||
use crate::util::io::create_file_mod;
|
||||
use crate::util::serde::{display_serializable, HandlerExtSerde, WithIoFormat};
|
||||
use crate::{ensure_code, Error, ResultExt};
|
||||
|
||||
@@ -41,6 +43,30 @@ impl Map for Sessions {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn write_shadow(password: &str) -> Result<(), Error> {
|
||||
let shadow_contents = tokio::fs::read_to_string("/etc/shadow").await?;
|
||||
let mut shadow_file =
|
||||
create_file_mod("/media/startos/config/overlay/etc/shadow", 0o640).await?;
|
||||
for line in shadow_contents.lines() {
|
||||
if line.starts_with("start9:") {
|
||||
let rest = line.splitn(3, ":").nth(2).ok_or_else(|| {
|
||||
Error::new(eyre!("malformed /etc/shadow"), ErrorKind::ParseSysInfo)
|
||||
})?;
|
||||
let pw = sha_crypt::sha512_simple(password, &sha_crypt::Sha512Params::default())
|
||||
.map_err(|e| Error::new(eyre!("{e:?}"), ErrorKind::Serialization))?;
|
||||
shadow_file
|
||||
.write_all(format!("start9:{pw}:{rest}\n").as_bytes())
|
||||
.await?;
|
||||
} else {
|
||||
shadow_file.write_all(line.as_bytes()).await?;
|
||||
shadow_file.write_all(b"\n").await?;
|
||||
}
|
||||
}
|
||||
shadow_file.sync_all().await?;
|
||||
tokio::fs::copy("/media/startos/config/overlay/etc/shadow", "/etc/shadow").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, TS)]
|
||||
#[serde(untagged)]
|
||||
#[ts(export)]
|
||||
@@ -210,7 +236,7 @@ pub async fn login_impl(
|
||||
) -> Result<LoginRes, Error> {
|
||||
let password = password.unwrap_or_default().decrypt(&ctx)?;
|
||||
|
||||
if ephemeral {
|
||||
let tok = if ephemeral {
|
||||
check_password_against_db(&ctx.db.peek().await, &password)?;
|
||||
let hash_token = HashSessionToken::new();
|
||||
ctx.ephemeral_sessions.mutate(|s| {
|
||||
@@ -242,7 +268,16 @@ pub async fn login_impl(
|
||||
})
|
||||
.await
|
||||
.result
|
||||
}?;
|
||||
|
||||
if tokio::fs::metadata("/media/startos/config/overlay/etc/shadow")
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
write_shadow(&password).await?;
|
||||
}
|
||||
|
||||
Ok(tok)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Parser, TS)]
|
||||
|
||||
@@ -17,6 +17,7 @@ use tracing::instrument;
|
||||
use ts_rs::TS;
|
||||
|
||||
use crate::account::AccountInfo;
|
||||
use crate::auth::write_shadow;
|
||||
use crate::backup::restore::recover_full_embassy;
|
||||
use crate::backup::target::BackupTargetFS;
|
||||
use crate::context::rpc::InitRpcContextPhases;
|
||||
@@ -88,8 +89,8 @@ async fn setup_init(
|
||||
.db
|
||||
.mutate(|m| {
|
||||
let mut account = AccountInfo::load(m)?;
|
||||
if let Some(password) = password {
|
||||
account.set_password(&password)?;
|
||||
if let Some(password) = &password {
|
||||
account.set_password(password)?;
|
||||
}
|
||||
account.save(m)?;
|
||||
m.as_public_mut()
|
||||
@@ -101,6 +102,10 @@ async fn setup_init(
|
||||
.await
|
||||
.result?;
|
||||
|
||||
if let Some(password) = &password {
|
||||
write_shadow(&password).await?;
|
||||
}
|
||||
|
||||
Ok((account, init_result))
|
||||
}
|
||||
|
||||
@@ -346,6 +351,8 @@ pub async fn complete(ctx: SetupContext) -> Result<SetupResult, Error> {
|
||||
.arg(format!("--hostname={}", res.hostname.0))
|
||||
.invoke(ErrorKind::ParseSysInfo)
|
||||
.await?;
|
||||
Command::new("sync").invoke(ErrorKind::Filesystem).await?;
|
||||
|
||||
Ok(res.clone())
|
||||
}
|
||||
Some(Err(e)) => Err(e.clone_output()),
|
||||
@@ -465,6 +472,8 @@ async fn fresh_setup(
|
||||
)
|
||||
.await?;
|
||||
|
||||
write_shadow(start_os_password).await?;
|
||||
|
||||
Ok(((&account).try_into()?, rpc_ctx))
|
||||
}
|
||||
|
||||
|
||||
@@ -944,6 +944,23 @@ pub async fn create_file(path: impl AsRef<Path>) -> Result<File, Error> {
|
||||
.with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("create {path:?}")))
|
||||
}
|
||||
|
||||
pub async fn create_file_mod(path: impl AsRef<Path>, mode: u32) -> Result<File, Error> {
|
||||
let path = path.as_ref();
|
||||
if let Some(parent) = path.parent() {
|
||||
tokio::fs::create_dir_all(parent)
|
||||
.await
|
||||
.with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("mkdir -p {parent:?}")))?;
|
||||
}
|
||||
OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.mode(mode)
|
||||
.open(path)
|
||||
.await
|
||||
.with_ctx(|_| (ErrorKind::Filesystem, lazy_format!("create {path:?}")))
|
||||
}
|
||||
|
||||
pub async fn append_file(path: impl AsRef<Path>) -> Result<File, Error> {
|
||||
let path = path.as_ref();
|
||||
if let Some(parent) = path.parent() {
|
||||
|
||||
@@ -31,7 +31,7 @@ impl VersionT for Version {
|
||||
fn up(self, db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
|
||||
let host = db["public"]["serverInfo"]["host"].clone();
|
||||
let mut wifi = db["public"]["serverInfo"]["wifi"].clone();
|
||||
wifi["enabled"] = Value::Bool(true);
|
||||
wifi["enabled"] = Value::Bool(!wifi["selected"].is_null());
|
||||
let mut network_interfaces = db["public"]["serverInfo"]["networkInterfaces"].clone();
|
||||
for (k, v) in network_interfaces
|
||||
.as_object_mut()
|
||||
|
||||
Reference in New Issue
Block a user