documentation:2.1:ssoaas

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

documentation:2.1:ssoaas [2019/01/15 15:55] (current)
Line 1: Line 1:
 +====== SSO as a service (SSOaaS) ======
  
 +===== Our concept of SSOaaS =====
 +
 +Access management provides 3 services:
 +  * Global Authentication: Single Sign-On
 +  * Authorization: to grant authentication is not enough. User rights must be checked
 +  * Accounting: SSO logs (access) + application logs //(transactions and results)//
 +
 +LL::NG affords all these services (except application logs of course, but headers are provided to permit this).
 +
 +Headers setting is an another LL::NG service. LL::NG can provide any user attributes to an application //(see [[writingrulesand_headers|Rules and headers]])//
 +
 +''*aaS'' means that application can drive underlying layer (IaaS for infrastructure, PaaS for platform,…). So for us, ''SSOaaS'' must provide the ability for an app to __manage authorizations__ and choose __user attributes__ to set. Authentication can not be really "*aaS": app must just use it, not manage it.
 +
 +LL::NG affords some features that can be used to provide SSO as a service: a web application can manage its rules and headers. Docker or VM images (Nginx only) includes LL::NG Nginx configuration that aims to a global [[platformsoverview#external_servers_for_nginx|LL::NG authorization server]]. By default, all authenticated users can access and one header is set: ''Auth-User''. If application gives a RULES_URL parameter that refers to a JSON file, authorization server will read it, apply specified rules and set required headers //(see [[devopshandler|DevOps Handler]])//.
 +
 +There are two different architectures to do this:
 +  * Using a [[psgi|global FastCGI (or uWSGI) server]]
 +  * Using front reverse-proxies //(some cloud installations use reverse-proxies in front-end)//
 +
 +In both case, Handler type must be set to [[devopshandler|DevOps]].
 +
 +===== Examples of webserver configuration for Docker/VM images =====
 +
 +==== Using a global FastCGI (or uWSGI) server ====
 +
 +=== Nginx ===
 +
 +In this example, web server templates (Nginx only) are configured to request authorization from a central FastCGI server:
 +<file nginx test-nginx.conf>
 +server {
 +  server_name myapp.domain.com;
 +  location = /lmauth {
 +    internal;
 +    include /etc/nginx/fastcgi_params;
 +    # Pass authorization requests to Central FastCGI server:
 +    fastcgi_pass 10.1.2.3:9090;
 +    fastcgi_param VHOSTTYPE DevOps;
 +    # Drop post datas
 +    fastcgi_pass_request_body  off;
 +    fastcgi_param CONTENT_LENGTH "";
 +    # Keep original hostname
 +    fastcgi_param HOST $http_host;
 +    # Keep original request (LLNG server will received /lmauth)
 +    fastcgi_param X_ORIGINAL_URI  $request_uri;
 +    
 +    # Set dynamically rules (LLNG will poll it every 10 mn)
 +    fastcgi_param RULES_URL http://rulesserver/my.json
 +  }
 +  location /rules.json {
 +    auth_request off;
 +    allow 10.1.2.3;
 +    deny all;
 +  }
 +  location ~ ^(.*\.php)$ {
 +    auth_request /lmauth;
 +    auth_request_set $lmremote_user $upstream_http_lm_remote_user;
 +    auth_request_set $lmlocation $upstream_http_location;
 +    error_page 401 $lmlocation;
 +    include /etc/lemonldap-ng/nginx-lua-headers.conf;
 +    ...
 +    # Example with php-fpm:
 +    include snippets/fastcgi-php.conf;
 +    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
 +  }
 +  location / {
 +    try_files $uri $uri/ =404;
 +  }
 +}
 +</file>
 +
 +=== Apache ===
 +
 +There is an experimental FactCGI client in LLNG. You just have to install FCGI::Client and add this in your apache2.conf:
 +
 +<file apache apache2.conf>
 +<VirtualHost ...>
 +    PerlHeaderParserHandler Lemonldap::NG::Handler::ApacheMP2::FCGIClient
 +    PerlSetVar LLNG_SERVER 127.0.0.1:9090
 +    PerlSetVar VHOSTTYPE DevOps
 +    PerlSetVar RULES_URL http://app.tld/rules.json
 +    ...
 +</VirtualHost>
 +</file>
 +
 +=== Node.js ===
 +
 +Using [[https://github.com/expressjs/express#readme|express]] and [[https://github.com/LemonLDAPNG/node-fastcgi-authz-client|fastcgi-authz-client]], you can protect also an Express server. Example:
 +
 +<file javascript app.js>
 +var express = require('express');
 +var app = express();
 +var FcgiAuthz = require('fastcgi-authz-client');
 +var handler = FcgiAuthz({
 +  host: '127.0.0.1',
 +  port: 9090,
 +  PARAMS: {
 +    RULES_URL: 'http://my-server/rules.json'
 +  }
 +});
 +
 +app.use(handler);
 +
 +// Simple express application
 +app.get('/', function(req, res) {
 +  return res.send('Hello ' + req.upstreamHeaders['auth-user'] + ' !');
 +});
 +
 +// Launch server
 +app.listen(3000, function() {
 +  return console.log('Example app listening on port 3000!');
 +});
 +</file>
 +
 +=== Plack application ===
 +
 +You just have to enable [[https://metacpan.org/pod/Plack::Middleware::Auth::FCGI|Plack::Middleware::Auth::FCGI]]. Simple example:
 +
 +<file perl app.psgi>
 +use Plack::Builder;
 +
 +my $app   = sub {
 +  my $env = shift;
 +  my $user = $env->{fcgiauth-auth-user};
 +  return [ 200, [ 'Content-Type' => 'text/plain' ], [ "Hello $user" ] ];
 +};
 +
 +# Optionally ($fcgiResponse is the PSGI response of remote FCGI auth server)
 +#sub on_reject {
 +#    my($self,$env,$fcgiResponse) = @_;
 +#    my $statusCode = $fcgiResponse->{status};
 +#    ...
 +#}
 +
 +builder
 +{
 +  enable "Auth::FCGI",
 +    host => '127.0.0.1',
 +    port => '9090',
 +    fcgi_auth_params => {
 +      RULES_URL => 'https://my-server/my.json',
 +    },
 +    # Optional rejection subroutine
 +    #on_reject => \&on_reject;
 +    ;
 +  $app;
 +};
 +</file>
 +
 +==== Using front reverse-proxies ====
 +
 +This is a simple Nginx configuration file. It looks like a standard LL::NG nginx configuration file except for:
 +  * VHOSTTYPE parameter forced to use DevOps handler
 +  * /rules.json must not be protected by LL::NG but by the web server itself
 +
 +This configuration handles ''*.dev.sso.my.domain'' URL and forwards authenticated requests to ''<vhost>.internal.domain''. Rules can be defined in ''/rules.json'' which is located at the website root directory.
 +
 +<file nginx test-nginx.conf>
 +server {
 +  server_name "~^(?<vhost>.+?)\.dev\.sso\.my\.domain$";
 +  location = /lmauth {
 +    internal;
 +    include /etc/nginx/fastcgi_params;
 +    fastcgi_pass unix:/home/xavier/dev/lemonldap/e2e-tests/conf/llng-fastcgi.sock;
 +    # Force handler type:
 +    fastcgi_param VHOSTTYPE DevOps;
 +    # Drop post datas
 +    fastcgi_pass_request_body  off;
 +    fastcgi_param CONTENT_LENGTH "";
 +    # Keep original hostname
 +    fastcgi_param HOST $http_host;
 +    # Keep original request (LLNG server will received /lmauth)
 +    fastcgi_param X_ORIGINAL_URI  $request_uri;
 +  }
 +  location /rules.json {
 +    auth_request off;
 +    allow 127.0.0.0/8;
 +    deny all;
 +  }
 +  location / {
 +    auth_request /lmauth;
 +    auth_request_set $lmremote_user $upstream_http_lm_remote_user;
 +    auth_request_set $lmlocation $upstream_http_location;
 +    error_page 401 $lmlocation;
 +    include /etc/lemonldap-ng/nginx-lua-headers.conf;
 +    proxy_pass https://$vhost.internal.domain;
 +  }
 +}
 +</file>