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:
Lucy C
2021-03-19 16:50:52 -06:00
committed by GitHub
parent 5b8f27e53e
commit 11b007a31d
8 changed files with 80 additions and 22 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -59,7 +60,8 @@ instance FromJSON RestoreBackupReq where
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

View File

@@ -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"

View File

@@ -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

View File

@@ -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(())
} }

View File

@@ -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)]

View File

@@ -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>