From 9630c356f41ccf02af62c579a8de55d4e158490a Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Thu, 24 Jun 2021 17:10:30 -0600 Subject: [PATCH] appmgr: wrap up tor --- appmgr/src/config/spec.rs | 2 +- appmgr/src/db/model.rs | 2 +- appmgr/src/dependencies.rs | 2 +- appmgr/src/id.rs | 36 ------------ appmgr/src/install/mod.rs | 8 ++- appmgr/src/net/interface.rs | 114 ++++++++++++++++++++++++++++++++++++ appmgr/src/net/mod.rs | 1 + appmgr/src/net/tor.rs | 41 +++++++------ appmgr/src/s9pk/manifest.rs | 34 +---------- appmgr/src/status/mod.rs | 2 +- appmgr/src/util.rs | 3 +- appmgr/src/volume/mod.rs | 10 +--- 12 files changed, 156 insertions(+), 99 deletions(-) create mode 100644 appmgr/src/net/interface.rs diff --git a/appmgr/src/config/spec.rs b/appmgr/src/config/spec.rs index b6dcfa088..926ebae69 100644 --- a/appmgr/src/config/spec.rs +++ b/appmgr/src/config/spec.rs @@ -18,7 +18,7 @@ use serde_json::{Number, Value}; use super::util::{self, CharSet, NumRange, UniqueBy, STATIC_NULL}; use super::{Config, MatchError, NoMatchWithPath, TimeoutError, TypeOf}; use crate::config::ConfigurationError; -use crate::id::InterfaceId; +use crate::net::interface::InterfaceId; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::Error; diff --git a/appmgr/src/db/model.rs b/appmgr/src/db/model.rs index 9e77ae1a2..2b2794b27 100644 --- a/appmgr/src/db/model.rs +++ b/appmgr/src/db/model.rs @@ -9,8 +9,8 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::config::spec::{PackagePointerSpecVariant, SystemPointerSpec}; -use crate::id::InterfaceId; use crate::install::progress::InstallProgress; +use crate::net::interface::InterfaceId; use crate::net::Network; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::health_check::HealthCheckId; diff --git a/appmgr/src/dependencies.rs b/appmgr/src/dependencies.rs index 93e21ca2d..04282e982 100644 --- a/appmgr/src/dependencies.rs +++ b/appmgr/src/dependencies.rs @@ -8,8 +8,8 @@ use serde::{Deserialize, Serialize}; use crate::action::ActionImplementation; use crate::config::{Config, ConfigSpec}; -use crate::id::InterfaceId; use crate::net::host::Hosts; +use crate::net::interface::InterfaceId; use crate::s9pk::manifest::PackageId; use crate::status::health_check::{HealthCheckId, HealthCheckResult, HealthCheckResultVariant}; use crate::status::{DependencyErrors, MainStatus, Status}; diff --git a/appmgr/src/id.rs b/appmgr/src/id.rs index 35c67f3ea..542e23601 100644 --- a/appmgr/src/id.rs +++ b/appmgr/src/id.rs @@ -166,39 +166,3 @@ where Ok(ImageId(Deserialize::deserialize(deserializer)?)) } } - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] -pub struct InterfaceId = String>(Id); -impl> std::fmt::Display for InterfaceId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", &self.0) - } -} -impl> std::ops::Deref for InterfaceId { - type Target = S; - fn deref(&self) -> &Self::Target { - &*self.0 - } -} -impl> AsRef for InterfaceId { - fn as_ref(&self) -> &str { - self.0.as_ref() - } -} -impl<'de, S> Deserialize<'de> for InterfaceId -where - S: AsRef, - Id: Deserialize<'de>, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(InterfaceId(Deserialize::deserialize(deserializer)?)) - } -} -impl> AsRef for InterfaceId { - fn as_ref(&self) -> &Path { - self.0.as_ref().as_ref() - } -} diff --git a/appmgr/src/install/mod.rs b/appmgr/src/install/mod.rs index 5ddd6b7fe..0c32b334a 100644 --- a/appmgr/src/install/mod.rs +++ b/appmgr/src/install/mod.rs @@ -331,6 +331,7 @@ pub async fn install_s9pk( progress_model.put(&mut db, &progress).await?; let mut tx = db.begin().await?; + let mut sql_tx = ctx.secret_store.begin().await?; let mut network = crate::db::DatabaseModel::new() .network() @@ -348,7 +349,10 @@ pub async fn install_s9pk( log::info!("Install {}@{}: Installed main", pkg_id, version); log::info!("Install {}@{}: Installing interfaces", pkg_id, version); - let interface_info = manifest.interfaces.install(ip).await?; + let interface_info = manifest + .interfaces + .install(&ctx, &mut sql_tx, pkg_id, ip) + .await?; log::info!("Install {}@{}: Installed interfaces", pkg_id, version); log::info!("Install {}@{}: Complete", pkg_id, version); @@ -461,6 +465,8 @@ pub async fn install_s9pk( } } + ctx.tor_controller.sync(&mut tx, &mut sql_tx).await?; + tx.commit(None).await?; Ok(()) diff --git a/appmgr/src/net/interface.rs b/appmgr/src/net/interface.rs new file mode 100644 index 000000000..200b9669b --- /dev/null +++ b/appmgr/src/net/interface.rs @@ -0,0 +1,114 @@ +use std::net::Ipv4Addr; +use std::path::Path; + +use indexmap::IndexMap; +use patch_db::DbHandle; +use serde::{Deserialize, Deserializer, Serialize}; +use sqlx::{Executor, Sqlite}; +use torut::onion::TorSecretKeyV3; + +use crate::context::RpcContext; +use crate::db::model::{InterfaceAddressMap, InterfaceAddresses, InterfaceInfo}; +use crate::id::Id; +use crate::s9pk::manifest::PackageId; +use crate::Error; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct Interfaces(pub IndexMap); // TODO +impl Interfaces { + pub async fn install( + &self, + ctx: &RpcContext, + secrets: &mut Ex, + package_id: &PackageId, + ip: Ipv4Addr, + ) -> Result + where + for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, + { + let mut interface_info = InterfaceInfo { + ip, + addresses: InterfaceAddressMap(IndexMap::new()), + }; + for (id, iface) in &self.0 { + let mut addrs = InterfaceAddresses { + tor_address: None, + lan_address: None, + }; + if iface.tor_config.is_some() { + let key = TorSecretKeyV3::generate(); + let key_vec = key.as_bytes().to_vec(); + sqlx::query!( + "INSERT INTO tor (package, interface, key) VALUES (?, ?, ?)", + **package_id, + **id, + key_vec, + ) + .execute(&mut *secrets) + .await?; + addrs.tor_address = Some(key.public().get_onion_address().to_string()); + } + interface_info.addresses.0.insert(id.clone(), addrs); + } + todo!() + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)] +pub struct InterfaceId = String>(Id); +impl> std::fmt::Display for InterfaceId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", &self.0) + } +} +impl> std::ops::Deref for InterfaceId { + type Target = S; + fn deref(&self) -> &Self::Target { + &*self.0 + } +} +impl> AsRef for InterfaceId { + fn as_ref(&self) -> &str { + self.0.as_ref() + } +} +impl<'de, S> Deserialize<'de> for InterfaceId +where + S: AsRef, + Id: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(InterfaceId(Deserialize::deserialize(deserializer)?)) + } +} +impl> AsRef for InterfaceId { + fn as_ref(&self) -> &Path { + self.0.as_ref().as_ref() + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct Interface { + pub tor_config: Option, + pub lan_config: Option>, + pub ui: bool, + pub protocols: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct TorConfig { + pub port_mapping: IndexMap, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct LanPortConfig { + pub ssl: bool, + pub mapping: u16, +} diff --git a/appmgr/src/net/mod.rs b/appmgr/src/net/mod.rs index c9f69524c..edfd9502b 100644 --- a/appmgr/src/net/mod.rs +++ b/appmgr/src/net/mod.rs @@ -10,6 +10,7 @@ use crate::s9pk::manifest::PackageId; use crate::{Error, ResultExt}; pub mod host; +pub mod interface; #[cfg(feature = "avahi")] pub mod mdns; pub mod tor; diff --git a/appmgr/src/net/tor.rs b/appmgr/src/net/tor.rs index 811ef6576..fa5ab6059 100644 --- a/appmgr/src/net/tor.rs +++ b/appmgr/src/net/tor.rs @@ -6,14 +6,13 @@ use futures::future::BoxFuture; use futures::FutureExt; use indexmap::IndexMap; use patch_db::DbHandle; -use sqlx::pool::PoolConnection; -use sqlx::Sqlite; +use sqlx::{Executor, Sqlite}; use tokio::net::TcpStream; use tokio::sync::RwLock; use torut::control::{AsyncEvent, AuthenticatedConn, ConnError}; use torut::onion::TorSecretKeyV3; -use crate::s9pk::manifest::TorConfig; +use super::interface::TorConfig; use crate::{Error, ResultExt as _}; fn event_handler(event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), ConnError>> { @@ -23,21 +22,23 @@ fn event_handler(event: AsyncEvent<'static>) -> BoxFuture<'static, Result<(), Co #[derive(Clone)] pub struct TorController(Arc>); impl TorController { - pub async fn init( + pub async fn init( tor_cp: SocketAddr, db: &mut Db, - secrets: &mut PoolConnection, - ) -> Result { + secrets: &mut Ex, + ) -> Result + where + for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, + { Ok(TorController(Arc::new(RwLock::new( TorControllerInner::init(tor_cp, db, secrets).await?, )))) } - pub async fn sync( - &self, - db: &mut Db, - secrets: &mut PoolConnection, - ) -> Result<(), Error> { + pub async fn sync(&self, db: &mut Db, secrets: &mut Ex) -> Result<(), Error> + where + for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, + { let new = TorControllerInner::get_services(db, secrets).await?; if &new != &self.0.read().await.services { self.0.write().await.sync(new).await?; @@ -62,10 +63,13 @@ pub struct TorControllerInner { services: IndexMap<[u8; 64], HiddenServiceConfig>, } impl TorControllerInner { - async fn get_services( + async fn get_services( db: &mut Db, - secrets: &mut PoolConnection, - ) -> Result, Error> { + secrets: &mut Ex, + ) -> Result, Error> + where + for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, + { let pkg_ids = crate::db::DatabaseModel::new() .package_data() .keys(db) @@ -189,11 +193,14 @@ impl TorControllerInner { Ok(()) } - async fn init( + async fn init( tor_cp: SocketAddr, db: &mut Db, - secrets: &mut PoolConnection, - ) -> Result { + secrets: &mut Ex, + ) -> Result + where + for<'a> &'a mut Ex: Executor<'a, Database = Sqlite>, + { let mut conn = torut::control::UnauthenticatedConn::new( TcpStream::connect(tor_cp).await?, // TODO ); diff --git a/appmgr/src/s9pk/manifest.rs b/appmgr/src/s9pk/manifest.rs index 1b6aa420e..6be2ac997 100644 --- a/appmgr/src/s9pk/manifest.rs +++ b/appmgr/src/s9pk/manifest.rs @@ -14,9 +14,10 @@ use crate::backup::BackupActions; use crate::config::action::ConfigActions; use crate::db::model::InterfaceInfo; use crate::dependencies::Dependencies; -use crate::id::{Id, InterfaceId, InvalidId, SYSTEM_ID}; +use crate::id::{Id, InvalidId, SYSTEM_ID}; use crate::migration::Migrations; use crate::net::host::Hosts; +use crate::net::interface::Interfaces; use crate::status::health_check::{HealthCheckResult, HealthChecks}; use crate::util::Version; use crate::volume::Volumes; @@ -132,37 +133,6 @@ pub struct Manifest { pub dependencies: Dependencies, } -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct Interfaces(pub IndexMap); // TODO -impl Interfaces { - pub async fn install(&self, ip: Ipv4Addr) -> Result { - todo!() - } -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct Interface { - pub tor_config: Option, - pub lan_config: Option>, - pub ui: bool, - pub protocols: Vec, -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct TorConfig { - pub port_mapping: IndexMap, -} - -#[derive(Clone, Debug, Deserialize, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct LanPortConfig { - pub ssl: bool, - pub mapping: u16, -} - #[derive(Clone, Debug, Default, Deserialize, Serialize)] pub struct Assets { #[serde(default)] diff --git a/appmgr/src/status/mod.rs b/appmgr/src/status/mod.rs index 0892ab375..423c3c65f 100644 --- a/appmgr/src/status/mod.rs +++ b/appmgr/src/status/mod.rs @@ -18,8 +18,8 @@ use crate::db::model::{ CurrentDependencyInfo, InstalledPackageDataEntryModel, PackageDataEntryModel, }; use crate::dependencies::{Dependencies, DependencyError}; -use crate::id::InterfaceId; use crate::net::host::Hosts; +use crate::net::interface::InterfaceId; use crate::s9pk::manifest::{Manifest, PackageId}; use crate::status::health_check::HealthCheckResultVariant; use crate::util::Invoke; diff --git a/appmgr/src/util.rs b/appmgr/src/util.rs index d79300481..1aa044fa3 100644 --- a/appmgr/src/util.rs +++ b/appmgr/src/util.rs @@ -1,7 +1,7 @@ use std::future::Future; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; use std::path::Path; use std::process::{exit, Stdio}; use std::str::FromStr; @@ -12,6 +12,7 @@ use async_trait::async_trait; use clap::ArgMatches; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::Value; +use sqlx::{Executor, Sqlite}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf}; use tokio::sync::RwLock; diff --git a/appmgr/src/volume/mod.rs b/appmgr/src/volume/mod.rs index 49d33d09a..743091842 100644 --- a/appmgr/src/volume/mod.rs +++ b/appmgr/src/volume/mod.rs @@ -6,7 +6,8 @@ use indexmap::IndexMap; use patch_db::{HasModel, Map, MapModel}; use serde::{Deserialize, Deserializer, Serialize}; -use crate::id::{Id, IdUnchecked, InterfaceId}; +use crate::id::{Id, IdUnchecked}; +use crate::net::interface::InterfaceId; use crate::s9pk::manifest::PackageId; pub mod disk; @@ -129,8 +130,6 @@ pub enum Volume { #[serde(rename_all = "kebab-case")] Certificate { interface_id: InterfaceId }, #[serde(rename_all = "kebab-case")] - HiddenService { interface_id: InterfaceId }, - #[serde(rename_all = "kebab-case")] #[serde(skip)] Backup { readonly: bool }, } @@ -155,10 +154,6 @@ impl Volume { .join(pkg_id) .join("certificates") .join(interface_id), - Volume::HiddenService { interface_id } => Path::new(PKG_VOLUME_DIR) - .join(pkg_id) - .join("hidden-services") - .join(interface_id), Volume::Backup { .. } => Path::new(BACKUP_DIR).join(pkg_id), } } @@ -181,7 +176,6 @@ impl Volume { Volume::Data { readonly } => *readonly, Volume::Pointer { readonly, .. } => *readonly, Volume::Certificate { .. } => true, - Volume::HiddenService { .. } => true, Volume::Backup { readonly } => *readonly, } }