lemonldap-ng/doc/pages/documentation/current/authssl.html
Xavier Guimard ce59789747 Update doc
2019-06-28 16:53:45 +02:00

438 lines
21 KiB
HTML

<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
<title>documentation:2.0:authssl</title>
<meta name="generator" content="DokuWiki"/>
<meta name="robots" content="index,follow"/>
<meta name="keywords" content="documentation,2.0,authssl"/>
<link rel="search" type="application/opensearchdescription+xml" href="lib/exe/opensearch.html" title="LemonLDAP::NG"/>
<link rel="start" href="authssl.html"/>
<link rel="contents" href="authssl.html" title="Sitemap"/>
<link rel="stylesheet" type="text/css" href="lib/exe/css.php.t.bootstrap3.css"/>
<!-- //if:usedebianlibs
<link rel="stylesheet" type="text/css" href="/javascript/bootstrap/css/bootstrap.min.css" />
//elsif:useexternallibs
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"></script>
//elsif:cssminified
<link rel="stylesheet" type="text/css" href="/static/bwr/bootstrap/dist/css/bootstrap.min.css" />
//else -->
<link rel="stylesheet" type="text/css" href="/static/bwr/bootstrap/dist/css/bootstrap.css" />
<!-- //endif -->
<script type="text/javascript">/*<![CDATA[*/var NS='documentation:2.0';var JSINFO = {"id":"documentation:2.0:authssl","namespace":"documentation:2.0"};
/*!]]>*/</script>
<script type="text/javascript" charset="utf-8" src="lib/exe/js.php.t.bootstrap3.js"></script>
<!-- //if:usedebianlibs
<script type="text/javascript" src="/javascript/jquery/jquery.min.js"></script>
//elsif:useexternallibs
<script type="text/javascript" src="http://code.jquery.com/jquery-2.2.0.min.js"></script>
//elsif:jsminified
<script type="text/javascript" src="/static/bwr/jquery/dist/jquery.min.js"></script>
//else -->
<script type="text/javascript" src="/static/bwr/jquery/dist/jquery.js"></script>
<!-- //endif -->
<!-- //if:usedebianlibs
<script type="text/javascript" src="/javascript/jquery-ui/jquery-ui.min.js"></script>
//elsif:useexternallibs
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"></script>
//elsif:jsminified
<script type="text/javascript" src="/static/bwr/jquery-ui/jquery-ui.min.js"></script>
//else -->
<script type="text/javascript" src="/static/bwr/jquery-ui/jquery-ui.js"></script>
<!-- //endif -->
</head>
<body>
<div class="dokuwiki export container">
<!-- TOC START -->
<div id="dw__toc">
<h3 class="toggle">Table of Contents</h3>
<div>
<ul class="toc">
<li class="level1"><div class="li"><a href="#presentation">Presentation</a></div></li>
<li class="level1"><div class="li"><a href="#configuration">Configuration</a></div>
<ul class="toc">
<li class="level2"><div class="li"><a href="#with_apache">With Apache</a></div>
<ul class="toc">
<li class="level3"><div class="li"><a href="#enable_ssl_in_apache">Enable SSL in Apache</a></div></li>
<li class="level3"><div class="li"><a href="#apache_ssl_global_configuration">Apache SSL global configuration</a></div></li>
<li class="level3"><div class="li"><a href="#apache_portal_ssl_configuration">Apache portal SSL configuration</a></div></li>
</ul>
</li>
<li class="level2"><div class="li"><a href="#with_nginx">With Nginx</a></div>
<ul class="toc">
<li class="level3"><div class="li"><a href="#nginx_ssl_virtual_host_example_with_uwsgi">Nginx SSL Virtual Host example with uWSGI</a></div></li>
</ul>
</li>
<li class="level2"><div class="li"><a href="#configuration_of_lemonldapng">Configuration of LemonLDAP::NG</a></div></li>
<li class="level2"><div class="li"><a href="#auto_reloading_ssl_certificates">Auto reloading SSL Certificates</a></div></li>
</ul>
</li>
<li class="level1"><div class="li"><a href="#ssl_by_ajax">SSL by Ajax</a></div></li>
</ul>
</div>
</div>
<!-- TOC END -->
<h1 class="sectionedit1" id="ssl">SSL</h1>
<div class="level1">
<div class="table sectionedit2"><table class="inline table table-bordered table-striped">
<thead>
<tr class="row0 roweven">
<th class="col0 centeralign"> Authentication </th><th class="col1 centeralign"> Users </th><th class="col2 centeralign"> Password </th>
</tr>
</thead>
<tr class="row1 rowodd">
<td class="col0 centeralign"></td><td class="col1"> </td><td class="col2"> </td>
</tr>
</table></div>
<!-- EDIT2 TABLE [19-76] -->
</div>
<!-- EDIT1 SECTION "SSL" [1-77] -->
<h2 class="sectionedit3" id="presentation">Presentation</h2>
<div class="level2">
<p>
<abbr title="LemonLDAP::NG">LL::NG</abbr> uses <a href="http://httpd.apache.org/docs/current/mod/mod_ssl.html" class="urlextern" title="http://httpd.apache.org/docs/current/mod/mod_ssl.html" rel="nofollow">Apache SSL module</a>, like any other <a href="authapache.html" class="wikilink1" title="documentation:2.0:authapache">Apache authentication module</a>, with extra features:
</p>
<ul>
<li class="level1"><div class="li"> Choice of any certificate attribute as user main login</div>
</li>
<li class="level1"><div class="li"> Allow no certificate to chain with other authentication methods</div>
</li>
</ul>
</div>
<!-- EDIT3 SECTION "Presentation" [78-401] -->
<h2 class="sectionedit4" id="configuration">Configuration</h2>
<div class="level2">
<p>
By default, SSL is required before the portal is displayed (handled by webserver). If you want to display a button to connect to LLNG <em>(compatible with <a href="authcombination.html" class="wikilink1" title="documentation:2.0:authcombination">Combination</a>)</em>, you can activate “SSL by Ajax request” in the manager. See <a href="#ssl_by_ajax" title="documentation:2.0:authssl ↵" class="wikilink1">SSL by Ajax</a> below.
</p>
</div>
<!-- EDIT4 SECTION "Configuration" [402-713] -->
<h3 class="sectionedit5" id="with_apache">With Apache</h3>
<div class="level3">
</div>
<h4 id="enable_ssl_in_apache">Enable SSL in Apache</h4>
<div class="level4">
<p>
You have to install mod_ssl for Apache.
</p>
<p>
For CentOS/RHEL:
</p>
<pre class="code shell">yum install mod_ssl</pre>
<div class="notetip">In Debian/Ubuntu mod_ssl is already shipped in <code>apache*-common</code> package.
</div><div class="notetip">For CentOS/RHEL, We advice to disable the default SSL virtual host configured in /etc/httpd/conf.d/ssl.conf.
</div>
</div>
<h4 id="apache_ssl_global_configuration">Apache SSL global configuration</h4>
<div class="level4">
<p>
You can then use this default SSL configuration, for example in the head of /etc/lemonldap-ng/portal-apache2.conf:
</p>
<pre class="code file apache"><span class="kw1">SSLProtocol</span> <span class="kw2">all</span> -SSLv2
<span class="kw1">SSLCipherSuite</span> HIGH:MEDIUM
<span class="kw1">SSLCertificateFile</span> /etc/httpd/certs/ow2.cert
<span class="kw1">SSLCertificateKeyFile</span> /etc/httpd/certs/ow2.key
<span class="kw1">SSLCACertificateFile</span> /etc/httpd/certs/ow2-ca.cert</pre>
<div class="noteclassic">Put your own files instead of <code>ow2.cert</code>, <code>ow2.key</code>, <code>ow2-ca.cert</code>:<ul>
<li class="level1"><div class="li"> <strong>SSLCertificateFile</strong>: Server certificate</div>
</li>
<li class="level1"><div class="li"> <strong>SSLCertificateKeyFile</strong>: Server private key</div>
</li>
<li class="level1"><div class="li"> <strong>SSLCACertificateFile</strong>: CA certificate to validate client certificates</div>
</li>
</ul>
</div>
<p>
If you specify port in virtual host, then declare SSL port:
</p>
<pre class="code file apache"><span class="kw1">NameVirtualHost</span> *:<span class="nu0">80</span>
<span class="kw1">NameVirtualHost</span> *:<span class="nu0">443</span></pre>
</div>
<h4 id="apache_portal_ssl_configuration">Apache portal SSL configuration</h4>
<div class="level4">
<p>
Edit the portal virtual host to enable SSL double authentication:
</p>
<pre class="code file apache"><span class="kw1">SSLEngine</span> <span class="kw2">On</span>
<span class="kw1">SSLVerifyClient</span> optional
<span class="kw1">SSLVerifyDepth</span> <span class="nu0">10</span>
<span class="kw1">SSLOptions</span> +StdEnvVars
<span class="kw1">SSLUserName</span> SSL_CLIENT_S_DN_CN</pre>
<p>
All SSL options are documented in <a href="http://httpd.apache.org/docs/current/mod/mod_ssl.html" class="urlextern" title="http://httpd.apache.org/docs/current/mod/mod_ssl.html" rel="nofollow">Apache mod_ssl page</a>.
</p>
<p>
Here are the main options used by <abbr title="LemonLDAP::NG">LL::NG</abbr>:
</p>
<ul>
<li class="level1"><div class="li"> <strong>SSLVerifyClient</strong>: set to <code>optional</code> to allow user with a bad certificate to access to <abbr title="LemonLDAP::NG">LL::NG</abbr> portal page. To switch to another authentication backend, use the <a href="authmulti.html" class="wikilink1" title="documentation:2.0:authmulti">Multi</a> module, for example: <code>Multi SSL;LDAP</code></div>
</li>
<li class="level1"><div class="li"> <strong>SSLOptions</strong>: set to <code>+StdEnvVars</code> to get certificate fields in environment variables</div>
</li>
<li class="level1"><div class="li"> <strong>SSLUserName</strong> (optional): certificate field that will be used to identify user in <abbr title="LemonLDAP::NG">LL::NG</abbr> portal virtual host</div>
</li>
</ul>
</div>
<!-- EDIT5 SECTION "With Apache" [714-2684] -->
<h3 class="sectionedit6" id="with_nginx">With Nginx</h3>
<div class="level3">
<p>
Enable SSL:
</p>
<pre class="code file nginx">ssl on;
ssl_verify_client optional;
ssl_certificate /etc/letsencrypt/live/my/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my/privkey.pem;
ssl_verify_depth 3;
ssl_client_certificate /etc/nginx/ssl/ca.pem;
ssl_crl /etc/nginx/ssl/crl/my.crl;</pre>
<p>
You must also export SSL_CLIENT_S_<abbr title="Distinguished Name">DN</abbr>_CN in FastCGI params:
</p>
<pre class="code file nginx"># map directive must be in http context
map $ssl_client_s_dn $ssl_client_s_dn_cn {
default &quot;&quot;;
~/CN=(?&lt;CN&gt;[^/]+) $CN; # prior Nginx 1.11.6
#~,CN=(?&lt;CN&gt;[^,]+) $CN; # Nginx &gt;= 1.11.6
}
fastcgi_param SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn;</pre>
</div>
<h4 id="nginx_ssl_virtual_host_example_with_uwsgi">Nginx SSL Virtual Host example with uWSGI</h4>
<div class="level4">
<pre class="code file nginx">server {
listen 443;
server_name authssl.example.com;
root /usr/share/lemonldap-ng/portal/htdocs/;
# Use &quot;lm_app&quot; format to get username in nginx.log (see nginx-lmlog.conf)
access_log /var/log/nginx/access.log lm_app;
&nbsp;
ssl_verify_client on;
ssl_verify_depth 3;
&nbsp;
# Full chain CRL is required
# All CRLs must be concatenated in a single .pem format file
ssl_crl /etc/nginx/ssl/crl/crls.pem;
if ($uri !~ ^/((static|javascript|favicon).*|.*\.psgi)) {
rewrite ^/(.*)$ /index.psgi/$1 break;
}
&nbsp;
location ~ ^(?&lt;sc&gt;/.*\.psgi)(?:$|/) {
# uWSGI Configuration
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:5000;
uwsgi_param LLTYPE psgi;
uwsgi_param SCRIPT_FILENAME $document_root$sc;
uwsgi_param SCRIPT_NAME $sc;
uwsgi_param SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn;
}
&nbsp;
#index index.psgi;
location / {
try_files $uri $uri/ =404;
add_header Strict-Transport-Security &quot;max-age=15768000&quot;;
}
}</pre>
<div class="noteimportant">Nginx 1.11.6 change: format of the $ssl_client_s_dn and $ssl_client_i_dn variables
has been changed to follow <abbr title="Request for Comments">RFC</abbr> 2253 (<abbr title="Request for Comments">RFC</abbr> 4514); values in the old format are available
in the $ssl_client_s_dn_legacy and $ssl_client_i_dn_legacy variables.
</div>
</div>
<!-- EDIT6 SECTION "With Nginx" [2685-4659] -->
<h3 class="sectionedit7" id="configuration_of_lemonldapng">Configuration of LemonLDAP::NG</h3>
<div class="level3">
<p>
In Manager, go in <code>General Parameters</code> &gt; <code>Authentication modules</code> and choose SSL for authentication.
</p>
<div class="notetip">You can then choose any other module for users and password.
</div>
<p>
Then, go in <code>SSL parameters</code>:
</p>
<ul>
<li class="level1"><div class="li"> <strong>Authentication level</strong>: authentication level for this module</div>
</li>
<li class="level1"><div class="li"> <strong>Extracted certificate field</strong>: field of the certificate affected to $user internal variable</div>
</li>
</ul>
</div>
<!-- EDIT7 SECTION "Configuration of LemonLDAP::NG" [4660-5085] -->
<h3 class="sectionedit8" id="auto_reloading_ssl_certificates">Auto reloading SSL Certificates</h3>
<div class="level3">
<p>
A known problematic is that many browser (Firefox, Chrome) remembers the fact that the certificate is not available at a certain time.
It is particularly important for smart cards: when the card is not inserted before the browser starts, the user must restart his browser, or at least refresh (F5) the page.
</p>
<p>
It is possible with AJAX code and 3 Apache locations to bypass this limitation.
</p>
<p>
1. Modify the portal virtual host to match this example:
</p>
<pre class="code file apache"> <span class="kw1">SSLEngine</span> <span class="kw2">On</span>
<span class="kw1">SSLCACertificateFile</span> /etc/apache2/ssl/ca.crt
<span class="kw1">SSLCertificateKeyFile</span> /etc/apache2/ssl/lemonldap.key
<span class="kw1">SSLCertificateFile</span> /etc/apache2/ssl/lemonldap.crt
&nbsp;
<span class="kw1">SSLVerifyDepth</span> <span class="nu0">10</span>
<span class="kw1">SSLOptions</span> +StdEnvVars
<span class="kw1">SSLUserName</span> SSL_CLIENT_S_DN_CN
&nbsp;
<span class="co1"># DocumentRoot</span>
<span class="kw1">DocumentRoot</span> /var/lib/lemonldap-ng/portal/
&lt;<span class="kw3">Directory</span> /var/lib/lemonldap-ng/portal/&gt;
<span class="kw1">Order</span> <span class="kw1">Deny</span>,<span class="kw1">Allow</span>
<span class="kw1">Allow</span> from <span class="kw2">all</span>
<span class="kw1">Options</span> +ExecCGI +<span class="kw2">FollowSymLinks</span>
<span class="kw1">SSLVerifyClient</span> <span class="kw2">none</span>
&lt;/<span class="kw3">Directory</span>&gt;
&nbsp;
&lt;<span class="kw3">Location</span> /index&gt;
<span class="kw1">Order</span> <span class="kw1">Deny</span>,<span class="kw1">Allow</span>
<span class="kw1">Allow</span> from <span class="kw2">all</span>
<span class="kw1">SSLVerifyClient</span> <span class="kw2">none</span>
&lt;/<span class="kw3">Location</span>&gt;
&nbsp;
&lt;<span class="kw3">Location</span> /testssl&gt;
<span class="kw1">Order</span> <span class="kw1">Deny</span>,<span class="kw1">Allow</span>
<span class="kw1">Allow</span> from <span class="kw2">all</span>
<span class="kw1">SSLVerifyClient</span> <span class="kw1">require</span>
&lt;/<span class="kw3">Location</span>&gt;
&nbsp;
<span class="kw1">Alias</span> /sslok /var/lib/lemonldap-ng/portal
&lt;<span class="kw3">Location</span> /sslok&gt;
<span class="kw1">Order</span> <span class="kw1">Deny</span>,<span class="kw1">Allow</span>
<span class="kw1">Allow</span> from <span class="kw2">all</span>
<span class="kw1">SSLVerifyClient</span> <span class="kw1">require</span>
&lt;/<span class="kw3">Location</span>&gt;</pre>
<ul>
<li class="level1"><div class="li"> /index/ is an unprotected page to display a SSL test button</div>
</li>
<li class="level1"><div class="li"> /testssl/ is a SSL protected page to check the certificate</div>
</li>
<li class="level1"><div class="li"> /sslok/ is the new LemonLDAP::NG portal. You need to declare the new url in the manager: Portal -&gt; <abbr title="Uniform Resource Locator">URL</abbr>: <a href="https://auth.example.com/sslok/" class="urlextern" title="https://auth.example.com/sslok/" rel="nofollow">https://auth.example.com/sslok/</a></div>
</li>
</ul>
<p>
2. Then you need to construct the Ajax page, for example in /index/bouton.html. It looks like this:
</p>
<pre class="code file html4strict"><span class="sc2">&lt;<a href="http://december.com/html/4/element/body.html"><span class="kw2">body</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/script.html"><span class="kw2">script</span></a> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;./jquery-2.1.4.min.js&quot;</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/javascript&quot;</span>&gt;</span> <span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/script.html"><span class="kw2">script</span></a>&gt;</span>
<span class="sc-1">&lt;!--&lt;script src=&quot;./jquery-ui-1.8-rass.js&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;--&gt;</span>
&nbsp;
&nbsp;
<span class="sc2">&lt;<a href="http://december.com/html/4/element/a.html"><span class="kw2">a</span></a> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;http://www.google.fr&quot;</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;enteteBouton&quot;</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;continuerButton&quot;</span>&gt;&lt;<a href="http://december.com/html/4/element/img.html"><span class="kw2">img</span></a> <span class="kw3">src</span><span class="sy0">=</span>authent.png&gt;&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/a.html"><span class="kw2">a</span></a>&gt;</span>
<span class="sc2">&lt;<a href="http://december.com/html/4/element/script.html"><span class="kw2">script</span></a>&gt;</span>
$('.enteteBouton').click( function (e) {
var b=navigator.userAgent.toLowerCase();
if(b.indexOf(&quot;msie&quot;)!==-1){
document.execCommand(&quot;ClearAuthenticationCache&quot;)
}
e.preventDefault();
$.ajax({
url:&quot;https://auth.example.com/testssl&quot;,
beforeSend:function(){},
type:&quot;GET&quot;,
dataType:&quot;html&quot;,
success:function(c,a){
if (c !== &quot;&quot;) {
alert(&quot;Carte OK&quot;);
window.location.href = &quot;https://auth.example.com/sslok/&quot;;
}
else {
alert('Carte KO');
}
},
error:function (xhr, ajaxOptions, thrownError){
if(xhr.status==404) {
alert(&quot;Carte OK&quot;);
window.location.href = &quot;https://auth.example.com/sslok/&quot;;
}
else {
alert('Carte KO');
}
},
complete:function(c,a){}
});
});
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/script.html"><span class="kw2">script</span></a>&gt;</span>
<span class="sc2">&lt;<span class="sy0">/</span><a href="http://december.com/html/4/element/body.html"><span class="kw2">body</span></a>&gt;</span></pre>
<div class="notewarning">It is incompatible with authentication combination because of Apache parameter “SSLVerifyClient”, which must have the value “require”. To enable SSL with <a href="authcombination.html" class="wikilink1" title="documentation:2.0:authcombination">Combination</a>, use <a href="#ssl_by_ajax" title="documentation:2.0:authssl ↵" class="wikilink1">SSL by Ajax</a>
</div>
</div>
<!-- EDIT8 SECTION "Auto reloading SSL Certificates" [5086-8349] -->
<h2 class="sectionedit9" id="ssl_by_ajax">SSL by Ajax</h2>
<div class="level2">
<p>
If you enable this feature, you must configure 2 portal virtual hosts:
</p>
<ul>
<li class="level1"><div class="li"> the main <em>(which corresponds to portal <abbr title="Uniform Resource Locator">URL</abbr>)</em> with <code>SSLVerifyClient none</code></div>
</li>
<li class="level1"><div class="li"> the second with <code>SSLVerifyClient require</code> and a <code>Header set Allow-Control-Allow-Origin https://portal-main-url</code></div>
</li>
</ul>
<p>
then declare the second <abbr title="Uniform Resource Locator">URL</abbr> in SSL options in the Manager. That&#039;s all ! Then you can chain it in a <a href="authcombination.html" class="wikilink1" title="documentation:2.0:authcombination">combination</a>.
</p>
<div class="noteclassic">With <a href="authchoice.html" class="wikilink1" title="documentation:2.0:authchoice">choice</a>, the second <abbr title="Uniform Resource Locator">URL</abbr> should be also declared in module <abbr title="Uniform Resource Locator">URL</abbr> parameter to redirect user to Portal menu.
</div><div class="noteimportant"><strong>Content Security Policy</strong> may prevent to submit Ajax Request.
To avoid security warning,
<p>
Go to : <code>General Parameters &gt; Advanced Parameters &gt; Security &gt; Content security policy</code>
</p>
<p>
and set :
</p>
<p>
<strong>Default value</strong> =&gt; &#039;self&#039; “Ajax request <abbr title="Uniform Resource Locator">URL</abbr>
</p>
<p>
<strong>Form destinations</strong> =&gt; &#039;self&#039; “Ajax request <abbr title="Uniform Resource Locator">URL</abbr>
</p>
<p>
<strong>Ajax destinations</strong> =&gt; &#039;self&#039; “Ajax request <abbr title="Uniform Resource Locator">URL</abbr>
</p>
</div>
</div>
<!-- EDIT9 SECTION "SSL by Ajax" [8350-] --></div>
</body>
</html>