packages feed

sproxy2 1.90.0 → 1.90.1

raw patch · 4 files changed

+92/−37 lines, 4 files

Files

ChangeLog.md view
@@ -1,5 +1,19 @@ For differences with the original Sproxy scroll down. ++1.90.1+======++  * Fixed headers processing. Wrong headers were making Chromium drop connection in HTTP/2.+    Firefox sometimes couldn't handle gzipped and chunked responses in HTTP/1.1.++  * After authenticating, redirect to original path with query parameters if+    method was GET.  Otherwise redirect to "/". Previously, when unauthenticated+    users click on "https://example.net/foo?bar", they are redirected to+    "https://example.net/foo" regardless of the method.+++ 1.90.0 (Preview Release) ======================== 
README.md view
@@ -1,5 +1,8 @@-# Sproxy2 - HTTP proxy for authenticating users via OAuth2+# Sproxy2 +HTTP proxy for authenticating users via OAuth2.++ ## Motivation  This is overhaul of original [Sproxy](https://hackage.haskell.org/package/sproxy).@@ -32,8 +35,10 @@    Examples are [MyWatch](https://hackage.haskell.org/package/mywatch) and    [Juan de la Cosa](https://hackage.haskell.org/package/juandelacosa) -## How it works +How it works+============+ When an HTTP client makes a request, Sproxy checks for a *session cookie*. If it doesn't exist (or it's invalid, expired), it responses with [HTTP status 511](https://tools.ietf.org/html/rfc6585) with the page, where the@@ -48,25 +53,8 @@ back-end server (if allowed).  -## Logout--Hitting the endpoint `/.sproxy/logout` will invalidate the session cookie.-The user will be redirected to `/` after logout.---## Robots--Since all sproxied resources are private, it doesn't make sense for web-crawlers to try to index them. In fact, crawlers will index only the login-page. To prevent this, sproxy returns the following for `/robots.txt`:--```-User-agent: *-Disallow: /-```---## Permissions system+Permissions system+------------------  Permissions are stored in a PostgreSQL database. See sproxy.sql for details. Here are the main concepts:@@ -88,9 +76,20 @@ tables, because only these tables are used for authorization. The other tables serve for data integrity. +Keep in mind that: -### Privileges example+- Domains are converted into lower case (coming from PostgreSQL or HTTP requests).+- Emails are converted into lower case (coming from PostgreSQL or OAuth2 providers).+- Groups are case-sensitive and treated as is.+- HTTP methods are *case-sensitive*.+- HTTP query parameters are ignored when matching a request against the rules.+- Privileges are case-sensitive and treated as is.+- SQL wildcards (`_` and `%`) are supported for emails, domains, paths. ++Privileges example+------------------+ Consider this `group_privilege` and `privilege_rule` relations:  group            | privilege | domain@@ -124,7 +123,8 @@ Likewise `readers` have no access to e.g. `/wiki/edit/delete_everything.php`.  -## HTTP headers passed to the back-end server:+HTTP headers passed to the back-end server+------------------------------------------  header               | value -------------------- | -----@@ -148,14 +148,49 @@ devops           | all            | Access denied  -## Configuration file+Logout+------ -By default `sproxy2` will read its configuration from-`sproxy.yml`.  There is example file with documentation-[sproxy.yml.example](sproxy.yml.example). You can specify a-custom path with:+Hitting the endpoint `/.sproxy/logout` will invalidate the session cookie.+The user will be redirected to `/` after logout. ++Robots+------++Since all sproxied resources are private, it doesn't make sense for web+crawlers to try to index them. In fact, crawlers will index only the login+page. To prevent this, sproxy returns the following for `/robots.txt`:+ ```-sproxy --config /path/to/sproxy.yml+User-agent: *+Disallow: /+```+++Requirements+============+Sproxy2 is written in Haskell with [GHC](http://www.haskell.org/ghc/).+All required Haskell libraries are listed in [sproxy2.cabal](sproxy2.cabal).+Use [cabal-install](http://www.haskell.org/haskellwiki/Cabal-Install)+to fetch and build all pre-requisites automatically.+++Installation+============+    $ git clone https://github.com/zalora/sproxy2.git+    $ cd sproxy2+    $ cabal install+++Configuration+=============++By default `sproxy2` will read its configuration from `sproxy.yml`.  There is+example file with documentation [sproxy.yml.example](sproxy.yml.example). You+can specify a custom path with:++```+sproxy2 --config /path/to/sproxy.yml ``` 
sproxy2.cabal view
@@ -1,5 +1,5 @@ name: sproxy2-version: 1.90.0+version: 1.90.1 synopsis: Secure HTTP proxy for authenticating users via OAuth2 description:   Sproxy is secure by default. No requests makes it to the backend
src/Sproxy/Application.hs view
@@ -28,8 +28,9 @@ import Foreign.C.Types (CTime(..)) import Network.HTTP.Client.Conduit (bodyReaderSource) import Network.HTTP.Conduit (requestBodySourceChunkedIO, requestBodySourceIO)-import Network.HTTP.Types (RequestHeaders, ResponseHeaders, hConnection,-  hContentLength, hContentType, hCookie, hLocation, methodGet)+import Network.HTTP.Types (RequestHeaders, ResponseHeaders, methodGet)+import Network.HTTP.Types.Header ( hConnection,+  hContentLength, hContentType, hCookie, hLocation, hTransferEncoding ) import Network.HTTP.Types.Status ( Status(..), badRequest400, forbidden403, found302,   internalServerError500, methodNotAllowed405, movedPermanently301,   networkAuthenticationRequired511, notFound404, ok200, seeOther303, temporaryRedirect307 )@@ -213,12 +214,12 @@   Log.debug $ "BACKEND <<< " ++ msg ++ " " ++ show (BE.requestHeaders beReq)   BE.withResponse beReq mgr $ \res -> do         let status = BE.responseStatus res-            headers = modifyResponseHeaders $ BE.responseHeaders res+            headers = BE.responseHeaders res             body = mapOutput (Chunk . fromByteString) . bodyReaderSource $ BE.responseBody res             logging = if statusCode status `elem` [ 400, 500 ] then                       Log.warn else Log.debug-        logging $ "BACKEND >>> " ++ show (statusCode status) ++ " on " ++ msg ++ "\n"-        resp $ responseSource status headers body+        logging $ "BACKEND >>> " ++ show (statusCode status) ++ " on " ++ msg ++ " " ++ show headers ++ "\n"+        resp $ responseSource status (modifyResponseHeaders headers) body   modifyRequestHeaders :: RequestHeaders -> RequestHeaders@@ -227,7 +228,8 @@     ban =       [         hConnection-      , hContentLength -- XXX to avoid duplicate header+      , hContentLength    -- XXX This is set automtically before sending request to backend+      , hTransferEncoding -- XXX Likewise       ]  modifyResponseHeaders :: ResponseHeaders -> ResponseHeaders@@ -236,6 +238,7 @@     ban =       [         hConnection+      , hTransferEncoding -- XXX This is set automtically when sending respond from sproxy       ]  authenticationRequired :: ByteString -> HashMap Text OAuth2Client -> W.Application@@ -243,7 +246,9 @@   Log.info $ "511 Unauthenticated: " ++ showReq req   resp $ W.responseLBS networkAuthenticationRequired511 [(hContentType, "text/html; charset=utf-8")] page   where-    path = W.rawPathInfo req -- FIXME: make it more robust for non-GET or XMLHTTPRequest?+    path = if W.requestMethod req == methodGet+           then W.rawPathInfo req <> W.rawQueryString req+           else "/"     state = State.encode key path     authLink :: Text -> OAuth2Client -> ByteString -> ByteString     authLink provider oa2c html = @@ -366,6 +371,7 @@     unpack ( W.requestMethod req <> " "            <> fromMaybe "<no host>" (W.requestHeaderHost req)            <> W.rawPathInfo req <> W.rawQueryString req <> " " )+    ++ show (W.httpVersion req) ++ " "     ++ show (fromMaybe "-" $ W.requestHeaderReferer req) ++ " "     ++ show (fromMaybe "-" $ W.requestHeaderUserAgent req)     ++ " from " ++ show (W.remoteHost req)