packages feed

sproxy2 1.93.0 → 1.94.0

raw patch · 7 files changed

+48/−22 lines, 7 files

Files

ChangeLog.md view
@@ -1,5 +1,20 @@ For differences with the original Sproxy scroll down. +1.94.0+======++  * BREAKING: Disregard possible port in the Host HTTP header.+    Previously, Sproxy took possible port number into account when+    looking for backend and privileges. Now it ignores port and considers+    domain name only.  This also gets Sproxy in line with browsers and SSL+    certificates: certificates do not include port numbers, browsers ignore+    ports when sending cookies.++  * BREAKING: no SQL wildcards (`%` or `_`) in domain names when looking up+    for privileges.  This feature was ambiguous (in the same way as paths are)+    and never used anyway.++ 1.93.0 ====== @@ -72,7 +87,7 @@     as sproxy does it on every HTTP request. Sproxy2 pulls data into local SQLite3 database.    * At this release Sproxy2 is compatible with Sproxy database with one exception:-    SQL wildcards are not supported for HTTP methods. E. i. you have to change '%' in+    SQL wildcards are not supported for HTTP methods. I. e. you have to change '%' in     the database to specific methods like GET, POST, etc.    * OAuth2 callback URLs changed: Sproxy2 uses `/.sproxy/oauth2/:provider`,
README.md view
@@ -33,9 +33,11 @@    application's API.  It would likely be [a single-page    application](https://en.wikipedia.org/wiki/Single-page_application).    Examples are [MyWatch](https://hackage.haskell.org/package/mywatch) and-   [Juan de la Cosa](https://hackage.haskell.org/package/juandelacosa)+   [Juan de la Cosa](https://hackage.haskell.org/package/juandelacosa). + * Replace HTTP Basic authentication. + How it works ============ @@ -135,7 +137,7 @@ - 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.+- SQL wildcards (`_` and `%`) are supported for emails, paths (this _will_ change in future versions).   HTTP headers passed to the back-end server
sproxy.example.yml view
@@ -8,7 +8,10 @@ # The port Sproxy listens on (HTTPS). # Optional. Default is 443. #-# listen: 443+# Example:+# listen: 8443+#+# listen:  # Whether SSL is used on port defined by `listen`. # You should only set it to false iff you intent to do SSL-termination@@ -26,7 +29,7 @@  # Port used in redirection of HTTP requests to HTTPS. # I. e., http://example.com -> https://example.com[:https_port],-# If `http_port` == 443, the port part if omitted.+# If `https_port` == 443, the port part if omitted. # This is useful when behind a dumb proxy or load-balancer, like Amazon ELB, # (and`ssl` == false). It's unlikely that something other than 443 # is exposed to users, but if you are behind a proxy@@ -144,11 +147,10 @@ # Unix sockets should be secured with proper unix file permissions. # # Backend attributes:-#   name      - the host name as in the Host HTTP header.+#   name      - the domain name as in the Host HTTP header (without optional colon and port). #               May include wildcards * and ?. The first matching #               backend will be used. Examples: "*.example.com", "wiki.corp.com".-#               Optional. Default is "*". Note, that the name must include-#               port number if non-standard.+#               Optional. Default is "*". #   address   - backend IP address. Optional. Default is 127.0.0.1. #   port      - backend TCP port. Required unless unix socket is defined. #   socket    - unix socket. Highly recommended for security reasons.
sproxy.sql view
@@ -166,7 +166,10 @@   INSERT INTO group_member ("group", email) VALUES ('dev', '%');   INSERT INTO privilege (domain, privilege) VALUES ('example.com', 'full');   INSERT INTO group_privilege ("group", domain, privilege) VALUES ('dev', 'example.com', 'full');-  INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', '%');+  INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', 'GET');+  INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', 'HEAD');+  INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', 'POST');+  INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', 'PUT'); */  END;
sproxy2.cabal view
@@ -1,5 +1,5 @@ name: sproxy2-version: 1.93.0+version: 1.94.0 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
@@ -55,14 +55,13 @@  redirect :: Word16 -> W.Application redirect p req resp =-  case W.requestHeaderHost req of+  case requestDomain req of     Nothing -> badRequest "missing host" req resp-    Just host -> do+    Just domain -> do       Log.info $ "redirecting to " ++ show location ++ ": " ++ showReq req       resp $ W.responseBuilder status [(hLocation, location)] mempty       where         status = if W.requestMethod req == methodGet then movedPermanently301 else temporaryRedirect307-        (domain, _) = BS.break (== _colon) host         newhost = if p == 443 then domain else domain <> ":" <> pack (show p)         location = "https://" <> newhost <> W.rawPathInfo req <> W.rawQueryString req @@ -70,10 +69,10 @@ sproxy :: ByteString -> Database -> HashMap Text OAuth2Client -> [(Pattern, BackendConf, BE.Manager)] -> W.Application sproxy key db oa2 backends = logException $ \req resp -> do   Log.debug $ "sproxy <<< " ++ showReq req-  case W.requestHeaderHost req of+  case requestDomain req of     Nothing -> badRequest "missing host" req resp-    Just host ->-      case find (\(p, _, _) -> match p (unpack host)) backends of+    Just domain ->+      case find (\(p, _, _) -> match p (unpack domain)) backends of         Nothing -> notFound "backend" req resp         Just (_, be, mgr) -> do           let cookieName = pack $ beCookieName be@@ -145,8 +144,7 @@ authenticate :: ByteString -> BackendConf -> AuthUser -> ByteString -> W.Application authenticate key be user path req resp = do   now <- epochTime-  let host = fromJust $ W.requestHeaderHost req-      domain = pack <$> beCookieDomain be+  let domain = pack <$> beCookieDomain be       expiry = now + CTime (beCookieMaxAge be)       authCookie = AuthCookie { acUser = user, acExpiry = expiry }       cookie = WC.def {@@ -160,7 +158,7 @@       , WC.setCookieExpires = Just . posixSecondsToUTCTime . realToFrac $ expiry       }   resp $ W.responseLBS seeOther303 [-           (hLocation, "https://" <> host <> path)+           (hLocation, "https://" <> fromJust (W.requestHeaderHost req) <> path)          , ("Set-Cookie", toByteString $ WC.renderSetCookie cookie)          ] "" @@ -169,7 +167,7 @@ authorize db (authCookie, otherCookies) req = do   let     user       = acUser authCookie-    domain     = decodeUtf8 . fromJust $ W.requestHeaderHost req+    domain     = decodeUtf8 . fromJust $ requestDomain req     email      = getEmail user     emailUtf8  = getEmailUtf8 user     familyUtf8 = getFamilyNameUtf8 user@@ -386,6 +384,12 @@ redirectURL req provider =   "https://" <> fromJust (W.requestHeaderHost req)              <> "/.sproxy/oauth2/" <> encodeUtf8 provider+++requestDomain :: W.Request -> Maybe ByteString+requestDomain req = do+  h <- W.requestHeaderHost req+  return . fst . BS.break (== _colon) $ h   -- XXX: make sure not to reveal the cookie, which can be valid (!)
src/Sproxy/Server/DB.hs view
@@ -66,10 +66,10 @@   withResource db $ \c -> fmap SQLite.fromOnly <$> SQLite.queryNamed c [q|       SELECT gm."group" FROM group_privilege gp JOIN group_member gm ON gm."group"  = gp."group"       WHERE :email LIKE gm.email-      AND :domain LIKE gp.domain+      AND gp.domain = :domain       AND gp.privilege IN (         SELECT privilege FROM privilege_rule-        WHERE :domain LIKE domain+        WHERE domain = domain         AND :path LIKE path         AND method = :method         ORDER BY length(path) - length(replace(path, '/', '')) DESC LIMIT 1