sproxy2 1.96.0 → 1.97.0
raw patch · 9 files changed
+44/−41 lines, 9 filesdep −containers
Dependencies removed: containers
Files
- ChangeLog.md +7/−1
- sproxy.example.yml +5/−4
- sproxy2.cabal +3/−4
- src/Sproxy/Application.hs +15/−17
- src/Sproxy/Application/Access.hs +4/−6
- src/Sproxy/Config.hs +3/−1
- src/Sproxy/Logging.hs +2/−3
- src/Sproxy/Server.hs +4/−3
- src/Sproxy/Server/DB/DataFile.hs +1/−2
ChangeLog.md view
@@ -1,4 +1,10 @@-For differences with the original Sproxy scroll down.+1.97.0+======++ * Added new option `timeout` to configure backend response timeout.++ * Changed default random key length to 64 bytes (from 32).+ 1.96.0 ======
sproxy.example.yml view
@@ -105,12 +105,11 @@ # Arbitrary string used to sign sproxy cookie and other things (secret!).-# Optional. If not specified, a random key is generated on startup, and-# as a consequence, restaring sproxy will invalidate existing user sessions.+# Optional. If not specified, a random key of length 64 is generated on startup,+# and as a consequence, restaring sproxy will invalidate existing user sessions. # This option could be useful for load-balancing with multiple sproxy instances, # when all instances must understand cookies created by each other.-# This should not be very large, a few random bytes are fine.-# +# # key: !include /run/keys/sproxy.secret @@ -164,6 +163,8 @@ # cookie_name - sproxy cookie name. Optional. Default is "sproxy". # cookie_domain - sproxy cookie domain. Optional. Default is the request host name as per RFC2109. # cookie_max_age - sproxy cookie shelflife in seconds. Optional. Default is 604800 (7 days).+#+# timeout - response timeout in seconds. Optional. Default is 30. # conn_count - number of connections to keep alive. Optional. Default is 32. # This is specific to Haskell HTTP Client library, and is per host name, # not per backend. HTTP Client's default is 10.
sproxy2.cabal view
@@ -1,5 +1,5 @@ name: sproxy2-version: 1.96.0+version: 1.97.0 synopsis: Secure HTTP proxy for authenticating users via OAuth2 description: Sproxy is secure by default. No requests makes it to the backend@@ -12,10 +12,10 @@ maintainer: Igor Pashev <pashev.igor@gmail.com> copyright: 2016-2017, Zalora South East Asia Pte. Ltd;- 2017, Igor Pashev <pashev.igor@gmail.com>+ 2017-2018, Igor Pashev <pashev.igor@gmail.com> category: Databases, Web build-type: Simple-cabal-version: >= 1.20+cabal-version: 1.20 extra-source-files: ChangeLog.md README.md@@ -55,7 +55,6 @@ , bytestring , cereal , conduit- , containers , cookie >= 0.4.2 , docopt , entropy
src/Sproxy/Application.hs view
@@ -13,14 +13,12 @@ (Exception, Handler(..), SomeException, catches, displayException) import qualified Data.Aeson as JSON import Data.ByteString (ByteString)-import Data.ByteString as BS (break, intercalate)+import qualified Data.ByteString as BS import Data.ByteString.Char8 (pack, unpack) import Data.ByteString.Lazy (fromStrict) import Data.Conduit (Flush(Chunk), mapOutput)-import Data.HashMap.Strict as HM (HashMap, foldrWithKey, lookup)+import qualified Data.HashMap.Strict as HM import Data.List (find, partition)-import Data.Map as Map- (delete, fromListWith, insert, insertWith, toList) import Data.Maybe (fromJust, fromMaybe) import Data.Monoid ((<>)) import Data.Text (Text)@@ -83,7 +81,7 @@ sproxy :: ByteString -> Database- -> HashMap Text OAuth2Client+ -> HM.HashMap Text OAuth2Client -> [(Pattern, BackendConf, BE.Manager)] -> W.Application sproxy key db oa2 backends =@@ -230,20 +228,20 @@ return . Just $ req { W.requestHeaders =- toList $- insert "From" emailUtf8 $- insert "X-Groups" (BS.intercalate "," $ encodeUtf8 <$> grps) $- insert "X-Given-Name" givenUtf8 $- insert "X-Family-Name" familyUtf8 $- insert "X-Forwarded-Proto" "https" $- insertWith (flip combine) "X-Forwarded-For" ip $+ HM.toList $+ HM.insert "From" emailUtf8 $+ HM.insert "X-Groups" (BS.intercalate "," $ encodeUtf8 <$> grps) $+ HM.insert "X-Given-Name" givenUtf8 $+ HM.insert "X-Family-Name" familyUtf8 $+ HM.insert "X-Forwarded-Proto" "https" $+ HM.insertWith (flip combine) "X-Forwarded-For" ip $ setCookies otherCookies $- fromListWith combine $ W.requestHeaders req+ HM.fromListWith combine $ W.requestHeaders req } where combine a b = a <> "," <> b- setCookies [] = delete hCookie- setCookies cs = insert hCookie (toByteString . renderCookies $ cs)+ setCookies [] = HM.delete hCookie+ setCookies cs = HM.insert hCookie (toByteString . renderCookies $ cs) checkAccess :: Database -> AuthCookie -> W.Application checkAccess db authCookie req resp = do@@ -321,7 +319,7 @@ ] authenticationRequired ::- ByteString -> HashMap Text OAuth2Client -> W.Application+ ByteString -> HM.HashMap Text OAuth2Client -> W.Application authenticationRequired key oa2 req resp = do Log.info $ "511 Unauthenticated: " ++ showReq req resp $@@ -342,7 +340,7 @@ let u = oauth2AuthorizeURL oa2c state (redirectURL req provider) d = pack $ oauth2Description oa2c in [qc|{html}<p><a href="{u}">Authenticate with {d}</a></p>|]- authHtml = foldrWithKey authLink "" oa2+ authHtml = HM.foldrWithKey authLink "" oa2 page = fromStrict [qc|
src/Sproxy/Application/Access.hs view
@@ -1,21 +1,19 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-} module Sproxy.Application.Access ( Inquiry , Question(..) ) where -import Data.Aeson (FromJSON)+import Data.Aeson.TH (defaultOptions, deriveFromJSON) import Data.HashMap.Strict (HashMap) import Data.Text (Text)-import GHC.Generics (Generic) data Question = Question { path :: Text , method :: Text- } deriving (Generic, Show)+ } deriving (Show) -instance FromJSON Question+$(deriveFromJSON defaultOptions ''Question) type Inquiry = HashMap Text Question
src/Sproxy/Config.hs view
@@ -65,6 +65,7 @@ , beCookieDomain :: Maybe String , beCookieMaxAge :: Int64 , beConnCount :: Int+ , beTimeout :: Int } deriving (Show) instance FromJSON BackendConf where@@ -75,7 +76,8 @@ m .:? "cookie_name" .!= "sproxy" <*> m .:? "cookie_domain" <*> m .:? "cookie_max_age" .!= (7 * 24 * 60 * 60) <*>- m .:? "conn_count" .!= 32+ m .:? "conn_count" .!= 32 <*>+ m .:? "timeout" .!= 30 parseJSON _ = empty data OAuth2Conf = OAuth2Conf
src/Sproxy/Logging.hs view
@@ -13,7 +13,7 @@ import Control.Applicative (empty) import Control.Concurrent (forkIO) import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)-import Control.Monad (forever, when)+import Control.Monad (forever, void, when) import Data.Aeson (FromJSON, ToJSON) import qualified Data.Aeson as JSON import Data.Char (toLower)@@ -28,8 +28,7 @@ start lvl = do writeIORef logLevel lvl ch <- readIORef chanRef- _ <- forkIO . forever $ readChan ch >>= hPrint stderr- return ()+ void . forkIO . forever $ readChan ch >>= hPrint stderr info :: String -> IO () info = send . Message Info
src/Sproxy/Server.hs view
@@ -6,14 +6,14 @@ import Control.Exception (bracketOnError) import Control.Monad (void, when) import Data.ByteString.Char8 (pack)-import Data.HashMap.Strict as HM (fromList, lookup, toList)+import qualified Data.HashMap.Strict as HM import Data.Maybe (fromMaybe) import Data.Text (Text) import Data.Word (Word16) import Data.Yaml.Include (decodeFileEither) import Network.HTTP.Client (Manager, ManagerSettings(..), defaultManagerSettings, newManager,- socketConnection)+ responseTimeoutMicro, socketConnection) import Network.HTTP.Client.Internal (Connection) import Network.Socket (Family(AF_INET, AF_UNIX), SockAddr(SockAddrInet, SockAddrUnix),@@ -75,7 +75,7 @@ db <- DB.start (cfHome cf) ds key <- maybe- (Log.info "using new random key" >> getEntropy 32)+ (Log.info "using new random key" >> getEntropy 64) (return . pack) (cfKey cf) let settings =@@ -152,6 +152,7 @@ defaultManagerSettings { managerRawConnection = return $ \_ _ _ -> openConn , managerConnCount = beConnCount be+ , managerResponseTimeout = responseTimeoutMicro (1000000 * beTimeout be) } newServer :: ConfigFile -> IO (Settings -> Socket -> Application -> IO ())
src/Sproxy/Server/DB/DataFile.hs view
@@ -8,9 +8,8 @@ ) where import Control.Applicative (empty)-import Data.Aeson (FromJSON, parseJSON)+import Data.Aeson (FromJSON, Value(Object), (.:), parseJSON) import Data.Text (Text)-import Data.Yaml (Value(Object), (.:)) data DataFile = DataFile { groupMember :: [GroupMember]