diff --git a/gen/ad_group_vsup b/gen/ad_group_vsup index 85183c9c..2341698d 100755 --- a/gen/ad_group_vsup +++ b/gen/ad_group_vsup @@ -53,6 +53,10 @@ my $usersByResource = {}; foreach my $resourceId ($data->getResourceIds()) { my $group = $data->getResourceAttributeValue( resource => $resourceId, attrName => $A_R_GROUP_NAME ); + unless (defined $group) { + print STDERR "Resource with ID: $resourceId has no AD group name!"; + exit 1; + } $groups->{$group} = 1; # FOR EACH MEMBER ON RESOURCE diff --git a/gen/banned_facility_users b/gen/banned_facility_users new file mode 100755 index 00000000..9ab4655c --- /dev/null +++ b/gen/banned_facility_users @@ -0,0 +1,45 @@ +#!/usr/bin/perl +use strict; +use warnings; +use perunServicesInit; +use perunServicesUtils; +use Perun::Agent; +use JSON::XS; + +our $SERVICE_NAME = "banned_facility_users"; +our $PROTOCOL_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.0"; + +perunServicesInit::init; +my $DIRECTORY = perunServicesInit::getDirectory; +my $data = perunServicesInit::getHashedHierarchicalData; + +my $agent = Perun::Agent->new(); +my $bansAgent = $agent->getBanOnFacilityAgent; + +#Constants +our $A_U_F_IS_BANNED; *A_U_F_IS_BANNED = \'urn:perun:user_facility:attribute-def:virt:isBanned'; + +my %bansStruc; +my $facilityId = perunServicesInit::getFacility->getId; +my @bans = $bansAgent->getBansForFacility(facilityId => $facilityId); + +foreach my $memberId ($data->getMemberIdsForFacility) { + my $isBanned = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_U_F_IS_BANNED ); + if ($isBanned) { + my $uid = $data->getUserIdForMember(member => $memberId); + foreach my $ban (@bans) { + if ($ban->getUserId() eq $uid) { + $bansStruc{$uid} = $ban; + } + } + } +} + +my $fileName = "$DIRECTORY/$SERVICE_NAME"; +open FILE, ">$fileName" or die "Cannot open $fileName: $! \n"; +print FILE JSON::XS->new->utf8->pretty->canonical->convert_blessed->encode(\%bansStruc); +close FILE or die "Cannot close $fileName: $! \n"; + + +perunServicesInit::finalize; diff --git a/gen/du_info_export b/gen/du_info_export index b1964b17..4f083908 100755 --- a/gen/du_info_export +++ b/gen/du_info_export @@ -9,7 +9,7 @@ use Tie::IxHash; our $SERVICE_NAME = "du_info_export"; our $PROTOCOL_VERSION = "3.0.0"; -my $SCRIPT_VERSION = "3.0.1"; +my $SCRIPT_VERSION = "3.0.2"; perunServicesInit::init; my $DIRECTORY = perunServicesInit::getDirectory; @@ -22,7 +22,7 @@ my $attributesAgent = $agent->getAttributesAgent; #Constants our $A_USER_MAIL; *A_USER_MAIL = \'urn:perun:user:attribute-def:def:preferredMail'; -our $A_USER_LOGIN_EINFRA; *A_USER_LOGIN_EINFRA = \'urn:perun:user:attribute-def:def:login-namespace:einfra'; +our $A_USER_LOGIN_EINFRA; *A_USER_LOGIN_EINFRA = \'urn:perun:user:attribute-def:virt:optional-login-namespace:einfra'; our $A_RESOURCE_NAME; *A_RESOURCE_NAME = \'urn:perun:resource:attribute-def:core:name'; our $A_R_VO_NAME; *A_R_VO_NAME = \'urn:perun:resource:attribute-def:virt:voShortName'; our $A_F_NAME; *A_F_NAME = \'urn:perun:facility:attribute-def:core:name'; @@ -77,6 +77,7 @@ foreach my $resourceId ($data->getResourceIds()) { foreach my $memberId ($data->getMemberIdsForResource(resource => $resourceId)) { my $uuid = $data->getUserAttributeValue(attrName => $A_U_UUID, member => $memberId); my $einfraLogin = $data->getUserAttributeValue(attrName => $A_USER_LOGIN_EINFRA, member => $memberId); + $einfraLogin = defined $einfraLogin ? $einfraLogin : ""; unless(defined $attributesByUUID{$uuid}) { diff --git a/gen/scs_it4i b/gen/scs_it4i new file mode 100755 index 00000000..ccc1b130 --- /dev/null +++ b/gen/scs_it4i @@ -0,0 +1,53 @@ +#!/usr/bin/perl +use strict; +use warnings; +use perunServicesInit; +use perunServicesUtils; +use File::Basename; + +our $SERVICE_NAME = basename($0); +our $PROTOCOL_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.0"; + +perunServicesInit::init; +my $DIRECTORY = perunServicesInit::getDirectory; +my $data = perunServicesInit::getHashedHierarchicalData; + +#Constants +our $A_USER_LOGIN_EINFRA; *A_USER_LOGIN_EINFRA = \'urn:perun:user:attribute-def:def:login-namespace:einfra'; +our $A_ORGANIZATION; *A_ORGANIZATION = \'urn:perun:user:attribute-def:def:organization'; +our $A_BLOCK_COLLISION; *A_BLOCK_COLLISION = \'urn:perun:user:attribute-def:def:it4iBlockCollision'; + +my $service_file_name = "$DIRECTORY/$::SERVICE_NAME"; + +my $users; + +foreach my $memberId ($data->getMemberIdsForFacility()) { + + my $collision = $data->getUserAttributeValue( member => $memberId, attrName => $A_BLOCK_COLLISION ); + my $login = $data->getUserAttributeValue( member => $memberId, attrName => $A_USER_LOGIN_EINFRA ); + my $org = $data->getUserAttributeValue( member => $memberId, attrName => $A_ORGANIZATION ) || ""; + + # Check if user is not prohibited in IT4I !! + if (defined $collision) { + die "Login '$login' has collision with old IT4I data. Propagations was stopped for safety." + } + + $users->{$login}->{"login"} = $login; + $users->{$login}->{"organization"} = $org; + $users->{$login}->{"citizenship"} = ""; # TODO + +} + +# convert structure to the result json +my @result; +foreach my $login (sort keys %{$users}) { + push(@result, $users->{$login}) +} + +####### output file ###################### +open SERVICE_FILE, ">:encoding(UTF-8)", "$service_file_name" or die "Cannot open $service_file_name: $! \n"; +print SERVICE_FILE JSON::XS->new->utf8->pretty->canonical->encode(\@result); +close(SERVICE_FILE); +##################################################### +perunServicesInit::finalize; diff --git a/send/banned_facility_users b/send/banned_facility_users new file mode 100755 index 00000000..a7dba5d6 --- /dev/null +++ b/send/banned_facility_users @@ -0,0 +1,4 @@ +#!/bin/bash +export SERVICE_NAME="banned_facility_users" + +python3 generic_send.py "$1" "$2" "$3" diff --git a/send/scs_it4i b/send/scs_it4i new file mode 100755 index 00000000..b47f25f5 --- /dev/null +++ b/send/scs_it4i @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +import sys +import os +import requests +import json +import re +from json.decoder import JSONDecodeError + +urlPattern = re.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;()*$']*[-a-zA-Z0-9+&@#/%=~_|()*$']") + +if __name__ == "__main__": + + # check input + if len(sys.argv) != 4 and len(sys.argv) != 3: + print("Error: Expected number of arguments is 2 or 3 (FACILITY_NAME, DESTINATION and optional DESTINATION_TYPE)", file=sys.stderr) + exit(1) + + facility_name = sys.argv[1] + destination = sys.argv[2] + if len(sys.argv) == 3: + # if there is no destination type, use default 'url' + destination_type = "url" + else: + destination_type = sys.argv[3] + + if destination_type != "url": + print("Only 'url' type of destination is supported.", file=sys.stderr) + exit(1) + + if not (re.fullmatch(urlPattern, destination)): + print("Destination '" + destination + "' is not in valid URL format!", file=sys.stderr) + exit(1) + + # Import client config (file must have .py -> "scs_it4i.py") + try: + sys.path.insert(1, '/etc/perun/services/scs_it4i/') + CLIENT_ID = __import__("scs_it4i").CLIENT_ID + CLIENT_SECRET = __import__("scs_it4i").CLIENT_SECRET + TOKEN_API = __import__("scs_it4i").TOKEN_API + except ImportError as ie: + # this means that config file does not exist + print("Failed to import config! - " + ie.msg, file=sys.stderr) + exit(1) + + if not CLIENT_ID: + print("CLIENT_ID configuration is empty!", file=sys.stderr) + exit(1) + + if not CLIENT_SECRET: + print("CLIENT_SECRET configuration is empty!", file=sys.stderr) + exit(1) + + if not TOKEN_API: + print("TOKEN_API configuration is empty!", file=sys.stderr) + exit(1) + + # Request authorization token via client_id/client_secret + token_req = requests.post( + TOKEN_API, + data = { + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "grant_type": "client_credentials" + } + ) + + if token_req.status_code != 200: + print("Unable to acquire token!", file=sys.stderr) + exit(1) + + try: + token_st = json.loads(token_req.text) + except JSONDecodeError: + print("Invalid token!", file=sys.stderr) + exit(1) + + # read all lines at once + service_files_base_dir = os.getcwd() + "/../gen/spool" + service_files_dir = service_files_base_dir + "/" + facility_name + "/scs_it4i" + + file = open(service_files_dir + "/scs_it4i", mode='r') + all_of_it = file.read() + file.close() + + try: + all_of_it_json = json.loads(all_of_it) + except JSONDecodeError: + print("Invalid JSON in generated data!", file=sys.stderr) + exit(1) + + # Call einfra-user-attr with auth token + user_attr_req = requests.post( + destination, + headers = { "Authorization": "Bearer " + token_st["access_token"] }, + json = all_of_it + ) + + response = user_attr_req.text.strip() + + if user_attr_req.status_code != 200: + print(f"Failed to import data ({response})", file=sys.stderr) + + else: + print(f"Import succeeded ({response})")