mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
misc fixes
This commit is contained in:
committed by
Aiden McClelland
parent
be5952cb67
commit
e9faf1f74d
@@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS tor
|
||||
(
|
||||
package TEXT NOT NULL,
|
||||
interface TEXT NOT NULL,
|
||||
key BLOB NOT NULL,
|
||||
key BLOB NOT NULL CHECK (length(key) = 64),
|
||||
PRIMARY KEY (package, interface)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS session
|
||||
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS account
|
||||
(
|
||||
id INTEGER PRIMARY KEY CHECK (id = 0),
|
||||
password TEXT NOT NULL,
|
||||
tor_key BLOB NOT NULL
|
||||
tor_key BLOB NOT NULL CHECK (length(tor_key) = 64)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS ssh_keys
|
||||
(
|
||||
|
||||
@@ -10,7 +10,7 @@ use serde_json::Value;
|
||||
use crate::id::{Id, ImageId};
|
||||
use crate::s9pk::manifest::{PackageId, SYSTEM_PACKAGE_ID};
|
||||
use crate::util::{IoFormat, Version};
|
||||
use crate::volume::{Volume, VolumeId, Volumes};
|
||||
use crate::volume::{VolumeId, Volumes};
|
||||
use crate::{Error, ResultExt, HOST_IP};
|
||||
|
||||
pub const NET_TLD: &'static str = "embassy";
|
||||
@@ -195,7 +195,7 @@ impl DockerAction {
|
||||
let mut res = Vec::with_capacity(
|
||||
(2 * self.mounts.len()) // --mount <MOUNT_ARG>
|
||||
+ (2 * self.shm_size_mb.is_some() as usize) // --shm-size <SHM_SIZE>
|
||||
+ 3 // --entrypoint <ENTRYPOINT> <IMAGE>
|
||||
+ 4 // --log-driver=journald --entrypoint <ENTRYPOINT> <IMAGE>
|
||||
+ self.args.len(), // [ARG...]
|
||||
);
|
||||
for (volume_id, dst) in &self.mounts {
|
||||
@@ -227,6 +227,7 @@ impl DockerAction {
|
||||
res.push(OsString::from(Self::container_name(pkg_id, None)).into());
|
||||
res.push(OsStr::new(&self.entrypoint).into());
|
||||
} else {
|
||||
res.push(OsStr::new("--log-driver=journald").into());
|
||||
res.push(OsStr::new("--entrypoint").into());
|
||||
res.push(OsStr::new(&self.entrypoint).into());
|
||||
if self.system {
|
||||
|
||||
@@ -117,7 +117,7 @@ pub async fn login(
|
||||
res.headers.insert(
|
||||
"set-cookie",
|
||||
HeaderValue::from_str(&format!(
|
||||
"session={}; HttpOnly; SameSite=Strict; Expires=Fri, 31 Dec 9999 23:59:59 GMT;",
|
||||
"session={}; SameSite=Strict; Expires=Fri, 31 Dec 9999 23:59:59 GMT;",
|
||||
token
|
||||
))
|
||||
.with_kind(crate::ErrorKind::Unknown)?, // Should be impossible, but don't want to panic
|
||||
|
||||
@@ -19,7 +19,7 @@ pub async fn tor_health_check_daemon(tor_controller: &TorController) {
|
||||
json!({
|
||||
"jsonrpc": "2.0",
|
||||
"method": "echo",
|
||||
"params": [{ "message": "Follow the orange rabbit" }],
|
||||
"params": { "message": "Follow the orange rabbit" },
|
||||
})
|
||||
.to_string()
|
||||
.into_bytes(),
|
||||
@@ -28,7 +28,7 @@ pub async fn tor_health_check_daemon(tor_controller: &TorController) {
|
||||
.await;
|
||||
match result {
|
||||
// if success, do nothing
|
||||
Ok(response) => {}
|
||||
Ok(_) => {}
|
||||
// if failure, disconnect tor control port, and restart tor controller
|
||||
Err(e) => {
|
||||
log::error!("Unable to reach self over tor: {}", e);
|
||||
|
||||
@@ -4,7 +4,7 @@ pub mod util;
|
||||
use std::future::Future;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use futures::{FutureExt, SinkExt, StreamExt};
|
||||
use patch_db::json_ptr::JsonPointer;
|
||||
use patch_db::{Dump, Revision};
|
||||
use rpc_toolkit::command;
|
||||
@@ -34,7 +34,17 @@ async fn ws_handler<
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Network)?
|
||||
.with_kind(crate::ErrorKind::Unknown)?;
|
||||
stream.next().await;
|
||||
loop {
|
||||
if let Some(Message::Text(_)) = stream
|
||||
.next()
|
||||
.await
|
||||
.transpose()
|
||||
.with_kind(crate::ErrorKind::Network)?
|
||||
{
|
||||
// TODO: check auth
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream
|
||||
.send(Message::Text(
|
||||
rpc_toolkit::serde_json::to_string(&dump).with_kind(crate::ErrorKind::Serialization)?,
|
||||
@@ -43,20 +53,44 @@ async fn ws_handler<
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
|
||||
loop {
|
||||
let rev = sub.recv().await.with_kind(crate::ErrorKind::Database)?;
|
||||
stream
|
||||
.send(Message::Text(
|
||||
rpc_toolkit::serde_json::to_string(&rev)
|
||||
.with_kind(crate::ErrorKind::Serialization)?,
|
||||
))
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
futures::select! {
|
||||
new_rev = sub.recv().fuse() => {
|
||||
let rev = new_rev.with_kind(crate::ErrorKind::Database)?;
|
||||
stream
|
||||
.send(Message::Text(
|
||||
rpc_toolkit::serde_json::to_string(&rev)
|
||||
.with_kind(crate::ErrorKind::Serialization)?,
|
||||
))
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
}
|
||||
message = stream.next().fuse() => {
|
||||
match message.transpose().with_kind(crate::ErrorKind::Network)? {
|
||||
Some(Message::Ping(a)) => {
|
||||
stream
|
||||
.send(Message::Pong(a))
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
}
|
||||
Some(Message::Close(frame)) => {
|
||||
if let Some(reason) = frame.as_ref() {
|
||||
log::info!("Closing WebSocket: Reason: {} {}", reason.code, reason.reason);
|
||||
}
|
||||
stream
|
||||
.send(Message::Close(frame))
|
||||
.await
|
||||
.with_kind(crate::ErrorKind::Network)?;
|
||||
return Ok(())
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn subscribe(ctx: RpcContext, req: Request<Body>) -> Result<Response<Body>, Error> {
|
||||
let (parts, body) = req.into_parts();
|
||||
// is_authed(&ctx, &parts).await?;
|
||||
let req = Request::from_parts(parts, body);
|
||||
let (res, ws_fut) = hyper_ws_listener::create_ws(req).with_kind(crate::ErrorKind::Network)?;
|
||||
if let Some(ws_fut) = ws_fut {
|
||||
|
||||
@@ -59,11 +59,12 @@ pub fn echo(#[arg] message: String) -> Result<String, RpcError> {
|
||||
#[command(subcommands(
|
||||
version::git_info,
|
||||
echo,
|
||||
developer::init,
|
||||
s9pk::pack,
|
||||
s9pk::verify,
|
||||
developer::init,
|
||||
inspect::inspect,
|
||||
package,
|
||||
net::net,
|
||||
auth::auth,
|
||||
db::db,
|
||||
))]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use rpc_toolkit::command;
|
||||
use torut::onion::TorSecretKeyV3;
|
||||
|
||||
use self::interface::{Interface, InterfaceId};
|
||||
@@ -16,6 +17,11 @@ pub mod mdns;
|
||||
pub mod tor;
|
||||
pub mod wifi;
|
||||
|
||||
#[command(subcommands(tor::tor))]
|
||||
pub fn net() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct NetController {
|
||||
pub tor: TorController,
|
||||
#[cfg(feature = "avahi")]
|
||||
|
||||
@@ -3,8 +3,10 @@ use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use clap::ArgMatches;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::FutureExt;
|
||||
use rpc_toolkit::command;
|
||||
use sqlx::{Executor, Sqlite};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::sync::Mutex;
|
||||
@@ -12,7 +14,9 @@ use torut::control::{AsyncEvent, AuthenticatedConn, ConnError};
|
||||
use torut::onion::{OnionAddressV3, TorSecretKeyV3};
|
||||
|
||||
use super::interface::{InterfaceId, TorConfig};
|
||||
use crate::context::RpcContext;
|
||||
use crate::s9pk::manifest::PackageId;
|
||||
use crate::util::{display_serializable, IoFormat};
|
||||
use crate::{Error, ErrorKind, ResultExt as _};
|
||||
|
||||
#[test]
|
||||
@@ -20,6 +24,36 @@ fn random_key() {
|
||||
println!("'0x{}'", hex::encode(TorSecretKeyV3::generate().as_bytes()));
|
||||
}
|
||||
|
||||
#[command(subcommands(list_services))]
|
||||
pub fn tor() -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_services(services: Vec<OnionAddressV3>, matches: &ArgMatches<'_>) {
|
||||
use prettytable::*;
|
||||
|
||||
if matches.is_present("format") {
|
||||
return display_serializable(services, matches);
|
||||
}
|
||||
|
||||
let mut table = Table::new();
|
||||
for service in services {
|
||||
let row = row![&service.to_string()];
|
||||
table.add_row(row);
|
||||
}
|
||||
table.print_tty(false);
|
||||
}
|
||||
|
||||
#[command(rename = "list-services", display(display_services))]
|
||||
pub async fn list_services(
|
||||
#[context] ctx: RpcContext,
|
||||
#[allow(unused_variables)]
|
||||
#[arg(long = "format")]
|
||||
format: Option<IoFormat>,
|
||||
) -> Result<Vec<OnionAddressV3>, Error> {
|
||||
ctx.net_controller.tor.list_services().await
|
||||
}
|
||||
|
||||
pub async fn os_key<Ex>(secrets: &mut Ex) -> Result<TorSecretKeyV3, Error>
|
||||
where
|
||||
for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>,
|
||||
@@ -79,6 +113,10 @@ impl TorController {
|
||||
pub async fn embassyd_onion(&self) -> OnionAddressV3 {
|
||||
self.0.lock().await.embassyd_onion()
|
||||
}
|
||||
|
||||
pub async fn list_services(&self) -> Result<Vec<OnionAddressV3>, Error> {
|
||||
self.0.lock().await.list_services().await
|
||||
}
|
||||
}
|
||||
|
||||
type AuthenticatedConnection = AuthenticatedConn<
|
||||
@@ -154,10 +192,7 @@ impl TorControllerInner {
|
||||
self.connection
|
||||
.as_mut()
|
||||
.ok_or_else(|| {
|
||||
Error::new(
|
||||
anyhow!("Missing Tor Control Connection"),
|
||||
ErrorKind::Unknown,
|
||||
)
|
||||
Error::new(anyhow!("Missing Tor Control Connection"), ErrorKind::Tor)
|
||||
})?
|
||||
.del_onion(
|
||||
&key.public()
|
||||
@@ -200,9 +235,13 @@ impl TorControllerInner {
|
||||
}
|
||||
|
||||
async fn add_embassyd_onion(&mut self) -> Result<(), Error> {
|
||||
log::info!(
|
||||
"Registering Main Tor Service: {}",
|
||||
self.embassyd_tor_key.public().get_onion_address()
|
||||
);
|
||||
self.connection
|
||||
.as_mut()
|
||||
.expect("Tor Connection is None")
|
||||
.ok_or_else(|| Error::new(anyhow!("Missing Tor Control Connection"), ErrorKind::Tor))?
|
||||
.add_onion_v3(
|
||||
&self.embassyd_tor_key,
|
||||
false,
|
||||
@@ -212,6 +251,10 @@ impl TorControllerInner {
|
||||
&mut std::iter::once(&(self.embassyd_addr.port(), self.embassyd_addr)),
|
||||
)
|
||||
.await?;
|
||||
log::info!(
|
||||
"Registered Main Tor Service: {}",
|
||||
self.embassyd_tor_key.public().get_onion_address()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -223,6 +266,7 @@ impl TorControllerInner {
|
||||
let uptime = c.get_info("uptime").await?.parse::<u64>()?;
|
||||
// we never want to restart the tor daemon if it hasn't been up for at least a half hour
|
||||
if uptime < 1800 {
|
||||
self.connection = Some(c); // put it back
|
||||
return Ok(false);
|
||||
}
|
||||
// when connection closes below, tor daemon is restarted
|
||||
@@ -251,11 +295,11 @@ impl TorControllerInner {
|
||||
let uptime_new = new_connection.get_info("uptime").await?.parse::<u64>()?;
|
||||
// if the new uptime exceeds the one we got at the beginning, it's the same tor daemon, do not proceed
|
||||
match uptime {
|
||||
Some(uptime) if uptime_new < uptime => {
|
||||
Some(uptime) if uptime_new > uptime => (),
|
||||
_ => {
|
||||
new_connection.set_async_event_handler(Some(event_handler));
|
||||
break;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -289,6 +333,17 @@ impl TorControllerInner {
|
||||
fn embassyd_onion(&self) -> OnionAddressV3 {
|
||||
self.embassyd_tor_key.public().get_onion_address()
|
||||
}
|
||||
|
||||
async fn list_services(&mut self) -> Result<Vec<OnionAddressV3>, Error> {
|
||||
self.connection
|
||||
.as_mut()
|
||||
.ok_or_else(|| Error::new(anyhow!("Missing Tor Control Connection"), ErrorKind::Tor))?
|
||||
.get_info("onions/current")
|
||||
.await?
|
||||
.lines()
|
||||
.map(|l| l.trim().parse().with_kind(ErrorKind::Tor))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
24
ui/package-lock.json
generated
24
ui/package-lock.json
generated
@@ -16820,7 +16820,9 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz",
|
||||
"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.16.0",
|
||||
@@ -16898,7 +16900,9 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz",
|
||||
"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
@@ -16942,7 +16946,9 @@
|
||||
"integrity": "sha512-Brah4Uo5/U8v76c6euTwtjVFFaVishwnJrQBYpev1JRh4vjA1F4HY3UzQez41YUCszUCXKagG8v6eVRBHV1gkw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
@@ -16995,7 +17001,9 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz",
|
||||
"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
@@ -17073,7 +17081,9 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz",
|
||||
"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
@@ -18622,7 +18632,9 @@
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz",
|
||||
"integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"requires": {
|
||||
"ajv": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
|
||||
Reference in New Issue
Block a user