chore: Convert the migration to use receipt. (#1842)

This commit is contained in:
J M
2022-09-28 13:47:04 -06:00
committed by Aiden McClelland
parent 2ddd38796d
commit 78ad5d5879
7 changed files with 100 additions and 45 deletions

View File

@@ -82,8 +82,8 @@ async fn inner_main(cfg_path: Option<&str>) -> Result<Option<Shutdown>, Error> {
});
let mut db = rpc_ctx.db.handle();
embassy::hostname::sync_hostname(&mut db).await?;
let receipts = embassy::context::rpc::RpcSetNginxReceipts::new(&mut db).await?;
embassy::hostname::sync_hostname(&mut db, &receipts.hostname_receipts).await?;
rpc_ctx.set_nginx_conf(&mut db, receipts).await?;
drop(db);

View File

@@ -23,6 +23,7 @@ use tracing::instrument;
use crate::core::rpc_continuations::{RequestGuid, RestHandler, RpcContinuation};
use crate::db::model::{Database, InstalledPackageDataEntry, PackageDataEntry};
use crate::hostname::HostNameReceipt;
use crate::init::{init_postgres, pgloader};
use crate::install::cleanup::{cleanup_failed, uninstall, CleanupFailedReceipts};
use crate::manager::ManagerMap;
@@ -175,6 +176,7 @@ impl RpcCleanReceipts {
}
pub struct RpcSetNginxReceipts {
pub hostname_receipts: HostNameReceipt,
server_info: LockReceipt<crate::db::model::ServerInfo, ()>,
}
@@ -189,12 +191,14 @@ impl RpcSetNginxReceipts {
pub fn setup(
locks: &mut Vec<patch_db::LockTargetId>,
) -> impl FnOnce(&patch_db::Verifier) -> Result<Self, Error> {
let hostname_receipts = HostNameReceipt::setup(locks);
let server_info = crate::db::DatabaseModel::new()
.server_info()
.make_locker(LockType::Read)
.add_to_keys(locks);
move |skeleton_key| {
Ok(Self {
hostname_receipts: hostname_receipts(skeleton_key)?,
server_info: server_info.verify(skeleton_key)?,
})
}

View File

@@ -56,36 +56,83 @@ pub async fn set_hostname(hostname: &Hostname) -> Result<(), Error> {
Ok(())
}
#[instrument(skip(handle))]
pub async fn get_id<Db: DbHandle>(handle: &mut Db) -> Result<String, Error> {
let id = crate::db::DatabaseModel::new()
.server_info()
.id()
.get(handle, false)
.await?;
Ok(id.to_string())
#[instrument(skip(handle, receipts))]
pub async fn get_id<Db: DbHandle>(
handle: &mut Db,
receipts: &HostNameReceipt,
) -> Result<String, Error> {
let id = receipts.id.get(handle).await?;
Ok(id)
}
pub async fn get_hostname<Db: DbHandle>(handle: &mut Db) -> Result<Hostname, Error> {
if let Ok(hostname) = crate::db::DatabaseModel::new()
.server_info()
.hostname()
.get(handle, false)
.await
{
pub async fn get_hostname<Db: DbHandle>(
handle: &mut Db,
receipts: &HostNameReceipt,
) -> Result<Hostname, Error> {
if let Ok(hostname) = receipts.hostname.get(handle).await {
if let Some(hostname) = hostname.to_owned() {
return Ok(Hostname(hostname));
}
}
let id = get_id(handle).await?;
let id = get_id(handle, receipts).await?;
if id.len() != 8 {
return Ok(generate_hostname());
}
return Ok(Hostname(format!("embassy-{}", id)));
}
#[instrument(skip(handle))]
pub async fn sync_hostname<Db: DbHandle>(handle: &mut Db) -> Result<(), Error> {
set_hostname(&get_hostname(handle).await?).await?;
pub async fn ensure_hostname_is_set<Db: DbHandle>(
handle: &mut Db,
receipts: &HostNameReceipt,
) -> Result<(), Error> {
let hostname = get_hostname(handle, &receipts).await?;
receipts.hostname.set(handle, Some(hostname.0)).await?;
Ok(())
}
#[derive(Clone)]
pub struct HostNameReceipt {
hostname: patch_db::LockReceipt<Option<String>, ()>,
pub id: patch_db::LockReceipt<String, ()>,
}
impl HostNameReceipt {
pub async fn new<'a>(db: &'a mut impl DbHandle) -> Result<Self, Error> {
let mut locks = Vec::new();
let setup = Self::setup(&mut locks);
setup(&db.lock_all(locks).await?)
}
pub fn setup(
locks: &mut Vec<patch_db::LockTargetId>,
) -> impl FnOnce(&patch_db::Verifier) -> Result<Self, Error> {
use patch_db::LockType;
let hostname = crate::db::DatabaseModel::new()
.server_info()
.hostname()
.make_locker(LockType::Write)
.add_to_keys(locks);
let id = crate::db::DatabaseModel::new()
.server_info()
.id()
.make_locker(LockType::Write)
.add_to_keys(locks);
move |skeleton_key| {
Ok(Self {
hostname: hostname.verify(skeleton_key)?,
id: id.verify(skeleton_key)?,
})
}
}
}
#[instrument(skip(handle, receipts))]
pub async fn sync_hostname<Db: DbHandle>(
handle: &mut Db,
receipts: &HostNameReceipt,
) -> Result<(), Error> {
set_hostname(&get_hostname(handle, receipts).await?).await?;
Command::new("systemctl")
.arg("restart")
.arg("avahi-daemon")

View File

@@ -66,7 +66,9 @@ impl NetController {
None => SslManager::init(db, handle).await,
Some(a) => SslManager::import_root_ca(db, a.0, a.1).await,
}?;
let hostname = get_hostname(handle).await?;
let hostname_receipts = crate::hostname::HostNameReceipt::new(handle).await?;
let hostname = get_hostname(handle, &hostname_receipts).await?;
Ok(Self {
tor: TorController::init(embassyd_addr, embassyd_tor_key, tor_control).await?,
#[cfg(feature = "avahi")]

View File

@@ -165,7 +165,8 @@ impl SslManager {
#[instrument(skip(db, handle))]
pub async fn init<Db: DbHandle>(db: PgPool, handle: &mut Db) -> Result<Self, Error> {
let store = SslStore::new(db)?;
let id = crate::hostname::get_id(handle).await?;
let receipts = crate::hostname::HostNameReceipt::new(handle).await?;
let id = crate::hostname::get_id(handle, &receipts).await?;
let (root_key, root_cert) = match store.load_root_certificate().await? {
None => {
let root_key = generate_key()?;
@@ -528,7 +529,7 @@ fn make_leaf_cert(
// let root_cert1 = mgr.root_cert;
// let int_key1 = mgr.int_key;
// let int_cert1 = mgr.int_cert;
//
//
// assert_eq!(root_cert0.to_pem()?, root_cert1.to_pem()?);
// assert_eq!(
// int_key0.private_key_to_pem_pkcs8()?,
@@ -537,7 +538,7 @@ fn make_leaf_cert(
// assert_eq!(int_cert0.to_pem()?, int_cert1.to_pem()?);
// Ok(())
// }
//
//
// #[tokio::test]
// async fn certificate_details_persist() -> Result<(), Error> {
// let pool = sqlx::Pool::<sqlx::Postgres>::connect("postgres::memory:").await?;
@@ -549,7 +550,7 @@ fn make_leaf_cert(
// let package_id = "bitcoind".parse().unwrap();
// let (key0, cert_chain0) = mgr.certificate_for("start9", &package_id).await?;
// let (key1, cert_chain1) = mgr.certificate_for("start9", &package_id).await?;
//
//
// assert_eq!(
// key0.private_key_to_pem_pkcs8()?,
// key1.private_key_to_pem_pkcs8()?

View File

@@ -38,7 +38,7 @@ use crate::disk::mount::filesystem::ReadOnly;
use crate::disk::mount::guard::TmpMountGuard;
use crate::disk::util::{pvscan, recovery_info, DiskInfo, EmbassyOsRecoveryInfo};
use crate::disk::REPAIR_DISK_PATH;
use crate::hostname::{get_hostname, Hostname};
use crate::hostname::{get_hostname, HostNameReceipt, Hostname};
use crate::id::Id;
use crate::init::init;
use crate::install::PKG_PUBLIC_DIR;
@@ -158,7 +158,9 @@ pub async fn attach(
db_tx.commit().await?;
secrets_tx.commit().await?;
let hostname = get_hostname(&mut db_handle).await?;
let hostname_receipts = HostNameReceipt::new(&mut db_handle).await?;
let hostname = get_hostname(&mut db_handle, &hostname_receipts).await?;
let (_, root_ca) = SslManager::init(secrets, &mut db_handle)
.await?
@@ -321,9 +323,10 @@ pub async fn complete(#[context] ctx: SetupContext) -> Result<SetupResult, Error
};
let secrets = ctx.secret_store().await?;
let mut db = ctx.db(&secrets).await?.handle();
let hostname = crate::hostname::get_hostname(&mut db).await?;
let receipts = crate::hostname::HostNameReceipt::new(&mut db).await?;
let hostname = crate::hostname::get_hostname(&mut db, &receipts).await?;
let si = crate::db::DatabaseModel::new().server_info();
let id = crate::hostname::get_id(&mut db).await?;
let id = crate::hostname::get_id(&mut db, &receipts).await?;
si.clone().id().put(&mut db, &id).await?;
si.lan_address()
.put(&mut db, &hostname.lan_address().parse().unwrap())
@@ -378,7 +381,11 @@ pub async fn execute_inner(
let db = init(&RpcContextConfig::load(ctx.config_path.as_ref()).await?)
.await?
.db;
let hostname = get_hostname(&mut db.handle()).await?;
let hostname = {
let mut handle = db.handle();
let receipts = crate::hostname::HostNameReceipt::new(&mut handle).await?;
get_hostname(&mut handle, &receipts).await?
};
let res = (hostname.clone(), tor_addr, root_ca.clone());
tokio::spawn(async move {
if let Err(e) = recover_fut
@@ -412,15 +419,17 @@ pub async fn execute_inner(
let db = init(&RpcContextConfig::load(ctx.config_path.as_ref()).await?)
.await?
.db;
let mut handle = db.handle();
let receipts = crate::hostname::HostNameReceipt::new(&mut handle).await?;
*ctx.setup_result.write().await = Some((
guid,
SetupResult {
tor_address: format!("http://{}", tor_addr),
lan_address: get_hostname(&mut db.handle()).await?.lan_address(),
lan_address: get_hostname(&mut handle, &receipts).await?.lan_address(),
root_ca: String::from_utf8(root_ca.to_pem()?)?,
},
));
let hostname = get_hostname(&mut db.handle()).await?;
let hostname = get_hostname(&mut handle, &receipts).await?;
(hostname, tor_addr, root_ca)
};

View File

@@ -1,6 +1,6 @@
use emver::VersionRange;
use crate::hostname::{generate_id, get_hostname, sync_hostname};
use crate::hostname::{generate_id, sync_hostname};
use super::v0_3_0::V0_3_0_COMPAT;
use super::*;
@@ -22,19 +22,11 @@ impl VersionT for Version {
&*V0_3_0_COMPAT
}
async fn up<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> {
let hostname = get_hostname(db).await?;
crate::db::DatabaseModel::new()
.server_info()
.hostname()
.put(db, &Some(hostname.0))
.await?;
crate::db::DatabaseModel::new()
.server_info()
.id()
.put(db, &generate_id())
.await?;
let receipts = crate::hostname::HostNameReceipt::new(db).await?;
crate::hostname::ensure_hostname_is_set(db, &receipts).await?;
receipts.id.set(db, generate_id()).await?;
sync_hostname(db).await?;
sync_hostname(db, &receipts).await?;
Ok(())
}
async fn down<Db: DbHandle>(&self, _db: &mut Db) -> Result<(), Error> {