From ff36b81e730d692bea3f82f878e908dfb68c804d Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Thu, 18 Feb 2021 22:46:18 +0100 Subject: [PATCH] Append accessor to avoid modify conf (#2451) --- doc/sources/admin/crowdsec.rst | 2 +- doc/sources/admin/start.rst | 38 +++++++++---------- .../Lemonldap/NG/Portal/Plugins/CrowdSec.pm | 15 ++++---- .../site/htdocs/static/common/js/portal.js | 4 +- .../htdocs/static/common/js/portal.min.js | 2 +- lemonldap-ng-portal/t/61-CrowdSec-warn.t | 2 +- lemonldap-ng-portal/t/61-CrowdSec.t | 2 +- 7 files changed, 33 insertions(+), 32 deletions(-) diff --git a/doc/sources/admin/crowdsec.rst b/doc/sources/admin/crowdsec.rst index 61605b9b1..a9c48d616 100644 --- a/doc/sources/admin/crowdsec.rst +++ b/doc/sources/admin/crowdsec.rst @@ -11,7 +11,7 @@ community-powered IP reputation system. LL::NG provides a **CrowdSec** bouncer that can reject Crowdsec banned-IP requests or just provide an environment variable that can be used in another plugin rule. For example, a second factor may be required if user's -IP is CrowdSec bans it. +IP is CrowdSec-banned. Configuration ------------- diff --git a/doc/sources/admin/start.rst b/doc/sources/admin/start.rst index 55be9dcab..c69c43344 100644 --- a/doc/sources/admin/start.rst +++ b/doc/sources/admin/start.rst @@ -276,21 +276,21 @@ Name Description :doc:`Check user` [6]_ |new| Check access rights, transmitted headers and session attibutes for a specific user and URL :doc:`Configuration viewer` |new| Edit WebSSO configuration in Read Only mode :doc:`Context switching` [7]_\ |new| Switch context other users -:doc:`CrowdSec` [16]_\ |new| CrowdSec bouncer +:doc:`CrowdSec` [8]_\ |new| CrowdSec bouncer :doc:`Custom` Write a custom plugin -:doc:`Decrypt value` [8]_\ |image35| Decrypt ciphered values +:doc:`Decrypt value` [9]_\ |image35| Decrypt ciphered values :doc:`Display login history` Display Success/Fails logins :doc:`Force Authentication` Force authentication to access to Portal -:doc:`Global Logout` [9]_ Suggest to close all opened sessions at logout +:doc:`Global Logout` [10]_ Suggest to close all opened sessions at logout :doc:`Grant Sessions` Rules to apply before allowing a user to open a session -:doc:`Impersonation` [10]_\ |new| Allow users to use another identity -:doc:`Find user` [11]_\ |new| Search for user account +:doc:`Impersonation` [11]_\ |new| Allow users to use another identity +:doc:`Find user` [12]_\ |new| Search for user account :doc:`Notifications system` DIsplay a message during log in process :doc:`Portal Status` Experimental portal status page :doc:`Public pages` Enable public pages system -:doc:`Refresh session API` [12]_ Plugin that provides an API to refresh a user session +:doc:`Refresh session API` [13]_ Plugin that provides an API to refresh a user session :doc:`Reset password by mail` Send a mail to reset its password -:doc:`Reset certificate by mail` [13]_\ |image37| Allow users to reset their certificate +:doc:`Reset certificate by mail` [14]_\ |image37| Allow users to reset their certificate :doc:`REST services` |new| REST server for :doc:`Proxy` :doc:`SOAP services` |deprecated| SOAP server for :doc:`Proxy` :doc:`Stay connected` |new| Enable persistent connection on same browser @@ -308,12 +308,12 @@ Handlers are software control agents to be installed on your web servers ==================================================================== ========== ============================================================= =========================================== ================================================================================== =============================================== ====================================================================================================================== Handler type Apache LLNG FastCGI/uWSGI server (Nginx, or :doc:`SSOaaS`) `Plack servers `__ Node.js ( `express apps `__\ or :doc:`SSOaaS`) :doc:`Self protected apps` Comment ==================================================================== ========== ============================================================= =========================================== ================================================================================== =============================================== ====================================================================================================================== -Main *(default handler)* ✔ ✔ ✔ :doc:`Partial` ** [14]_ ** ✔ +Main *(default handler)* ✔ ✔ ✔ :doc:`Partial` ** [15]_ ** ✔ :doc:`AuthBasic` ✔ ✔ ✔ ✔ Designed for some server-to-server applications :doc:`CDA` ✔ ✔ ✔ ✔ For Cross Domain Authentication :doc:`DevOps` (:doc:`SSOaaS`) |new| ✔ ✔ ✔ ✔ Allows application developers to define their own rules and headers inside their applications :doc:`DevOpsST` (:doc:`SSOaaS`) |new| ✔ ✔ ✔ ✔ Enables both :doc:`DevOps` and :doc:`Service Token` -:doc:`OAuth2` [15]_\ |new| ✔ ✔ ✔ ✔ Uses OpenID Connect/OAuth2 access token to check authentication and authorization, can be used to protect Web Services +:doc:`OAuth2` [16]_\ |new| ✔ ✔ ✔ ✔ Uses OpenID Connect/OAuth2 access token to check authentication and authorization, can be used to protect Web Services :doc:`Secure Token` ✔ ✔ ✔ Designed to secure exchanges between a LLNG reverse-proxy and a remote app :doc:`Service Token` |new| *(Server-to-Server)* ✔ ✔ ✔ ✔ ✔ Designed to permit underlying requests *(API-Based Infrastructure)* :doc:`Zimbra PreAuth` ✔ ✔ ✔ @@ -579,38 +579,38 @@ by your language code): LLNG ≥ 2.0.6 .. [8] + :doc:`CrowdSec bouncer ` is available with LLNG ≥ 2.0.12 + +.. [9] :doc:`Decrypt value plugin` is available with LLNG ≥ 2.0.7 -.. [9] +.. [10] :doc:`Global Logout plugin` is available with LLNG ≥ 2.0.7 -.. [10] +.. [11] :doc:`Impersonation plugin` is available with LLNG ≥ 2.0.3 -.. [11] +.. [12] :doc:`Find user plugin` is available with LLNG ≥ 2.0.11 -.. [12] +.. [13] :doc:`Refresh session API plugin` is available with LLNG ≥ 2.0.7 -.. [13] +.. [14] :doc:`Reset certificate by mail plugin` is available with LLNG ≥ 2.0.7 -.. [14] +.. [15] :doc:`Node.js handler` has not yet reached the same level of functionalities -.. [15] - :doc:`OAuth2 Handler` is available with LLNG ≥ 2.0.4 - .. [16] - :doc:`CrowdSec bouncer ` is available with LLNG ≥ 2.0.12 + :doc:`OAuth2 Handler` is available with LLNG ≥ 2.0.4 .. |image0| image:: /icons/kthememgr.png .. |image1| image:: /icons/warehause.png diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CrowdSec.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CrowdSec.pm index 80178473b..2ff0b98c5 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CrowdSec.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/CrowdSec.pm @@ -5,12 +5,12 @@ use Mouse; use JSON qw(from_json); use Lemonldap::NG::Common::UserAgent; use Lemonldap::NG::Portal::Main::Constants qw( - PE_ERROR PE_OK + PE_ERROR PE_SESSIONNOTGRANTED ); -our $VERSION = '2.0.10'; +our $VERSION = '2.0.12'; extends 'Lemonldap::NG::Portal::Main::Plugin'; @@ -28,18 +28,19 @@ has ua => ( return $ua; } ); +has crowdsecUrl => ( is => 'rw' ); sub init { my ($self) = @_; if ( $self->conf->{crowdsecUrl} ) { - $self->conf->{crowdsecUrl} =~ s#/+$##; + $self->crowdsecUrl( $self->conf->{crowdsecUrl} =~ s#/+$## ); } else { $self->logger->warn( "crowdsecUrl isn't set, fallback to http://localhost:8080"); - $self->conf->{crowdsecUrl} = 'http://localhost:8080'; + $self->crowdsecUrl('http://localhost:8080'); } - $self->logger->notice( "CrowdSec policy is: " + $self->logger->notice( 'CrowdSec policy is: ' . ( $self->conf->{crowdsecAction} ? 'reject' : 'warn' ) ); return 1; } @@ -48,12 +49,12 @@ sub check { my ( $self, $req ) = @_; my $ip = $req->address; my $resp = $self->ua->get( - $self->conf->{crowdsecUrl} . "/v1/decisions?ip=$ip", + $self->crowdsecUrl . "/v1/decisions?ip=$ip", 'Accept' => 'application/json', 'X-Api-Key' => $self->conf->{crowdsecKey}, ); if ( $resp->is_error ) { - $self->logger->error( "Bad CrowdSec response: " . $resp->message ); + $self->logger->error( 'Bad CrowdSec response: ' . $resp->message ); $self->logger->debug( $resp->content ); return PE_ERROR; } diff --git a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js index 283c36599..0f0c7473f 100644 --- a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js +++ b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.js @@ -588,11 +588,11 @@ LemonLDAP::NG Portal jQuery scripts } }); $('#resetfinduserform').on('click', function() { - console.log('Clear form'); + console.log('Reset form'); return $('#finduserForm').trigger('reset'); }); $('#finduserModal').on('hidden.bs.modal', function() { - console.log('Reset modal'); + console.log('Clear modal'); return $('#finduserForm').trigger('reset'); }); return $('#finduserbutton').on('click', function(event) { diff --git a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js index d0cad62cb..c8daecd79 100644 --- a/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js +++ b/lemonldap-ng-portal/site/htdocs/static/common/js/portal.min.js @@ -1 +1 @@ -(function(){var G,a,D,R,M,N,U,V,_,e,J,g,F,q,r,H=[].indexOf||function(e){for(var a=0,t=this.length;a div.category",update:function(){return J()}}),V(),$("div.message").fadeIn("slow"),$("input[name=timezone]").val(-(new Date).getTimezoneOffset()/60),k=$("#menu").tabs({active:0}),(b=$('#menu a[href="#'+G.displaytab+'"]').parent().index())<0&&(b=0),k.tabs("option","active",b),n=$("#authMenu").tabs({active:0}),(t=$('#authMenu a[href="#'+G.displaytab+'"]').parent().index())<0&&(t=0),n.tabs("option","active",t),G.choicetab&&n.tabs("option","active",$('#authMenu a[href="#'+G.choicetab+'"]').parent().index()),G.login?$("input[type=password]:first").focus():0===$("input[autofocus]").length&&$("input[type!=hidden]:first").focus(),G.newwindow&&$("#appslist a").attr("target","_blank"),$("p.removeOther").length&&(e=$("#form").attr("action"),x=$("#form").attr("method"),console.log("method=",x),i="",$("#form input[type=hidden]")&&(console.log("Parse hidden values"),$("#form input[type=hidden]").each(function(e){return console.log(" ->",$(this).attr("name"),$(this).val()),i+="&"+$(this).attr("name")+"="+$(this).val()})),o="",e&&(console.log("action=",e),-1!==e.indexOf("?")?e.substring(0,e.indexOf("?")):o=e+"?",o+=i,i=""),y=$("p.removeOther a").attr("href")+"&method="+x+i,o&&(y+="&url="+btoa(o)),$("p.removeOther a").attr("href",y)),window.location.search&&((S=R("llnglanguage"))&&console.log("Get lang from parameter"),1===(A=R("setCookieLang"))&&console.log("Set lang cookie")),c||(c=D("llnglanguage"))&&!S&&console.log("Get lang from cookie"),c)H.call(window.availableLanguages,c)<0&&(c=window.availableLanguages[0],S||console.log("Lang not available -> Get default lang"));else if(navigator){for(p=[],g=[],O=[navigator.language],navigator.languages&&(O=navigator.languages),l=0,f=(E=window.availableLanguages).length;l ';for(v=0,h=O.length;v Get default lang"),S=window.availableLanguages[0]),console.log("Selected lang ->",S),A&&(console.log("Set cookie lang ->",S),_("llnglanguage",S)),q(S)):(console.log("Selected lang ->",c),_("llnglanguage",c),q(c)),d="",L=0,m=(z=window.availableLanguages).length;L ';return $("#languages").html(d),$(".langicon").on("click",function(){return c=$(this).attr("title"),_("llnglanguage",c),q(c)}),u=function(e){var a;return 47<(a=e.charCodeAt(0))&&a<58||64=window.datas.ppolicy.minsize?($("#ppolicy-minsize-feedback").addClass("fa-check text-success"),$("#ppolicy-minsize-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minsize-feedback").removeClass("fa-check text-success"),$("#ppolicy-minsize-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.minupper?($("#ppolicy-minupper-feedback").addClass("fa-check text-success"),$("#ppolicy-minupper-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minupper-feedback").removeClass("fa-check text-success"),$("#ppolicy-minupper-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.minlower?($("#ppolicy-minlower-feedback").addClass("fa-check text-success"),$("#ppolicy-minlower-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minlower-feedback").removeClass("fa-check text-success"),$("#ppolicy-minlower-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.mindigit?($("#ppolicy-mindigit-feedback").addClass("fa-check text-success"),$("#ppolicy-mindigit-feedback").removeClass("fa-times text-danger")):($("#ppolicy-mindigit-feedback").removeClass("fa-check text-success"),$("#ppolicy-mindigit-feedback").addClass("fa-times text-danger"),d=!1)),window.datas.ppolicy.allowedspechar){for(r=window.datas.ppolicy.allowedspechar.replace(/\s/g,""),t=!1,n=0,o=e.length;n=window.datas.ppolicy.minspechar?($("#ppolicy-minspechar-feedback").addClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minspechar-feedback").removeClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").addClass("fa-times text-danger"),d=!1)}if(0=window.datas.ppolicy.minspechar?($("#ppolicy-minspechar-feedback").addClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minspechar-feedback").removeClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").addClass("fa-times text-danger"),d=!1)}d?($(".ppolicy").removeClass("border-danger").addClass("border-success"),null!=(l=$("#newpassword").get(0))&&l.setCustomValidity("")):($(".ppolicy").removeClass("border-success").addClass("border-danger"),null!=(c=$("#newpassword").get(0))&&c.setCustomValidity(F("PE28")))},null!=window.datas.ppolicy&&$("#newpassword").length&&(s(""),$("#newpassword").keyup(function(e){s(e.target.value)})),I=function(e){var a;return e.target.checked?($("#newpassword").off("keyup"),null!=(a=$("#newpassword").get(0))?a.setCustomValidity(""):void 0):($("#newpassword").keyup(function(e){s(e.target.value)}),s(""))},r=function(){var e,a,t,n;return(null!=(e=$("#confirmpassword").get(0))?e.value:void 0)===(null!=(a=$("#newpassword").get(0))?a.value:void 0)?(null!=(t=$("#confirmpassword").get(0))&&t.setCustomValidity(""),!0):(null!=(n=$("#confirmpassword").get(0))&&n.setCustomValidity(F("PE34")),!1)},$("#newpassword").change(r),$("#confirmpassword").change(r),null!=window.datas.ppolicy&&$("#newpassword").length&&$("#reset").change(I),G.pingInterval&&0 div.category",update:function(){return J()}}),V(),$("div.message").fadeIn("slow"),$("input[name=timezone]").val(-(new Date).getTimezoneOffset()/60),k=$("#menu").tabs({active:0}),(b=$('#menu a[href="#'+G.displaytab+'"]').parent().index())<0&&(b=0),k.tabs("option","active",b),n=$("#authMenu").tabs({active:0}),(t=$('#authMenu a[href="#'+G.displaytab+'"]').parent().index())<0&&(t=0),n.tabs("option","active",t),G.choicetab&&n.tabs("option","active",$('#authMenu a[href="#'+G.choicetab+'"]').parent().index()),G.login?$("input[type=password]:first").focus():0===$("input[autofocus]").length&&$("input[type!=hidden]:first").focus(),G.newwindow&&$("#appslist a").attr("target","_blank"),$("p.removeOther").length&&(e=$("#form").attr("action"),x=$("#form").attr("method"),console.log("method=",x),i="",$("#form input[type=hidden]")&&(console.log("Parse hidden values"),$("#form input[type=hidden]").each(function(e){return console.log(" ->",$(this).attr("name"),$(this).val()),i+="&"+$(this).attr("name")+"="+$(this).val()})),o="",e&&(console.log("action=",e),-1!==e.indexOf("?")?e.substring(0,e.indexOf("?")):o=e+"?",o+=i,i=""),y=$("p.removeOther a").attr("href")+"&method="+x+i,o&&(y+="&url="+btoa(o)),$("p.removeOther a").attr("href",y)),window.location.search&&((S=R("llnglanguage"))&&console.log("Get lang from parameter"),1===(A=R("setCookieLang"))&&console.log("Set lang cookie")),c||(c=D("llnglanguage"))&&!S&&console.log("Get lang from cookie"),c)H.call(window.availableLanguages,c)<0&&(c=window.availableLanguages[0],S||console.log("Lang not available -> Get default lang"));else if(navigator){for(p=[],g=[],O=[navigator.language],navigator.languages&&(O=navigator.languages),l=0,f=(E=window.availableLanguages).length;l ';for(v=0,h=O.length;v Get default lang"),S=window.availableLanguages[0]),console.log("Selected lang ->",S),A&&(console.log("Set cookie lang ->",S),_("llnglanguage",S)),q(S)):(console.log("Selected lang ->",c),_("llnglanguage",c),q(c)),d="",L=0,m=(z=window.availableLanguages).length;L ';return $("#languages").html(d),$(".langicon").on("click",function(){return c=$(this).attr("title"),_("llnglanguage",c),q(c)}),u=function(e){var a;return 47<(a=e.charCodeAt(0))&&a<58||64=window.datas.ppolicy.minsize?($("#ppolicy-minsize-feedback").addClass("fa-check text-success"),$("#ppolicy-minsize-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minsize-feedback").removeClass("fa-check text-success"),$("#ppolicy-minsize-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.minupper?($("#ppolicy-minupper-feedback").addClass("fa-check text-success"),$("#ppolicy-minupper-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minupper-feedback").removeClass("fa-check text-success"),$("#ppolicy-minupper-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.minlower?($("#ppolicy-minlower-feedback").addClass("fa-check text-success"),$("#ppolicy-minlower-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minlower-feedback").removeClass("fa-check text-success"),$("#ppolicy-minlower-feedback").addClass("fa-times text-danger"),d=!1)),0=window.datas.ppolicy.mindigit?($("#ppolicy-mindigit-feedback").addClass("fa-check text-success"),$("#ppolicy-mindigit-feedback").removeClass("fa-times text-danger")):($("#ppolicy-mindigit-feedback").removeClass("fa-check text-success"),$("#ppolicy-mindigit-feedback").addClass("fa-times text-danger"),d=!1)),window.datas.ppolicy.allowedspechar){for(r=window.datas.ppolicy.allowedspechar.replace(/\s/g,""),t=!1,n=0,o=e.length;n=window.datas.ppolicy.minspechar?($("#ppolicy-minspechar-feedback").addClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minspechar-feedback").removeClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").addClass("fa-times text-danger"),d=!1)}if(0=window.datas.ppolicy.minspechar?($("#ppolicy-minspechar-feedback").addClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").removeClass("fa-times text-danger")):($("#ppolicy-minspechar-feedback").removeClass("fa-check text-success"),$("#ppolicy-minspechar-feedback").addClass("fa-times text-danger"),d=!1)}d?($(".ppolicy").removeClass("border-danger").addClass("border-success"),null!=(l=$("#newpassword").get(0))&&l.setCustomValidity("")):($(".ppolicy").removeClass("border-success").addClass("border-danger"),null!=(c=$("#newpassword").get(0))&&c.setCustomValidity(F("PE28")))},null!=window.datas.ppolicy&&$("#newpassword").length&&(s(""),$("#newpassword").keyup(function(e){s(e.target.value)})),I=function(e){var a;return e.target.checked?($("#newpassword").off("keyup"),null!=(a=$("#newpassword").get(0))?a.setCustomValidity(""):void 0):($("#newpassword").keyup(function(e){s(e.target.value)}),s(""))},r=function(){var e,a,t,n;return(null!=(e=$("#confirmpassword").get(0))?e.value:void 0)===(null!=(a=$("#newpassword").get(0))?a.value:void 0)?(null!=(t=$("#confirmpassword").get(0))&&t.setCustomValidity(""),!0):(null!=(n=$("#confirmpassword").get(0))&&n.setCustomValidity(F("PE34")),!1)},$("#newpassword").change(r),$("#confirmpassword").change(r),null!=window.datas.ppolicy&&$("#newpassword").length&&$("#reset").change(I),G.pingInterval&&0new( { ini => { - logLevel => 'debug', + logLevel => 'error', authentication => 'Demo', userDB => 'Same', crowdsec => 1, diff --git a/lemonldap-ng-portal/t/61-CrowdSec.t b/lemonldap-ng-portal/t/61-CrowdSec.t index 395b6b86b..8ede7724b 100644 --- a/lemonldap-ng-portal/t/61-CrowdSec.t +++ b/lemonldap-ng-portal/t/61-CrowdSec.t @@ -32,7 +32,7 @@ my $res; my $client = LLNG::Manager::Test->new( { ini => { - logLevel => 'debug', + logLevel => 'error', authentication => 'Demo', userDB => 'Same', crowdsec => 1,