Some raw thinking on user level authorization and authentication
This is as much gathering my thoughts on research. Anyone with questions or comments or ideas welcome. Just raw ideas at this stage.
The goal is to build user level REST authentication for Mailman on top of the existing REST API.
Mailman user REST authentication/authorization.
Use Falcon/Talons wherever appropriate for consistency with Mailman.
Authentication - establish the identity of the user Authorization - allow or deny access to specific Mailman resources based on the user identity
################Authentication & authorization process overview:
step 1: authentication —- HTTP client provides username and password —- username and password sent to Mailman REST server —- if Mailman REST server authenticates username and password: —- authentication token returned to client
step 2: authorization -- examines inbound requests —- if request contains valid authentication information, continue —- examine requested Mailman resource -— send REST request to Mailman REST server to find out if this user is allowed to do this resource request —- if user is allowed access to resource, goto step 3
step 3: action At this stage I have three candidates for what happens next: action 1: —- treat the inbound request as an external proxy authentication subrequest action 2: —- directly proxy the request action 3: -- wsgi drop-through - just let the request pass through to the next level in the wsgi stack
################Possible actions
action 1: —- treat the inbound request as an external proxy authentication subrequest In which the inbound HTTP request is first handled by an external proxy server (for example Nginx), which first sends a “subrequest” to our authentication/authorization server. If our authentication/authorization server approves the request, it responses 200 OK to the external proxy server which then directly sends the request to the Mailman REST API ** downside of subrequest based proxying —- depends on external proxy (i.e. Nginx) that suports subrequests based authentication http://nginx.org/en/docs/http/ngx_http_auth_request_module.html —- it would be possible to write the pure Python proxy to user this mechanism, making an external subrequesting authenticating proxy an option rather than requirement ** upside of subrequest based proxying: — once the request is authenticated/authorized, it makes alot of sense for a specialised, high performance proxy to handle the proxying directly with the back end. All proxying edges cases and gotchas are left to the specialised proxy (i.e. Nginx) to handle, and proxy performance is as fast as the external proxy server and the Mailman REST API can talk to each other.
action 2: —- directly proxy the request In which the request is then sent on to the Mailman REST API and the response returned to the HTTP client **downside of proxying: —- proxying is a minefield of gotchas and edge cases —- places the authenticating proxy in the path of all requests, certainly slower than raw access to Mailman REST API **upside of proxying: —- can be done as pure Python, no reliance on the behaviour of external proxy servers —- the are probably fewer gotchas when dealing with one know API (i.e. Mailman REST API) versus trying to implement a generalised proxy server
action 3: -- wsgi drop-through - just let the request pass through to the next level in the wsgi stack In which the inbound HTTP request comes first through the authorization/authentication wsgi layers then directly to the existing Mailman API via wsgi ** downside of wsgi drop through: —- requires execution of the Mailman REST API as a wsgi application, which is potentially complex and more tightly coupled than desirable and would require implementation into the Mailman code base —- put another way, the auth functions will operate entirely via queries to the Mailman REST API, and such decoupling of auth functions makes for a simpler system
Hi Andrew, thanks for starting to look at this.
On Dec 17, 2014, at 09:29 AM, Andrew Stuart wrote:
step 1: authentication —- HTTP client provides username and password —- username and password sent to Mailman REST server —- if Mailman REST server authenticates username and password: —- authentication token returned to client
MM3's REST API has the resource <api>/users/<uid>/login which you can POST to
with form data cleartext_password
as the authentication step. You get back
a 204 if the password matches, and a 403 if it does not.
step 2: authorization -- examines inbound requests —- if request contains valid authentication information, continue —- examine requested Mailman resource -— send REST request to Mailman REST server to find out if this user is -allowed to do this resource request
This is the trickiest part because we don't currently codify what a particular user is or is not allowed to do. We'll need to do this carefully, and the question is whether that information should be kept in the core or in the proxy layer. I wonder if there is prior art or best practices on how best to specify authorizations to REST resources and methods.
—- requires execution of the Mailman REST API as a wsgi application, which is potentially complex and more tightly coupled than desirable and would require implementation into the Mailman code base
It already is a wsgi application actually. But I think the bigger problem is that we want admins to be comfortable exposing the full admin API only on localhost, and they'll need to expose the proxy on a public IP, so it's likely that the proxy would run on a separate machine/VM from core.
Cheers, -Barry
participants (2)
-
Andrew Stuart
-
Barry Warsaw