diff --git a/gen/ad_admin_group_mu_ucn b/gen/ad_admin_group_mu_ucn new file mode 100755 index 00000000..6532a639 --- /dev/null +++ b/gen/ad_admin_group_mu_ucn @@ -0,0 +1,143 @@ +#!/usr/bin/perl +use feature "switch"; +use Switch; +use strict; +use warnings; +use perunServicesInit; +use perunServicesUtils; +no if $] >= 5.017011, warnings => 'experimental::smartmatch'; + +local $::SERVICE_NAME = "ad_admin_group_mu_ucn"; +local $::PROTOCOL_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.0"; + +sub addMemberToGroup; +sub processWorkplaces; +sub processGroup; +sub createGroup; +sub processTree; +sub writeDebug; + +perunServicesInit::init; +my $DIRECTORY = perunServicesInit::getDirectory; +my $fileName = "$DIRECTORY/$::SERVICE_NAME".".ldif"; + +#Get hierarchical data without expired members +my $data = perunServicesInit::getHashedDataWithGroups(1); +my $DEBUG = 0; + +#Constants +our $A_LOGIN; *A_LOGIN = \'urn:perun:user:attribute-def:def:login-namespace:mu-adm'; +our $A_R_GROUP_NAME; *A_R_GROUP_NAME = \'urn:perun:resource:attribute-def:def:adGroupName'; +our $A_MR_V_IS_BANNED; *A_MR_V_IS_BANNED = \'urn:perun:member_resource:attribute-def:virt:isBanned'; +our $A_R_DESCRIPTION; *A_R_DESCRIPTION = \'urn:perun:resource:attribute-def:core:description'; + +# Default description of group in Active Directory +my $defaultDescription = "no-desc in Perun"; +# OUs for groups and users +my $adOuNameGroups = "OU=PrivilegedGroups,OU=MU,DC=ucn,DC=muni,DC=cz"; +my $adOuNameUsers = "OU=PrivilegedUsers,OU=MU,DC=ucn,DC=muni,DC=cz"; + +our $groups = {}; +our $usersByGroups = {}; + +# FOR EACH RESOURCE +foreach my $resourceId ($data->getResourceIds()) { + processGroup($resourceId); +} + +# +# Print group data LDIF +# +open FILE,">:encoding(UTF-8)","$fileName" or die "Cannot open $fileName: $! \n"; + +for my $group (sort keys %$groups) { + + print FILE "dn: CN=" . $group . "," . $adOuNameGroups . "\n"; + print FILE "cn: " . $group . "\n"; + print FILE "samAccountName: " . $group . "\n"; + print FILE "description: " . $groups->{$group}->{"description"} . "\n"; + print FILE "objectClass: group\n"; + print FILE "objectClass: top\n"; + + my @groupMembers = sort keys %{$usersByGroups->{$group}}; + for my $member (@groupMembers) { + print FILE "member: " . $member . "\n"; + } + + # there must be empty line after each entry + print FILE "\n"; + +} + +close FILE; + +perunServicesInit::finalize; + +#################### +# Helper functions # +#################### + +sub addMemberToGroup { + my $memberId = shift; + my $group = shift; + my $resourceId = shift; + + my $login = $data->getUserAttributeValue( member => $memberId, attrName => $A_LOGIN ); + my $isBanned = $data->getMemberResourceAttributeValue( member => $memberId, resource => $resourceId, attrName => $A_MR_V_IS_BANNED ); + + addMember($login, $group, $isBanned) +} + +sub processGroup { + my $resourceId = shift; + + my $group = $data->getResourceAttributeValue( resource => $resourceId, attrName => $A_R_GROUP_NAME ); + my $description = $data->getResourceAttributeValue( resource => $resourceId, attrName => $A_R_DESCRIPTION ); + + writeDebug("Process Standard Group: '$group'", 1); + createGroup($group, $description); + + writeDebug("Continue to add members", 3); + foreach my $memberId ($data->getMemberIdsForResource( resource => $resourceId )) { + addMemberToGroup($memberId, $group, $resourceId); + } +} + +sub createGroup { + my $name = shift; + my $description = shift; + + # Ensure that there is one group with specific name + $groups->{$name}->{"description"} = $description || $defaultDescription; + writeDebug("Group created", 3); +} + +sub addMember { + my $login = shift; + my $group = shift; + my $isBanned = shift; + + #skip banned members + return if $isBanned; + + # allow only UČOadm, 9UČOadm logins + + return unless $login; + if ($login =~ /^9[0-9]{6}adm$/ or $login =~ /^[0-9]{1,6}adm$/) { + + # store UČO and 9UČO users + $usersByGroups->{$group}->{"CN=" . $login . "," . $adOuNameUsers} = 1 + + } +} + +sub writeDebug { + my $message = shift; + my $indentation = shift; + + return unless $DEBUG; + + print "\t" x $indentation; + print $message . "\n"; +} diff --git a/gen/ad_admin_user_mu_ucn b/gen/ad_admin_user_mu_ucn new file mode 100755 index 00000000..451d1e68 --- /dev/null +++ b/gen/ad_admin_user_mu_ucn @@ -0,0 +1,118 @@ +#!/usr/bin/perl +use feature "switch"; +use strict; +use warnings; +use perunServicesInit; +use perunServicesUtils; +use MIME::Base64; +use utf8; +use Encode; + +local $::SERVICE_NAME = "ad_admin_user_mu_ucn"; +local $::PROTOCOL_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.0"; + +perunServicesInit::init; +my $DIRECTORY = perunServicesInit::getDirectory; +my $fileName = "$DIRECTORY/$::SERVICE_NAME".".ldif"; + +my $data = perunServicesInit::getHashedHierarchicalData(1); + +#Constants +our $A_F_DOMAIN; *A_F_DOMAIN = \'urn:perun:facility:attribute-def:def:adDomain'; + +our $A_LOGIN; *A_LOGIN = \'urn:perun:user:attribute-def:def:login-namespace:mu-adm'; +our $A_FIRST_NAME; *A_FIRST_NAME = \'urn:perun:user:attribute-def:core:firstName'; +our $A_LAST_NAME; *A_LAST_NAME = \'urn:perun:user:attribute-def:core:lastName'; +our $A_DISPLAY_NAME; *A_DISPLAY_NAME = \'urn:perun:user:attribute-def:core:displayName'; +our $A_MAIL; *A_MAIL = \'urn:perun:user:attribute-def:def:preferredMail'; + +our $A_MEMBER_STATUS; *A_MEMBER_STATUS = \'urn:perun:member:attribute-def:core:status'; + +our $STATUS_VALID; *STATUS_VALID = \'VALID'; +our $STATUS_EXPIRED; *STATUS_EXPIRED = \'EXPIRED'; + +# Get the facility ID +my $facilityId = $data->getFacilityId(); + +# CHECK ON FACILITY ATTRIBUTES +if (!defined($data->getFacilityAttributeValue( attrName => $A_F_DOMAIN ))) { + exit 1; +} + +my $baseDN = "OU=PrivilegedUsers,OU=MU,DC=ucn,DC=muni,DC=cz"; +my $domain = $data->getFacilityAttributeValue( attrName => $A_F_DOMAIN ); +my $uac = "66048"; + +# GATHER USERS +my $users; # $users->{$login}->{ATTR} = $attrValue; + +# +# AGGREGATE DATA +# +# FOR EACH RESOURCE +foreach my $resourceId ( $data->getResourceIds() ){ + + # EACH USER ON RESOURCE + foreach my $memberId ($data->getMemberIdsForResource( resource => $resourceId )) { + + my $login = $data->getUserAttributeValue( member => $memberId, attrName => $A_LOGIN ); + next unless $login; + my $memberStatus = $data->getMemberAttributeValue( member => $memberId, attrName => $A_MEMBER_STATUS ); + next unless ($memberStatus eq $STATUS_VALID); + + # store standard attrs + $users->{$login}->{"DN"} = "CN=" . $login . "," . $baseDN; + $users->{$login}->{$A_FIRST_NAME} = $data->getUserAttributeValue(member => $memberId, attrName => $A_FIRST_NAME); + $users->{$login}->{$A_LAST_NAME} = $data->getUserAttributeValue(member => $memberId, attrName => $A_LAST_NAME); + $users->{$login}->{$A_DISPLAY_NAME} = $data->getUserAttributeValue(member => $memberId, attrName => $A_DISPLAY_NAME); + $users->{$login}->{$A_MAIL} = $data->getUserAttributeValue(member => $memberId, attrName => $A_MAIL); + } +} + +# +# PRINT user data LDIF +# +open FILE,">$fileName" or die "Cannot open $fileName: $! \n"; +binmode FILE, ":utf8"; + +# FOR EACH USER ON FACILITY +my @logins = sort keys %{$users}; +for my $login (@logins) { + + # print attributes, which are never empty + print FILE "dn: " . $users->{$login}->{"DN"} . "\n"; + + print FILE "cn: " . $login . "\n"; + print FILE "samAccountName: " . $login . "\n"; + print FILE "userPrincipalName: " . $login . "\@" . $domain . "\n"; + # enable accounts (if not) using service propagation + print FILE "userAccountControl: " . $uac . "\n"; + + # skip attributes which are empty and LDAP can't handle it (FIRST_NAME, EMAIL) + my $sn = $users->{$login}->{$A_LAST_NAME}; + my $givenName = $users->{$login}->{$A_FIRST_NAME}; + my $displayName = ($users->{$login}->{$A_FIRST_NAME} || "") . " " . ($users->{$login}->{$A_LAST_NAME} || "") . " (adm)"; + my $mail = $users->{$login}->{$A_MAIL}; + + if (defined $displayName and length $displayName) { + print FILE "displayName: " . $displayName . "\n"; + } + if (defined $sn and length $sn) { + print FILE "sn: " . $sn . "\n"; + } + if (defined $givenName and length $givenName) { + print FILE "givenName: " . $givenName . "\n"; + } + if (defined $mail and length $mail) { + print FILE "mail: " . $mail . "\n"; + } + + # There MUST be an empty line after each entry, so entry sorting and diff works on slave part + print FILE "\n"; + +} + +close(FILE); + +perunServicesInit::finalize; diff --git a/gen/mailman_vsup b/gen/mailman_vsup deleted file mode 100755 index f7f60558..00000000 --- a/gen/mailman_vsup +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/perl -# -# Generates members of a mailing list -# -use strict; -use warnings; -use perunServicesInit; -use perunServicesUtils; -use Text::Unidecode; -use POSIX qw/strftime/; - -local $::SERVICE_NAME = "mailman_vsup"; -local $::PROTOCOL_VERSION = "3.1.0"; -my $SCRIPT_VERSION = "3.0.1"; - -perunServicesInit::init; -my $DIRECTORY = perunServicesInit::getDirectory; -my $data = perunServicesInit::getHashedHierarchicalData; - -#Constants -our $A_USER_NAME; *A_USER_NAME = \'urn:perun:user:attribute-def:core:displayName'; -our $A_USER_MAIL; *A_USER_MAIL = \'urn:perun:user:attribute-def:def:preferredMail'; -our $A_USER_STATUS; *A_USER_STATUS = \'urn:perun:member:attribute-def:core:status'; - -our $A_RESOURCE_MAILING_LIST_NAME; *A_RESOURCE_MAILING_LIST_NAME = \'urn:perun:resource:attribute-def:def:mailingListName'; -our $A_RESOURCE_MAILING_LIST_MANAGER_MAIL; *A_RESOURCE_MAILING_LIST_MANAGER_MAIL = \'urn:perun:resource:attribute-def:def:mailingListManagerMail'; - -my $mailinglistStruc = {}; # $mailinglistStruc->{"mailing list name"}->{"user's e-mail"}->{A_USER_*} -my $mailinglistAdminMailStruc = {}; # $mailinglistAdminMailStruc->{"mailing list name"}->{"admin's e-mail"} - -my $mailinglistsDirectory = "$DIRECTORY/mailinglists"; -mkdir $mailinglistsDirectory or die "Can't mkdir $mailinglistsDirectory: $!"; - -foreach my $resourceId ($data->getResourceIds()) { - - my $listNameAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_MAILING_LIST_NAME); - my $adminMailAttribute = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_RESOURCE_MAILING_LIST_MANAGER_MAIL); - my $listName = "$listNameAttribute"; - my $adminMail = "$adminMailAttribute"; - - # Store the admin's mail - $mailinglistAdminMailStruc->{$listName} = $adminMail; - - foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) { - - my $memberStatus = $data->getMemberAttributeValue(member => $memberId, attrName => $A_USER_STATUS); - my $userMailAttribute = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_MAIL); - my $userNameAttribute = $data->getUserAttributeValue(member => $memberId, attrName => $A_USER_NAME); - - #list only VALID members except if allowNonvalidUsers is true - next unless($memberStatus eq "VALID"); - - $mailinglistStruc->{$listName}->{$userMailAttribute}->{$A_USER_NAME} = $userNameAttribute; - } -} - -for my $listName (keys %$mailinglistStruc) { - my $fileName = "$mailinglistsDirectory/$listName"; - open FILE,">$fileName" or die "Cannot open $fileName: $! \n"; - - # As a first line, print header - print FILE "#MANAGERS_MAIL=", $mailinglistAdminMailStruc->{$listName},"\n"; - - for my $mail (sort keys %{$mailinglistStruc->{$listName}}) { - print FILE "\"", unidecode($mailinglistStruc->{$listName}->{$mail}->{$A_USER_NAME}); - print FILE "\" <", $mail, ">\n"; - } - - close FILE or die $!; -} - -perunServicesInit::finalize; diff --git a/gen/oidc_with_groups b/gen/oidc_with_groups new file mode 100755 index 00000000..aa11e4b5 --- /dev/null +++ b/gen/oidc_with_groups @@ -0,0 +1,120 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use File::Basename; +use perunServicesInit; +use Exporter 'import'; + +our $JSON_FORMAT = "json"; +our @EXPORT = qw($JSON_FORMAT); + +sub process_user; + +local $::SERVICE_NAME = basename($0); +local $::PROTOCOL_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.0"; + +perunServicesInit::init; +my $DIRECTORY = perunServicesInit::getDirectory; +my $data = perunServicesInit::getHashedDataWithGroups; +my $agent = perunServicesInit->getAgent; +my $attributesAgent = $agent->getAttributesAgent; +my $servicesAgent = $agent->getServicesAgent; +my $service = $servicesAgent->getServiceByName( name => $::SERVICE_NAME); + +our $A_R_UNIX_NAME; *A_R_UNIX_NAME = \'urn:perun:resource:attribute-def:def:unixGroupName-namespace:einfra'; +our $A_G_UNIX_NAME; *A_G_UNIX_NAME = \'urn:perun:group:attribute-def:def:unixGroupName-namespace:einfra'; + +my @requiredAttributesDefinitions = $attributesAgent->getRequiredAttributesDefinition(service => $service->getId); +my @userRequiredAttributes = (); +my @userFacilityRequiredAttributes = (); +foreach my $attrDef (@requiredAttributesDefinitions) { + # if attribute's namespace starts with "urn:perun:user:" + my $o = index $attrDef->getNamespace, "urn:perun:user:"; + if ($o == 0) { + push @userRequiredAttributes, $attrDef; + next; + } + $o = index $attrDef->getNamespace, "urn:perun:user_facility:"; + if ($o == 0) { + push @userFacilityRequiredAttributes, $attrDef; + next; + } +} + +####### prepare data ###################### +my %usersIds = (); +my %groupData = (); +foreach my $resourceId ($data->getResourceIds()) { + + my $resourceName = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_R_UNIX_NAME); + + my @users; + # process members on resource + foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) { + my $userId = $data->getUserIdForMember(member => $memberId); + if (exists($usersIds{$userId}) && $usersIds{$userId} eq $resourceName) { + next; + } else { + $usersIds{$userId} = $resourceName; + } + my $userData = process_user($memberId); + push @users, $userData; + } + push(@{$groupData{$resourceName}}, @users); + + # process members on groups of resource + foreach my $groupId ($data->getGroupIdsForResource(resource => $resourceId)) { + my $groupName = $data->getGroupAttributeValue(group => $groupId, attrName => $A_G_UNIX_NAME); + my @usersFromGroup; + + foreach my $memberId ($data->getMemberIdsForResourceAndGroup(resource => $resourceId, group => $groupId)) { + my $userId = $data->getUserIdForMember(member => $memberId); + if (exists($usersIds{$userId}) && $usersIds{$userId} eq $groupName) { + next; + } else { + $usersIds{$userId} = $groupName; + } + my $userData = process_user($memberId); + push @usersFromGroup, $userData; + } + push(@{$groupData{$groupName}}, @usersFromGroup); + } +} + +####### output file ###################### +my $fileName = "$DIRECTORY/$::SERVICE_NAME"; +open FILE, ">$fileName" or die "Cannot open $fileName: $! \n"; +print FILE JSON::XS->new->utf8->pretty->canonical->encode(\%groupData); +close FILE or die "Cannot close $fileName: $! \n"; + +perunServicesInit::finalize; +# END of main script + +sub process_user($) { + my $memberId = shift; + + my $userData = (); + foreach my $userAttribute (@userRequiredAttributes) { + my $attrValue = $data->getUserAttributeValue(member => $memberId, attrName => $userAttribute->getName); + # In case there is an undefined boolean attribute, we have to change it to false + if ($userAttribute->getType eq "boolean" && !defined $attrValue) { + $userData->{$userAttribute->getName} = \0; + } else { + $userData->{$userAttribute->getName} = $attrValue; + } + } + + foreach my $userFacilityAttribute (@userFacilityRequiredAttributes) { + my $attrValue = $data->getUserFacilityAttributeValue(member => $memberId, attrName => $userFacilityAttribute->getName); + # In case there is an undefined boolean attribute, we have to change it to false + if ($userFacilityAttribute->getType eq "boolean" && !defined $attrValue) { + $userData->{$userFacilityAttribute->getName} = \0; + } else { + $userData->{$userFacilityAttribute->getName} = $attrValue; + } + } + + return $userData; +} diff --git a/gen/vsup_zimbra b/gen/vsup_zimbra deleted file mode 100755 index e301f6b2..00000000 --- a/gen/vsup_zimbra +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use perunServicesInit; -use perunServicesUtils; -use File::Copy; -use Time::Piece; -use Perun::Agent; - -sub getStatus; - -local $::SERVICE_NAME = "vsup_zimbra"; -local $::PROTOCOL_VERSION = "3.1.0"; -my $SCRIPT_VERSION = "3.0.3"; - -perunServicesInit::init; -my $DIRECTORY = perunServicesInit::getDirectory; -my $fileName = "$DIRECTORY/$::SERVICE_NAME".".csv"; -my $data = perunServicesInit::getHashedHierarchicalData; -my $agent = Perun::Agent->new(); -my $attributesAgent = $agent->getAttributesAgent; - -# Constants -our $A_LOGIN; *A_LOGIN = \'urn:perun:user_facility:attribute-def:virt:login'; -our $A_UCO; *A_UCO = \'urn:perun:user:attribute-def:def:ucoVsup'; -our $A_FIRST_NAME; *A_FIRST_NAME = \'urn:perun:user:attribute-def:core:firstName'; -our $A_LAST_NAME; *A_LAST_NAME = \'urn:perun:user:attribute-def:core:lastName'; -our $A_ARTISTIC_FIRST_NAME; *A_ARTISTIC_FIRST_NAME = \'urn:perun:user:attribute-def:def:artisticFirstName'; -our $A_ARTISTIC_LAST_NAME; *A_ARTISTIC_LAST_NAME = \'urn:perun:user:attribute-def:def:artisticLastName'; -our $A_EMAIL_VSUP; *A_EMAIL_VSUP = \'urn:perun:user:attribute-def:def:vsupMail'; -our $A_R_RELATION_TYPE; *A_R_RELATION_TYPE = \'urn:perun:resource:attribute-def:def:relationType'; -our $A_BLACKLISTED; *A_BLACKLISTED = \'urn:perun:user_facility:attribute-def:virt:blacklisted'; -our $A_EXPIRATION_KOS; *A_EXPIRATION_KOS = \'urn:perun:user:attribute-def:def:expirationKos'; -our $A_EXPIRATION_DC2; *A_EXPIRATION_DC2 = \'urn:perun:user:attribute-def:def:expirationDc2'; -our $A_EXPIRATION_MANUAL; *A_EXPIRATION_MANUAL = \'urn:perun:user:attribute-def:def:expirationManual'; -our $A_ZIMBRA_DISPLAY_NAME; *A_ZIMBRA_DISPLAY_NAME = \'urn:perun:user:attribute-def:def:zimbraDisplayName'; -# following are manually retrieved -our $A_EMAIL_VSUP_ALIAS; *A_EMAIL_VSUP_ALIAS = \'urn:perun:user:attribute-def:def:vsupMailAlias'; -our $A_EMAIL_VSUP_ALIASES; *A_EMAIL_VSUP_ALIASES = \'urn:perun:user:attribute-def:def:vsupMailAliases'; - -# Read which accounts are "system wide" => IGNORED by Perun. -open FILE, "<" . "/etc/perun/services/$::SERVICE_NAME/vsup_zimbra_ignored_accounts"; -my @ignoredAccountsList = ; -close FILE; -chomp(@ignoredAccountsList); -my %ignoredAccounts = map { $_ => 1 } @ignoredAccountsList; - -# GATHER USERS -my $users; # $users->{$uco}->{ATTR} = $attrValue; - -# -# AGGREGATE DATA -# -# FOR EACH USER -foreach my $resourceId ($data->getResourceIds()) { - - my $relationType = $data->getResourceAttributeValue(resource => $resourceId, attrName => $A_R_RELATION_TYPE); - - # Users from Resource must be in a relation - unless ($relationType) { - next; - } - - foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) { - - my $login = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_LOGIN); - - # SKIP MEMBERS WHICH SUPPOSED TO BE SYSTEM WIDE ACCOUNTS => IGNORED BY PERUN - if (exists $ignoredAccounts{$login}) { - next; - } - - my $uco = $data->getUserAttributeValue(member => $memberId, attrName => $A_UCO); - my $vsupMail = $data->getUserAttributeValue(member => $memberId, attrName => $A_EMAIL_VSUP); - my $userId = $data->getUserIdForMember(member => $memberId); - my $artisticFirstName = $data->getUserAttributeValue(member => $memberId, attrName => $A_ARTISTIC_FIRST_NAME); - my $firstName = $data->getUserAttributeValue(member => $memberId, attrName => $A_FIRST_NAME); - my $artisticLastName = $data->getUserAttributeValue(member => $memberId, attrName => $A_ARTISTIC_LAST_NAME); - my $lastName = $data->getUserAttributeValue(member => $memberId, attrName => $A_LAST_NAME); - my $displayName = $data->getUserAttributeValue(member => $memberId, attrName => $A_ZIMBRA_DISPLAY_NAME); - my $blacklisted = $data->getUserFacilityAttributeValue(member => $memberId, attrName => $A_BLACKLISTED); - my $expirationKOS = $data->getUserAttributeValue(member => $memberId, attrName => $A_EXPIRATION_KOS); - my $expirationDC2 = $data->getUserAttributeValue(member => $memberId, attrName => $A_EXPIRATION_DC2); - my $expirationManual = $data->getUserAttributeValue(member => $memberId, attrName => $A_EXPIRATION_MANUAL); - - $users->{$uco}->{$A_LOGIN} = $login; - $users->{$uco}->{'EMAIL'} = ($vsupMail || $login . '@vsup.cz'); - - $users->{$uco}->{'USER_ID'} = $userId; - - # determine user account type - if ($relationType eq "ZAM") { - # prefer ZAM over anything - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = '0603cf86-f917-4448-bb34-57dd11a2c381'; - } elsif ($relationType eq "PED") { - # prefer active PED before STU or EXPIRED or not yet set - if ((!defined $users->{$uco}->{'TYPE'}) || $users->{$uco}->{'TYPE'} ne 'ZAM') { - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = 'e3c33612-98c2-4c53-8b67-80ac1b133546'; - } - } elsif ($relationType eq "STU") { - # prefer active STU if is also EXPIRED or not yet set - if ((!defined $users->{$uco}->{'TYPE'}) || (($users->{$uco}->{'TYPE'} ne 'ZAM') && ($users->{$uco}->{'TYPE'} ne 'PED'))) { - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = 'e00428a1-0c00-11d9-836a-000d93afea2a'; - } - } elsif ($relationType eq "EXPIRED") { - # mark user expired if has no other relation (STU/ZAM) - unless ($users->{$uco}->{'TYPE'}) { - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = 'e00428a1-0c00-11d9-836a-000d93afea2a'; - } - } elsif ($relationType eq "GEN") { - # CAN'T OVERLAP WITH ANOTHER - unless ($users->{$uco}->{'TYPE'}) { - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = 'e69e98ba-e16b-4bdd-bc2c-0ae5e697337d'; - } else { - die "User: '$login' was both GENERIC type and $users->{$uco}->{'TYPE'} type."; - } - } elsif ($relationType eq "MML") { - # CAN'T OVERLAP WITH ANOTHER - unless ($users->{$uco}->{'TYPE'}) { - $users->{$uco}->{'TYPE'} = $relationType; - $users->{$uco}->{'COS'} = '867a2875-136f-40be-aab8-751658db0300'; - } else { - die "User: '$login' was both MAILMAN-LIST type and $users->{$uco}->{'TYPE'} type."; - } - } - - # get users name - $firstName = ($artisticFirstName || ($firstName || '')); - $lastName = ($artisticLastName || ($lastName || '')); - # use custom zimbra displayName - $displayName = $displayName || ''; - # if custom name not present, create it from givenName and sn - unless(defined $displayName and length $displayName) { - if (defined $firstName and length $firstName and defined $lastName and length $lastName) { - $displayName = $firstName . " " . $lastName; - } elsif (defined $firstName and length $firstName and !(defined $lastName and length $lastName)) { - $displayName = $firstName; - } elsif (!(defined $firstName and length $firstName) and defined $lastName and length $lastName) { - $displayName = $lastName; - } - } - - $users->{$uco}->{"FIRST_NAME"} = ($firstName || ''); - $users->{$uco}->{"LAST_NAME"} = ($lastName || ''); - $users->{$uco}->{"DISPLAY_NAME"} = ($displayName || ''); - - if (defined $blacklisted and ($blacklisted == 1)) { - # blacklisted users !security ban! are locked - $users->{$uco}->{"STATUS"} = 'locked'; - } else { - $users->{$uco}->{"STATUS"} = getStatus($expirationKOS, $expirationDC2, $expirationManual); - } - - } -} - -# manually get mail aliases -my @uco_keys = sort keys %{$users}; -for my $uco (@uco_keys) { - - my $uid = $users->{$uco}->{'USER_ID'}; - my @attrNames = ($A_EMAIL_VSUP_ALIAS, $A_EMAIL_VSUP_ALIASES); - - my @attributes = $attributesAgent->getAttributes( user => $uid , attrNames => \@attrNames ); - foreach (@attributes) { - if ($_->getName() eq $A_EMAIL_VSUP_ALIAS) { - - $users->{$uco}->{$A_EMAIL_VSUP_ALIAS} = $_->getValue || ''; - - } elsif ($_->getName() eq $A_EMAIL_VSUP_ALIASES) { - - my $aliases = $_->getValue; - my @aliases = (); - if ($aliases) { - @aliases = @$aliases; - } - $users->{$uco}->{$A_EMAIL_VSUP_ALIASES} = join(",",@aliases) || ''; - - } - } - -} - -# -# PRINT user data -# -open FILE,">$fileName" or die "Cannot open $fileName: $! \n"; -binmode FILE, ":utf8"; - -# print personal info -my @keys = sort keys %{$users}; -for my $uco (@keys) { - - # print attributes, which are never empty - print FILE $uco . "\t" . $users->{$uco}->{$A_LOGIN} . "\t" . $users->{$uco}->{'TYPE'} . "\t" . - $users->{$uco}->{'EMAIL'} . "\t" . $users->{$uco}->{"FIRST_NAME"} . "\t" . $users->{$uco}->{"LAST_NAME"} . - "\t" . $users->{$uco}->{"DISPLAY_NAME"} . "\t" . $users->{$uco}->{"STATUS"} . "\t" . $users->{$uco}->{"COS"} . - "\t" . $users->{$uco}->{$A_EMAIL_VSUP_ALIAS} . "\t" . $users->{$uco}->{$A_EMAIL_VSUP_ALIASES} . "\n"; - -} - -close(FILE); - -# -# Copy ignored accounts -# -copy("/etc/perun/services/$::SERVICE_NAME/vsup_zimbra_ignored_accounts", "$DIRECTORY/vsup_zimbra_ignored_accounts") or die "Couldn't copy file of ignored Zimbra accounts."; - -perunServicesInit::finalize; - -# -# active - výchozí stav, netřeba nastavovat při vytváření schránky, pouze pokud byl účet předtím v jiném stavu -# locked - uzamčen pro přihlašování, maily jsou doručovány -# closed - nelze se přihlásit, maily nejsou doručovány - soft-delete -# -sub getStatus() { - - # read input - my $expirationKos = shift; - my $expirationDc2 = shift; - my $expirationMan = shift; - # parse to time or undef - my $expirationKosTime = ($expirationKos) ? Time::Piece->strptime($expirationKos,"%Y-%m-%d") : undef; - my $expirationDc2Time = ($expirationDc2) ? Time::Piece->strptime($expirationDc2,"%Y-%m-%d") : undef; - my $expirationManTime = ($expirationMan) ? Time::Piece->strptime($expirationMan,"%Y-%m-%d") : undef; - - my @expirations = (); - if (defined $expirationKosTime) { push(@expirations, $expirationKosTime->epoch); } - if (defined $expirationDc2Time) { push(@expirations, $expirationDc2Time->epoch); } - if (defined $expirationManTime) { push(@expirations, $expirationManTime->epoch); } - - # sort all expirations - my @sorted_expirations = sort { $a <=> $b } @expirations; - - my $latest_expiration = $sorted_expirations[$#sorted_expirations]; - my $currentDate = Time::Piece->strptime(localtime->ymd,"%Y-%m-%d"); - - if (!defined $expirationKos and !defined $expirationDc2 and !defined $expirationMan) { - # if no expiration set in source data - take as "never" - return 'active'; - } - - # Add time 23:59:59 to the date, since we want accounts to be active on the last day - $latest_expiration = $latest_expiration + 86399; - - if ($latest_expiration > $currentDate->epoch) { - return 'active'; - } - - # (will) expire by studies - add 21 days grace period - if ($expirationKosTime and ($latest_expiration == $expirationKosTime->epoch + 86399)) { - - # within 14 days grace period - still active - if (($latest_expiration + (21*24*60*60)) > $currentDate->epoch) { - return 'active'; - } else { - # is within 30 days period - if (($latest_expiration + (30*24*60*60)) > $currentDate->epoch) { - return 'locked'; - } - return 'closed' - } - - } else { - # Expired by employment or manual - if (($latest_expiration + (30*24*60*60)) > $currentDate->epoch) { - return 'locked'; - } - return 'closed'; - } - -} diff --git a/gen/vsup_zimbra_aliases b/gen/vsup_zimbra_aliases deleted file mode 100755 index 624657ab..00000000 --- a/gen/vsup_zimbra_aliases +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; -use Perun::Agent; -use perunServicesInit; -use perunServicesUtils; - -local $::SERVICE_NAME = "vsup_zimbra_aliases"; -local $::PROTOCOL_VERSION = "3.0.0"; -my $SCRIPT_VERSION = "3.0.1"; - -perunServicesInit::init; -my $DIRECTORY = perunServicesInit::getDirectory; - -my $agent = Perun::Agent->new(); -my $servicesAgent = $agent->getServicesAgent; - -# -# Zimbra ALIASES are now managed by "vsup_zimbra" service, hence on attribute change we just plan service propagation for it. -# We expect it's on the same facility. - -my $service = $servicesAgent->getServiceByName(name => 'vsup_zimbra'); -$servicesAgent->planServicePropagation(service => $service->getId, facility => perunServicesInit->getFacility->getId); - -perunServicesInit::finalize; diff --git a/send/ad_admin_group_mu_ucn b/send/ad_admin_group_mu_ucn new file mode 100755 index 00000000..cbd1264f --- /dev/null +++ b/send/ad_admin_group_mu_ucn @@ -0,0 +1,270 @@ +#!/usr/bin/perl +use strict; +use warnings; +no if $] >= 5.017011, warnings => 'experimental::smartmatch'; +use Net::LDAPS; +use Net::LDAP::Entry; +use Net::LDAP::Message; +use Net::LDAP::LDIF; + +# Import shared AD library +use ADConnector; +use ScriptLock; + +sub process_add; +sub process_remove; +sub process_update; + +# log counters +my $counter_group_added = 0; +my $counter_group_not_added = 0; +my $counter_group_not_emptied = 0; +my $counter_group_removed = 0; +my $counter_group_not_removed = 0; +my $counter_group_members_updated = 0; +my $counter_group_members_updated_with_errors = 0; +my $counter_group_members_not_updated = 0; + +# define service +my $service_name = "ad_admin_group_mu_ucn"; + +# operations results +my $RESULT_ERRORS = "errors"; +my $RESULT_CHANGED = "changed"; +my $RESULT_UNCHANGED = "unchanged"; +my $SUCCESS = 1; +my $FAIL = 0; + +# GEN folder location +my $facility_name = $ARGV[0]; +chomp($facility_name); +my $service_files_base_dir="../gen/spool"; +my $service_files_dir="$service_files_base_dir/$facility_name/$service_name"; + +# BASE DN +my $base_dn = "OU=PrivilegedGroups,OU=MU,DC=ucn,DC=muni,DC=cz"; + +# propagation destination +my $namespace = $ARGV[1]; +chomp($namespace); + +# create service lock +my $lock = ScriptLock->new($facility_name . "_" . $service_name . "_" . $namespace); +($lock->lock() == 1) or die "Unable to get lock, service propagation was already running."; + +# init configuration +my @conf = init_config($namespace); +my @ldap_locations = resolve_domain_controlers($conf[0]); + +my $ldap = ldap_connect_multiple_options(\@ldap_locations); +my $filter = '(objectClass=group)'; +my @baseAttrs = ('cn', 'samAccountName', 'objectClass', 'description'); + + +# connect +ldap_bind($ldap, $conf[1], $conf[2]); + +# load all data +my @perun_entries = load_perun($service_files_dir . "/" . $service_name . ".ldif"); +my @ad_entries = load_ad($ldap, $base_dn, $filter, ['cn', 'description']); + +my %ad_entries_map = (); +my %perun_entries_map = (); + +foreach my $ad_entry (@ad_entries) { + my $cn = $ad_entry->get_value('cn'); + $ad_entries_map{ lc $cn } = $ad_entry; +} +foreach my $perun_entry (@perun_entries) { + my $cn = $perun_entry->get_value('cn'); + $perun_entries_map{ lc $cn } = $perun_entry; +} + +# process data +process_add(); +process_remove(); +process_update(); + +# disconnect +ldap_unbind($ldap); + +# log results +ldap_log($service_name, "Group added (without members): " . $counter_group_added . " entries."); +ldap_log($service_name, "Group failed to add: " . $counter_group_not_added. " entries."); +ldap_log($service_name, "-------------------------------------------------------------------------------------------------------"); +ldap_log($service_name, "Group updated (members): " . $counter_group_members_updated . " entries."); +ldap_log($service_name, "Group updated with errors (members): " . $counter_group_members_updated_with_errors . " entries."); +ldap_log($service_name, "Group failed to update (members): " . $counter_group_members_not_updated. " entries."); +ldap_log($service_name, "-------------------------------------------------------------------------------------------------------"); +ldap_log($service_name, "Group removed: " . $counter_group_removed . " entries."); +ldap_log($service_name, "Group failed to empty during removal: " . $counter_group_not_emptied . " entries."); +ldap_log($service_name, "Group failed to remove: " . $counter_group_not_removed. " entries."); + +# print results for TaskResults in GUI +print "Group added (without members): " . $counter_group_added . " entries.\n"; +print "Group failed to add: " . $counter_group_not_added. " entries.\n"; +print "-------------------------------------------------------------------------------------------------------\n"; +print "Group updated (members): " . $counter_group_members_updated . " entries.\n"; +print "Group updated with errors (members): " . $counter_group_members_updated_with_errors . " entries.\n"; +print "Group failed to update (members): " . $counter_group_members_not_updated. " entries.\n"; +print "-------------------------------------------------------------------------------------------------------\n"; +print "Group removed: " . $counter_group_removed . " entries.\n"; +print "Group failed to empty during removal: " . $counter_group_not_emptied . " entries.\n"; +print "Group failed to remove: " . $counter_group_not_removed. " entries.\n"; + +$lock->unlock(); + +if ($counter_group_not_added or $counter_group_members_not_updated or $counter_group_not_removed or $counter_group_not_emptied) { + die "Some entries failed to process.\nSee log at: ~/perun-engine/send/logs/$service_name.log"; +} +if ($counter_group_members_updated_with_errors > 0) { die "Some members were not updated.\nSee log at: ~/perun-engine/send/logs/$service_name.log";} + +# END of main script + +########################################### +# +# Main processing functions +# +########################################### + +# +# Add new group entries to AD +# +sub process_add() { + + foreach my $perun_entry (@perun_entries) { + + my $cn = $perun_entry->get_value('cn'); + unless (exists $ad_entries_map{lc $cn}) { + my $new_ad_entry = clone_entry_with_specific_attributes($perun_entry, \@baseAttrs); + # Add new entry to AD + my $response = $new_ad_entry->update($ldap); + unless ($response->is_error()) { + # SUCCESS + ldap_log($service_name, "Group added (without members): " . $perun_entry->dn()); + $counter_group_added++; + } else { + # FAIL + print STDERR "Group NOT added: " . $perun_entry->dn() . " | " . $response->error() . "\n"; + ldap_log($service_name, "Group NOT added: " . $perun_entry->dn() . " | " . $response->error()); + ldap_log($service_name, $new_ad_entry->ldif()); + $counter_group_not_added++; + } + + } + } + +} + +# +# Remove group entries in AD +# +sub process_remove() { + + foreach my $ad_entry (@ad_entries) { + my $cn = $ad_entry->get_value('cn'); + unless (exists $perun_entries_map{ lc $cn }) { + + # clear members + # load members of a group from AD + my @to_be_removed = load_group_members($ldap, $ad_entry->dn(), $filter); + + # Focus only on users + my $response_remove = remove_members_from_entry($ldap, $service_name, $ad_entry, \@to_be_removed); + unless ($response_remove == $SUCCESS) { + print STDERR "Failed to remove all members from group during the group removal process: ".$ad_entry->dn() . "\n"; + ldap_log($service_name, "Failed to remove all members from group during the group removal process: ".$ad_entry->dn()); + $counter_group_not_emptied++; + } + } + } + +} + +# +# Update group members in AD +# +sub process_update() { + my %params; + foreach my $perun_entry (@perun_entries) { + + %params = ( + description => $perun_entry->get_value('description') + ); + + if (exists $ad_entries_map{ lc $perun_entry->get_value('cn') }){ + update_info(clone_entry_with_specific_attributes($perun_entry, \@baseAttrs), $ad_entries_map{ lc $perun_entry->get_value('cn') }, \%params); + } + + my @per_val = $perun_entry->get_value('member'); + + # load members of a group from AD based on DN in Perun => Group must exists in AD + my @ad_val = load_group_members($ldap, $perun_entry->dn(), $filter); + + if ($? != 0) { + print STDERR "Unable to load Perun group members from AD: " . $perun_entry->dn() . "\n"; + ldap_log($service_name, "Unable to load Perun group members from AD: " . $perun_entry->dn()); + next; + } + + # sort to compare + my @sorted_ad_val = sort(@ad_val); + my @sorted_per_val = sort(@per_val); + + # compare using smart-match (perl 5.10.1+) + unless(@sorted_ad_val ~~ @sorted_per_val) { + + my %ad_val_map = map { $_ => 1 } @sorted_ad_val; + my %per_val_map = map { $_ => 1 } @sorted_per_val; + + # members of group are not equals + # we must get reference to real group from AD in order to call "replace" + my $response_ad = $ldap->search( base => $perun_entry->dn(), filter => $filter, scope => 'base' ); + unless ($response_ad->is_error()) { + # SUCCESS + my $ad_entry = $response_ad->entry(0); + my $result = update_group_membership($ldap, $service_name, $ad_entry, \%ad_val_map, \%per_val_map); + $counter_group_members_updated++ if ($result eq $RESULT_CHANGED); + $counter_group_members_updated_with_errors++ if ($result eq $RESULT_ERRORS); + } else { + # FAIL (to get group from AD) + $counter_group_members_not_updated++; + print STDERR "Group members NOT updated: " . $perun_entry->dn() . " | " . $response_ad->error() . "\n"; + ldap_log($service_name, "Group members NOT updated: " . $perun_entry->dn() . " | " . $response_ad->error()); + } + } + + # group is unchanged + + } + +} + +sub update_info { + my $entry = shift; + my $update_entry = shift; + my $params = shift; + + my $params_udapted = 0; + foreach (keys %{$params}){ + if (compare_entry($update_entry, $entry, $_) == 1){ + $update_entry->replace( + "$_" => $params->{$_}, + ); + $params_udapted = 1; + } + } + if ($params_udapted == 1){ + my $response = $update_entry->update($ldap); + if ($response) { + unless ($response->is_error()) { + ldap_log($service_name, "Group Attributes Updated: " . $update_entry->dn() . " | "); + return 0; + } else { + print STDERR "Group Attributes NOT updated: " . $update_entry->ldif("change" => "true") . " | " . $response->error() . "\n"; + ldap_log($service_name, "Group Attributes NOT updated: " . $update_entry->ldif("change" => "true") . " | " . $response->error() . " | "); + return 1; + } + } + } +} diff --git a/send/ad_admin_user_mu_ucn b/send/ad_admin_user_mu_ucn new file mode 100755 index 00000000..5890b9be --- /dev/null +++ b/send/ad_admin_user_mu_ucn @@ -0,0 +1,196 @@ +#!/usr/bin/perl +use strict; +use warnings; +no if $] >= 5.017011, warnings => 'experimental::smartmatch'; +use Net::LDAPS; +use Net::LDAP::Entry; +use Net::LDAP::Message; +use Net::LDAP::LDIF; +use DBI; + +# Import shared AD library +use ADConnector; +use ScriptLock; + +sub process_disable; +sub process_update; + +# log counters +my $counter_remove = 0; +my $counter_remove_fail = 0; +my $counter_update = 0; +my $counter_update_fail = 0; + +# define service +my $service_name = "ad_admin_user_mu_ucn"; + +# GEN folder location +my $facility_name = $ARGV[0]; +chomp($facility_name); +my $service_files_base_dir="../gen/spool"; +my $service_files_dir="$service_files_base_dir/$facility_name/$service_name"; + +my $base_dn = "OU=PrivilegedUsers,OU=MU,DC=ucn,DC=muni,DC=cz"; + +# propagation destination +my $namespace = $ARGV[1]; +chomp($namespace); + +my $filter = '(objectClass=person)'; + +# create service lock +my $lock = ScriptLock->new($facility_name . "_" . $service_name . "_" . $namespace); +($lock->lock() == 1) or die "Unable to get lock, service propagation was already running."; + +# init configuration +my @conf = init_config($namespace); +my @ldap_locations = resolve_domain_controlers($conf[0]); +my $ldap = ldap_connect_multiple_options(\@ldap_locations); +# connect +ldap_bind($ldap, $conf[1], $conf[2]); + +# load all data +my @perun_entries = load_perun($service_files_dir . "/" . $service_name . ".ldif"); +my @ad_entries = load_ad($ldap, $base_dn, $filter, ['cn','displayName','sn','givenName','mail','userAccountControl','samAccountName']); + +my %ad_entries_map = (); +my %perun_entries_map = (); + +foreach my $entry (@ad_entries) { + my $login = $entry->get_value('cn'); + $ad_entries_map{ $login } = $entry; +} + +foreach my $entry (@perun_entries) { + my $login = $entry->get_value('cn'); + $perun_entries_map{ $login } = $entry; +} + +# process data +process_disable(); +process_update(); + +# disconnect +ldap_unbind($ldap); + +# log results +ldap_log($service_name, "Disabled: " . $counter_remove . " entries."); +ldap_log($service_name, "NOT Disabled: " . $counter_remove_fail . " entries."); +ldap_log($service_name, "Updated: " . $counter_update. " entries."); +ldap_log($service_name, "NOT Updated: " . $counter_update_fail . " entries."); + +# print results for TaskResults in GUI +print "Disabled: " . $counter_remove . " entries.\n"; +print "NOT Disabled: " . $counter_remove_fail . " entries.\n"; +print "Updated: " . $counter_update. " entries.\n"; +print "NOT Updated: " . $counter_update_fail. " entries.\n"; + +$lock->unlock(); +my $counter_fail = $counter_remove_fail + $counter_update_fail; +if ($counter_fail > 0) { die "Failed to process: " . $counter_fail . " entries.\nSee log at: ~/perun-engine/send/logs/$service_name.log";} + +# END of main script + +########################################### +# +# Main processing functions +# +########################################### + +sub process_disable() { + foreach my $entry (@ad_entries) { + + # We create only entries for normal UČO users + my $login = $entry->get_value('cn'); + next if exists $perun_entries_map{$login}; + + my $entry_uac = $entry->get_value('userAccountControl'); + if (is_uac_enabled($entry_uac) == 1){ + # Account enabled -> disable it + $entry->replace( + 'userAccountControl' => disable_uac($entry_uac) + ); + my $response = $entry->update($ldap); + unless ($response->is_error()) { + # SUCCESS + ldap_log($service_name, "Disabled user: " . $entry->dn()); + $counter_remove++; + } else { + # FAIL + print STDERR "User NOT Disabled: " . $entry->dn() . " | " . $response->error() . "\n"; + ldap_log($service_name, "NOT Disabled: " . $entry->dn() . " | " . $response->error()); + ldap_log($service_name, $entry->ldif()); + $counter_remove_fail++; + } + } + } +} + +# +# Update existing user entries in AD +# +sub process_update() { + + foreach my $perun_entry (@perun_entries) { + + if (exists $ad_entries_map{$perun_entry->get_value('cn')}) { + + my $ad_entry = $ad_entries_map{$perun_entry->get_value('cn')}; + + # attrs without cn since it's part of DN to be updated + my @attrs = ('displayName','sn','givenName','mail'); + + # stored log messages to check if entry should be updated + my @entry_changed = (); + + # check each attribute + foreach my $attr (@attrs) { + if (compare_entry($ad_entry , $perun_entry , $attr) == 1) { + # store value for log + my @ad_val = $ad_entry->get_value($attr); + my @perun_val = $perun_entry->get_value($attr); + push(@entry_changed, "$attr | " . join(", ",sort(@ad_val)) . " => " . join(", ",sort(@perun_val))); + # replace value + $ad_entry->replace( + $attr => \@perun_val + ); + } + } + + # check UAC + my $ad_entry_uac = $ad_entry->get_value('userAccountControl'); + + # if disabled -> enable it + unless (is_uac_enabled($ad_entry_uac) == 1) { + + my $original_ad_entry_uac = $ad_entry_uac; + my $new_ad_entry_uac = enable_uac($ad_entry_uac); + push( @entry_changed, "userAccountControl | $original_ad_entry_uac => $new_ad_entry_uac" ); + $ad_entry->replace( + 'userAccountControl' => $new_ad_entry_uac + ); + + } + + if (@entry_changed) { + # Update entry in AD + my $response = $ad_entry->update($ldap); + unless ($response->is_error()) { + # SUCCESS + foreach my $log_message (@entry_changed) { + #ldap_log($service_name, "Updated: " . $ad_entry->dn() . " | " . $log_message); + } + $counter_update++; + } else { + # FAIL + print STDERR "User NOT updated: " . $ad_entry->dn() . " | " . $response->error() . "\n"; + ldap_log($service_name, "NOT updated: " . $ad_entry->dn() . " | " . $response->error()); + ldap_log($service_name, $ad_entry->ldif()); + $counter_update_fail++; + } + } + + } + + } +} diff --git a/send/mailman_vsup b/send/mailman_vsup deleted file mode 100755 index dcb9c4e0..00000000 --- a/send/mailman_vsup +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -SERVICE_NAME="mailman_vsup" - -. generic_send diff --git a/send/oidc_with_groups b/send/oidc_with_groups new file mode 100644 index 00000000..086f0139 --- /dev/null +++ b/send/oidc_with_groups @@ -0,0 +1,4 @@ +#!/bin/bash +SERVICE_NAME="oidc_with_groups" + +. generic_send diff --git a/send/openstack_projects b/send/openstack_projects index dc13ac19..43a017bf 100755 --- a/send/openstack_projects +++ b/send/openstack_projects @@ -1,4 +1,43 @@ #!/bin/bash SERVICE_NAME="openstack_projects" -. generic_send +TIMEOUT="5400" #90s * 60 sec = 1.5h +TIMEOUT_KILL="60" # 60 sec to kill after timeout + +FACILITY_NAME=$1 +DESTINATION=$2 +DESTINATION_TYPE=$3 + +SERVICE_FILES_BASE_DIR="`pwd`/../gen/spool" +FILE_NAME="access.json" + +FILE="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME/$FILE_NAME" + + +# Destination type has to be 'url' +if [ "$DESTINATION_TYPE" != "url" ]; then + echo "Unknown destination type '$DESTINATION_TYPE' (url type required)." >&2 + exit 1; +fi + +# Read user name and password from configuration if it is present ( expect string "-u user:pass" ) +[ -r /etc/perun/services/$SERVICE_NAME ] && . /etc/perun/services/$SERVICE_NAME + +# Specify command to transfer the data +TRANSPORT_COMMAND="curl -Ss -i -H Content-Type:application/json -f -X POST -d @- $DESTINATION" + +# HTTP Request with timeout for USERS +cat "$FILE" | timeout -k $TIMEOUT_KILL $TIMEOUT $TRANSPORT_COMMAND +# Catch errors +ERR_CODE=$? +#Error code 124 means - timed out +if [ $ERR_CODE -eq 124 ]; then + echo "Communication with the peer has timed out with return code: $ERR_CODE (Warning: this error can mask original error 124 from peer!)" >&2 +else + if [ $ERR_CODE -ne 0 ]; then + echo "Communication with the peer ends with return code: $ERR_CODE" >&2 + fi +fi + +exit $ERR_CODE + \ No newline at end of file diff --git a/send/vsup_zimbra b/send/vsup_zimbra deleted file mode 100755 index 935eb711..00000000 --- a/send/vsup_zimbra +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -SERVICE_NAME="vsup_zimbra" - -. generic_send diff --git a/send/vsup_zimbra_aliases b/send/vsup_zimbra_aliases deleted file mode 100755 index 9d52aaef..00000000 --- a/send/vsup_zimbra_aliases +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -SERVICE_NAME="vsup_zimbra_aliases" - -. generic_send diff --git a/slave/process-mailman-vsup/bin/process-mailman_vsup.sh b/slave/process-mailman-vsup/bin/process-mailman_vsup.sh deleted file mode 100755 index 3b74839a..00000000 --- a/slave/process-mailman-vsup/bin/process-mailman_vsup.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -PROTOCOL_VERSION='3.1.0' - -function process { - - FROM_PERUN_DIR="${WORK_DIR}/mailinglists/" - - I_MAILING_LIST_UPDATED=(0 '${MAILING_LIST_NAME} successfully updated.') - - create_lock - - for MAILING_LIST_NAME in `ls $FROM_PERUN_DIR/` ; do - # set list members - cat "${FROM_PERUN_DIR}/${MAILING_LIST_NAME}" | grep -v "^#" | sudo /usr/lib/mailman/bin/sync_members --welcome-msg=no --goodbye-msg=no -f - $MAILING_LIST_NAME - log_msg I_MAILING_LIST_UPDATED - done - -} diff --git a/slave/process-mailman-vsup/changelog b/slave/process-mailman-vsup/changelog deleted file mode 100644 index 8b9c8b35..00000000 --- a/slave/process-mailman-vsup/changelog +++ /dev/null @@ -1,17 +0,0 @@ -perun-slave-process-mailman-vsup (3.1.2) stable; urgency=medium - - * Changed architecture to all - - -- Martin Kuba Fri, 09 Nov 2018 15:32:49 +0100 - -perun-slave-process-mailman-vsup (3.1.1) stable; urgency=medium - - * Changed sync_members command to: /usr/lib/mailman/bin/sync_members - - -- Pavel Zlamal Mon, 24 Jul 2017 05:53:00 +0200 - -perun-slave-process-mailman-vsup (3.1.0) stable; urgency=low - - * New package version for perun-slave-process-mailman-vsup - - -- Pavel Zlamal Fri, 30 Jun 2017 12:57:00 +0200 diff --git a/slave/process-mailman-vsup/dependencies b/slave/process-mailman-vsup/dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-mailman-vsup/dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-mailman-vsup/rpm.dependencies b/slave/process-mailman-vsup/rpm.dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-mailman-vsup/rpm.dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-mailman-vsup/short_desc b/slave/process-mailman-vsup/short_desc deleted file mode 100644 index 6877e558..00000000 --- a/slave/process-mailman-vsup/short_desc +++ /dev/null @@ -1 +0,0 @@ -Package for perun service - mailman_vsup diff --git a/slave/process-vsup-zimbra-aliases/bin/process-vsup_zimbra_aliases.sh b/slave/process-vsup-zimbra-aliases/bin/process-vsup_zimbra_aliases.sh deleted file mode 100755 index 49aeb5d0..00000000 --- a/slave/process-vsup-zimbra-aliases/bin/process-vsup_zimbra_aliases.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# Script for managing mail aliases in Zimbra mail server - -PROTOCOL_VERSION='3.0.0' - -function process { - - EXECSCRIPT="${LIB_DIR}/${SERVICE}/process-vsup_zimbra_aliases.pl" - - create_lock - - FROM_PERUN="${WORK_DIR}/vsup_zimbra_aliases.csv" - IGNORED="${WORK_DIR}/vsup_zimbra_ignored_accounts" - - # support czech chars in Zimbra values, since Zimbra has and perun exports the "C" - export LANG=cs_CZ.UTF-8 - - perl $EXECSCRIPT $FROM_PERUN $IGNORED - - exit $? -} diff --git a/slave/process-vsup-zimbra-aliases/changelog b/slave/process-vsup-zimbra-aliases/changelog deleted file mode 100644 index 091d486b..00000000 --- a/slave/process-vsup-zimbra-aliases/changelog +++ /dev/null @@ -1,11 +0,0 @@ -perun-slave-process-vsup-zimbra-aliases (3.0.1) stable; urgency=medium - - * Changed architecture to all - - -- Martin Kuba Fri, 09 Nov 2018 15:32:51 +0100 - -perun-slave-process-vsup-zimbra-aliases (3.0.0) stable; urgency=low - - * Package for managing aliases in Zimbra from Perun. - - -- Pavel Zlamal Wed, 11 Oct 2017 07:00:00 +0200 diff --git a/slave/process-vsup-zimbra-aliases/dependencies b/slave/process-vsup-zimbra-aliases/dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-vsup-zimbra-aliases/dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-vsup-zimbra-aliases/lib/process-vsup_zimbra_aliases.pl b/slave/process-vsup-zimbra-aliases/lib/process-vsup_zimbra_aliases.pl deleted file mode 100755 index 515126a9..00000000 --- a/slave/process-vsup-zimbra-aliases/lib/process-vsup_zimbra_aliases.pl +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; - -sub getAllAccounts; -sub updateAliases; -sub addAlias; -sub removeAlias; -sub setPrefFrom; -sub logMessage; - -my $perunAccounts; # $perunAccounts->{login}->{MAILBOX|zimbraPrefFromAddress|zimbraMailAlias}=value|value|{alias1 = 1, alias2 = 1} -my $zimbraAccounts; # $zimbraAccounts->{login}->{MAILBOX|zimbraPrefFromAddress|zimbraMailAlias}=value|value|{alias1 = 1, alias2 = 1} - -# IF SET TO 1, no changes are actually done to Zimbra mail server -my $dry_run = 0; - -# read input files path -my $accountsFilePath = shift; -my $ignoredFilePath = shift; - -# -# Read accounts sent from Perun -# -open FILE, "<" . $accountsFilePath; -my @lines = ; -close FILE; - -foreach my $line ( @lines ) { - - my @parts = split /\t/, $line; - chomp(@parts); - - $perunAccounts->{$parts[1]}->{'TYPE'} = $parts[2]; # original relation to prevent creation of wrong "active". - $perunAccounts->{$parts[1]}->{'MAILBOX'} = $parts[3]; - $perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'} = (($parts[4] ne '') ? $parts[4] : undef); - - my $aliases = (($parts[5] ne '') ? $parts[5] : undef); - if ($aliases) { - my @existing_aliases = split /,/, $aliases; - foreach my $alias (@existing_aliases) { - $perunAccounts->{$parts[1]}->{'zimbraMailAlias'}->{$alias} = 1; - } - } - - # put prefered alias between aliases - if ($perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'}) { - $perunAccounts->{$parts[1]}->{'zimbraMailAlias'}->{$perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'}} = 1; - } else { - # prefered from is set to mailbox name - in such case is NOT alias - $perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'} = $parts[3]; - } - -} - -# -# Read which accounts are supposed to be IGNORED by Perun -# -open FILE, "<" . $ignoredFilePath; -my @ignoredAccountsList = ; -close FILE; -chomp(@ignoredAccountsList); -my %ignoredAccounts = map { $_ => 1 } @ignoredAccountsList; - -# -# Read existing accounts from Zimbra -# -$zimbraAccounts = getAllAccounts(); - -updateAliases(); - -exit 0; - -##################### -# -# HELPING METHODS -# -##################### - -# -# Read all accounts from Zimbra mail server -# Exit script with ret.code = 1 if contacting Zimbra fails. -# -sub getAllAccounts() { - - my $existingAccounts; # $existingAccounts->{login}->{MAILBOX|ALIAS|ALIASES}=value - my $currentLogin; # current step in output parsing - - # read versbose output of all accounts in zimbra - my @output = `sudo -u zimbra /opt/zimbra/bin/zmprov -l gaa -v vsup.cz`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - if ($ret != 0) { - print "Unable to read all accounts from Zimbra, err.code: $ret, output: @output"; - logMessage("Unable to read all accounts from Zimbra, err.code: $ret, output: @output"); - exit 1; - } - - chomp(@output); - - foreach my $line (@output) { - - if ($line =~ m/^# name (.*\@vsup.cz)(.*)$/) { - $currentLogin = ($line =~ m/^# name (.*)\@vsup.cz(.*)$/)[0]; - my $currentMailbox = ($line =~ m/^# name (.*\@vsup.cz)(.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"MAILBOX"} = $currentMailbox; - } - - if ($line =~ m/^zimbraMailAlias: (.*)$/) { - my $currentAlias = ($line =~ m/^zimbraMailAlias: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraMailAlias"}->{$currentAlias} = 1; - } - - if ($line =~ m/^zimbraPrefFromAddress: (.*)$/) { - my $currentPrefFrom = ($line =~ m/^zimbraPrefFromAddress: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraPrefFromAddress"} = $currentPrefFrom; - } - - } - - return $existingAccounts; - -} - -# -# Iterate through Zimbra and Perun accounts and update changed aliases and preferred from addresses -# -# Only accounts pushed from Perun are modified !! -# -sub updateAliases() { - - # 1. ADD all new aliases - foreach my $login (sort keys %$perunAccounts) { - - # skip ignored - if (exists $ignoredAccounts{$login}) { - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Belongs to ignored."); - next; - } - - # skip not yet existing - unless (exists $zimbraAccounts->{$login}) { - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored - not yet created in Zimbra.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Not yet created in Zimbra."); - next; - - } else { - - # check and update existing - my $perunAliases = $perunAccounts->{$login}->{"zimbraMailAlias"}; - my $zimbraAliases = $zimbraAccounts->{$login}->{"zimbraMailAlias"}; - my @to_be_added; - foreach my $perunAlias (sort keys %{$perunAliases}) { - unless (exists $zimbraAliases->{$perunAlias}) { - push (@to_be_added, $perunAlias); - } - } - - foreach my $perunAlias (@to_be_added) { - - if ($dry_run) { - print $perunAccounts->{$login}->{"MAILBOX"} . " alias would be added '$perunAlias'.\n"; - logMessage($perunAccounts->{$login}->{"MAILBOX"} . " alias would be added '$perunAlias'."); - } else { - addAlias($perunAccounts->{$login}->{"MAILBOX"}, $perunAlias); - } - - } - - } - - } - - # 2. Set all pref addresses - - foreach my $login (sort keys %$perunAccounts) { - - # skip ignored - if (exists $ignoredAccounts{$login}) { - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Belongs to ignored."); - next; - } - - # skip not yet existing - unless (exists $zimbraAccounts->{$login}) { - - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored - not yet created in Zimbra.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Not yet created in Zimbra."); - next; - - } else { - - # check and update existing - - my $perunPrefFromAddress = $perunAccounts->{$login}->{"zimbraPrefFromAddress"}; - my $zimbraPrefFromAddress = $zimbraAccounts->{$login}->{"zimbraPrefFromAddress"} || ''; - - unless ($perunPrefFromAddress eq $zimbraPrefFromAddress) { - - if ($dry_run) { - print $perunAccounts->{$login}->{"MAILBOX"} . " zimbraPrefFromAddress would be updated '$perunPrefFromAddress'.\n"; - logMessage($perunAccounts->{$login}->{"MAILBOX"} . " zimbraPrefFromAddress would be updated '$perunPrefFromAddress'."); - } else { - setPrefFrom($perunAccounts->{$login}->{"MAILBOX"}, $perunPrefFromAddress); - } - - } - - } - - } - - # 3. Remove all deleted aliases - - foreach my $login (sort keys %$perunAccounts) { - - # skip ignored - if (exists $ignoredAccounts{$login}) { - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Belongs to ignored."); - next; - } - - # skip not yet existing - unless (exists $zimbraAccounts->{$login}) { - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored - not yet created in Zimbra.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Not yet created in Zimbra."); - next; - - } else { - - # check and update existing - my $perunAliases = $perunAccounts->{$login}->{"zimbraMailAlias"}; - my $zimbraAliases = $zimbraAccounts->{$login}->{"zimbraMailAlias"}; - my @to_be_removed; - foreach my $zimbraAlias (sort keys %{$zimbraAliases}) { - unless (exists $perunAliases->{$zimbraAlias}) { - push (@to_be_removed, $zimbraAlias); - } - } - - foreach my $zimbraAlias (@to_be_removed) { - - if ($dry_run) { - print $perunAccounts->{$login}->{"MAILBOX"} . " alias would be removed '$zimbraAlias'.\n"; - logMessage($perunAccounts->{$login}->{"MAILBOX"} . " alias would be removed '$zimbraAlias'."); - } else { - removeAlias($perunAccounts->{$login}->{"MAILBOX"}, $zimbraAlias); - } - - } - - } - - } - -} - -# -# Set one of aliases as PreferredFromAddress attribute in Zimbra -# -# 1. param: mailbox name -# 2. param: preferredFrom address -# -sub setPrefFrom() { - - my $account = shift; - my $value = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov ma '$account' zimbraPrefFromAddress '$value'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - if ($ret != 0) { - print "ERROR: $account preferred from address not set, ret.code: $ret, output: $output.\n"; - logMessage("ERROR: $account preferred from address not set, ret.code: $ret, output: $output.\n"); - } else { - print "$account set preferred from address $value.\n"; - logMessage("$account set preferred from address $value, ret.code: $ret, output: $output."); - } - -} - -# -# Add alias to Zimbra account -# -# 1. param: name of Zimbra account to update (mail) -# 2. param: value of alias to be added -# -# Return: return code of zmprov command -# -sub addAlias() { - - my $account = shift; - my $alias = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov aaa '$account' '$alias'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - # only for logging verbose output - if ($ret != 0) { - print "ERROR: $account alias $alias not added.\n"; - logMessage("ERROR: $account alias $alias not added, ret.code: $ret, output: $output."); - } else { - print "$account alias $alias added.\n"; - logMessage("$account alias $alias added, ret.code: $ret, output: $output."); - } - - return $ret; - -} - -# -# Remove alias from Zimbra account -# -# 1. param: name of Zimbra account to update (mail) -# 2. param: value of alias to be removed -# -# Return: return code of zmprov command -# -sub removeAlias() { - - my $account = shift; - my $alias = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov raa '$account' '$alias'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - # only for logging verbose output - if ($ret != 0) { - print "ERROR: $account alias $alias not removed.\n"; - logMessage("ERROR: $account alias $alias not removed, ret.code: $ret, output: $output."); - } else { - print "$account alias $alias removed.\n"; - logMessage("$account alias $alias removed, ret.code: $ret, output: $output."); - } - - return $ret; - -} - -# -# Log message to local file /home/perun/vsup_zimbra_aliases.log -# -# 1. param Message to log -# -sub logMessage() { - my $message = shift; - open(LOGFILE, ">>/home/perun/vsup_zimbra_aliases.log"); - print LOGFILE (localtime(time) . ": " . $message . "\n"); - close(LOGFILE); -} diff --git a/slave/process-vsup-zimbra-aliases/rpm.dependencies b/slave/process-vsup-zimbra-aliases/rpm.dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-vsup-zimbra-aliases/rpm.dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-vsup-zimbra-aliases/short_desc b/slave/process-vsup-zimbra-aliases/short_desc deleted file mode 100644 index 6380ca71..00000000 --- a/slave/process-vsup-zimbra-aliases/short_desc +++ /dev/null @@ -1 +0,0 @@ -Package for perun service - Manages mail aliases in Zimbra mail server at VŠUP diff --git a/slave/process-vsup-zimbra/bin/process-vsup_zimbra.sh b/slave/process-vsup-zimbra/bin/process-vsup_zimbra.sh deleted file mode 100755 index 14720dee..00000000 --- a/slave/process-vsup-zimbra/bin/process-vsup_zimbra.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# Script for managing users in Zimbra mail server - -PROTOCOL_VERSION='3.1.0' - -function process { - - EXECSCRIPT="${LIB_DIR}/${SERVICE}/process-vsup_zimbra.pl" - - create_lock - - FROM_PERUN="${WORK_DIR}/vsup_zimbra.csv" - IGNORED="${WORK_DIR}/vsup_zimbra_ignored_accounts" - - # support czech chars in Zimbra values, since Zimbra has and perun exports the "C" - export LANG=cs_CZ.UTF-8 - - perl $EXECSCRIPT $FROM_PERUN $IGNORED - - exit $? -} diff --git a/slave/process-vsup-zimbra/changelog b/slave/process-vsup-zimbra/changelog deleted file mode 100644 index b95e94ab..00000000 --- a/slave/process-vsup-zimbra/changelog +++ /dev/null @@ -1,56 +0,0 @@ -perun-slave-process-vsup-zimbra (3.0.8) stable; urgency=medium - - * Changed architecture to all - - -- Martin Kuba Fri, 09 Nov 2018 15:32:51 +0100 - -perun-slave-process-vsup-zimbra (3.0.7) stable; urgency=low - - * Sanitize value input for manageAccount() function. - - -- Pavel Zlamal Thu, 11 Jan 2018 13:00:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.6) stable; urgency=medium - - * Manage also aliases and preferredFrom in Zimbra for each account. - - -- Pavel Zlamal Tue, 09 Jan 2018 07:00:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.5) stable; urgency=medium - - * Fixed setting of zimbraCOSId attribute. - - -- Pavel Zlamal Fri, 10 Nov 2017 07:00:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.4) stable; urgency=medium - - * Export LANG=cs_CZ.UTF-8 to support Czech chars. - By default Zimbra has "C" and same value - is exported by Perun, so we must override it locally. - - -- Pavel Zlamal Mon, 09 Oct 2017 13:58:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.3) stable; urgency=medium - - * Fixed account attributes update in Zimbra. - - -- Pavel Zlamal Fri, 06 Oct 2017 07:46:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.2) stable; urgency=low - - * Close zmprov param values in a single quotes. - - -- Pavel Zlamal Mon, 02 Oct 2017 07:00:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.1) stable; urgency=low - - * Prevent use of initialized variable in print, caused print - of warning to STDOUT. - - -- Pavel Zlamal Tue, 26 Sep 2017 10:58:00 +0100 - -perun-slave-process-vsup-zimbra (3.0.0) stable; urgency=low - - * New package version for perun-slave-process-vsup-zimbra - - -- Pavel Zlamal Wed, 31 May 2017 06:40:00 +0200 diff --git a/slave/process-vsup-zimbra/dependencies b/slave/process-vsup-zimbra/dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-vsup-zimbra/dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-vsup-zimbra/lib/process-vsup_zimbra.pl b/slave/process-vsup-zimbra/lib/process-vsup_zimbra.pl deleted file mode 100755 index 642af056..00000000 --- a/slave/process-vsup-zimbra/lib/process-vsup_zimbra.pl +++ /dev/null @@ -1,559 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; - -sub getAllAccounts; -sub createAccount; -sub updateAccount; -sub createAccounts; -sub updateAccounts; -sub compareAndUpdateAttribute($$$); -sub addAlias; -sub removeAlias; -sub setPrefFrom; -sub resolveAliasChange; -sub logMessage; - -my $perunAccounts; # $perunAccounts->{login}->{MAILBOX|givenName|sn|displayName|zimbraAccountStatus|zimbraCOSId|zimbraPrefFromAddress|zimbraMailAlias}=value -my $zimbraAccounts; # $zimbraAccounts->{login}->{MAILBOX|givenName|sn|displayName|zimbraAccountStatus|zimbraCOSId|zimbraPrefFromAddress|zimbraMailAlias}=value - -# IF SET TO 1, no changes are actually done to Zimbra mail server -my $dry_run = 0; - -# read input files path -my $accountsFilePath = shift; -my $ignoredFilePath = shift; - -# -# Read accounts sent from Perun -# -open FILE, "<" . $accountsFilePath; -my @lines = ; -close FILE; - -foreach my $line ( @lines ) { - - my @parts = split /\t/, $line; - chomp(@parts); - - $perunAccounts->{$parts[1]}->{'TYPE'} = $parts[2]; # original relation to prevent creation of wrong "active". - $perunAccounts->{$parts[1]}->{'MAILBOX'} = $parts[3]; - $perunAccounts->{$parts[1]}->{'givenName'} = (($parts[4] ne '') ? $parts[4] : undef); - $perunAccounts->{$parts[1]}->{'sn'} = (($parts[5] ne '') ? $parts[5] : undef); - $perunAccounts->{$parts[1]}->{'displayName'} = (($parts[6] ne '') ? $parts[6] : undef); - $perunAccounts->{$parts[1]}->{'zimbraAccountStatus'} = (($parts[7] ne '') ? $parts[7] : undef); - $perunAccounts->{$parts[1]}->{'zimbraCOSId'} = (($parts[8] ne '') ? $parts[8] : undef); - $perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'} = (($parts[9] ne '') ? $parts[9] : undef); - - my $aliases = (($parts[10] ne '') ? $parts[10] : undef); - if ($aliases) { - my @existing_aliases = split /,/, $aliases; - foreach my $alias (@existing_aliases) { - $perunAccounts->{$parts[1]}->{'zimbraMailAlias'}->{$alias} = 1; - } - } else { - # no aliases -> set to empty hash ref, so we can safely "sort keys" on it later - $perunAccounts->{$parts[1]}->{'zimbraMailAlias'} = {}; - } - - # put preferred alias between aliases - if ($perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'}) { - $perunAccounts->{$parts[1]}->{'zimbraMailAlias'}->{$perunAccounts->{$parts[1]}->{'zimbraPrefFromAddress'}} = 1; - } - -} - -# -# Read which accounts are supposed to be IGNORED by Perun -# -open FILE, "<" . $ignoredFilePath; -my @ignoredAccountsList = ; -close FILE; -chomp(@ignoredAccountsList); -my %ignoredAccounts = map { $_ => 1 } @ignoredAccountsList; - -# -# Read existing accounts from Zimbra -# -$zimbraAccounts = getAllAccounts(); - -createAccounts(); -updateAccounts(); - -exit 0; - -##################### -# -# HELPING METHODS -# -##################### - -# -# Read all accounts from Zimbra mail server -# Exit script with ret.code = 1 if contacting Zimbra fails. -# -sub getAllAccounts() { - - my $existingAccounts; # $existingAccounts->{login}->{MAILBOX|COS|STATUS|NAME}=value - my $currentLogin; # current step in output parsing - - # read versbose output of all accounts in zimbra - my @output = `sudo -u zimbra /opt/zimbra/bin/zmprov -l gaa -v vsup.cz`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - if ($ret != 0) { - print "Unable to read all accounts from Zimbra, err.code: $ret, output: @output"; - logMessage("Unable to read all accounts from Zimbra, err.code: $ret, output: @output"); - exit 1; - } - - chomp(@output); - - foreach my $line (@output) { - - if ($line =~ m/^# name (.*\@vsup.cz)(.*)$/) { - $currentLogin = ($line =~ m/^# name (.*)\@vsup.cz(.*)$/)[0]; - my $currentMailbox = ($line =~ m/^# name (.*\@vsup.cz)(.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"MAILBOX"} = $currentMailbox; - # expect COS is default for each entry if not present - $existingAccounts->{$currentLogin}->{"zimbraCOSId"} = "e00428a1-0c00-11d9-836a-000d93afea2a"; - } - - if ($line =~ m/^zimbraAccountStatus: (.*)$/) { - my $currentStatus = ($line =~ m/^zimbraAccountStatus: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraAccountStatus"}=$currentStatus; - } - - # replace default COS with actuall value if present - if ($line =~ m/^zimbraCOSId: (.*)$/) { - my $currentCos = ($line =~ m/^zimbraCOSId: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraCOSId"} = $currentCos; - } - - if ($line =~ m/^displayName: (.*)$/) { - my $currentName = ($line =~ m/^displayName: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"displayName"} = $currentName; - } - - if ($line =~ m/^givenName: (.*)$/) { - my $currentName = ($line =~ m/^givenName: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"givenName"} = $currentName; - } - - if ($line =~ m/^sn: (.*)$/) { - my $currentName = ($line =~ m/^sn: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"sn"} = $currentName; - } - - if ($line =~ m/^zimbraMailAlias: (.*)$/) { - my $currentAlias = ($line =~ m/^zimbraMailAlias: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraMailAlias"}->{$currentAlias} = 1; - } - - if ($line =~ m/^zimbraPrefFromAddress: (.*)$/) { - my $currentPrefFrom = ($line =~ m/^zimbraPrefFromAddress: (.*)$/)[0]; - $existingAccounts->{$currentLogin}->{"zimbraPrefFromAddress"} = $currentPrefFrom; - } - - } - - return $existingAccounts; - -} - -# -# Create new accounts in Zimbra. -# only 'active' and not ignored accounts are created. -# -sub createAccounts() { - - print "Create accounts\n--------------\n"; - - foreach my $login (sort keys %$perunAccounts) { - unless (exists $zimbraAccounts->{$login}) { - - # try to create new account - - if (exists $ignoredAccounts{$login}) { - # skip IGNORED accounts - print $perunAccounts->{$login}->{"MAILBOX"} . " ignored.\n"; - logMessage("WARN: " . $perunAccounts->{$login}->{"MAILBOX"} . " not created. Belongs to ignored."); - next; - } - - if (($perunAccounts->{$login}->{"zimbraAccountStatus"} eq 'active') and ($perunAccounts->{$login}->{"TYPE"} ne 'EXPIRED')) { - - # create new account for active STU/ZAM - if ($dry_run) { - print $perunAccounts->{$login}->{"MAILBOX"} . " would be created.\n"; - logMessage($perunAccounts->{$login}->{"MAILBOX"} . " would be created."); - } else { - # create account - createAccount($perunAccounts->{$login}); - } - - # has dry-run inside - resolveAliasChange($perunAccounts->{$login}, undef); - - } else { - - # not-active or EXPIRED accounts are not created in Zimbra again ! - print $perunAccounts->{$login}->{"MAILBOX"} . " skipped.\n"; - logMessage("WARN: " . $perunAccounts->{$login}->{"MAILBOX"} . " not created - is not in active state and was probably manually deleted from Zimbra."); - - } - - } - } - -} - -# -# Iterate through Zimbra and Perun accounts and update changed attributes -# also 'close' accounts left in Zimbra which are missing in Perun. -# -sub updateAccounts() { - - print "Update accounts\n--------------\n"; - - foreach my $login (sort keys %$zimbraAccounts) { - - if (exists $ignoredAccounts{$login}) { - print $zimbraAccounts->{$login}->{"MAILBOX"} . " ignored.\n"; - logMessage("WARN: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not updated. Belongs to ignored."); - next; - } - - if (exists $perunAccounts->{$login}) { - - # compare and update each attribute - compareAndUpdateAttribute($perunAccounts->{$login}, $zimbraAccounts->{$login}, "zimbraCOSId"); - compareAndUpdateAttribute($perunAccounts->{$login}, $zimbraAccounts->{$login}, "givenName"); - compareAndUpdateAttribute($perunAccounts->{$login}, $zimbraAccounts->{$login}, "sn"); - compareAndUpdateAttribute($perunAccounts->{$login}, $zimbraAccounts->{$login}, "displayName"); - compareAndUpdateAttribute($perunAccounts->{$login}, $zimbraAccounts->{$login}, "zimbraAccountStatus"); - - resolveAliasChange($perunAccounts->{$login}, $zimbraAccounts->{$login}); - - } else { - - # is missing from perun but present in zimbra => 'closed', in future delete !! - - if ($zimbraAccounts->{$login}->{"zimbraAccountStatus"} ne 'closed') { - - if ($dry_run) { - print $zimbraAccounts->{$login}->{"MAILBOX"}." would be closed.\n"; - logMessage($zimbraAccounts->{$login}->{"MAILBOX"}." would be closed."); - } else { - my $ret = updateAccount($zimbraAccounts->{$login}->{"MAILBOX"}, "zimbraAccountStatus", 'closed'); - if ($ret != 0) { - print "ERROR: " . $zimbraAccounts->{$login}->{"MAILBOX"} . " not closed.\n"; - logMessage("ERROR: ".$zimbraAccounts->{$login}->{"MAILBOX"}." not closed, ret.code: ".$ret); - } else { - print $zimbraAccounts->{$login}->{"MAILBOX"}." closed.\n"; - logMessage($zimbraAccounts->{$login}->{"MAILBOX"}." closed."); - } - } - } else { - logMessage($zimbraAccounts->{$login}->{"MAILBOX"}." already is closed - skipped."); - } - - resolveAliasChange(undef, $zimbraAccounts->{$login}); - - } - } - -} - -# -# Compare Zimbra account attribute between Zimbra and Perun version -# and perform update if necessary -# -# 1. param: hash reference of perun account -# 2. param: hash reference of zimbra account -# 3. param: name of attribute -# -sub compareAndUpdateAttribute($$$) { - - my $perunAccount = shift; - my $zimbraAccount = shift; - my $attrName = shift; - - # Make sure comparison and print work - my $perunAttr = ($perunAccount->{$attrName}) ? $perunAccount->{$attrName} : ''; - my $zimbraAttr = ($zimbraAccount->{$attrName}) ? $zimbraAccount->{$attrName} : ''; - - if ($perunAttr ne $zimbraAttr) { - - if ($dry_run) { - print $perunAccount->{"MAILBOX"} . " $attrName would be updated '$zimbraAttr'=>'$perunAttr'.\n"; - logMessage($perunAccount->{"MAILBOX"} . " $attrName would be updated '$zimbraAttr'=>'$perunAttr'."); - } else { - # user original value in update call - my $ret = updateAccount($perunAccount->{"MAILBOX"}, $attrName, $perunAccount->{$attrName}); - if ($ret != 0) { - print "ERROR: " . $perunAccount->{"MAILBOX"} . " update of $attrName failed.\n"; - logMessage("ERROR: " . $perunAccount->{"MAILBOX"} . " update of $attrName failed, ret.code: " . $ret); - } else { - print $perunAccount->{"MAILBOX"} . " $attrName updated '$zimbraAttr'=>'$perunAttr'.\n"; - logMessage($perunAccount->{"MAILBOX"} . " $attrName updated '$zimbraAttr'=>'$perunAttr'.\n"); - } - } - } - -} - -# -# Compare Zimbra account aliases and prefFrom attributes between Zimbra and Perun version -# and perform update if necessary -# -# 1. param: hash reference of perun account -# 2. param: hash reference of zimbra account -# -sub resolveAliasChange() { - - my $perunAccount = shift; - my $zimbraAccount = shift; - - if (!$perunAccount && $zimbraAccount) { - - # CLOSING/DELETING ZIMBRA ACCOUNT -> remove preferred from and aliases - - # 1. unset preferred from address - my $zimbraAttr = $zimbraAccount->{'zimbraPrefFromAddress'}; - my $zimbraAliases = ($zimbraAccount->{'zimbraMailAlias'}) ? $zimbraAccount->{'zimbraMailAlias'} : {}; - - if ($zimbraAttr) { - # only if previously preferred mail was set - if ($dry_run) { - print $zimbraAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' would be updated '$zimbraAttr'=>''.\n"; - logMessage($zimbraAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' would be updated '$zimbraAttr'=>''."); - } else { - # set preferred from to '' (aka empty it) - my $ret = updateAccount($zimbraAccount->{"MAILBOX"}, 'zimbraPrefFromAddress', ''); - if ($ret != 0) { - print "ERROR: " . $zimbraAccount->{"MAILBOX"} . " update of 'zimbraPrefFromAddress' failed.\n"; - logMessage("ERROR: " . $zimbraAccount->{"MAILBOX"} . " update of 'zimbraPrefFromAddress' failed, ret.code: " . $ret); - } else { - print $zimbraAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' updated '$zimbraAttr'=>''.\n"; - logMessage($zimbraAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' updated '$zimbraAttr'=>''.\n"); - } - } - } - - # 2. remove non-existing aliases - foreach my $zimbraAlias (sort keys %{$zimbraAliases}) { - if ($dry_run) { - print $zimbraAccount->{"MAILBOX"} . " alias would be removed '$zimbraAlias'.\n"; - logMessage($zimbraAccount->{"MAILBOX"} . " alias would be removed '$zimbraAlias'."); - } else { - removeAlias($zimbraAccount->{"MAILBOX"}, $zimbraAlias); - } - } - - } elsif ($perunAccount && $zimbraAccount) { - - # UPDATE ZIMBRA ACCOUNT -> add and remove aliases, set preferred - - my $perunAliases = $perunAccount->{"zimbraMailAlias"}; # set to empty hash ref from perun if empty, so it's safe - my $zimbraAliases = ($zimbraAccount->{"zimbraMailAlias"}) ? $zimbraAccount->{"zimbraMailAlias"} : {}; - - # 1. add missing aliases - my @to_be_added; - foreach my $perunAlias (sort keys %{$perunAliases}) { - unless (exists $zimbraAliases->{$perunAlias}) { - push (@to_be_added, $perunAlias); - } - } - - foreach my $perunAlias (@to_be_added) { - if ($dry_run) { - print $perunAccount->{"MAILBOX"} . " alias would be added '$perunAlias'.\n"; - logMessage($perunAccount->{"MAILBOX"} . " alias would be added '$perunAlias'."); - } else { - addAlias($perunAccount->{"MAILBOX"}, $perunAlias); - } - } - - # 2. set preferred from address (usually one of aliases) - compareAndUpdateAttribute($perunAccount, $zimbraAccount, "zimbraPrefFromAddress"); - - # 3. remove non-existing aliases - my @to_be_removed; - foreach my $zimbraAlias (sort keys %{$zimbraAliases}) { - unless (exists $perunAliases->{$zimbraAlias}) { - push (@to_be_removed, $zimbraAlias); - } - } - - foreach my $zimbraAlias (@to_be_removed) { - if ($dry_run) { - print $perunAccount->{"MAILBOX"} . " alias would be removed '$zimbraAlias'.\n"; - logMessage($perunAccount->{"MAILBOX"} . " alias would be removed '$zimbraAlias'."); - } else { - removeAlias($perunAccount->{"MAILBOX"}, $zimbraAlias); - } - } - - } elsif ($perunAccount && !$zimbraAccount) { - - # CREATE/ENABLE ZIMBRA ACCOUNT - - my $perunAliases = $perunAccount->{"zimbraMailAlias"}; - my $perunAttr = $perunAccount->{'zimbraPrefFromAddress'}; - - # 1. add missing aliases - foreach my $perunAlias (sort keys %{$perunAliases}) { - if ($dry_run) { - print $perunAccount->{"MAILBOX"} . " alias would be added '$perunAlias'.\n"; - logMessage($perunAccount->{"MAILBOX"} . " alias would be added '$perunAlias'."); - } else { - addAlias($perunAccount->{"MAILBOX"}, $perunAlias); - } - } - - # 2. set preferred from address (usually one of aliases) and only if exists - if ($perunAttr) { - if ($dry_run) { - print $perunAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' would be updated '$perunAttr'=>''.\n"; - logMessage($perunAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' would be updated '$perunAttr'=>''."); - } else { - # user original value in update call - my $ret = updateAccount($perunAccount->{"MAILBOX"}, 'zimbraPrefFromAddress', $perunAttr); - if ($ret != 0) { - print "ERROR: " . $perunAccount->{"MAILBOX"} . " update of 'zimbraPrefFromAddress' failed.\n"; - logMessage("ERROR: " . $perunAccount->{"MAILBOX"} . " update of 'zimbraPrefFromAddress' failed, ret.code: " . $ret); - } else { - print $perunAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' updated '$perunAttr'=>''.\n"; - logMessage($perunAccount->{"MAILBOX"} . " 'zimbraPrefFromAddress' updated '$perunAttr'=>''.\n"); - } - } - - } - } - -} - -# -# Create single account in Zimbra and print/log the output -# -# 1. param: hash reference of account to be created -# -sub createAccount() { - - my $account = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov ca '$account->{"MAILBOX"}' '' zimbraCOSid '$account->{"zimbraCOSId"}' givenName '$account->{"givenName"}' sn '$account->{"sn"}' displayName '$account->{"displayName"}'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - if ($ret != 0) { - print "ERROR: $account->{'MAILBOX'} not created, ret.code: $ret, output: $output.\n"; - logMessage("ERROR: $account->{'MAILBOX'} not created, ret.code: $ret, output: $output."); - } else { - print "$account->{'MAILBOX'} created.\n"; - logMessage("$account->{'MAILBOX'} created, ret.code: $ret, output: $output."); - } - -} - -# -# Update account single attribute in Zimbra -# -# 1. param: name of Zimbra account to update (mail) -# 2. param: name of Zimbra attribute to update -# 3. param: value of Zimbra attribute to update -# -# Return: return code of zmprov command -# -sub updateAccount() { - - my $account = shift; - my $attrName = shift; - my $value = shift || ''; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov ma '$account' $attrName '$value'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - # only for logging verbose output - if ($ret != 0) { - logMessage("ERROR: $account attribute $attrName not updated, ret.code: $ret, output: $output."); - } - - return $ret; - -} - -# -# Add alias to Zimbra account -# -# 1. param: name of Zimbra account to update (mail) -# 2. param: value of alias to be added -# -# Return: return code of zmprov command -# -sub addAlias() { - - my $account = shift; - my $alias = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov aaa '$account' '$alias'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - # only for logging verbose output - if ($ret != 0) { - print "ERROR: $account alias $alias not added.\n"; - logMessage("ERROR: $account alias $alias not added, ret.code: $ret, output: $output."); - } else { - print "$account alias $alias added.\n"; - logMessage("$account alias $alias added, ret.code: $ret, output: $output."); - } - - return $ret; - -} - -# -# Remove alias from Zimbra account -# -# 1. param: name of Zimbra account to update (mail) -# 2. param: value of alias to be removed -# -# Return: return code of zmprov command -# -sub removeAlias() { - - my $account = shift; - my $alias = shift; - - my $output = `sudo -u zimbra /opt/zimbra/bin/zmprov raa '$account' '$alias'`; - my $ret = $?; # get ret.code of backticks command - $ret = ($ret >> 8); # shift 8 bits to get original return code - - # only for logging verbose output - if ($ret != 0) { - print "ERROR: $account alias $alias not removed.\n"; - logMessage("ERROR: $account alias $alias not removed, ret.code: $ret, output: $output."); - } else { - print "$account alias $alias removed.\n"; - logMessage("$account alias $alias removed, ret.code: $ret, output: $output."); - } - - return $ret; - -} - -# -# Log message to local file /home/perun/vsup_zimbra.log -# -# 1. param Message to log -# -sub logMessage() { - my $message = shift; - open(LOGFILE, ">>/home/perun/vsup_zimbra.log"); - print LOGFILE (localtime(time) . ": " . $message . "\n"); - close(LOGFILE); -} diff --git a/slave/process-vsup-zimbra/rpm.dependencies b/slave/process-vsup-zimbra/rpm.dependencies deleted file mode 100644 index a6717984..00000000 --- a/slave/process-vsup-zimbra/rpm.dependencies +++ /dev/null @@ -1 +0,0 @@ -perun-slave-base diff --git a/slave/process-vsup-zimbra/short_desc b/slave/process-vsup-zimbra/short_desc deleted file mode 100644 index e833fc35..00000000 --- a/slave/process-vsup-zimbra/short_desc +++ /dev/null @@ -1 +0,0 @@ -Package for perun service - Zimbra mail server at VŠUP