packages feed

sproxy 0.9.8 → 0.9.9

raw patch · 6 files changed

+91/−31 lines, 6 files

Files

ChangeLog.md view
@@ -1,7 +1,14 @@+0.9.9+=====++* This is the last release of this Sproxy. See [Sproxy2](http://hackage.haskell.org/package/sproxy2).+* Google: prompt for account only, don't ask for offline access.++ 0.9.8 ===== -* If the user is not authenticatedi, show login page with [HTTP status code+* If the user is not authenticated, show login page with [HTTP status code   511](https://tools.ietf.org/html/rfc6585), instead of 302 -> 200.  It had   bad UX for AJAX calls. * Always convert authenticated user's email to lowercase. This affects the
README.md view
@@ -9,9 +9,28 @@  * sproxy is independent.  Any web application written in any language can use    it. +## Use cases -## How it Works+ * Existing web applications with concept of roles. For example,+   [Mediawiki](https://www.mediawiki.org), [Jenkins](https://jenkins.io),+   [Icinga Web 2](https://www.icinga.org/products/icinga-web-2/). In+   this case you configure Sproxy to allow unrestricted access+   to the application for some groups defined by Sproxy. These+   groups are mapped to the application roles.  There is a [plugin for+   Jenkins](https://wiki.jenkins-ci.org/display/JENKINS/Reverse+Proxy+Auth+Plugin)+   which can be used for this. Mediawiki and Icinga Web 2 were also+   successfully deployed in this way, though it required changes to their+   source code. + * New web applications designed to work specifically behind Sproxy. In this case+   you define Sproxy rules to control access to the+   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)++## 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@@ -119,7 +138,7 @@ devops           | all            | Access denied  -## Configuration File+## Configuration file  By default `sproxy` will read its configuration from `config/sproxy.yml`.  There is example file with documentation
sproxy.cabal view
@@ -1,6 +1,10 @@ name: sproxy-version: 0.9.8+version: 0.9.9 synopsis: HTTP proxy for authenticating users via OAuth2+description:+  This version is no longer supported.+  Have a look at Sproxy2 (http://hackage.haskell.org/package/sproxy2),+  which goes far beyond Sproxy's features and limitations. license: MIT license-file: LICENSE copyright: 2013-2016, Zalora South East Asia Pte. Ltd
sproxy.sql view
@@ -1,9 +1,33 @@--- CREATE DATABASE sproxy;--- CREATE ROLE sproxy WITH LOGIN;--- GRANT SELECT ON ALL TABLES IN SCHEMA public TO sproxy;+/* +-- as super user:++-- NOT idempotent+CREATE DATABASE sproxy;+CREATE ROLE sproxy;            -- this is for management tools like sproxy-web+CREATE ROLE "sproxy-readonly"; -- this is for sproxy itself (sic!)++-- idempotent from here on:+ALTER DATABASE sproxy OWNER TO sproxy;+ALTER ROLE "sproxy-readonly" LOGIN;+ALTER ROLE sproxy LOGIN;++\c sproxy;++SET ROLE sproxy;+-- as database owner (sproxy) from here on:++GRANT SELECT ON ALL TABLES IN SCHEMA public TO "sproxy-readonly";+ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO "sproxy-readonly";++*/+++BEGIN;+ CREATE TABLE IF NOT EXISTS "group" (-  "group" TEXT NOT NULL PRIMARY KEY+  "group" TEXT NOT NULL PRIMARY KEY,+  "comment" TEXT );  -- | group        |@@ -13,11 +37,11 @@ -- | all          | -- | regional     | -CREATE EXTENSION IF NOT EXISTS citext;  CREATE TABLE IF NOT EXISTS group_member (   "group" TEXT REFERENCES "group" ("group") ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,-  email citext NOT NULL,+  email TEXT NOT NULL,+  "comment" TEXT,   PRIMARY KEY ("group", email) ); @@ -33,59 +57,63 @@ -- SELECT "group" FROM group_member WHERE 'email.address' LIKE email  CREATE TABLE IF NOT EXISTS domain (-  domain TEXT NOT NULL PRIMARY KEY+  domain TEXT NOT NULL PRIMARY KEY,+  "comment" TEXT );  -- | domain                | -- |-----------------------|--- | app1.example.com       |--- | app2.example.com       |--- | app3.example.com       |+-- | app1.example.com      |+-- | app2.example.com      |+-- | app3.example.com      |  CREATE TABLE IF NOT EXISTS privilege (   "domain" TEXT REFERENCES domain (domain) ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,   privilege TEXT NOT NULL,+  "comment" TEXT,   PRIMARY KEY ("domain", privilege) );  -- | domain                | privilege  | -- |-----------------------+------------|--- | app3.example.com       | view       |--- | app3.example.com       | export     |--- | app1.example.com       | list users |--- | app1.example.com       | add users  |+-- | app3.example.com      | view       |+-- | app3.example.com      | export     |+-- | app1.example.com      | list users |+-- | app1.example.com      | add users  |  CREATE TABLE IF NOT EXISTS privilege_rule (   "domain" TEXT NOT NULL,   privilege TEXT NOT NULL,   "path" TEXT NOT NULL,   "method" TEXT NOT NULL,+  "comment" TEXT,   FOREIGN KEY ("domain", privilege) REFERENCES privilege ("domain", privilege) ON UPDATE CASCADE ON DELETE CASCADE,   PRIMARY KEY ("domain", "path", "method") );  -- | domain                | privilege  | path      | method | -- |-----------------------+------------+-----------+--------|--- | app3.example.com       | view       | /%        | %      |--- | app3.example.com       | export     | /export/% | %      |--- | app1.example.com       | list users | /users    | GET    |--- | app1.example.com       | list users | /user/%   | GET    |--- | app1.example.com       | add users  | /users    | POST   |+-- | app3.example.com      | view       | /%        | %      |+-- | app3.example.com      | export     | /export/% | %      |+-- | app1.example.com      | list users | /users    | GET    |+-- | app1.example.com      | list users | /user/%   | GET    |+-- | app1.example.com      | add users  | /users    | POST   |  CREATE TABLE IF NOT EXISTS group_privilege (   "group" TEXT REFERENCES "group" ("group") ON UPDATE CASCADE ON DELETE CASCADE NOT NULL,   "domain" TEXT NOT NULL,   privilege TEXT NOT NULL,+  "comment" TEXT,   FOREIGN KEY ("domain", privilege) REFERENCES privilege ("domain", privilege) ON UPDATE CASCADE ON DELETE CASCADE,   PRIMARY KEY ("group", "domain", privilege) );  -- | group        | domain                | privilege  | -- |--------------+-----------------------+------------|--- | data science | app3.example.com       | view       |--- | data science | app3.example.com       | export     |--- | all          | app1.example.com       | list users |--- | devops       | app1.example.com       | add users  |+-- | data science | app3.example.com      | view       |+-- | data science | app3.example.com      | export     |+-- | all          | app1.example.com      | list users |+-- | devops       | app1.example.com      | add users  |  -- Check if the user is authorized for the request. Let's break it -- down for understanding:@@ -135,4 +163,6 @@   INSERT INTO group_privilege ("group", domain, privilege) VALUES ('dev', 'example.com', 'full');   INSERT INTO privilege_rule (domain, privilege, path, method) VALUES ('example.com', 'full', '%', '%'); */++END; 
src/Authenticate/Google.hs view
@@ -33,7 +33,8 @@       , "&state=", urlEncode True path       , "&redirect_uri=", redirectUri base       , "&response_type=code&client_id=", cid-      , "&approval_prompt=force&access_type=offline"+      , "&prompt=select_account"+      , "&access_type=offline"       ]  authenticate :: AuthConfig -> ByteString -> ByteString -> ByteString -> IO (Response BodyReader)
src/Authorize.hs view
@@ -59,9 +59,8 @@ WHERE ? LIKE email AND ? LIKE "domain" AND privilege IN (-  SELECT p.privilege FROM privilege p-  INNER JOIN privilege_rule pr ON pr."domain" = p."domain" AND pr.privilege = p.privilege-  WHERE ? LIKE pr."domain" AND ? LIKE "path" AND ? ILIKE "method"+  SELECT privilege FROM privilege_rule+  WHERE ? LIKE "domain" AND ? LIKE "path" AND ? ILIKE "method"   ORDER by array_length(regexp_split_to_array("path", '/'), 1) DESC LIMIT 1 ) |] (email, domain, domain, path, method)