diff --git a/gen/o365_mu_users_export b/gen/o365_mu_users_export index 0c96064f..45579f03 100755 --- a/gen/o365_mu_users_export +++ b/gen/o365_mu_users_export @@ -9,7 +9,7 @@ use utf8; local $::SERVICE_NAME = "o365_mu_users_export"; local $::PROTOCOL_VERSION = "3.0.0"; -my $SCRIPT_VERSION = "3.0.0"; +my $SCRIPT_VERSION = "3.0.1"; perunServicesInit::init; my $DIRECTORY = perunServicesInit::getDirectory; @@ -17,13 +17,17 @@ my $data = perunServicesInit::getHashedHierarchicalData; #Constants our $A_UF_LOGIN; *A_UF_LOGIN = \'urn:perun:user_facility:attribute-def:virt:login'; +our $A_UF_MFA_STATUS; *A_UF_MFA_STATUS = \'urn:perun:user:attribute-def:virt:mfaStatus:mu'; our $A_UF_O365_STATE; *A_UF_O365_STATE = \'urn:perun:user_facility:attribute-def:def:o365InternalUserState'; our $A_UF_DISABLE_O365_MAIL_FORWARD; *A_UF_DISABLE_O365_MAIL_FORWARD = \'urn:perun:user_facility:attribute-def:def:disableO365MailForward'; our $A_UF_O365_STORE_AND_FORWARD; *A_UF_O365_STORE_AND_FORWARD = \'urn:perun:user_facility:attribute-def:def:o365MailStoreAndForward'; -my $validLogins = {}; +my $validLoginsO365 = {}; +my $validLoginsMFA = {}; #RULES: +# add any user with mfaStatus attribute value filled to the mfa structure +# for the O365 structure: #1] any user who has UCO #2] status of user in o365 is not 0 #3] disableMailForward == true @@ -31,8 +35,14 @@ my $validLogins = {}; #3] disableMailForward == false AND mailStoreAndForward == true foreach my $memberId ( $data->getMemberIdsForFacility() ) { my $uco = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_UF_LOGIN ); - #skip all users without UCO + # skip all users without UCO next unless $uco; + # check whether user has mfa configured and add to mfa structure if so + my $mfaStatus = $data->getUserAttributeValue( member => $memberId, attrName => $A_UF_MFA_STATUS ); + if ($mfaStatus && $mfaStatus ne "") { + $validLoginsMFA->{$uco} = $mfaStatus; + } + # now check for O365 rules my $o365Status = $data->getUserFacilityAttributeValue( member => $memberId, attrName => $A_UF_O365_STATE ); #skip all users with 0 or empty value in status attribute (everything except 0 is OK here) next unless $o365Status; @@ -43,16 +53,22 @@ foreach my $memberId ( $data->getMemberIdsForFacility() ) { next unless $storeAndForward; } #if all rules are met, add uco to the list - $validLogins->{$uco} = $uco; + $validLoginsO365->{$uco} = $uco; } my $fileName = "$DIRECTORY/$::SERVICE_NAME"; -open FILE,">$fileName" or die "Cannot open $fileName: $! \n"; -binmode FILE, ":utf8"; - -foreach my $uco (sort keys %{$validLogins}) { +open FILE,">:encoding(UTF-8)","$fileName" or die "Cannot open $fileName: $! \n"; +foreach my $uco (sort keys %{$validLoginsO365}) { print FILE $uco . "\n"; } +close (FILE); +my $mfaFileName = $fileName."_mfa"; +open FILE,">:encoding(UTF-8)","$mfaFileName" or die "Cannot open $mfaFileName: $! \n"; +foreach my $uco (sort keys %{$validLoginsMFA}) { + print FILE $uco . "\t"; + print FILE $validLoginsMFA->{$uco} . "\n" +} close (FILE); + perunServicesInit::finalize; diff --git a/send/atlassian_mu b/send/atlassian_mu index fda48d5e..5bf9c0ac 100755 --- a/send/atlassian_mu +++ b/send/atlassian_mu @@ -1,109 +1,36 @@ -#!/bin/bash +#!/usr/bin/env python3 -SERVICE_NAME="atlassian_mu" -EXECSCRIPT="./atlassian_mu_process.pl" +import re +import sys -FACILITY_NAME=$1 -DESTINATION=$2 -DESTINATION_TYPE=$3 +import send_lib - #Test if destination is in not empty and in the correct format -if [ -z "$DESTINATION" ]; then - echo "Missing Destination argument (Name of configuration file to retrieve endpoint URL and key from)" >&2 - exit 252 -else - if echo "$DESTINATION" | grep "[^.A-Za-z_0-9-]"; then - echo "Bad format of destination!" >&2 - exit 251 - fi -fi +SERVICE_NAME = "atlassian_mu" +EXECSCRIPT = "./atlassian_mu_process.pl" -#Test if name of facility is not empty -if [ -z "$FACILITY_NAME" ]; then - echo "Missing FacilityName argument" >&2 - exit 245 -fi +OK = 0 +NOK = 1 -#Basic path to find data from gen service -SERVICE_FILES_BASE_DIR="`pwd`/../gen/spool" -SERVICE_FILES_DIR="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME" -#Just safety check. This should not happen -if [ ! -d "$SERVICE_FILES_DIR" ]; then echo '$SERVICE_FILES_DIR: '$SERVICE_FILES_DIR' is not a directory' >&2 ; exit 1; fi +DESTINATION_REGEX = "[.A-Za-z_0-9-]*" -#Create lock to disallow calling more than once at time (method similar to locks in slave scripts) -LOCK_DIR=${LOCK_DIR:=/var/lock} -LOCK_FILE="${LOCK_DIR}/perun-${SERVICE_NAME}-$DESTINATION.lock" -LOCK_PIDFILE="$LOCK_FILE/pid" -function create_lock { - if mkdir "${LOCK_FILE}"; then - trap 'rm -r -f "${LOCK_FILE}"' EXIT - echo $$ > "$LOCK_PIDFILE"; - if [ $? -ne 0 ]; then - echo "Can't create lock file." >&2 - exit 250 - fi - else - # lock file exists, check for existence of concurrent process - if ps ax | grep "$SERVICE_NAME" | sed 's/^\([0-9]\+\).*/\1/' | grep "\(^\| \)`cat $LOCK_PIDFILE`\( \|$\)"; then - # concurrent process is running - this skript must terminate - echo "Concurrent process $SERVICE_NAME is running" >&2 - exit 249 - else - # lock is not valid; it should be deleted - rm -r "$LOCK_FILE" - if [ $? -ne 0 ]; then - echo "Can't remove not valid lock file." >&2 - exit 248 - fi - echo "Invalid lock file found and deleted: $LOCK_FILE" >&2 - mkdir "${LOCK_FILE}" - if [ $? -ne 0 ]; then - echo "Can't create lock after removing invalid lock." >&2 - exit 247 - fi - trap 'rm -r -f "${LOCK_FILE}"' EXIT - echo $$ > "$LOCK_PIDFILE" - if [ $? -ne 0 ]; then - echo "Can't create lock file after removing invalid lock file." >&2 - exit 246 - fi - fi - fi -} -#start script by creating new lock -create_lock +if __name__ == "__main__": -#prepare temporary working directory -TMP_HOSTNAME_DIR="`mktemp -d /tmp/perun-send.XXXXXXXXXX`" -if [ $? -ne 0 ]; then - echo "Can't create temporary dir" >&2 - exit 255 -fi + send_lib.check_input_fields(sys.argv) + facility_name = sys.argv[1] + destination = sys.argv[2] + send_lib.check_destination_format(destination, '', re.compile(DESTINATION_REGEX)) -#prepare after exit removing of temporary files and directories -trap 'rm -r -f "${LOCK_FILE}" "${TMP_HOSTNAME_DIR}"' EXIT + # create lock to ensure only one script of this type is running + send_lib.create_lock(SERVICE_NAME, destination) -#copy all needed files to the temporary directory -cp $SERVICE_FILES_DIR/*.scim $TMP_HOSTNAME_DIR -if [ $? -ne 0 ]; then - echo "Can't copy service file to temporary dir" >&2 - exit 254 -fi + # prepare temporary working directory and copy all needed files into it + with send_lib.prepare_temporary_directory() as tmpDir: + send_lib.copy_files_to_directory(send_lib.get_gen_folder(facility_name, SERVICE_NAME), tmpDir, re.compile(".*scim$")) -#test if exists perl script to call from this one -if [ ! -f "$EXECSCRIPT" ]; then - echo "Can't locate connector file!" >&2 - exit 253 -fi + # run script + process_return_code = send_lib.exec_script(EXECSCRIPT, ["-c", f"/etc/perun/services/{SERVICE_NAME}/{destination}", "-d", f"{tmpDir}/"]).wait() + if process_return_code != OK: + send_lib.die_with_error("Process exit with error", process_return_code) -#call perl script with mandatory options -$EXECSCRIPT -c "/etc/perun/services/$SERVICE_NAME/$DESTINATION" -d "$TMP_HOSTNAME_DIR/" - -#catch return statement and process it -ERRORCODE=$? -if [ $ERRORCODE -ne 0 ]; then - echo "Process exit with error" >&2 -fi - -exit $ERRORCODE + exit(OK) diff --git a/send/bbmri_collections b/send/bbmri_collections old mode 100755 new mode 100644 index dddb8a96..7d6f6ecd --- a/send/bbmri_collections +++ b/send/bbmri_collections @@ -1,59 +1,66 @@ -#!/bin/bash -SERVICE_NAME="bbmri_collections" - -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" -USER_FILE_NAME="users.scim" -GROUP_FILE_NAME="groups.scim" -USER_FILE="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME/$USER_FILE_NAME" -GROUP_FILE="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME/$GROUP_FILE_NAME" -USER_ENDPOINT="users" -GROUP_ENDPOINT="mapping" - -# 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/$SERVICE_NAME ] && . /etc/perun/services/$SERVICE_NAME/$SERVICE_NAME - -# Specify command to transfer the data -TRANSPORT_COMMAND="curl -Ss -i --http1.1 -H Content-Type:application/json -f -X POST" -USER_TRANSPORT_COMMAND="$TRANSPORT_COMMAND -d @- $USERNAME_AND_PASSWORD $DESTINATION$USER_ENDPOINT" -GROUP_TRANSPORT_COMMAND="$TRANSPORT_COMMAND -d @- $USERNAME_AND_PASSWORD $DESTINATION$GROUP_ENDPOINT" - -# HTTP Request with timeout for USERS -cat "$USER_FILE" | timeout -k $TIMEOUT_KILL $TIMEOUT $USER_TRANSPORT_COMMAND -# Catch errors -ERR_CODE=$? -#Error code 124 means - timed out -if [ $ERR_CODE -eq 124 ]; then - echo "Propagation users - 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 "Propagation users - Communication with the peer ends with return code: $ERR_CODE" >&2 - fi -fi - -# HTTP Request with timeout for GROUPS -cat "$GROUP_FILE" | timeout -k $TIMEOUT_KILL $TIMEOUT $GROUP_TRANSPORT_COMMAND -# Catch errors -ERR_CODE=$? -#Error code 124 means - timed out -if [ $ERR_CODE -eq 124 ]; then - echo "Propagation groups - Communication with the peer ends with return code: $ERR_CODE (Warning: this error can mask original error 124 from peer!)" >&2 -else - if [ $ERR_CODE -ne 0 ]; then - echo "Propagation groups - Communication with the peer ends with return code: $ERR_CODE" >&2 - fi -fi - -exit $ERR_CODE +#!/usr/bin/env python3 +import os +import send_lib +import sys +import requests +import json + +SERVICE_NAME = "bbmri_collections" +TIMEOUT = 5400 # 90s * 60 sec = 1.5h + +send_lib.check_input_fields(sys.argv, True) + +facility = sys.argv[1] +destination = sys.argv[2] +destination_type = sys.argv[3] + +send_lib.check_destination_type_allowed(destination_type, send_lib.DESTINATION_TYPE_URL) +send_lib.check_destination_format(destination, destination_type) + +gen_folder = send_lib.get_gen_folder(facility, SERVICE_NAME) +user_file_name = "users.scim" +group_file_name = "groups.scim" +user_filepath = os.path.join(gen_folder, user_file_name) +group_filepath = os.path.join(gen_folder, group_file_name) +user_endpoint = "users" +group_endpoint = "mapping" + + +# Read username and password from configuration if it is present - else auth is not added to the request +auth = None +try: + # expected format of the auth file /etc/perun/services/bbmri_collections/bbmri_collections.py + # supplement $ variables with destination url, username and password + # credentials = { + # '$url1': { 'username': '$user1', 'password': '$pwd1' }, + # '$url2': { 'username': '$user2', 'password': '$pwd2' } + # } + sys.path.insert(1, '/etc/perun/services/' + SERVICE_NAME + '/') + credentials = __import__(SERVICE_NAME).credentials + if destination in credentials.keys(): + username = credentials.get(destination).get('username') + password = credentials.get(destination).get('password') + auth = (username, password) +except ImportError: + # this means that config file does not exist + pass + +with open(user_filepath, 'rb') as f: + headers = {'Content-Type': 'application/json'} + response = requests.post(destination + user_endpoint, headers=headers, auth=auth, timeout=TIMEOUT, json=json.load(f)) + if response.status_code == 124: + send_lib.die_with_error("Propagation users - Communication with the peer has timed out with return code:" + " 124 (Warning: this error can mask original error 124 from peer!)") + if not response.ok: + send_lib.die_with_error( + "Propagation users - Communication with the peer ends with return code: " + str(response.status_code)) + +with open(group_filepath, 'rb') as f: + headers = {'Content-Type': 'application/json'} + response = requests.post(destination + group_endpoint, headers=headers, auth=auth, timeout=TIMEOUT, json=json.load(f)) + if response.status_code == 124: + send_lib.die_with_error("Propagation groups - Communication with the peer has timed out with return code:" + " 124 (Warning: this error can mask original error 124 from peer!)") + if not response.ok: + send_lib.die_with_error( + "Propagation groups - Communication with the peer ends with return code: " + str(response.status_code)) diff --git a/send/bbmri_networks b/send/bbmri_networks old mode 100755 new mode 100644 index 39b11160..07b63d7f --- a/send/bbmri_networks +++ b/send/bbmri_networks @@ -1,60 +1,66 @@ -#!/bin/bash -SERVICE_NAME="bbmri_networks" - -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" -USER_FILE_NAME="users.scim" -GROUP_FILE_NAME="groups.scim" -USER_FILE="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME/$USER_FILE_NAME" -GROUP_FILE="$SERVICE_FILES_BASE_DIR/$FACILITY_NAME/$SERVICE_NAME/$GROUP_FILE_NAME" -USER_ENDPOINT="users" -GROUP_ENDPOINT="mapping" - -# 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/$SERVICE_NAME ] && . /etc/perun/services/$SERVICE_NAME/$SERVICE_NAME - -# Specify command to tranfer the data -#TRANSPORT_COMMAND="curl --cacert /etc/ssl/chain_TERENA_SSL_CA_3.pem -i -H Content-Type:application/json -f -X POST" -TRANSPORT_COMMAND="curl -Ss -i -H Content-Type:application/json -f -X POST" -USER_TRANSPORT_COMMAND="$TRANSPORT_COMMAND -d @- $USERNAME_AND_PASSWORD $DESTINATION$USER_ENDPOINT" -GROUP_TRANSPORT_COMMAND="$TRANSPORT_COMMAND -d @- $USERNAME_AND_PASSWORD $DESTINATION$GROUP_ENDPOINT" - -# HTTP Request with timeout for USERS -cat "$USER_FILE" | timeout -k $TIMEOUT_KILL $TIMEOUT $USER_TRANSPORT_COMMAND -# Catch errors -ERR_CODE=$? -#Error code 124 means - timed out -if [ $ERR_CODE -eq 124 ]; then - echo "Propagation users - 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 "Propagation users - Communication with the peer ends with return code: $ERR_CODE" >&2 - fi -fi - -# HTTP Request with timeout for GROUPS -cat "$GROUP_FILE" | timeout -k $TIMEOUT_KILL $TIMEOUT $GROUP_TRANSPORT_COMMAND -# Catch errors -ERR_CODE=$? -#Error code 124 means - timed out -if [ $ERR_CODE -eq 124 ]; then - echo "Propagation groups - Communication with the peer ends with return code: $ERR_CODE (Warning: this error can mask original error 124 from peer!)" >&2 -else - if [ $ERR_CODE -ne 0 ]; then - echo "Propagation groups - Communication with the peer ends with return code: $ERR_CODE" >&2 - fi -fi - -exit $ERR_CODE +#!/usr/bin/env python3 +import os +import send_lib +import sys +import requests +import json + +SERVICE_NAME = "bbmri_networks" +TIMEOUT = 5400 # 90s * 60 sec = 1.5h + +send_lib.check_input_fields(sys.argv, True) + +facility = sys.argv[1] +destination = sys.argv[2] +destination_type = sys.argv[3] + +send_lib.check_destination_type_allowed(destination_type, send_lib.DESTINATION_TYPE_URL) +send_lib.check_destination_format(destination, destination_type) + +gen_folder = send_lib.get_gen_folder(facility, SERVICE_NAME) +user_file_name = "users.scim" +group_file_name = "groups.scim" +user_filepath = os.path.join(gen_folder, user_file_name) +group_filepath = os.path.join(gen_folder, group_file_name) +user_endpoint = "users" +group_endpoint = "mapping" + + +# Read username and password from configuration if it is present - else auth is not added to the request +auth = None +try: + # expected format of the auth file /etc/perun/services/bbmri_networks/bbmri_networks.py + # supplement $ variables with destination url, username and password + # credentials = { + # '$url1': { 'username': '$user1', 'password': '$pwd1' }, + # '$url2': { 'username': '$user2', 'password': '$pwd2' } + # } + sys.path.insert(1, '/etc/perun/services/' + SERVICE_NAME + '/') + credentials = __import__(SERVICE_NAME).credentials + if destination in credentials.keys(): + username = credentials.get(destination).get('username') + password = credentials.get(destination).get('password') + auth = (username, password) +except ImportError: + # this means that config file does not exist + pass + +with open(user_filepath, 'rb') as f: + headers = {'Content-Type': 'application/json'} + response = requests.post(destination + user_endpoint, headers=headers, auth=auth, timeout=TIMEOUT, json=json.load(f)) + if response.status_code == 124: + send_lib.die_with_error("Propagation users - Communication with the peer has timed out with return code:" + " 124 (Warning: this error can mask original error 124 from peer!)") + if not response.ok: + send_lib.die_with_error( + "Propagation users - Communication with the peer ends with return code: " + str(response.status_code)) + +with open(group_filepath, 'rb') as f: + headers = {'Content-Type': 'application/json'} + response = requests.post(destination + group_endpoint, headers=headers, auth=auth, timeout=TIMEOUT, json=json.load(f)) + if response.status_code == 124: + send_lib.die_with_error("Propagation groups - Communication with the peer has timed out with return code:" + " 124 (Warning: this error can mask original error 124 from peer!)") + if not response.ok: + send_lib.die_with_error( + "Propagation groups - Communication with the peer ends with return code: " + str(response.status_code)) diff --git a/send/generic_sender.py b/send/generic_sender.py index 2f40b67a..355b07e3 100644 --- a/send/generic_sender.py +++ b/send/generic_sender.py @@ -173,13 +173,13 @@ def prepare_ssh_transport_command(): # in this situation 'curl' was used if return_code == 0: # check if curl ended without an error (ERR_CODE = 0) (if not, we can continue as usual, because there is an error on STDERR) - if int(stdout) != 200: - # check if HTTP_CODE is different from OK (200) + if int(stdout) not in send_lib.http_ok_codes: + # check if HTTP_CODE is different from OK # if yes, then we will use HTTP_CODE as ERROR_CODE which is always non-zero temp.seek(0, 0) print(temp.read(), file=sys.stderr) else: - # if HTTP_CODE is 200, then call was successful and result call can be printed with info + # if HTTP_CODE is OK, then call was successful and result call can be printed with info # result call is saved in temp file temp.seek(0, 0) print(temp.read()) diff --git a/send/o365_mu_users_export_process.pl b/send/o365_mu_users_export_process.pl index b5cdce9f..d05e75a2 100755 --- a/send/o365_mu_users_export_process.pl +++ b/send/o365_mu_users_export_process.pl @@ -13,6 +13,7 @@ my $pathToServiceFile; my $serviceName; my $tableName; +my $MFATableName; GetOptions ("dbname|d=s" => \$dbname, "pathToServiceFile|p=s" => \$pathToServiceFile, "serviceName|s=s" => \$serviceName); @@ -31,6 +32,7 @@ exit 12; } +my $filenameMFA = "$pathToServiceFile/$serviceName"."_mfa"; my $filename = "$pathToServiceFile/$serviceName"; if(! -f $filename) { print "Missing service file with data.\n"; @@ -46,6 +48,8 @@ $password = ($line =~ m/^password: (.*)$/)[0]; } elsif($line =~ /^tablename: .*/) { $tableName = ($line =~ m/^tablename: (.*)$/)[0]; + } elsif($line =~ /^mfatablename: .*/) { + $MFATableName = ($line =~ m/^mfatablename: (.*)$/)[0]; } elsif($line =~ /^database: .*/) { $database = ($line =~ m/^database: (.*)$/)[0]; } @@ -57,36 +61,63 @@ } #Main Structure -my $validLogins = {}; +my $validLoginsMFA = {}; +my $validLoginsO365 = {}; + +if (defined($MFATableName)) { + if (! -f $filenameMFA) { + print "MFA table is set in the config file, but service file with MFA data is missing. \n"; + exit 15; + } + open FILE, $filenameMFA or die "Could not open $filenameMFA: $!"; + while(my $line = ) { + chomp( $line ); + my @parts = split /\t/, $line; + my $uco = $parts[0]; + my $mfaStatus = $parts[1]; + $validLoginsMFA->{$uco} = $mfaStatus; + } + close FILE; +} open FILE, $filename or die "Could not open $filename: $!"; while(my $line = ) { chomp( $line ); - $validLogins->{$line} = $line; + $validLoginsO365->{$line} = $line; } close FILE; my $dbh = DBI->connect("dbi:Oracle:$database",$username, $password,{RaiseError=>1,AutoCommit=>0,LongReadLen=>65536, ora_charset => 'AL32UTF8'}) or die "Connect to database $database Error!\n"; +# prepare queries +my $insertLogin = $dbh->prepare(qq{INSERT INTO $tableName (uco) VALUES (?)}); +my $deleteLogin = $dbh->prepare(qq{DELETE from $tableName where uco=?}); +my $updateLoginMFA = $dbh->prepare(qq{UPDATE $MFATableName SET mfa=? WHERE uco=?}); +my $deleteLoginMFA = $dbh->prepare(qq{DELETE from $MFATableName where uco=?}); +my $insertLoginMFA = $dbh->prepare(qq{INSERT INTO $MFATableName (uco, mfa) VALUES (?, ?)}); +my $allLoginsFromTable = $dbh->prepare(qq{select distinct uco from $tableName}); +my $allLoginsFromMFATable = $dbh->prepare(qq{select uco, mfa from $MFATableName}); #statistic and information variables my $skipped = 0; my $inserted = 0; my $deleted = 0; +my $skippedMFA = 0; +my $insertedMFA = 0; +my $deletedMFA = 0; +my $updatedMFA = 0; #return all logins from the table my $loginsInTable = {}; -my $allLoginsFromTable = $dbh->prepare(qq{select distinct uco from $tableName}); $allLoginsFromTable->execute(); while(my $alft = $allLoginsFromTable->fetch) { $loginsInTable->{$$alft[0]} = $$alft[0]; } #insert new logins -foreach my $uco (sort keys %$validLogins) { +foreach my $uco (sort keys %$validLoginsO365) { if($loginsInTable->{$uco}) { $skipped++; } else { - my $insertLogin = $dbh->prepare(qq{INSERT INTO $tableName (uco) VALUES (?)}); $insertLogin->execute($uco); $inserted++; } @@ -94,21 +125,75 @@ #remove old logins foreach my $uco (sort keys %$loginsInTable) { - unless($validLogins->{$uco}) { - my $deleteLogin = $dbh->prepare(qq{DELETE from $tableName where uco=?}); + unless($validLoginsO365->{$uco}) { $deleteLogin->execute($uco); $deleted++; } } +# MFA TABLE +# only process MFA information if the name of the MFA table is configured +#return all logins from the MFA table (in case MFA table has not yet been filled => logins in this table would not match the other table) +my $loginsInMFATable = {}; +if (defined $MFATableName) { + $allLoginsFromMFATable->execute(); + while (my $alft = $allLoginsFromMFATable->fetch) { + $loginsInMFATable->{$$alft[0]} = $$alft[1]; + } + + foreach my $uco (sort keys %$validLoginsMFA) { + if ($loginsInMFATable->{$uco}) { + if ($loginsInMFATable->{$uco} ne $validLoginsMFA->{$uco} && $validLoginsMFA->{$uco} ne "none") { + #update different mfa settings + $updateLoginMFA->execute($validLoginsMFA->{$uco}, $uco); + $updatedMFA++; + } + elsif ($validLoginsMFA->{$uco} eq "none") { + #delete users that no longer have mfa settings + $deleteLoginMFA->execute($uco); + $deletedMFA++; + } + else { + $skippedMFA++; + } + } + elsif ($validLoginsMFA->{$uco} ne "none") { + #insert new mfa settings + $insertLoginMFA->execute($uco, $validLoginsMFA->{$uco}); + $insertedMFA++; + } + else { + $skippedMFA++; + } + } + + + #remove old logins MFA + foreach my $uco (sort keys %$loginsInMFATable) { + unless ($validLoginsMFA->{$uco}) { + $deleteLoginMFA->execute($uco); + $deletedMFA++; + } + } +} + commit $dbh; $dbh->disconnect(); #Info about operations print "================================\n"; +print "Table $tableName:\n"; print "Inserted:\t$inserted\n"; print "Skipped: \t$skipped\n"; print "Deleted: \t$deleted\n"; +if (defined $MFATableName) { + print "\n"; + print "Table $MFATableName:\n"; + print "Inserted:\t$insertedMFA\n"; + print "Skipped: \t$skippedMFA\n"; + print "Deleted: \t$deletedMFA\n"; + print "Updated: \t$updatedMFA\n"; +} print "================================\n"; exit 0; diff --git a/send/openstack_projects b/send/openstack_projects index 515501a6..1a2ec0a1 100755 --- a/send/openstack_projects +++ b/send/openstack_projects @@ -20,13 +20,21 @@ send_lib.check_destination_type_allowed(destination_type, send_lib.DESTINATION_T send_lib.check_destination_format(destination, destination_type) filepath = os.path.join(gen_folder, file_name) -# Read username and password from configuration if it is present +# Read username and password from configuration if it is present - else auth is not added to the request auth = None try: + # expected format of the auth file /etc/perun/services/openstack_projects/openstack_projects.py + # supplement $ variables with destination url, username and password + # credentials = { + # '$url1': { 'username': '$user1', 'password': '$pwd1' }, + # '$url2': { 'username': '$user2', 'password': '$pwd2' } + # } sys.path.insert(1, '/etc/perun/services/' + service_name + '/') - username = __import__(service_name).username - password = __import__(service_name).password - auth = (username, password) + credentials = __import__(service_name).credentials + if destination in credentials.keys(): + username = credentials.get(destination).get('username') + password = credentials.get(destination).get('password') + auth = (username, password) except ImportError: # this means that config file does not exist pass diff --git a/send/send_lib.py b/send/send_lib.py index 79e3d29b..b147fd2c 100644 --- a/send/send_lib.py +++ b/send/send_lib.py @@ -27,6 +27,8 @@ TIMEOUT = 7200 # 120 * 60 sec = 2h TIMEOUT_KILL = 60 # 60 sec to kill after timeout +http_ok_codes = [200, 201, 202, 203, 204] + # regex checks HOST_PATTERN = re.compile( "^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$|^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$")