Make checkUser option rules (#2173)

This commit is contained in:
Christophe Maudoux 2020-04-24 00:04:43 +02:00
parent c8c50d2575
commit 6018610196
8 changed files with 75 additions and 30 deletions

View File

@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
use constant APPLYSECTION => "apply";
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:Empty(?:Header|Value)s|PersistentInfo))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|da)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );

View File

@ -36,6 +36,9 @@ sub defaultValues {
'http://auth.example.com/certificateReset',
'certificateResetByMailValidityDelay' => 0,
'checkTime' => 600,
'checkUserDisplayEmptyHeaders' => 0,
'checkUserDisplayEmptyValues' => 0,
'checkUserDisplayPersistentInfo' => 0,
'checkUserHiddenAttributes' => '_loginHistory _session_id hGroups',
'checkUserIdRule' => 1,
'checkXSS' => 1,

View File

@ -851,15 +851,15 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'checkUserDisplayEmptyHeaders' => {
'default' => 0,
'type' => 'bool'
'type' => 'boolOrExpr'
},
'checkUserDisplayEmptyValues' => {
'default' => 0,
'type' => 'bool'
'type' => 'boolOrExpr'
},
'checkUserDisplayPersistentInfo' => {
'default' => 0,
'type' => 'bool'
'type' => 'boolOrExpr'
},
'checkUserHiddenAttributes' => {
'default' => '_loginHistory _session_id hGroups',
@ -2271,10 +2271,6 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => 0,
'type' => 'bool'
},
'oidcServiceAllowPasswordGrant' => {
'default' => 0,
'type' => 'boolOrExpr'
},
'oidcServiceAuthorizationCodeExpiration' => {
'default' => 60,
'type' => 'int'

View File

@ -468,20 +468,20 @@ sub attributes {
},
checkUserDisplayPersistentInfo => {
default => 0,
type => 'bool',
documentation => 'Display persistent session info',
type => 'boolOrExpr',
documentation => 'Display persistent session info rule',
flags => 'p',
},
checkUserDisplayEmptyValues => {
default => 0,
type => 'bool',
documentation => 'Display session empty values',
type => 'boolOrExpr',
documentation => 'Display session empty values rule',
flags => 'p',
},
checkUserDisplayEmptyHeaders => {
default => 0,
type => 'bool',
documentation => 'Display empty headers',
type => 'boolOrExpr',
documentation => 'Display empty headers rule',
flags => 'p',
},
globalLogoutRule => {

File diff suppressed because one or more lines are too long

View File

@ -29,9 +29,12 @@ has ott => (
return $ott;
}
);
has idRule => ( is => 'rw', default => sub { 1 } );
has sorted => ( is => 'rw', default => sub { 0 } );
has merged => ( is => 'rw', default => '' );
has IdRule => ( is => 'rw', default => sub { 1 } );
has DisplayEmptyValuesRule => ( is => 'rw', default => sub { 0 } );
has DisplayEmptyHeadersRule => ( is => 'rw', default => sub { 0 } );
has DisplayPersistentInfoRule => ( is => 'rw', default => sub { 0 } );
has sorted => ( is => 'rw', default => sub { 0 } );
has merged => ( is => 'rw', default => '' );
sub hAttr {
$_[0]->{conf}->{checkUserHiddenAttributes} . ' '
@ -49,17 +52,60 @@ sub init {
$self->addAuthRoute( checkuser => 'check', ['POST'] );
$self->addAuthRouteWithRedirect( checkuser => 'display', ['GET'] );
# Parse identity rule
# Parse checkUser rules
# Id DisplayEmptyHeaders DisplayEmptyValues DisplayPersistentInfo
$self->logger->debug(
"checkUser identities rule -> " . $self->conf->{checkUserIdRule} );
"checkUser: Idrule -> " . $self->conf->{checkUserIdRule} )
if $self->conf->{checkUserIdRule};
my $rule =
$hd->buildSub( $hd->substitute( $self->conf->{checkUserIdRule} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error("Bad checkUser identities rule -> $error");
$self->error("Bad checkUser Id rule -> $error");
return 0;
}
$self->idRule($rule);
$self->IdRule($rule);
$self->logger->debug( "checkUser: DisplayEmptyHeaders -> "
. $self->conf->{checkUserDisplayEmptyHeaders} )
if $self->conf->{checkUserDisplayEmptyHeaders};
$rule =
$hd->buildSub(
$hd->substitute( $self->conf->{checkUserDisplayEmptyHeaders} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error("Bad checkUser DisplayEmptyHeaders rule -> $error");
return 0;
}
$self->DisplayEmptyHeadersRule($rule);
$self->logger->debug( "checkUser: DisplayEmptyValues -> "
. $self->conf->{checkUserDisplayEmptyValues} )
if $self->conf->{checkUserDisplayEmptyValues};
$rule =
$hd->buildSub(
$hd->substitute( $self->conf->{checkUserDisplayEmptyValues} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error("Bad checkUser DisplayEmptyValues rule -> $error");
return 0;
}
$self->DisplayEmptyValuesRule($rule);
$self->logger->debug( "checkUser: DisplayPersistentInfo -> "
. $self->conf->{checkUserDisplayPersistentInfo} )
if $self->conf->{checkUserDisplayPersistentInfo};
$rule =
$hd->buildSub(
$hd->substitute( $self->conf->{checkUserDisplayPersistentInfo} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error("Bad checkUser DisplayPersistentInfo rule -> $error");
return 0;
}
$self->DisplayPersistentInfoRule($rule);
# Init. other options
$self->sorted( $self->conf->{impersonationRule}
|| $self->conf->{contextSwitchingRule} );
$self->merged( $self->conf->{impersonationMergeSSOgroups}
@ -78,11 +124,11 @@ sub display {
$attrs = $req->userData;
$attrs = $self->_removePersistentAttributes($attrs)
unless $self->conf->{checkUserDisplayPersistentInfo};
unless $self->DisplayPersistentInfoRule->( $req, $req->userData );
# Create an array of hashes for template loop
$self->logger->debug("Delete hidden or empty attributes");
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
if ( $self->DisplayEmptyValuesRule->( $req, $req->userData ) ) {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes
@ -247,7 +293,7 @@ sub check {
else {
$msg = 'checkUser' . $self->merged;
$attrs = $self->_removePersistentAttributes($attrs)
unless $self->conf->{checkUserDisplayPersistentInfo};
unless $self->DisplayPersistentInfoRule->( $req, $req->userData );
if ($compute) {
$msg = 'checkUserComputeSession';
@ -274,7 +320,7 @@ sub check {
# Create an array of hashes for template loop
$self->logger->debug("Delete hidden or empty attributes");
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
if ( $self->DisplayEmptyValuesRule->( $req, $req->userData ) ) {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes
@ -400,7 +446,7 @@ sub _userData {
}
# Check identities rule
unless ( $self->idRule->( $req, $req->sessionInfo ) ) {
unless ( $self->IdRule->( $req, $req->sessionInfo ) ) {
$self->userLogger->warn(
'checkUser requested for an unvalid user (' . $req->{user} . ")" );
$req->{sessionInfo} = {};
@ -454,7 +500,7 @@ sub _headers {
$self->logger->debug(
"Return \"$attrs->{ $self->{conf}->{whatToTrace} }\" headers");
return $self->p->HANDLER->checkHeaders( $req, $attrs )
if ( $self->conf->{checkUserDisplayEmptyHeaders} );
if ( $self->DisplayEmptyHeadersRule->( $req, $req->userData ) );
$self->logger->debug("Remove empty headers");
my @headers = grep $_->{value} =~ /.+/,

View File

@ -33,7 +33,7 @@ my $client = LLNG::Manager::Test->new( {
oldNotifFormat => 0,
notificationsExplorer => 1,
checkUser => 1,
checkUserDisplayPersistentInfo => 1
checkUserDisplayPersistentInfo => '$uid eq "dwho"',
}
}
);

View File

@ -21,7 +21,7 @@ my $client = LLNG::Manager::Test->new( {
checkUserIdRule => '$uid ne "msmith"',
checkUserSearchAttributes => 'employee_nbr test1 _user test2 mail',
checkUserDisplayPersistentInfo => 1,
checkUserDisplayEmptyHeaders => 1,
checkUserDisplayEmptyHeaders => '$uid eq "dwho"',
checkUserDisplayEmptyValues => 1,
totp2fSelfRegistration => 1,
totp2fActivation => 1,