Skip to content

Commit

Permalink
add config option server-unix-socket-mode (#1415)
Browse files Browse the repository at this point in the history
* added config option server-unix-socket-mode to enable custom socket permissions

* added server-unix-socket-mode input validation
  • Loading branch information
Dansvidania authored and steve-chavez committed Nov 23, 2019
1 parent f9c64d9 commit 2e6c78d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
19 changes: 13 additions & 6 deletions main/Main.hs
Expand Up @@ -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 (..))
Expand All @@ -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',
Expand Down Expand Up @@ -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 =
Expand All @@ -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

--
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions postgrest.cabal
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions src/PostgREST/Config.hs
Expand Up @@ -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
Expand All @@ -63,6 +65,7 @@ import Protolude hiding (concat, hPutStrLn, intercalate, null,
take, (<>))



-- | Config file settings for the server
data AppConfig = AppConfig {
configDatabase :: Text
Expand All @@ -72,6 +75,7 @@ data AppConfig = AppConfig {
, configHost :: Text
, configPort :: Int
, configSocket :: Maybe Text
, configSocketMode :: Either Text FileMode

, configJwtSecret :: Maybe B.ByteString
, configJwtSecretIsBase64 :: Bool
Expand Down Expand Up @@ -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"
Expand All @@ -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
Expand Down Expand Up @@ -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 = ""
Expand Down
2 changes: 2 additions & 0 deletions test/SpecHelper.hs
Expand Up @@ -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
Expand Down

0 comments on commit 2e6c78d

Please sign in to comment.