CAS per-service macros portal code (#2042)

This commit is contained in:
Maxime Besson 2019-10-22 18:52:04 +02:00
parent 2a15bb0523
commit a410793122
4 changed files with 148 additions and 3 deletions

View File

@ -118,6 +118,7 @@
"casAppMetaDataOptions":"Seçenekler",
"casAppMetaDataOptionsService":"Servis URL'si",
"casAppMetaDataOptionsRule":"Kural",
"casAppMetaDataMacros":"Makrolar",
"casAppMetaDataOptionsUserAttribute":"Kullanıcı niteliği",
"casAppName":"CAS Uygulama Adı",
"casAttr":"CAS girişi",

View File

@ -801,9 +801,21 @@ sub _validate2 {
}
foreach my $casAttribute ( keys %$ev ) {
my $localSessionValue = $localSession->data->{ $ev->{$casAttribute} };
$attributes->{$casAttribute} = $localSessionValue
if defined $localSessionValue;
my $sessionAttr = $ev->{$casAttribute};
my $value;
# Lookup per-service macros first, and then local sessions
#
if ( $app and $self->spMacros->{$app}->{$sessionAttr} ) {
$value = $self->spMacros->{$app}->{$sessionAttr}
->( $req, $localSession->data );
}
else {
$value = $localSession->data->{$sessionAttr};
}
$attributes->{$casAttribute} = $value
if defined $value;
}
# Return success message

View File

@ -26,6 +26,7 @@ has ua => (
has casSrvList => ( is => 'rw', default => sub { {} }, );
has casAppList => ( is => 'rw', default => sub { {} }, );
has spRules => ( is => 'rw', default => sub { {} }, );
has spMacros => ( is => 'rw', default => sub { {} }, );
# RUNNING METHODS
@ -67,6 +68,22 @@ sub loadApp {
}
$self->spRules->{$_} = $rule;
}
# Load per-application macros
my $macros = $self->conf->{casAppMetaDataMacros}->{$_};
for my $macroAttr ( keys %{$macros} ) {
my $macroRule = $macros->{$macroAttr};
if ( length $macroRule ) {
$macroRule = $self->p->HANDLER->substitute($macroRule);
unless ( $macroRule = $self->p->HANDLER->buildSub($macroRule) )
{
$self->error( 'SAML SP macro error: '
. $self->p->HANDLER->tsv->{jail}->error );
return 0;
}
$self->spMacros->{$_}->{$macroAttr} = $macroRule;
}
}
}
return 1;
}

View File

@ -0,0 +1,115 @@
use lib 'inc';
use Test::More; # skip_all => 'CAS is in rebuild';
use strict;
use IO::String;
use LWP::UserAgent;
use LWP::Protocol::PSGI;
use MIME::Base64;
BEGIN {
require 't/test-lib.pm';
}
my $debug = 'error';
my ( $issuer, $res );
eval { require XML::Simple };
plan skip_all => "Missing dependencies: $@" if ($@);
ok( $issuer = issuer(), 'Issuer portal' );
count(1);
ok(
$res = $issuer->_get(
'/cas/login',
query => 'service=http://auth.sp.com/',
accept => 'text/html'
),
'Query CAS server'
);
count(1);
expectOK($res);
my $pdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
# Try to authenticate to IdP
my $body = $res->[2]->[0];
$body =~ s/^.*?<form.*?>//s;
$body =~ s#</form>.*$##s;
my %fields =
( $body =~ /<input type="hidden".+?name="(.+?)".+?value="(.*?)"/sg );
$fields{user} = $fields{password} = 'french';
use URI::Escape;
my $s = join( '&', map { "$_=" . uri_escape( $fields{$_} ) } keys %fields );
ok(
$res = $issuer->_post(
'/cas/login',
IO::String->new($s),
cookie => $pdata,
accept => 'text/html',
length => length($s),
),
'Post authentication'
);
count(1);
my $idpId = expectCookie($res);
# Expect pdata to be cleared
$pdata = expectCookie( $res, 'lemonldappdata' );
ok( $pdata !~ 'issuerRequestsaml', 'SAML request cleared from pdata' );
count(1);
my ($query) =
expectRedirection( $res, qr#^http://auth.sp.com/\?(ticket=[^&]+)$# );
ok(
$res = $issuer->_get(
'/cas/p3/serviceValidate',
query => 'service=http://auth.sp.com/&' . $query,
accept => 'text/html'
),
'Query CAS server'
);
expectOK($res);
count(1);
ok( $res->[2]->[0] =~ m#<cas:sn>Accents</cas:sn>#, "Found macro attribute" );
count(1);
clean_sessions();
done_testing( count() );
sub issuer {
return LLNG::Manager::Test->new( {
ini => {
logLevel => $debug,
domain => 'idp.com',
portal => 'http://auth.idp.com',
authentication => 'Demo',
userDB => 'Same',
issuerDBCASActivation => 1,
casAttr => 'uid',
casAppMetaDataOptions => {
sp => {
casAppMetaDataOptionsService => 'http://auth.sp.com/',
},
},
casAppMetaDataExportedVars => {
sp => {
cn => 'cn',
sn => 'extracted_sn',
mail => 'mail',
uid => 'uid',
},
},
casAppMetaDataMacros => {
sp => {
extracted_sn => '(split(/\s/, $cn))[1]',
}
},
casAccessControlPolicy => 'error',
multiValuesSeparator => ';',
}
}
);
}