reworked constants into configurable settings

This commit is contained in:
Lucy Cifferello
2020-03-12 17:26:27 -06:00
parent 924f5df8e1
commit 74d3c0c1b8
10 changed files with 97 additions and 92 deletions

View File

@@ -0,0 +1,6 @@
{
"0.1.0": "1.0.0",
"0.1.1": "1.0.0",
"0.1.2": "1.1.0",
"0.1.3": "1.1.0"
}

View File

@@ -28,4 +28,7 @@ ip-from-header: "_env:YESOD_IP_FROM_HEADER:false"
# NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:YESOD_PGPASS:'123'") # NB: If you need a numeric value (e.g. 123) to parse as a String, wrap it in single quotes (e.g. "_env:YESOD_PGPASS:'123'")
# See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings # See https://github.com/yesodweb/yesod/wiki/Configuration#parsing-numeric-values-as-strings
app-compatibility-path: "_env:APP_COMPATIBILITY_CONFIG:/etc/start9/registry/compatibility.json" app-compatibility-path: "_env:APP_COMPATIBILITY_CONFIG:/etc/start9/registry/compatibility.json"
resources-path: "_env:RESOURCES_PATH:/var/www/html/resources"
ssl-path: "_env:SSL_PATH:/var/ssl"
registry-hostname: "_env:REGISTRY_HOSTNAME:registry.start9labs.com"

View File

@@ -165,16 +165,15 @@ startApp :: AgentCtx -> IO ()
startApp foundation = do startApp foundation = do
-- set up ssl certificates -- set up ssl certificates
putStrLn @Text "Setting up SSL" putStrLn @Text "Setting up SSL"
setupSsl _ <- setupSsl <$> getAppSettings
putStrLn @Text "SSL Setup Complete" putStrLn @Text "SSL Setup Complete"
startWeb foundation startWeb foundation
startWeb :: AgentCtx -> IO () startWeb :: AgentCtx -> IO ()
startWeb foundation = do startWeb foundation = do
app <- makeApplication foundation app <- makeApplication foundation
let AppSettings{..} = appSettings foundation
putStrLn @Text $ "Launching Web Server on port " <> show (appPort $ appSettings foundation) putStrLn @Text $ "Launching Web Server on port " <> show appPort
action <- async $ runTLS action <- async $ runTLS
(tlsSettings sslCertLocation sslKeyLocation) (tlsSettings sslCertLocation sslKeyLocation)
(warpSettings foundation) (warpSettings foundation)

View File

@@ -1,21 +0,0 @@
module Constants where
import Data.Aeson
import Data.Aeson.Types
import Data.Maybe
import Data.Version (showVersion)
import Lib.Types.Semver
import Paths_start9_registry (version)
import Startlude
sslPath :: FilePath
sslPath = "/var/ssl"
resourcesDir :: FilePath
resourcesDir = "/var/www/html/resources" -- "./resources" --
registryVersion :: AppVersion
registryVersion = fromJust . parseMaybe parseJSON . String . toS . showVersion $ version
getRegistryHostname :: IsString a => a
getRegistryHostname = "registry.start9labs.com"

View File

@@ -23,8 +23,9 @@ import Yesod.Core
import Foundation import Foundation
import Lib.Registry import Lib.Registry
import Lib.Semver import Lib.Semver
import System.FilePath ((<.>)) import System.FilePath ((<.>), (</>))
import System.Posix.Files (fileSize, getFileStatus) import System.Posix.Files (fileSize, getFileStatus)
import Settings
pureLog :: Show a => a -> Handler a pureLog :: Show a => a -> Handler a
pureLog = liftA2 (*>) ($logInfo . show) pure pureLog = liftA2 (*>) ($logInfo . show) pure
@@ -38,13 +39,22 @@ instance Show FileExtension where
show (FileExtension f (Just e)) = f <.> e show (FileExtension f (Just e)) = f <.> e
getAppsManifestR :: Handler TypedContent getAppsManifestR :: Handler TypedContent
getAppsManifestR = respondSource typePlain $ CB.sourceFile appManifestPath .| awaitForever sendChunkBS getAppsManifestR = do
AppSettings{..} <- appSettings <$> getYesod
let appResourceDir = resourcesDir </> "apps" </> "apps.yaml"
respondSource typePlain $ CB.sourceFile appResourceDir .| awaitForever sendChunkBS
getSysR :: Extension "" -> Handler TypedContent getSysR :: Extension "" -> Handler TypedContent
getSysR = getApp sysResourceDir getSysR e = do
AppSettings{..} <- appSettings <$> getYesod
let sysResourceDir = resourcesDir </> "sys"
getApp sysResourceDir e
getAppR :: Extension "s9pk" -> Handler TypedContent getAppR :: Extension "s9pk" -> Handler TypedContent
getAppR = getApp appResourceDir getAppR e = do
AppSettings{..} <- appSettings <$> getYesod
let appResourceDir = resourcesDir </> "apps" </> "apps.yaml"
getApp appResourceDir e
getApp :: KnownSymbol a => FilePath -> Extension a -> Handler TypedContent getApp :: KnownSymbol a => FilePath -> Extension a -> Handler TypedContent
getApp rootDir ext = do getApp rootDir ext = do

