Impersonation.pm 5.2 KB
Newer Older
1
package Lemonldap::NG::Portal::Plugins::Impersonation;
2 3 4

use strict;
use Mouse;
5
use Lemonldap::NG::Portal::Main::Constants
Xavier Guimard's avatar
Xavier Guimard committed
6
  qw( PE_OK PE_BADCREDENTIALS PE_IMPERSONATION_SERVICE_NOT_ALLOWED PE_MALFORMEDUSER );
7 8 9 10 11 12 13 14 15

our $VERSION = '2.0.3';

extends 'Lemonldap::NG::Portal::Main::Plugin';

# INITIALIZATION

use constant endAuth => 'run';

16 17
has rule   => ( is => 'rw', default => sub { 1 } );
has idRule => ( is => 'rw', default => sub { 1 } );
18

19
sub hAttr {
20
    $_[0]->{conf}->{impersonationHiddenAttributes} . ' '
Xavier Guimard's avatar
Xavier Guimard committed
21
      . $_[0]->{conf}->{hiddenAttributes};
22 23
}

24 25
sub init {
    my ($self) = @_;
26
    my $hd = $self->p->HANDLER;
27 28 29

    # Parse activation rule
    $self->logger->debug(
30
        "Impersonation rule -> " . $self->conf->{impersonationRule} );
Xavier Guimard's avatar
Xavier Guimard committed
31 32
    my $rule =
      $hd->buildSub( $hd->substitute( $self->conf->{impersonationRule} ) );
33
    unless ($rule) {
Xavier Guimard's avatar
Xavier Guimard committed
34
        $self->error( "Bad impersonation rule -> " . $hd->tsv->{jail}->error );
35 36 37
        return 0;
    }
    $self->{rule} = $rule;
38 39

    # Parse identity rule
40
    $self->logger->debug( "Impersonation identities rule -> "
41 42 43 44 45
          . $self->conf->{impersonationIdRule} );
    $rule =
      $hd->buildSub( $hd->substitute( $self->conf->{impersonationIdRule} ) );
    unless ($rule) {
        $self->error(
46
            "Bad impersonation identities rule -> " . $hd->tsv->{jail}->error );
47 48 49 50
        return 0;
    }
    $self->{idRule} = $rule;

51 52
    return 1;
}
53 54 55 56 57

# RUNNING METHOD

sub run {
    my ( $self, $req ) = @_;
58

59
    my $spoofId = $req->param('spoofId') || $req->{user};
Christophe Maudoux's avatar
Christophe Maudoux committed
60 61
    return PE_MALFORMEDUSER
      if (  $spoofId
62
        and $spoofId !~ /$self->{conf}->{userControl}/o );
63 64

    # Skip if no submitted SpoofId
65
    return PE_OK unless $spoofId;
66

67 68
    # Check activation rule
    unless ( $self->rule->( $req, $req->sessionInfo ) ) {
69 70
        $self->userLogger->error('Impersonation service not authorized');
        return PE_IMPERSONATION_SERVICE_NOT_ALLOWED;
71 72
    }

73 74
    # Fill spoof session
    my ( $realSession, $spoofSession ) = ( {}, {} );
75
    $self->logger->debug("Spoofing Id: $spoofId...");
76 77
    my $spk = '';
    foreach my $k ( keys %{ $req->{sessionInfo} } ) {
78
        if ( $self->{conf}->{impersonationSkipEmptyValues} ) {
79 80
            next unless defined $req->{sessionInfo}->{$k};
        }
81
        $spk = "$self->{conf}->{impersonationPrefix}$k";
82 83 84 85
        unless ( $self->hAttr =~ /\b$k\b/ ) {
            $realSession->{$spk} = $req->{sessionInfo}->{$k};
            $self->logger->debug("-> Store $k in realSession key: $spk");
        }
86 87
        $self->logger->debug("Delete $k");
        delete $req->{sessionInfo}->{$k};
88
    }
89

90 91 92 93
    # Compute Macros and Groups with real and spoofed sessions
    $req->{sessionInfo} = {%$realSession};
    $req->{user}        = $spoofId;
    $spoofSession       = $self->_userDatas($req);
94 95
    return $req->error if $req->error;

96 97 98 99 100 101
    # Update spoofed session
    foreach (qw (_auth _userDB)) {
        $self->logger->debug("Processing $_...");
        $spk = "$self->{conf}->{impersonationPrefix}$_";
        $spoofSession->{$_} = $realSession->{$spk};
    }
102 103

    # Merging SSO groups and hGroups & Dedup
104
    $spoofSession->{groups} ||= '';
105
    if ( $self->{conf}->{impersonationMergeSSOgroups} ) {
106
        $self->userLogger->warn("MERGING SSO groups and hGroups...");
107 108
        my $spg       = "$self->{conf}->{impersonationPrefix}groups";
        my $sphg      = "$self->{conf}->{impersonationPrefix}hGroups";
109
        my $separator = $self->{conf}->{multiValuesSeparator};
110
        $realSession->{$spg} ||= '';
111

112 113 114
        $self->logger->debug("Processing groups...");
        my @spoofGrps = my @realGrps = ();
        @spoofGrps = split /\Q$separator/, $spoofSession->{groups};
115
        @realGrps  = split /\Q$separator/, $realSession->{$spg};
116 117 118 119 120 121 122
        @spoofGrps = ( @spoofGrps, @realGrps );
        my %hash = map { $_, 1 } @spoofGrps;
        $spoofSession->{groups} = join $separator, sort keys %hash;

        $self->logger->debug("Processing hGroups...");
        $spoofSession->{hGroups} ||= {};
        $realSession->{$sphg} ||= {};
Xavier Guimard's avatar
Xavier Guimard committed
123 124
        $spoofSession->{hGroups} =
          { %{ $spoofSession->{hGroups} }, %{ $realSession->{$sphg} } };
125 126
    }

127
    # Main session
128
    $self->p->updateSession( $req, $spoofSession );
129
    return PE_OK;
130 131 132 133 134 135
}

sub _userDatas {
    my ( $self, $req ) = @_;

    # Search user in database
Xavier Guimard's avatar
Xavier Guimard committed
136 137
    $req->steps( [
            'getUser',   'setSessionInfo',
138 139
            'setMacros', 'setGroups',
            'setLocalGroups'
140 141 142 143 144
        ]
    );
    if ( my $error = $self->p->process($req) ) {
        if ( $error == PE_BADCREDENTIALS ) {
            $self->userLogger->warn(
Xavier Guimard's avatar
Xavier Guimard committed
145 146 147
                    'Impersonation requested for an unvalid user ('
                  . $req->{user}
                  . ")" );
148 149 150 151
        }
        $self->logger->debug("Process returned error: $error");
        return $req->error($error);
    }
152

153
    # Check identities rule
154 155 156 157 158
    unless ( $self->idRule->( $req, $req->sessionInfo ) ) {
        $self->userLogger->warn(
                'Impersonation requested for an unvalid user ('
              . $req->{user}
              . ")" );
159
        $req->{sessionInfo} = {};
160 161 162 163
        $self->logger->debug('Identity not authorized');
        return $req->error(PE_BADCREDENTIALS);
    }

164
    $self->logger->debug("Populating spoofed session...");
165 166 167 168
    return $req->{sessionInfo};
}

1;