diff --git a/CHANGELOG.md b/CHANGELOG.md index c25c5eafd..2e2940fc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- #1415, Add support for user defined socket permission via `server-unix-socket-mode` config option - @Dansvidania - #1383, Add support for HEAD request - @steve-chavez - #1378, Add support for `Prefer: count=planned` and `Prefer: count=estimated` on GET /table - @steve-chavez diff --git a/main/Main.hs b/main/Main.hs index b5b4f67b7..0438e7e96 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -12,6 +12,7 @@ import Control.AutoUpdate (defaultUpdateSettings, mkAutoUpdate, import Control.Retry (RetryStatus, capDelay, exponentialBackoff, retrying, rsPreviousDelay) +import Data.Either.Combinators (whenLeft) import Data.IORef (IORef, atomicWriteIORef, newIORef, readIORef) import Data.String (IsString (..)) @@ -31,6 +32,8 @@ import Network.Wai.Handler.Warp (defaultSettings, runSettings, import System.Directory (removeFile) import System.IO (BufferMode (..), hSetBuffering) import System.IO.Error (isDoesNotExistError) +import System.Posix.Files (setFileMode) +import System.Posix.Types (FileMode) import PostgREST.App (postgrest) import PostgREST.Config (AppConfig (..), configPoolTimeout', @@ -163,6 +166,7 @@ main = do port = configPort conf proxy = configProxyUri conf maybeSocketAddr = configSocket conf + socketFileMode = configSocketMode conf pgSettings = toS (configDatabase conf) -- is the db-uri roleClaimKey = configRoleClaimKey conf appSettings = @@ -171,13 +175,15 @@ main = do . setServerName (toS $ "postgrest/" <> prettyVersion) $ defaultSettings + whenLeft socketFileMode panic + -- Checks that the provided proxy uri is formated correctly when (isMalformedProxyUri $ toS <$> proxy) $ panic "Malformed proxy uri, a correct example: https://example.com:8443/basePath" -- Checks that the provided jspath is valid - when (isLeft roleClaimKey) $ + whenLeft roleClaimKey $ panic $ show roleClaimKey -- @@ -250,7 +256,7 @@ main = do runSettings appSettings postgrestApplication Just socketAddr -> do -- run postgrest application with user defined socket - sock <- createAndBindSocket (unpack socketAddr) + sock <- createAndBindSocket (unpack socketAddr) (rightToMaybe socketFileMode) listen sock maxListenQueue putStrLn $ ("Listening on unix socket " :: Text) <> show socketAddr runSettingsSocket appSettings sock postgrestApplication @@ -324,11 +330,12 @@ loadDbUriFile conf = extractDbUri mDbUri Just filename -> strip <$> readFile (toS filename) setDbUri dbUri = conf {configDatabase = dbUri} -createAndBindSocket :: FilePath -> IO Socket -createAndBindSocket filePath = do - deleteSocketFileIfExist filePath +createAndBindSocket :: FilePath -> Maybe FileMode -> IO Socket +createAndBindSocket socketFilePath maybeSocketFileMode = do + deleteSocketFileIfExist socketFilePath sock <- socket AF_UNIX Stream defaultProtocol - bind sock $ SockAddrUnix filePath + bind sock $ SockAddrUnix socketFilePath + mapM_ (setFileMode socketFilePath) maybeSocketFileMode return sock where deleteSocketFileIfExist path = removeFile path `catch` handleDoesNotExist diff --git a/postgrest.cabal b/postgrest.cabal index 781ef2d7e..46ea4c592 100644 --- a/postgrest.cabal +++ b/postgrest.cabal @@ -97,6 +97,7 @@ executable postgrest , base64-bytestring >= 1 && < 1.1 , bytestring >= 0.10.8 && < 0.11 , directory >= 1.2.6 && < 1.4 + , either >= 4.4.1 && < 5.1 , hasql >= 1.4 && < 1.5 , hasql-pool >= 0.5 && < 0.6 , hasql-transaction >= 0.7.2 && < 0.8 diff --git a/src/PostgREST/Config.hs b/src/PostgREST/Config.hs index 023e111e2..74deb825f 100644 --- a/src/PostgREST/Config.hs +++ b/src/PostgREST/Config.hs @@ -46,8 +46,10 @@ import Data.Text.IO (hPutStrLn) import Data.Version (versionBranch) import Development.GitRev (gitHash) import Network.Wai.Middleware.Cors (CorsResourcePolicy (..)) +import Numeric (readOct) import Paths_postgrest (version) import System.IO.Error (IOError) +import System.Posix.Types (FileMode) import Control.Applicative import Data.Monoid @@ -63,6 +65,7 @@ import Protolude hiding (concat, hPutStrLn, intercalate, null, take, (<>)) + -- | Config file settings for the server data AppConfig = AppConfig { configDatabase :: Text @@ -72,6 +75,7 @@ data AppConfig = AppConfig { , configHost :: Text , configPort :: Int , configSocket :: Maybe Text + , configSocketMode :: Either Text FileMode , configJwtSecret :: Maybe B.ByteString , configJwtSecretIsBase64 :: Bool @@ -155,6 +159,7 @@ readOptions = do <*> (fromMaybe "!4" <$> optString "server-host") <*> (fromMaybe 3000 <$> optInt "server-port") <*> optString "server-unix-socket" + <*> parseSocketFileMode "server-unix-socket-mode" <*> (fmap encodeUtf8 <$> optString "jwt-secret") <*> (fromMaybe False <$> optBool "secret-is-base64") <*> parseJwtAudience "jwt-aud" @@ -169,6 +174,19 @@ readOptions = do <*> optString "root-spec" <*> (maybe [] (fmap encodeUtf8 . splitOnCommas) <$> optValue "raw-media-types") + parseSocketFileMode :: C.Key -> C.Parser C.Config (Either Text FileMode) + parseSocketFileMode k = + C.optional k C.string >>= \case + Nothing -> pure $ Right 493 -- return default 755 mode if no value was provided + Just fileModeText -> + case (readOct . unpack) fileModeText of + [] -> + pure $ Left "Invalid server-unix-socket-mode: not an octal" + (fileMode, _):_ -> + if fileMode < 384 || fileMode > 511 + then pure $ Left "Invalid server-unix-socket-mode: needs to be between 600 and 777" + else pure $ Right fileMode + parseJwtAudience :: C.Key -> C.Parser C.Config (Maybe StringOrURI) parseJwtAudience k = C.optional k C.string >>= \case @@ -248,6 +266,9 @@ readOptions = do |## unix socket location |## if specified it takes precedence over server-port |# server-unix-socket = "/tmp/pgrst.sock" + |## unix socket file mode + |## when none is provided, 755 is applied by default + |# server-unix-socket-mode = "755" | |## base url for swagger output |# server-proxy-uri = "" diff --git a/test/SpecHelper.hs b/test/SpecHelper.hs index e57efc8d1..d57a501e7 100644 --- a/test/SpecHelper.hs +++ b/test/SpecHelper.hs @@ -66,6 +66,8 @@ _baseCfg = -- Connection Settings AppConfig mempty "postgrest_test_anonymous" Nothing "test" "localhost" 3000 -- No user configured Unix Socket Nothing + -- No user configured Unix Socket file mode (defaults to 755) + (Right 493) -- Jwt settings (Just $ encodeUtf8 "reallyreallyreallyreallyverysafe") False Nothing -- Connection Modifiers