View File

@@ -1,5 +1,6 @@
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RecordWildCards #-}
module Handler.Icons where module Handler.Icons where
@@ -12,10 +13,13 @@ import Yesod.Core
import Foundation import Foundation
import Lib.Registry import Lib.Registry
import Settings
import System.FilePath ((</>))
getIconsR :: Extension "png" -> Handler TypedContent getIconsR :: Extension "png" -> Handler TypedContent
getIconsR ext = do getIconsR ext = do
mPng <- liftIO $ getUnversionedFileFromDir iconsResourceDir ext AppSettings{..} <- appSettings <$> getYesod
mPng <- liftIO $ getUnversionedFileFromDir (resourcesDir </> "icons") ext
case mPng of case mPng of
Nothing -> notFound Nothing -> notFound
Just pngPath -> do Just pngPath -> do

View File

@@ -2,6 +2,8 @@
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE RecordWildCards #-}
module Handler.Version where module Handler.Version where
import Startlude import Startlude
@@ -14,24 +16,30 @@ import qualified Data.Text as T
import Network.HTTP.Types import Network.HTTP.Types
import Yesod.Core import Yesod.Core
import Constants
import Foundation import Foundation
import Handler.Types.Status import Handler.Types.Status
import Lib.Registry import Lib.Registry
import Lib.Semver import Lib.Semver
import Lib.Types.Semver import Lib.Types.Semver
import Settings
import System.FilePath ((</>))
getVersionR :: Handler AppVersionRes getVersionR :: Handler AppVersionRes
getVersionR = pure . AppVersionRes registryVersion $ Nothing getVersionR = do
AppSettings{..} <- appSettings <$> getYesod
pure . AppVersionRes registryVersion $ Nothing
getVersionAppR :: Text -> Handler (Maybe AppVersionRes) getVersionAppR :: Text -> Handler (Maybe AppVersionRes)
getVersionAppR appId = getVersionWSpec appResourceDir appExt getVersionAppR appId = do
AppSettings{..} <- appSettings <$> getYesod
getVersionWSpec (resourcesDir </> "apps") appExt
where where
appExt = Extension (toS appId) :: Extension "s9pk" appExt = Extension (toS appId) :: Extension "s9pk"
getVersionSysR :: Text -> Handler (Maybe AppVersionRes) getVersionSysR :: Text -> Handler (Maybe AppVersionRes)
getVersionSysR sysAppId = runMaybeT $ do getVersionSysR sysAppId = runMaybeT $ do
avr <- MaybeT $ getVersionWSpec sysResourceDir sysExt AppSettings{..} <- appSettings <$> getYesod
avr <- MaybeT $ getVersionWSpec (resourcesDir </> "sys") sysExt
minComp <- lift $ case sysAppId of minComp <- lift $ case sysAppId of
"agent" -> Just <$> meshCompanionCompatibility (appVersionVersion avr) "agent" -> Just <$> meshCompanionCompatibility (appVersionVersion avr)
_ -> pure Nothing _ -> pure Nothing

View File

@@ -14,25 +14,9 @@ import System.Directory
import System.FilePath import System.FilePath
import Yesod.Core import Yesod.Core
import Constants
import Lib.Semver import Lib.Semver
import Lib.Types.Semver import Lib.Types.Semver
appResourceDir :: FilePath
appResourceDir = resourcesDir </> "apps"
sysResourceDir :: FilePath
sysResourceDir = resourcesDir </> "sys"
iconsResourceDir :: FilePath
iconsResourceDir = resourcesDir </> "icons"
appManifestPath :: FilePath
appManifestPath = appResourceDir </> appManifestFile
appManifestFile :: FilePath
appManifestFile = "apps.yaml"
type Registry = HashMap String (HashMap AppVersion FilePath) type Registry = HashMap String (HashMap AppVersion FilePath)
newtype RegisteredAppVersion = RegisteredAppVersion (AppVersion, FilePath) deriving (Eq, Show) newtype RegisteredAppVersion = RegisteredAppVersion (AppVersion, FilePath) deriving (Eq, Show)

View File

