diff --git a/bin/synchronize_proteus_Users.pl b/bin/synchronize_proteus_Users.pl new file mode 100755 index 0000000000000000000000000000000000000000..5b0804aaec5df93fa0c95b7aa66a97790c4e788f --- /dev/null +++ b/bin/synchronize_proteus_Users.pl @@ -0,0 +1,543 @@ +#!/usr/bin/perl + +# ------------------------------------------------------------------------------ +# $Id$ +# +# ------------------------------------------------------------------------------ + +use strict; +use warnings; +use Getopt::Long; +use Data::Dumper; +use Config::IniFiles; +use Net::LDAP; +use File::Copy; +use File::Basename; +use Sys::Hostname; + +# unbuffered output: +$| = 1; + +use lib ( new Config::IniFiles( -file => "/opt/etc/ini/global.ini" )->val( 'APPLICATION', 'LIBRARY' ) ); + +BEGIN { + my $iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" ); + push( @INC, $iniFile->val( 'APPLICATION', 'LIBRARY' ) ); +} + +use SNET::common; +use SNET::snmpd; +use SNET::LdapNS qw(:all); +use SNET::libsoap; + +use vars qw($verbose $debug $help $force $cli_mode $dry_run ); +$verbose = 0; +$debug = 0; +$cli_mode = 1; + +my $PROGNAME = basename( $0 ); +$PROGNAME =~ s/\.p[lm]$//; + +my %options = ( + "help" => \$help, + "debug" => \$debug, + "verbose" => \$verbose, + "force" => \$force, + "dry-run" => \$dry_run, +); + +my $SNMP_ENTERPRISEOID = "99"; +my $SNMP_OID = "1.3.6.1.4.1.99999.$SNMP_ENTERPRISEOID"; +my $SNMP_GEN = "6"; +my $SNMP_SPE = "1"; +my $msg = ''; +my $title = "Proteus ImportUser"; + +help() if !GetOptions( %options ) or $help; +$verbose = 1 if $debug; + +# ldap_find_users_and_groups() +# +# Read users and groups from SNet LDAP. + +sub ldap_find_users_and_groups ($$$$$$$$$$) +{ + my ( + $cfg_ldap_server, $cfg_ldap_user, $cfg_ldap_passwd, $cfg_ldap_group_search, $cfg_ldap_search_scope, + $cfg_ldap_group_search_filter, $cfg_ldap_group_attribute, $cfg_ldap_groupname, $hostname, $cfg_ldap_cafile + ) = @_; + + my %users; + + # Connect to the LDAP server + metaprint( 'verbose', "Initiating connection to LDAP server <$cfg_ldap_server>:" ) if $verbose; + my $ldap = Net::LDAP->new( + $cfg_ldap_server, + async => 0, + onerror => ( + ( $debug == 0 ) ? sub { return $_[0] } : sub { + my $message = shift; + my $error = defined( $message->error_desc ) ? $message->error_desc : $message->error(); + $msg = "Ldap: Unable to process request: $error."; + metaprint( 'error', $title . ": " . $msg ); + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + return $message; + } + ), + ); + if ( !$ldap ) { + $msg = "LDAP connection to <$cfg_ldap_server> failed."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + metaprint( 'verbose', "* LDAP connection completed successfully." ) if $verbose; + + my $message; + eval { + print STDERR 'Starting tls' . "\n" if ( $debug ); + $message = $ldap->start_tls( verify => 'require', + cafile => $cfg_ldap_cafile, ); + if ( $message->is_error() ) { + $msg = "Could not encrypt LDAP connection."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + }; + if ( $@ ) { + $msg = "Crash - Could not encrypt LDAP connection."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + eval { + print STDERR 'binding' . "\n" if ( $debug ); + $message = $ldap->bind( + $cfg_ldap_user, + password => $cfg_ldap_passwd, + version => 3, + ); + if ( $message->is_error() ) { + $msg = "LDAP bind error occurred."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + }; + if ( $@ ) { + $msg = "Crash - LDAP bind error occurred ('" . $message->error_name . "')."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + metaprint( 'verbose', "* LDAP bind operation completed successfully." ) if $verbose; + + # Search AD for objects in a particular group using LDAP + + metaprint( 'info', "Getting the LDAP member with expiration." ) if $verbose; + my %searchargs; + $searchargs{base} = $cfg_ldap_group_search; + $searchargs{scope} = $cfg_ldap_search_scope; + $searchargs{filter} = $cfg_ldap_group_search_filter; + $searchargs{attrs} = $cfg_ldap_group_attribute; + + print Dumper( \%searchargs ) if $verbose; + + my $results; + eval { $results = $ldap->search( %searchargs ); }; + if ( $@ ) { + my $title = "Check Password"; + my $msg = "Crash - LDAP Users Search."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + + if ( $results->is_error() ) { + metaprint( 'error', 'search failed: ' . $results->error_text ); + metaprint( 'error', 'search failed: ' . $results->code ); + metaprint( 'error', 'search failed: ' . $results->error ); + } elsif ( $results->count() == 0 ) { + metaprint( 'error', 'no result' ); + } else { + metaprint( 'verbose', "* Search returned " . $results->count . " object." ) if $verbose; + print Dumper( $results->as_struct() ) if $verbose; + my $ldap_hash = $results->as_struct(); + + my $attribute = $searchargs{attrs}[0]; + if ( defined( $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} ) ) { + foreach my $url ( @{ $ldap_hash->{ "cn=$cfg_ldap_groupname," . $searchargs{base} }{$attribute} } ) { + + print "$url\n" if $verbose; + push( @{ $users{$url}{'groups'} }, $cfg_ldap_groupname ); + + # fetch the user gecos + my %usersearch; + $usersearch{base} = $cfg_ldap_group_search; + $usersearch{base} =~ s/groups/people/; + $usersearch{attrs} = [ 'gecos', 'uid', 'mail' ]; + $usersearch{scope} = 'sub'; + $usersearch{filter} = '(&(objectClass=posixAccount)(uid=' . $url . '))'; + print Dumper( \%usersearch ) if $verbose; + + my $userresults; + eval { $userresults = $ldap->search( %usersearch ); }; + if ( $@ ) { + my $title = "Check Password"; + my $msg = "Crash - LDAP Mail Users Search."; + metaprint( 'error', $title . ": " . $msg ) if $verbose; + snmp_trap_send_multi_vars( $SNMP_OID, $SNMP_GEN, $SNMP_SPE, [ $hostname, $title, $msg ] ); + exit 1; + } + if ( $userresults->is_error() ) { + metaprint( 'error', 'search failed: ' . $userresults->error_text ); + metaprint( 'error', 'search failed: ' . $userresults->code ); + metaprint( 'error', 'search failed: ' . $userresults->error ); + } elsif ( $userresults->count() == 0 ) { + metaprint( 'error', 'no result' ); + } else { + metaprint( 'info', "* Search returned " . $userresults->count . " url for '$url'." ) if $verbose; + print Dumper ( $userresults ) if $verbose; + + foreach my $uid ( $userresults->entries ) { + print "'" . $uid->get_value( 'uid' ) . "'\n" if $verbose; + if ( !defined( $uid->get_value( 'gecos' ) ) ) { + $users{ $uid->get_value( 'uid' ) } = ''; + } else { + $users{ $uid->get_value( 'uid' ) }{'gecos'} = $uid->get_value( 'gecos' ); + } + if ( !defined( $uid->get_value( 'mail' ) ) ) { + $users{ $uid->get_value( 'uid' ) } = ''; + } else { + $users{ $uid->get_value( 'uid' ) }{'mail'} = $uid->get_value( 'mail' ); + } + } + } + } + } else { + metaprint( 'error', "Could not parse the hash result: {" . "cn=$cfg_ldap_groupname," . $searchargs{base} . "} { " . $attribute . " }" ); + } + } + + print "\nClosing LDAP connection.\n" if $verbose; + $ldap->unbind; + return %users; +} + +# +# Global Declarations +# +# load the INI +metaprint( "info", "Loading INI file Parameters" ); +my $global_iniFile = new Config::IniFiles( -file => "/opt/etc/ini/global.ini" ); + +my $CiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'RME' ) ); +metaprint( "error", "error value of CiniFile is undefined" ) if ( !defined( $CiniFile ) ); + +my $outpath = $CiniFile->val( 'GLOBAL', 'OUTPATH' ); +metaprint( "error", "The defined outpath is not valid, please correct-it" ) if ( !defined( $outpath ) ); + +my $AiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'LDAP' ) ); +metaprint( "error", "error value of AiniFile is undefined" ) if ( !defined( $AiniFile ) ); + +my $cfg_ldap_server = $AiniFile->val( 'LDAP_SNET_NG', 'SERVER' ); +metaprint( "error", "error value of cfg_ldap_server is undefined" ) if ( !defined( $cfg_ldap_server ) ); +my $cfg_ldap_user = $AiniFile->val( 'LDAP_SNET_NG', 'USER' ); +metaprint( "error", "error value of cfg_ldap_user is undefined" ) if ( !defined( $cfg_ldap_user ) ); +my $cfg_ldap_passwd = $AiniFile->val( 'LDAP_SNET_NG', 'PASSWORD' ); +metaprint( "error", "error value of cfg_ldap_passwd is undefined" ) if ( !defined( $cfg_ldap_passwd ) ); +my $cfg_ldap_group_search = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_SEARCH' ); +metaprint( "error", "error value of cfg_ldap_group_search is undefined" ) if ( !defined( $cfg_ldap_group_search ) ); +my $cfg_ldap_group_search_filter = $AiniFile->val( 'LDAP_SNET_NG', 'FILTER' ); +metaprint( "error", "error value of cfg_ldap_group_search_filter is undefined" ) if ( !defined( $cfg_ldap_group_search_filter ) ); +$cfg_ldap_group_search_filter = "(&(objectclass=posixGroup)(cn=REPLACE))"; +my $cfg_ldap_group_attribute = $AiniFile->val( 'LDAP_SNET_NG', 'GRP_ATTRIBUTE' ); +metaprint( "error", "error value of cfg_ldap_group_attribute is undefined" ) if ( !defined( $cfg_ldap_group_attribute ) ); +$cfg_ldap_group_attribute = ["memberuid"]; +my $cfg_ldap_search_scope = $AiniFile->val( 'LDAP_SNET_NG', 'SEARCH_SCOPE' ); +metaprint( "error", "error value of cfg_ldap_search_scope is undefined" ) if ( !defined( $cfg_ldap_search_scope ) ); +my $cfg_ldap_cafile = $AiniFile->val( 'LDAP_SNET_NG', 'CA' ); +metaprint( "error", "error value of cfg_ldap_cafile is undefined" ) if ( !defined( $cfg_ldap_cafile ) ); + +my $PiniFile = new Config::IniFiles( -file => $global_iniFile->val( 'INI', 'Proteus' ) ); +print "error value of PiniFile is undefined" if ( !defined( $PiniFile ) ); + +# Proteus SOAP credentials +my $proteusUser = $PiniFile->val( 'PROTEUS_SOAP', 'USER' ); +print "error value of proteusUser is undefined" if ( !defined( $proteusUser ) ); +my $proteusPass = $PiniFile->val( 'PROTEUS_SOAP', 'PASSWORD' ); +print "error value of proteusPass is undefined" if ( !defined( $proteusPass ) ); +my $proteusServer = $PiniFile->val( 'PROTEUS_SOAP', 'SERVER' ); +print "error value of proteusDbServer is undefined" if ( !defined( $proteusServer ) ); +my $Proteus_cfg_name = $PiniFile->val( 'GLOBAL', 'CONFIG' ); +print "error value of Proteus_cfg_name is undefined" if ( !defined( $Proteus_cfg_name ) ); + +my @filters; +push( @filters, 'com' ); +push( @filters, 'mgt' ); +push( @filters, 'net' ); +push( @filters, 'pi' ); +push( @filters, 'pm' ); +push( @filters, 'sd' ); +push( @filters, 'sec' ); +push( @filters, 'ss' ); +push( @filters, 'tda' ); +push( @filters, 'officials' ); + +my %attr; +$attr{'mgt'} = 'snmc'; +$attr{'net'} = 'snmc'; +$attr{'pi'} = 'snmc'; +$attr{'sd'} = 'snmc'; +$attr{'sec'} = 'snmc'; +$attr{'ss'} = 'snmc'; +$attr{'tda'} = 'snmc'; +# +$attr{'pm'} = 'cn=pm,ou=groups,ou=SNet,ou=2,ou=C,o=DIGIT,dc=ec,dc=europa,dc=eu'; +$attr{'com'} = 'cn=com,ou=groups,ou=SNet,ou=2,ou=C,o=DIGIT,dc=ec,dc=europa,dc=eu'; +$attr{'officials'} = 'cn=officials,ou=groups,ou=SNet,ou=2,ou=C,o=DIGIT,dc=ec,dc=europa,dc=eu'; + +my $local_jrc = (); +$local_jrc->{'bossifa'} = 1; +$local_jrc->{'cacerja'} = 1; +$local_jrc->{'ceccman'} = 1; +$local_jrc->{'fotisva'} = 1; +$local_jrc->{'gysenpa'} = 1; +$local_jrc->{'meysjoh'} = 1; +$local_jrc->{'michojm'} = 1; +$local_jrc->{'peizean'} = 1; +$local_jrc->{'tomasje'} = 1; +$local_jrc->{'torreja'} = 1; +$local_jrc->{'vegthan'} = 1; +$local_jrc->{'watkipr'} = 1; +$local_jrc->{'wawakfa'} = 1; + +my $autogroup = (); +$autogroup->{'officials'} = 1; +$autogroup->{'com'} = 1; +$autogroup->{'pm'} = 1; + +my $authlocal = (); +$authlocal->{'admin'} = 1; +$authlocal->{'snet'} = 1; +$authlocal->{'dave'} = 1; + +my $hostname = hostname(); + +my $proteus_uid = (); + +=head2 initialise soap and SQL handlers + +Etablished the SOAP connection needed to connect to all the data. + +=cut + +# initiallise the SOAP connection : +my $service = soap_connect( $proteusServer, $proteusUser, $proteusPass ); + +if ( !$service ) { + metaprint( 'info', "Soap connection errors" ); + exit 1; +} + +# get group id +foreach my $a ( keys %attr ) { + if ( !defined( $proteus_uid->{ $attr{$a} } ) ) { + $proteus_uid->{$a} = soap_get_group( $service, $attr{$a} ); + $proteus_uid->{ $attr{$a} } = $proteus_uid->{$a}; + } +} +$proteus_uid->{'vernada'} = soap_get_user( $service, 'vernada' ); + +metaprint( 'info', "proteus_uid:" . Dumper( $proteus_uid ) ); + +# Main Application +metaprint( "info", "Starting users synchro" ); + +my $already_defined_users = (); +my $already_defined_auth = (); +my $already_defined_group = (); + +# get all existing ldap (up to 100) +my $proteus_authenticator; +eval { + @$proteus_authenticator = $service->getEntities( + SOAP::Data->type( 'long' )->name( 'parentId' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'string' )->name( 'type' )->value( ObjectTypes::LDAP )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'start' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'count' )->value( 100 )->attr( { xmlns => '' } ) + )->valueof( '//getEntitiesResponse/return/item' ); +}; + +if ( ( $@ ) || !defined( $proteus_authenticator ) ) { + print "get all users failed: " . Dumper( $@ ); +} else { + + print Dumper ( $proteus_authenticator ) if ( $debug ); + + # list configurations + foreach my $eachConfiguration ( @$proteus_authenticator ) { + my $obj = Service->blessAPIEntity( "object" => $eachConfiguration ); + my $tmp_name = $obj->get_name(); + $already_defined_auth->{$tmp_name}{'properties'} = $obj->get_properties(); + $already_defined_auth->{$tmp_name}{'id'} = $obj->get_id(); + } +} + +print Dumper ( $already_defined_auth ); + +# get all existing group (up to 10) +my $proteus_group; +eval { + @$proteus_group = $service->getEntities( + SOAP::Data->type( 'long' )->name( 'parentId' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'string' )->name( 'type' )->value( ObjectTypes::UserGroup )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'start' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'count' )->value( 100 )->attr( { xmlns => '' } ) + )->valueof( '//getEntitiesResponse/return/item' ); +}; + +if ( ( $@ ) || !defined( $proteus_group ) ) { + print "get all groups failed: " . Dumper( $@ ); +} else { + + print Dumper ( $proteus_group ); # if ( $debug ); + + # list configurations + foreach my $eachConfiguration ( @$proteus_group ) { + my $obj = Service->blessAPIEntity( "object" => $eachConfiguration ); + my $tmp_name = $obj->get_name(); + $already_defined_group->{$tmp_name}{'properties'} = $obj->get_properties(); + $already_defined_group->{$tmp_name}{'id'} = $obj->get_id(); + } +} + +print Dumper ( $already_defined_group ); + +# get all existing user (up to 10) +my $configurations; +eval { + @$configurations = $service->getEntities( + SOAP::Data->type( 'long' )->name( 'parentId' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'string' )->name( 'type' )->value( ObjectTypes::User )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'start' )->value( 0 )->attr( { xmlns => '' } ), + SOAP::Data->type( 'int' )->name( 'count' )->value( 100 )->attr( { xmlns => '' } ) + )->valueof( '//getEntitiesResponse/return/item' ); +}; + +if ( ( $@ ) || !defined( $configurations ) ) { + print "get all users failed: " . Dumper( $@ ); +} else { + + print Dumper ( $configurations ) if ( $debug ); + + # list configurations + foreach my $eachConfiguration ( @$configurations ) { + my $obj = Service->blessAPIEntity( "object" => $eachConfiguration ); + my $tmp_user = $obj->get_name(); + $already_defined_users->{$tmp_user}{'properties'} = $obj->get_properties(); + $already_defined_users->{$tmp_user}{'id'} = $obj->get_id(); + foreach my $auth ( keys %$already_defined_auth ) { + my $snet_auth = "\\\|authenticator=" . $already_defined_auth->{$auth}{'id'} . "\\\|"; + if ( $already_defined_users->{$tmp_user}{'properties'} =~ /$snet_auth/ ) { + $already_defined_users->{$tmp_user}{'realm'} = $auth; + } + } + } +} + +#Print Users from Proteus +metaprint( 'info', Dumper( $already_defined_users ) ) if $verbose; +metaprint( 'info', Dumper( $already_defined_users->{'snet'} ) ); # if $verbose; +metaprint( 'info', Dumper( $already_defined_users->{'vernada'} ) ); # if $verbose; + +# -- Create the import file +my $cpt = 0; +my $cpt_del = 0; + +foreach my $filter ( @filters ) { + + metaprint "info", "Checking groups '$filter'."; + my $cfg_ldap_group_search_f = $cfg_ldap_group_search_filter; + $cfg_ldap_group_search_f =~ s/REPLACE/$filter/; + print "$cfg_ldap_group_search_f\n" if $verbose; + my %ldap_users = ldap_find_users_and_groups( $cfg_ldap_server, $cfg_ldap_user, $cfg_ldap_passwd, $cfg_ldap_group_search, $cfg_ldap_search_scope, + $cfg_ldap_group_search_f, $cfg_ldap_group_attribute, $filter, $hostname, $cfg_ldap_cafile ); + + print Dumper ( \%ldap_users ) if $verbose; + + foreach my $u ( keys %ldap_users ) { + if ( defined( $already_defined_users->{$u} ) + && ( $already_defined_users->{$u} ) + && defined( $already_defined_users->{$u}{'realm'} ) + && ( $already_defined_users->{$u}{'realm'} eq 'LDAP' ) ) { + metaprint( "info", "Skipping user $u import, user is already defined." ) if $verbose; + $already_defined_users->{$u}{'found'} = 1; + next; + } elsif ( defined( $already_defined_users->{$u} ) && ( $already_defined_users->{$u} ) ) { + metaprint( "info", "Skipping user $u import, user is already defined, but user need to be checked." ); + $already_defined_users->{$u}{'found'} = 1; + next; + } + + next if ( $ldap_users{$u} =~ /^$/ ); + next if ( defined( $autogroup->{$filter} ) && ( $autogroup->{$filter} ) ); + if ( defined( $attr{$filter} ) && defined( $ldap_users{$u}{'gecos'} ) ) { + metaprint( "info", "$u '" . $ldap_users{$u}{'gecos'} . "' '" . $ldap_users{$u}{'mail'} . "' need to be created in group '" . $attr{$filter} . "'" ); + if ( !$dry_run ) { + + # email=david.vernazobres@ext.ec.europa.eu|authenticator=3816318|userType=ADMIN|userAccessType=GUI| + # my $prop = 'email=' . $ldap_users{$u}{'mail'} . '|authenticator=' . $already_defined_auth->{'nldap'}{'id'} . '|userType=UserType::ADMIN|userAccessType=UserAccessType::GUI|'; + my $prop = 'email=' . $ldap_users{$u}{'mail'} . '|authenticator=' . $already_defined_auth->{'nldap'}{'id'} . '|userType=ADMIN|userAccessType=GUI|'; + soap_add_user( $service, $prop, $u ); + } + + } elsif ( !defined( $attr{$filter} ) ) { + metaprint( "error", "checking user '$u': attr" ); + + } elsif ( !defined( $ldap_users{$u}{'gecos'} ) ) { + metaprint( "error", "checking user '$u': ldap_users" ); + print Dumper ( \%ldap_users ); + } else { + metaprint( "error", "checking user '$u'" ); + } + + # set user enabled + description of the user. + $cpt++; + } +} + +soap_disconnect( $service ); + +metaprint "info", "Checking all other Proteus users defined."; +foreach my $u ( keys %$already_defined_users ) { + if ( defined( $already_defined_users->{$u} ) && ( $already_defined_users->{$u} ) && ( defined( $already_defined_users->{$u}{'realm'} ) && ( $already_defined_users->{$u}{'realm'} !~ /LDAP/i ) ) + || ( !defined( $already_defined_users->{$u}{'realm'} ) ) ) { + if ( defined( $authlocal->{$u} ) && ( $authlocal->{$u} ) ) { + metaprint( "info", "User '$u' localy authorised." ); + next; + } else { + metaprint( "error", "User $u is defined locally and is not authorised? Please check-it manually." ); + next; + } + } elsif ( defined( $already_defined_users->{$u} ) + && ( $already_defined_users->{$u} ) + && defined( $already_defined_users->{$u}{'found'} ) + && ( $already_defined_users->{$u}{'found'} ) ) { + next; + } elsif ( defined( $local_jrc->{$u} ) && ( $local_jrc->{$u} ) ) { + metaprint( "warn", "User $u belong to JRC." ); + next; + } else { + metaprint( "error", "User $u need to be checked manually." ); + $cpt_del++; + } +} + +metaprint( "info", "$cpt user(s) created." ); +metaprint( "info", "$cpt_del user(s) need to be deleted." ); +metaprint( "info", "--- Process Done ---" ); +exit( 0 );