mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
Fix/integration/0.2.11 (#265)
* backports tor security fix to 0.2.10, adds functionality to allow for ssh key management during an update (#263) * actually upgrade to 0.3.5.14-1 * update lan services on backup restore * reload nginx, update welcome message, move reset lan to handler * moves lan refresh after backup restore to asynchronous part of restore * fix certificate generation * match guards Co-authored-by: Keagan McClelland <keagan.mcclelland@gmail.com>
This commit is contained in:
@@ -186,6 +186,8 @@ cutoffDuringUpdate m = do
|
|||||||
path <- asks $ pathInfo . reqWaiRequest . handlerRequest
|
path <- asks $ pathInfo . reqWaiRequest . handlerRequest
|
||||||
case path of
|
case path of
|
||||||
[v] | v == "v" <> (show . major $ agentVersion) -> m
|
[v] | v == "v" <> (show . major $ agentVersion) -> m
|
||||||
|
[auth] | auth == "auth" -> m
|
||||||
|
(_:ssh:_) | ssh == "sshKeys" -> m
|
||||||
_ -> handleS9ErrT $ throwE UpdateInProgressE
|
_ -> handleS9ErrT $ throwE UpdateInProgressE
|
||||||
Nothing -> m
|
Nothing -> m
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,11 @@ type AllEffects m
|
|||||||
( Labelled
|
( Labelled
|
||||||
"databaseConnection"
|
"databaseConnection"
|
||||||
(ReaderT ConnectionPool)
|
(ReaderT ConnectionPool)
|
||||||
(ReaderT AgentCtx (ErrorC S9Error (LiftC m)))
|
( Labelled
|
||||||
|
"lanThread"
|
||||||
|
(ReaderT (MVar ThreadId))
|
||||||
|
(ReaderT AgentCtx (ErrorC S9Error (LiftC m)))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -122,6 +126,8 @@ intoHandler m = do
|
|||||||
runM
|
runM
|
||||||
. handleS9ErrC
|
. handleS9ErrC
|
||||||
. flip runReaderT ctx
|
. flip runReaderT ctx
|
||||||
|
. flip runReaderT (appLanThread ctx)
|
||||||
|
. runLabelled @"lanThread"
|
||||||
. flip runReaderT (appConnPool ctx)
|
. flip runReaderT (appConnPool ctx)
|
||||||
. runLabelled @"databaseConnection"
|
. runLabelled @"databaseConnection"
|
||||||
. flip runReaderT fsbase
|
. flip runReaderT fsbase
|
||||||
@@ -376,6 +382,7 @@ postUninstallAppLogic :: ( HasFilesystemBase sig m
|
|||||||
, MonadIO m
|
, MonadIO m
|
||||||
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
||||||
, HasLabelled "iconTagCache" (Reader (TVar (HM.HashMap AppId (Digest MD5)))) sig m
|
, HasLabelled "iconTagCache" (Reader (TVar (HM.HashMap AppId (Digest MD5)))) sig m
|
||||||
|
, HasLabelled "lanThread" (Reader (MVar ThreadId)) sig m
|
||||||
)
|
)
|
||||||
=> AppId
|
=> AppId
|
||||||
-> AppMgr2.DryRun
|
-> AppMgr2.DryRun
|
||||||
@@ -413,6 +420,7 @@ postInstallNewAppR appId = do
|
|||||||
|
|
||||||
postInstallNewAppLogic :: forall sig m a
|
postInstallNewAppLogic :: forall sig m a
|
||||||
. ( Has (Reader AgentCtx) sig m
|
. ( Has (Reader AgentCtx) sig m
|
||||||
|
, HasLabelled "lanThread" (Reader (MVar ThreadId)) sig m
|
||||||
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
||||||
, HasLabelled "iconTagCache" (Reader (TVar (HM.HashMap AppId (Digest MD5)))) sig m
|
, HasLabelled "iconTagCache" (Reader (TVar (HM.HashMap AppId (Digest MD5)))) sig m
|
||||||
, Has (Error S9Error) sig m
|
, Has (Error S9Error) sig m
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import Startlude hiding ( Reader
|
|||||||
, runReader
|
, runReader
|
||||||
)
|
)
|
||||||
|
|
||||||
import Control.Effect.Labelled hiding ( Handler )
|
|
||||||
import Control.Effect.Reader.Labelled
|
|
||||||
import Control.Carrier.Error.Church
|
import Control.Carrier.Error.Church
|
||||||
import Control.Carrier.Lift
|
import Control.Carrier.Lift
|
||||||
import Control.Carrier.Reader ( runReader )
|
import Control.Carrier.Reader ( runReader )
|
||||||
|
import Control.Effect.Labelled hiding ( Handler )
|
||||||
|
import Control.Effect.Reader.Labelled
|
||||||
import Data.Aeson
|
import Data.Aeson
|
||||||
import qualified Data.HashMap.Strict as HM
|
import qualified Data.HashMap.Strict as HM
|
||||||
import Data.UUID.V4
|
import Data.UUID.V4
|
||||||
@@ -20,8 +20,13 @@ import Yesod.Auth
|
|||||||
import Yesod.Core
|
import Yesod.Core
|
||||||
import Yesod.Core.Types
|
import Yesod.Core.Types
|
||||||
|
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Exinst
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import Handler.Network
|
||||||
import Handler.Util
|
import Handler.Util
|
||||||
|
import qualified Lib.Algebra.Domain.AppMgr as AppMgr2
|
||||||
|
import Lib.Background
|
||||||
import Lib.Error
|
import Lib.Error
|
||||||
import qualified Lib.External.AppMgr as AppMgr
|
import qualified Lib.External.AppMgr as AppMgr
|
||||||
import qualified Lib.Notifications as Notifications
|
import qualified Lib.Notifications as Notifications
|
||||||
@@ -29,10 +34,6 @@ import Lib.Password
|
|||||||
import Lib.Types.Core
|
import Lib.Types.Core
|
||||||
import Lib.Types.Emver
|
import Lib.Types.Emver
|
||||||
import Model
|
import Model
|
||||||
import qualified Lib.Algebra.Domain.AppMgr as AppMgr2
|
|
||||||
import Lib.Background
|
|
||||||
import Control.Concurrent.STM
|
|
||||||
import Exinst
|
|
||||||
|
|
||||||
|
|
||||||
data CreateBackupReq = CreateBackupReq
|
data CreateBackupReq = CreateBackupReq
|
||||||
@@ -58,8 +59,9 @@ instance FromJSON RestoreBackupReq where
|
|||||||
pure RestoreBackupReq { .. }
|
pure RestoreBackupReq { .. }
|
||||||
|
|
||||||
data EjectDiskReq = EjectDiskReq
|
data EjectDiskReq = EjectDiskReq
|
||||||
{ ejectDiskLogicalName :: Text
|
{ ejectDiskLogicalName :: Text
|
||||||
} deriving (Eq, Show)
|
}
|
||||||
|
deriving (Eq, Show)
|
||||||
instance FromJSON EjectDiskReq where
|
instance FromJSON EjectDiskReq where
|
||||||
parseJSON = withObject "Eject Disk Req" $ \o -> do
|
parseJSON = withObject "Eject Disk Req" $ \o -> do
|
||||||
ejectDiskLogicalName <- o .: "logicalName"
|
ejectDiskLogicalName <- o .: "logicalName"
|
||||||
@@ -100,6 +102,8 @@ postRestoreBackupR appId = disableEndpointOnFailedUpdate $ do
|
|||||||
& runReader appConnPool
|
& runReader appConnPool
|
||||||
& runLabelled @"backgroundJobCache"
|
& runLabelled @"backgroundJobCache"
|
||||||
& runReader appBackgroundJobs
|
& runReader appBackgroundJobs
|
||||||
|
& runLabelled @"lanThread"
|
||||||
|
& runReader appLanThread
|
||||||
& handleS9ErrC
|
& handleS9ErrC
|
||||||
& runM
|
& runM
|
||||||
|
|
||||||
@@ -173,6 +177,7 @@ stopBackupLogic appId = do
|
|||||||
|
|
||||||
restoreBackupLogic :: ( HasLabelled "backgroundJobCache" (Reader (TVar JobCache)) sig m
|
restoreBackupLogic :: ( HasLabelled "backgroundJobCache" (Reader (TVar JobCache)) sig m
|
||||||
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
, HasLabelled "databaseConnection" (Reader ConnectionPool) sig m
|
||||||
|
, HasLabelled "lanThread" (Reader (MVar ThreadId)) sig m
|
||||||
, Has (Error S9Error) sig m
|
, Has (Error S9Error) sig m
|
||||||
, Has AppMgr2.AppMgr sig m
|
, Has AppMgr2.AppMgr sig m
|
||||||
, MonadIO m
|
, MonadIO m
|
||||||
@@ -181,10 +186,11 @@ restoreBackupLogic :: ( HasLabelled "backgroundJobCache" (Reader (TVar JobCache)
|
|||||||
-> RestoreBackupReq
|
-> RestoreBackupReq
|
||||||
-> m ()
|
-> m ()
|
||||||
restoreBackupLogic appId RestoreBackupReq {..} = do
|
restoreBackupLogic appId RestoreBackupReq {..} = do
|
||||||
jobCache <- ask @"backgroundJobCache"
|
lanThread <- ask @"lanThread"
|
||||||
db <- ask @"databaseConnection"
|
jobCache <- ask @"backgroundJobCache"
|
||||||
version <- fmap AppMgr2.infoResVersion $ AppMgr2.info [AppMgr2.flags| |] appId `orThrowM` NotFoundE "appId"
|
db <- ask @"databaseConnection"
|
||||||
(show appId)
|
version <- fmap AppMgr2.infoResVersion $ AppMgr2.info [AppMgr2.flags| |] appId `orThrowM` NotFoundE "appId"
|
||||||
|
(show appId)
|
||||||
res <- liftIO . atomically $ do
|
res <- liftIO . atomically $ do
|
||||||
(JobCache jobs) <- readTVar jobCache
|
(JobCache jobs) <- readTVar jobCache
|
||||||
case HM.lookup appId jobs of
|
case HM.lookup appId jobs of
|
||||||
@@ -206,10 +212,13 @@ restoreBackupLogic appId RestoreBackupReq {..} = do
|
|||||||
let notif = case appmgrRes of
|
let notif = case appmgrRes of
|
||||||
Left e -> Notifications.RestoreFailed e
|
Left e -> Notifications.RestoreFailed e
|
||||||
Right _ -> Notifications.RestoreSucceeded
|
Right _ -> Notifications.RestoreSucceeded
|
||||||
|
resetRes <- runExceptT @S9Error $ runReader lanThread . runLabelled @"lanThread" $ postResetLanLogic
|
||||||
|
case resetRes of
|
||||||
|
Left _ -> pure () -- temporarily forbidden is the only possible thing here so ignore it
|
||||||
|
Right () -> pure ()
|
||||||
flip runSqlPool db $ void $ Notifications.emit appId version notif
|
flip runSqlPool db $ void $ Notifications.emit appId version notif
|
||||||
liftIO . atomically $ modifyTVar jobCache (insertJob appId Restore tid)
|
liftIO . atomically $ modifyTVar jobCache (insertJob appId Restore tid)
|
||||||
|
|
||||||
|
|
||||||
listDisksLogic :: (Has (Error S9Error) sig m, MonadIO m) => m [AppMgr.DiskInfo]
|
listDisksLogic :: (Has (Error S9Error) sig m, MonadIO m) => m [AppMgr.DiskInfo]
|
||||||
listDisksLogic = runExceptT AppMgr.diskShow >>= liftEither
|
listDisksLogic = runExceptT AppMgr.diskShow >>= liftEither
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
module Handler.Network where
|
module Handler.Network where
|
||||||
|
|
||||||
import Startlude hiding ( Reader
|
import Startlude hiding ( Reader
|
||||||
|
, ask
|
||||||
, asks
|
, asks
|
||||||
, runReader
|
, runReader
|
||||||
)
|
)
|
||||||
|
|
||||||
import Control.Carrier.Lift ( runM )
|
import Control.Carrier.Lift ( runM )
|
||||||
import Control.Effect.Error
|
import Control.Effect.Error
|
||||||
import Control.Carrier.Reader
|
|
||||||
import Lib.Error
|
import Lib.Error
|
||||||
import Yesod.Core ( getYesod )
|
import Yesod.Core ( getYesod )
|
||||||
|
|
||||||
|
import Control.Carrier.Reader ( runReader )
|
||||||
|
import Control.Effect.Labelled ( runLabelled )
|
||||||
|
import Control.Effect.Reader.Labelled
|
||||||
import Foundation
|
import Foundation
|
||||||
import qualified Lib.Algebra.Domain.AppMgr as AppMgr2
|
import qualified Lib.Algebra.Domain.AppMgr as AppMgr2
|
||||||
import Lib.Types.Core
|
import Lib.Types.Core
|
||||||
@@ -18,11 +21,12 @@ import Lib.Types.Core
|
|||||||
postResetLanR :: Handler ()
|
postResetLanR :: Handler ()
|
||||||
postResetLanR = do
|
postResetLanR = do
|
||||||
ctx <- getYesod
|
ctx <- getYesod
|
||||||
runM . handleS9ErrC . runReader ctx $ postResetLanLogic
|
runM . handleS9ErrC . runReader (appLanThread ctx) . runLabelled @"lanThread" $ postResetLanLogic
|
||||||
|
|
||||||
postResetLanLogic :: (MonadIO m, Has (Reader AgentCtx) sig m, Has (Error S9Error) sig m) => m ()
|
postResetLanLogic :: (MonadIO m, HasLabelled "lanThread" (Reader (MVar ThreadId)) sig m, Has (Error S9Error) sig m)
|
||||||
|
=> m ()
|
||||||
postResetLanLogic = do
|
postResetLanLogic = do
|
||||||
threadVar <- asks appLanThread
|
threadVar <- ask @"lanThread"
|
||||||
mtid <- liftIO . tryTakeMVar $ threadVar
|
mtid <- liftIO . tryTakeMVar $ threadVar
|
||||||
case mtid of
|
case mtid of
|
||||||
Nothing -> throwError $ TemporarilyForbiddenE (AppId "LAN") "reset" "being reset"
|
Nothing -> throwError $ TemporarilyForbiddenE (AppId "LAN") "reset" "being reset"
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import System.Process ( callCommand )
|
|||||||
|
|
||||||
import Constants
|
import Constants
|
||||||
import Control.Effect.Error hiding ( run )
|
import Control.Effect.Error hiding ( run )
|
||||||
|
import Control.Effect.Labelled ( runLabelled )
|
||||||
import Daemon.ZeroConf ( getStart9AgentHostname )
|
import Daemon.ZeroConf ( getStart9AgentHostname )
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -438,10 +439,11 @@ syncInstallAppMgr = SyncOp "Install AppMgr" check migrate False
|
|||||||
Left _ -> pure True
|
Left _ -> pure True
|
||||||
Right v -> not . (v <||) <$> asks (appMgrVersionSpec . appSettings)
|
Right v -> not . (v <||) <$> asks (appMgrVersionSpec . appSettings)
|
||||||
migrate = fmap (either absurd id) . runExceptT . flip catchE failUpdate $ do
|
migrate = fmap (either absurd id) . runExceptT . flip catchE failUpdate $ do
|
||||||
|
lan <- asks appLanThread
|
||||||
avs <- asks $ appMgrVersionSpec . appSettings
|
avs <- asks $ appMgrVersionSpec . appSettings
|
||||||
av <- AppMgr.installNewAppMgr avs
|
av <- AppMgr.installNewAppMgr avs
|
||||||
unless (av <|| avs) $ throwE $ AppMgrVersionE av avs
|
unless (av <|| avs) $ throwE $ AppMgrVersionE av avs
|
||||||
postResetLanLogic -- to accommodate 0.2.x -> 0.2.9 where previous appmgr didn't correctly set up lan
|
flip runReaderT lan $ runLabelled @"lanThread" $ postResetLanLogic -- to accommodate 0.2.x -> 0.2.9 where previous appmgr didn't correctly set up lan
|
||||||
|
|
||||||
syncUpgradeLifeline :: SyncOp
|
syncUpgradeLifeline :: SyncOp
|
||||||
syncUpgradeLifeline = SyncOp "Upgrade Lifeline" check migrate False
|
syncUpgradeLifeline = SyncOp "Upgrade Lifeline" check migrate False
|
||||||
@@ -583,11 +585,11 @@ syncRestarterService = SyncOp "Install Restarter Service" check migrate True
|
|||||||
liftIO $ callCommand "systemctl enable restarter.timer"
|
liftIO $ callCommand "systemctl enable restarter.timer"
|
||||||
|
|
||||||
syncUpgradeTor :: SyncOp
|
syncUpgradeTor :: SyncOp
|
||||||
syncUpgradeTor = SyncOp "Install Tor 0.3.5.12-1" check migrate False
|
syncUpgradeTor = SyncOp "Install Tor 0.3.5.14-1" check migrate False
|
||||||
where
|
where
|
||||||
check =
|
check =
|
||||||
liftIO
|
liftIO
|
||||||
$ ( run (shell [i|dpkg -l|] $| shell [i|grep tor|] $| shell [i|grep 0.3.5.12-1|] $| conduit await)
|
$ ( run (shell [i|dpkg -l|] $| shell [i|grep tor|] $| shell [i|grep 0.3.5.14-1|] $| conduit await)
|
||||||
$> False
|
$> False
|
||||||
)
|
)
|
||||||
`catch` \(e :: ProcessException) -> case e of
|
`catch` \(e :: ProcessException) -> case e of
|
||||||
@@ -595,7 +597,7 @@ syncUpgradeTor = SyncOp "Install Tor 0.3.5.12-1" check migrate False
|
|||||||
_ -> throwIO e
|
_ -> throwIO e
|
||||||
migrate = liftIO . run $ do
|
migrate = liftIO . run $ do
|
||||||
shell "apt-get update"
|
shell "apt-get update"
|
||||||
shell "apt-get install -y tor=0.3.5.12-1"
|
shell "apt-get install -y tor=0.3.5.14-1"
|
||||||
|
|
||||||
syncDropCertificateUniqueness :: SyncOp
|
syncDropCertificateUniqueness :: SyncOp
|
||||||
syncDropCertificateUniqueness = SyncOp "Eliminate OpenSSL unique_subject=yes" check migrate False
|
syncDropCertificateUniqueness = SyncOp "Eliminate OpenSSL unique_subject=yes" check migrate False
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::os::unix::process::ExitStatusExt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use argon2::Config;
|
use argon2::Config;
|
||||||
@@ -10,6 +11,7 @@ use serde::Serialize;
|
|||||||
use crate::util::from_yaml_async_reader;
|
use crate::util::from_yaml_async_reader;
|
||||||
use crate::util::to_yaml_async_writer;
|
use crate::util::to_yaml_async_writer;
|
||||||
use crate::util::Invoke;
|
use crate::util::Invoke;
|
||||||
|
use crate::util::PersistencePath;
|
||||||
use crate::version::VersionT;
|
use crate::version::VersionT;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::ResultExt;
|
use crate::ResultExt;
|
||||||
@@ -224,6 +226,28 @@ pub async fn restore_backup<P: AsRef<Path>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
crate::tor::restart().await?;
|
crate::tor::restart().await?;
|
||||||
|
// Delete the fullchain certificate, so it can be regenerated with the restored tor pubkey address
|
||||||
|
PersistencePath::from_ref("apps")
|
||||||
|
.join(&app_id)
|
||||||
|
.join("cert-local.fullchain.crt.pem")
|
||||||
|
.delete()
|
||||||
|
.await?;
|
||||||
|
crate::tor::write_lan_services(
|
||||||
|
&crate::tor::services_map(&PersistencePath::from_ref(crate::SERVICES_YAML)).await?,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let svc_exit = std::process::Command::new("service")
|
||||||
|
.args(&["nginx", "reload"])
|
||||||
|
.status()?;
|
||||||
|
crate::ensure_code!(
|
||||||
|
svc_exit.success(),
|
||||||
|
crate::error::GENERAL_ERROR,
|
||||||
|
"Failed to Reload Nginx: {}",
|
||||||
|
svc_exit
|
||||||
|
.code()
|
||||||
|
.or_else(|| { svc_exit.signal().map(|a| 128 + a) })
|
||||||
|
.unwrap_or(0)
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,14 @@ impl PersistencePath {
|
|||||||
pub async fn for_update(self) -> Result<UpdateHandle<ForRead>, Error> {
|
pub async fn for_update(self) -> Result<UpdateHandle<ForRead>, Error> {
|
||||||
UpdateHandle::new(self).await
|
UpdateHandle::new(self).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete(&self) -> Result<(), Error> {
|
||||||
|
match tokio::fs::remove_file(self.path()).await {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(k) if k.kind() == std::io::ErrorKind::NotFound => Ok(()),
|
||||||
|
e => e.with_code(crate::error::FILESYSTEM_ERROR),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<li>Redirecting to HTTPS when navigating to LAN address</li>
|
<li>Redirecting to HTTPS when navigating to LAN address</li>
|
||||||
<li>Displaying warning messages during concurrent upgrades of dependent services</li>
|
<li>Displaying warning messages during concurrent upgrades of dependent services</li>
|
||||||
<li>Allowing larger file uploads</li>
|
<li>Allowing larger file uploads</li>
|
||||||
|
<li>Patching a security fix for Tor</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user