@@ -1,58 +1,49 @@
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
module Lib.Ssl where module Lib.Ssl where
import Startlude import Startlude
import Data.String.Interpolate.IsString import Data.String.Interpolate.IsString
import System.Directory import System.Directory
import System.FilePath
import System.Process import System.Process
import Settings
import Constants
-- openssl genrsa -out key.pem 2048 -- openssl genrsa -out key.pem 2048
-- openssl req -new -key key.pem -out certificate.csr -- openssl req -new -key key.pem -out certificate.csr
-- openssl x509 -req -in certificate.csr -signkey key.pem -out certificate.pem -- openssl x509 -req -in certificate.csr -signkey key.pem -out certificate.pem
sslKeyLocation :: FilePath setupSsl :: AppSettings -> IO ()
sslKeyLocation = sslPath </> "key.pem" setupSsl AppSettings{..} = do
sslCsrLocation :: FilePath
sslCsrLocation = sslPath </> "certificate.csr"
sslCertLocation :: FilePath
sslCertLocation = sslPath </> "certificate.pem"
checkForSslCert :: IO Bool
checkForSslCert =
doesPathExist sslKeyLocation <&&> doesPathExist sslCertLocation
generateSslKey :: IO ExitCode
generateSslKey = rawSystem "openssl" ["genrsa", "-out", sslKeyLocation, "2048"]
generateSslCert :: Text -> IO ExitCode
generateSslCert name = rawSystem
"openssl"
["req", "-new", "-key", sslKeyLocation, "-out", sslCsrLocation, "-subj", [i|/CN=#{name}.local|]]
selfSignSslCert :: IO ExitCode
selfSignSslCert = rawSystem
"openssl"
[ "x509"
, "-req"
, "-in"
, sslCsrLocation
, "-signkey"
, sslKeyLocation
, "-out"
, sslCertLocation
]
setupSsl :: IO ()
setupSsl = do
exists <- checkForSslCert exists <- checkForSslCert
unless exists $ do unless exists $ do
void $ system $ "mkdir -p " <> sslPath void $ system $ "mkdir -p " <> sslPath
void generateSslKey void generateSslKey
void $ generateSslCert getRegistryHostname void $ generateSslCert registryHostname
void selfSignSslCert void selfSignSslCert
where
checkForSslCert :: IO Bool
checkForSslCert =
doesPathExist sslKeyLocation <&&> doesPathExist sslCertLocation
generateSslKey :: IO ExitCode
generateSslKey = rawSystem "openssl" ["genrsa", "-out", sslKeyLocation, "2048"]
generateSslCert :: Text -> IO ExitCode
generateSslCert name = rawSystem
"openssl"
["req", "-new", "-key", sslKeyLocation, "-out", sslCsrLocation, "-subj", [i|/CN=#{name}.local|]]
selfSignSslCert :: IO ExitCode
selfSignSslCert = rawSystem
"openssl"
[ "x509"
, "-req"
, "-in"
, sslCsrLocation
, "-signkey"
, sslKeyLocation
, "-out"
, sslCertLocation
]

View File

@@ -10,11 +10,17 @@ module Settings where
import Startlude import Startlude
import qualified Control.Exception as Exception import qualified Control.Exception as Exception
import Data.Maybe
import Data.Aeson import Data.Aeson
import Data.Aeson.Types
import Data.Version (showVersion)
import Data.FileEmbed (embedFile) import Data.FileEmbed (embedFile)
import Data.Yaml (decodeEither') import Data.Yaml (decodeEither')
import Network.Wai.Handler.Warp (HostPreference) import Network.Wai.Handler.Warp (HostPreference)
import Yesod.Default.Config2 (applyEnvValue, configSettingsYml) import Yesod.Default.Config2 (applyEnvValue, configSettingsYml)
import Paths_start9_registry (version)
import Lib.Types.Semver
import System.FilePath ((</>))
-- | Runtime settings to configure this application. These settings can be -- | Runtime settings to configure this application. These settings can be
-- loaded from various sources: defaults, environment variables, config files, -- loaded from various sources: defaults, environment variables, config files,
@@ -33,6 +39,13 @@ data AppSettings = AppSettings
, appShouldLogAll :: Bool , appShouldLogAll :: Bool
-- ^ Should all log messages be displayed? -- ^ Should all log messages be displayed?
, appCompatibilityPath :: FilePath , appCompatibilityPath :: FilePath
, resourcesDir :: FilePath
, sslPath :: FilePath
, registryHostname :: Text
, registryVersion :: AppVersion
, sslKeyLocation :: FilePath
, sslCsrLocation :: FilePath
, sslCertLocation :: FilePath
} }
instance FromJSON AppSettings where instance FromJSON AppSettings where
@@ -43,7 +56,15 @@ instance FromJSON AppSettings where
appDetailedRequestLogging <- o .:? "detailed-logging" .!= True appDetailedRequestLogging <- o .:? "detailed-logging" .!= True
appShouldLogAll <- o .:? "should-log-all" .!= False appShouldLogAll <- o .:? "should-log-all" .!= False
appCompatibilityPath <- o .: "app-compatibility-path" appCompatibilityPath <- o .: "app-compatibility-path"
resourcesDir <- o .: "resources-path"
sslPath <- o .: "ssl-path"
registryHostname <- o .: "registry-hostname"
let sslKeyLocation = sslPath </> "key.pem"
let sslCsrLocation = sslPath </> "certificate.csr"
let sslCertLocation = sslPath </> "certificate.pem"
let registryVersion = fromJust . parseMaybe parseJSON . String . toS . showVersion $ version
return AppSettings { .. } return AppSettings { .. }
-- | Raw bytes at compile time of @config/settings.yml@ -- | Raw bytes at compile time of @config/settings.yml@