Require JWT secret, remove default, optionally read from file

Fixes #474, fixes #495 when file is used
This commit is contained in:
Joe Nelson
2016-09-24 21:28:08 -07:00
parent 7bf5b0106d
commit 449480bf01
4 changed files with 21 additions and 17 deletions
+10 -4
View File
@@ -12,6 +12,7 @@ import PostgREST.OpenAPI (isMalformedProxyUri)
import PostgREST.DbStructure
import Data.String (IsString (..))
import Data.Text (stripPrefix)
import Data.Function (id)
import qualified Hasql.Query as H
import qualified Hasql.Session as H
@@ -21,7 +22,6 @@ import qualified Hasql.Pool as P
import Network.Wai.Handler.Warp
import System.IO (BufferMode (..),
hSetBuffering)
import Web.JWT (secret)
import Data.IORef
#ifndef mingw32_HOST_OS
import System.Posix.Signals
@@ -42,7 +42,7 @@ main = do
hSetBuffering stdin LineBuffering
hSetBuffering stderr NoBuffering
conf <- readOptions
conf <- loadSecretFile =<< readOptions
let host = configHost conf
port = configPort conf
proxy = configProxyUri conf
@@ -55,8 +55,6 @@ main = do
when (isMalformedProxyUri $ toS <$> proxy) $ panic
"Malformed proxy uri, a correct example: https://example.com:8443/basePath"
unless (secret "secret" /= configJwtSecret conf) $
putStrLn ("WARNING, running in insecure mode, JWT secret is the default value" :: Text)
putStrLn $ ("Listening on port " :: Text) <> show (configPort conf)
pool <- P.acquire (configPool conf, 10, pgSettings)
@@ -86,3 +84,11 @@ main = do
#endif
runSettings appSettings $ postgrest conf refDbStructure pool
loadSecretFile :: AppConfig -> IO AppConfig
loadSecretFile conf = do
let s = configJwtSecret conf
real <- case stripPrefix "@" s of
Nothing -> return s -- the string is the secret, not a filename
Just filename -> readFile (toS filename)
return conf { configJwtSecret = real }
+5 -4
View File
@@ -25,12 +25,13 @@ import qualified Text.InterpolatedString.Perl6 as P6 (q)
import Network.HTTP.Types.Header
import Network.HTTP.Types.Status
import Network.HTTP.Types.URI (renderSimpleQuery)
import Network.HTTP.Types.URI (renderSimpleQuery)
import Network.Wai
import Network.Wai.Middleware.RequestLogger (logStdout)
import Web.JWT (secret)
import Data.Aeson
import Data.Aeson.Types (emptyArray)
import Data.Aeson.Types (emptyArray)
import Data.Time.Clock.POSIX (getPOSIXTime)
import qualified Data.Vector as V
import qualified Hasql.Transaction as H
@@ -79,7 +80,7 @@ postgrest conf refDbStructure pool =
let schema = toS $ configSchema conf
apiRequest = userApiRequest schema req body
eClaims = jwtClaims (configJwtSecret conf) (iJWT apiRequest) time
eClaims = jwtClaims (secret $ configJwtSecret conf) (iJWT apiRequest) time
authed = containsRole eClaims
handleReq = runWithClaims conf eClaims (app dbStructure conf) apiRequest
txMode = transactionMode $ iAction apiRequest
@@ -211,7 +212,7 @@ app dbStructure conf apiRequest =
Just (PayloadJSON (UniformObjects payload))) -> do
let p = V.head payload
singular = iPreferSingular apiRequest
jwtSecret = configJwtSecret conf
jwtSecret = secret $ configJwtSecret conf
returnType = lookup (qiName qi) $ dbProcs dbStructure
returnsJWT = fromMaybe False $
isInfixOf "jwt_claims" . pdReturnType <$> returnType
+2 -4
View File
@@ -31,7 +31,6 @@ import Options.Applicative
import Paths_postgrest (version)
import Protolude hiding (intercalate)
import Safe (readMay)
import Web.JWT (Secret, secret)
-- | Data type to store all command line options
data AppConfig = AppConfig {
@@ -41,7 +40,7 @@ data AppConfig = AppConfig {
, configSchema :: Text
, configHost :: Text
, configPort :: Int
, configJwtSecret :: Secret
, configJwtSecret :: Text
, configPool :: Int
, configMaxRows :: Maybe Integer
, configQuiet :: Bool
@@ -55,8 +54,7 @@ argParser = AppConfig
<*> (toS <$> strOption (long "schema" <> short 's' <> help "schema to use for API routes" <> metavar "NAME" <> value "public" <> showDefault))
<*> (toS <$> strOption (long "host" <> short 'l' <> help "hostname or ip on which to run HTTP server" <> metavar "HOST" <> value "*4" <> showDefault))
<*> option auto (long "port" <> short 'p' <> help "port number on which to run HTTP server" <> metavar "PORT" <> value 3000 <> showDefault)
<*> (secret . toS <$>
strOption (long "jwt-secret" <> short 'j' <> help "secret used to encrypt and decrypt JWT tokens" <> metavar "SECRET" <> value "secret" <> showDefault))
<*> (toS <$> strOption (long "jwt-secret" <> short 'j' <> help "secret used to encrypt and decrypt JWT tokens" <> metavar "SECRET"))
<*> option auto (long "pool" <> short 'o' <> help "max connections in database pool" <> metavar "COUNT" <> value 10 <> showDefault)
<*> (readMay <$> strOption (long "max-rows" <> short 'm' <> help "max rows in response" <> metavar "COUNT" <> value "infinity" <> showDefault))
<*> pure False
+4 -5
View File
@@ -8,7 +8,6 @@ import Data.CaseInsensitive (CI(..))
import Text.Regex.TDFA ((=~))
import qualified Data.ByteString.Char8 as BS
import System.Process (readProcess)
import Web.JWT (secret)
import PostgREST.Config (AppConfig(..))
@@ -52,19 +51,19 @@ testDbConn = "postgres://postgrest_test_authenticator@localhost:5432/postgrest_t
testCfg :: AppConfig
testCfg =
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 (secret "safe") 10 Nothing True
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 "safe" 10 Nothing True
testUnicodeCfg :: AppConfig
testUnicodeCfg =
AppConfig testDbConn "postgrest_test_anonymous" Nothing "تست" "localhost" 3000 (secret "safe") 10 Nothing True
AppConfig testDbConn "postgrest_test_anonymous" Nothing "تست" "localhost" 3000 "safe" 10 Nothing True
testLtdRowsCfg :: AppConfig
testLtdRowsCfg =
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 (secret "safe") 10 (Just 2) True
AppConfig testDbConn "postgrest_test_anonymous" Nothing "test" "localhost" 3000 "safe" 10 (Just 2) True
testProxyCfg :: AppConfig
testProxyCfg =
AppConfig testDbConn "postgrest_test_anonymous" (Just "https://postgrest.com/openapi.json") "test" "localhost" 3000 (secret "safe") 10 Nothing True
AppConfig testDbConn "postgrest_test_anonymous" (Just "https://postgrest.com/openapi.json") "test" "localhost" 3000 "safe" 10 Nothing True
setupDb :: IO ()
setupDb = do