diff --git a/demo/complex/tests/main.bats b/demo/complex/tests/main.bats
index f980cdf..6ec5782 100755
--- a/demo/complex/tests/main.bats
+++ b/demo/complex/tests/main.bats
@@ -21,8 +21,8 @@ load ../../../library
touch $BATS_TMPDIR/not-started
wait_for_midpoint_start complex_midpoint-server_1 complex_midpoint-data_1
wait_for_shibboleth_idp_start complex_idp_1
+ wait_for_grouper_ui_start complex_grouper-ui_1
rm $BATS_TMPDIR/not-started
-# TODO wait for shibboleth, grouper-ui, (also something other?)
}
@test "040 Check midPoint health" {
@@ -53,7 +53,7 @@ load ../../../library
add_object users /tmp/test110.xml
rm /tmp/test110.xml
search_and_check_object users test110
-# TODO delete user after
+ delete_object_by_name users test110
}
@test "200 Upload objects" {
@@ -61,11 +61,26 @@ load ../../../library
check_health
pwd >&2
./upload-objects
+
search_and_check_object objectTemplates template-org-course
search_and_check_object objectTemplates template-org-department
search_and_check_object objectTemplates template-role-affiliation
search_and_check_object objectTemplates template-role-generic-group
-# TODO check other objects that were uploaded
+
+ search_and_check_object orgs courses
+ search_and_check_object orgs departments
+
+ search_and_check_object resources "OpenLDAP (directory)"
+ search_and_check_object resources "Grouper SQL/MQ"
+ search_and_check_object resources "SQL SIS courses (sources)"
+ search_and_check_object resources "SQL SIS persons (sources)"
+
+ search_and_check_object roles metarole-affiliation
+ search_and_check_object roles metarole-course
+ search_and_check_object roles metarole-department
+ search_and_check_object roles metarole-generic-group
+ search_and_check_object roles role-grouper-sysadmin
+ search_and_check_object roles role-ldap-basic
}
@test "210 Test resource" {
@@ -81,7 +96,7 @@ load ../../../library
add_object tasks midpoint-objects-manual/tasks/task-import-sis-persons.xml
search_and_check_object tasks "Import from SIS persons"
- wait_for_task_completion 22c2a3d0-0961-4255-9eec-c550a79aeaaa
+ wait_for_task_completion 22c2a3d0-0961-4255-9eec-c550a79aeaaa 6 10
assert_task_success 22c2a3d0-0961-4255-9eec-c550a79aeaaa
search_and_check_object users jsmith
@@ -94,10 +109,39 @@ load ../../../library
search_and_check_object users amorrison
search_and_check_object users wprice
search_and_check_object users mroberts
- # TODO check in LDAP, check assignments etc
+
+ check_ldap_account_by_user_name jsmith complex_directory_1
+ check_ldap_account_by_user_name banderson complex_directory_1
+ check_ldap_account_by_user_name kwhite complex_directory_1
+ check_ldap_account_by_user_name whenderson complex_directory_1
+ check_ldap_account_by_user_name ddavis complex_directory_1
+ check_ldap_account_by_user_name cmorrison complex_directory_1
+ check_ldap_account_by_user_name danderson complex_directory_1
+ check_ldap_account_by_user_name amorrison complex_directory_1
+ check_ldap_account_by_user_name wprice complex_directory_1
+ check_ldap_account_by_user_name mroberts complex_directory_1
+ # TODO check assignments etc
}
+@test "230 Check 'TestUser230' in Midpoint and LDAP" {
+ if [ -e $BATS_TMPDIR/not-started ]; then skip 'not started'; fi
+ check_health
+ echo "TestUser230Test User230TestUser230password" >/tmp/testuser230.xml
+ add_object users /tmp/testuser230.xml
+ rm /tmp/testuser230.xml
+ search_and_check_object users TestUser230
+
+ execute_bulk_action tests/resources/bulk-action/recom-role-grouper-sysadmin.xml
+ execute_bulk_action tests/resources/bulk-action/assign-role-grouper-sysadmin-to-test-user.xml
+
+ check_ldap_account_by_user_name TestUser230 complex_directory_1
+ check_of_ldap_membership TestUser230 sysadmingroup complex_directory_1
+
+ delete_object_by_name users TestUser230
+}
+
+
@test "999 Clean up" {
-# skip TEMP
+ skip TEMP
docker-compose down -v
}
diff --git a/demo/complex/tests/resources/bulk-action/assign-role-grouper-sysadmin-to-test-user.xml b/demo/complex/tests/resources/bulk-action/assign-role-grouper-sysadmin-to-test-user.xml
new file mode 100644
index 0000000..c2736da
--- /dev/null
+++ b/demo/complex/tests/resources/bulk-action/assign-role-grouper-sysadmin-to-test-user.xml
@@ -0,0 +1,22 @@
+
+
+ c:UserType
+
+
+ c:name
+ TestUser230
+
+
+
+ assign
+
+ role
+ d48ec05b-fffd-4262-acd3-d9ff63365b62
+
+
+
+
diff --git a/demo/complex/tests/resources/bulk-action/recom-role-grouper-sysadmin.xml b/demo/complex/tests/resources/bulk-action/recom-role-grouper-sysadmin.xml
new file mode 100644
index 0000000..1356484
--- /dev/null
+++ b/demo/complex/tests/resources/bulk-action/recom-role-grouper-sysadmin.xml
@@ -0,0 +1,16 @@
+
+
+ c:RoleType
+
+
+ name
+ role-grouper-sysadmin
+
+
+
+ recompute
+
+
+
diff --git a/demo/shibboleth/test.sh b/demo/shibboleth/test.sh
deleted file mode 100755
index c23693b..0000000
--- a/demo/shibboleth/test.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-
-trap 'exitcode=$? ; error "Exiting $0 because of an error ($exitcode) occurred" ; exit $exitcode' ERR
-
-cd "$(dirname "$0")"
-. ../../test/common.sh
-
-heading "Cleaning up containers and volumes if they exist"
-docker-compose down -v || true
-ok "Done"
-echo
-
-heading "Composing and starting Shibboleth..."
-docker-compose up --build -d
-ok "OK"
-echo
-
-# TODO wait for Shib to start
-
-heading "Composing and starting midPoint..."
-pushd ../../midpoint
-MPDIR=`pwd`
-docker-compose down -v || true
-env AUTHENTICATION=shibboleth docker-compose up --build -d
-popd
-$MPDIR/test/t010-wait-for-start.sh
-ok "OK"
-echo
-
-heading "Test 100: Checking health via HTTP..."
-$MPDIR/test/t100-check-health.sh
-ok "Health check passed"
-echo
diff --git a/demo/shibboleth/tests/main.bats b/demo/shibboleth/tests/main.bats
index 4a791fa..105395d 100755
--- a/demo/shibboleth/tests/main.bats
+++ b/demo/shibboleth/tests/main.bats
@@ -15,8 +15,7 @@ load ../../../library
@test "020 Initialize and start Shibboleth" {
docker-compose up -d
- # TODO implement wait_for_shibboleth_start
- sleep 60
+ wait_for_shibboleth_idp_start shibboleth_idp_1
}
@test "030 Check health" {
diff --git a/library.bash b/library.bash
index 0b2172f..f22a759 100644
--- a/library.bash
+++ b/library.bash
@@ -12,7 +12,7 @@ function generic_wait_for_log () {
FAILURE="$4"
ADDITIONAL_CONTAINER_NAME=$5
ATTEMPT=0
- MAX_ATTEMPTS=20
+ MAX_ATTEMPTS=40
DELAY=10
until [[ $ATTEMPT = $MAX_ATTEMPTS ]]; do
@@ -45,28 +45,17 @@ function wait_for_midpoint_start () {
generic_wait_for_log $1 "INFO (com.evolveum.midpoint.web.boot.MidPointSpringApplication): Started MidPointSpringApplication in" "midPoint to start" "midPoint did not start" $2
}
-# Waits until Shibboleth IDP starts ... TODO refactor using generic waiting function
+# Waits until Shibboleth IDP starts
function wait_for_shibboleth_idp_start () {
- CONTAINER_NAME=$1
- ATTEMPT=0
- MAX_ATTEMPTS=20
- DELAY=10
-
- until [[ $ATTEMPT = $MAX_ATTEMPTS ]]; do
- ATTEMPT=$((ATTEMPT+1))
- echo "Waiting $DELAY seconds for Shibboleth IDP to start (attempt $ATTEMPT) ..."
- sleep $DELAY
- docker ps
- ( docker logs $CONTAINER_NAME 2>&1 | grep "INFO:oejs.Server:main: Started" ) && return 0
- done
+ generic_wait_for_log $1 "INFO:oejs.Server:main: Started" "shibboleth idp to start" "shibboleth idp did not start" $2
+}
- echo Shibboleth IDP did not start in $(( $MAX_ATTEMPTS * $DELAY )) seconds in $CONTAINER_NAME
- echo "========== Container log =========="
- docker logs $CONTAINER_NAME 2>&1
- echo "========== End of the container log =========="
- return 1
+# Waits until Grouper UI starts
+function wait_for_grouper_ui_start () {
+ generic_wait_for_log $1 "INFO org.apache.catalina.startup.Catalina- Server startup in" "grouper ui to start" "grouper ui did not start" $2
}
+
# Checks the health of midPoint server
function check_health () {
echo Checking health...
@@ -127,45 +116,117 @@ function get_and_check_object () {
}
# Adds object from a given file
-# TODO Returns the OID in OID variable
-# it can be found in the following HTTP reader returned: Location: "https://localhost:8443/midpoint/ws/rest/users/85e62669-d36b-41ce-b4f1-1ffdd9f66262"
function add_object () {
local TYPE=$1
local FILE=$2
+ TMPFILE=$(mktemp /tmp/execbulkaction.XXXXXX)
echo "Adding to $TYPE from $FILE..."
- response=$(curl -k -sD - --silent --write-out "%{http_code}" --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST "https://localhost:8443/midpoint/ws/rest/$TYPE" -d @$FILE)
- http_code=$(sed '$!d' <<<"$response")
+ curl -k -sD - --silent --write-out "%{http_code}" --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST "https://localhost:8443/midpoint/ws/rest/$TYPE" -d @$FILE >$TMPFILE
+ local HTTP_CODE=$(sed '$!d' $TMPFILE)
- if [ "$http_code" -eq 201 ] || [ "$http_code" -eq 202 ]; then
- headers=$(sed -n '1,/^\r$/p' <<<"$response")
+ if [ "$HTTP_CODE" -eq 201 ] || [ "$HTTP_CODE" -eq 202 ]; then
+
+ OID=$(grep -oP "Location: \K.*" $TMPFILE | awk -F "$TYPE/" '{print $2}') || (echo "Couldn't extract oid from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
- # get the real Location
- location=$(grep -oP 'Location: \K.*' <<<"$headers")
- oid=$(sed 's/.*\///' <<<"$location")
-
- echo "Oid created object: $oid"
+ echo "Oid created object: $OID"
+ rm $TMPFILE
return 0
else
- echo "Error code: $http_code"
- if [ "$http_code" -eq 500 ]; then
+ echo "Error code: $HTTP_CODE"
+ if [ "$HTTP_CODE" -ge 500 ]; then
echo "Error message: Internal server error. Unexpected error occurred, if necessary please contact system administrator."
else
- error_message=$(grep 'message' <<<"$response" | head -1 | awk -F">" '{print $2}' | awk -F"<" '{print $1}')
- echo "Error message: $error_message"
+ local ERROR_MESSAGE=$(xmllint --xpath "/*/*[local-name()='error']/text()" $TMPFILE) || (echo "Couldn't extract error message from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Error message: $ERROR_MESSAGE"
fi
+ rm $TMPFILE
+ return 1
+ fi
+}
+
+function execute_bulk_action () {
+ local FILE=$1
+ echo "Executing bulk action from $FILE..."
+ TMPFILE=$(mktemp /tmp/execbulkaction.XXXXXX)
+
+ (curl -k --silent --write-out "%{http_code}" --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST "https://localhost:8443/midpoint/ws/rest/rpc/executeScript" -d @$FILE >$TMPFILE) || (echo "Midpoint logs: " ; docker logs "complex_midpoint-server_1" ; return 1)
+ local HTTP_CODE=$(sed '$!d' $TMPFILE)
+ sed -i '$ d' $TMPFILE
+
+ if [ "$HTTP_CODE" -eq 200 ]; then
+
+ local STATUS=$(xmllint --xpath "/*/*/*[local-name()='status']/text()" $TMPFILE) || (echo "Couldn't extract status from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ if [ $STATUS = "success" ]; then
+ local CONSOLE_OUTPUT=$(xmllint --xpath "/*/*/*[local-name()='consoleOutput']/text()" $TMPFILE) || (echo "Couldn't extract console output from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Console output: $CONSOLE_OUTPUT"
+ rm $TMPFILE
+ return 0
+ else
+ echo "Bulk action status is not OK: $STATUS"
+ local CONSOLE_OUTPUT=$(xmllint --xpath "/*/*/*[local-name()='consoleOutput']/text()" $TMPFILE) || (echo "Couldn't extract console output from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Console output: $CONSOLE_OUTPUT"
+ rm $TMPFILE
+ return 1
+ fi
+
+ else
+ echo "Error code: $HTTP_CODE"
+ if [ "$HTTP_CODE" -ge 500 ]; then
+ echo "Error message: Internal server error. Unexpected error occurred, if necessary please contact system administrator."
+ else
+ local ERROR_MESSAGE=$(xmllint --xpath "/*/*[local-name()='error']/text()" $TMPFILE) || (echo "Couldn't extract error message from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Error message: $ERROR_MESSAGE"
+ fi
+ rm $TMPFILE
+ return 1
+ fi
+}
+
+function delete_object_by_name () {
+ local TYPE=$1
+ local NAME=$2
+ search_objects_by_name users $NAME
+ local OID=$(xmllint --xpath "/*/*[local-name()='object']/@oid" $SEARCH_RESULT_FILE | awk -F"\"" '{print $2}' ) || (echo "Couldn't extract oid from file:" ; cat $SEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE; return 1)
+ delete_object $TYPE $OID
+}
+
+function delete_object () {
+ local TYPE=$1
+ local OID=$2
+ echo "Deleting object with type $TYPE and oid $OID..."
+ TMPFILE=$(mktemp /tmp/delete.XXXXXX)
+
+ curl -k --silent --write-out "%{http_code}" --user administrator:5ecr3t -H "Content-Type: application/xml" -X DELETE "https://localhost:8443/midpoint/ws/rest/$TYPE/$OID" >$TMPFILE
+ local HTTP_CODE=$(sed '$!d' $TMPFILE)
+ sed -i '$ d' $TMPFILE
+
+ if [ "$HTTP_CODE" -eq 204 ]; then
+
+ echo "Object with type $TYPE and oid $OID was deleted"
+ rm $TMPFILE
+ return 0
+ else
+ echo "Error code: $HTTP_CODE"
+ if [ "$HTTP_CODE" -ge 500 ]; then
+ echo "Error message: Internal server error. Unexpected error occurred, if necessary please contact system administrator."
+ else
+ local ERROR_MESSAGE=$(xmllint --xpath "/*/*[local-name()='error']/text()" $TMPFILE) || (echo "Couldn't extract error message from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Error message: $ERROR_MESSAGE"
+ fi
+ rm $TMPFILE
return 1
fi
- #curl -k --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST "https://localhost:8443/midpoint/ws/rest/$TYPE" -d @$FILE || return 1
- #TODO check the returned XML
}
+
+
# Tries to find an object with a given name
# Results of the search are in the $SEARCH_RESULT_FILE
# TODO check if the result is valid (i.e. not an error) - return 1 if invalid, otherwise return 0 ("no objects" is considered OK here)
function search_objects_by_name () {
- TYPE=$1
- NAME="$2"
+ local TYPE=$1
+ local NAME="$2"
TMPFILE=$(mktemp /tmp/search.XXXXXX)
curl -k --write-out %{http_code} --user administrator:5ecr3t -H "Content-Type: application/xml" -X POST "https://localhost:8443/midpoint/ws/rest/$TYPE/search" -d @- << EOF >$TMPFILE || (rm $TMPFILE ; return 1)
@@ -178,15 +239,22 @@ function search_objects_by_name () {
EOF
- SEARCH_RESULT_FILE=$TMPFILE
-
- http_code=$(sed '$!d' <<<"$(cat $SEARCH_RESULT_FILE)")
+ local HTTP_CODE=$(sed '$!d' <<<"$(cat $TMPFILE)")
+ sed -i '$ d' $TMPFILE
+ cat $TMPFILE
- sed -i '$ d' $SEARCH_RESULT_FILE
- cat $SEARCH_RESULT_FILE
- if [ "$http_code" -eq 200 ]; then
+ if [ "$HTTP_CODE" -eq 200 ]; then
+ SEARCH_RESULT_FILE=$TMPFILE
return 0
else
+ echo "Error code: $HTTP_CODE"
+ if [ "$HTTP_CODE" -ge 500 ]; then
+ echo "Error message: Internal server error. Unexpected error occurred, if necessary please contact system administrator."
+ else
+ local ERROR_MESSAGE=$(xmllint --xpath "/*/*[local-name()='error']/text()" $TMPFILE) || (echo "Couldn't extract error message from file:" ; cat $TMPFILE ; rm $TMPFILE; return 1)
+ echo "Error message: $ERROR_MESSAGE"
+ fi
+ rm $SEARCH_RESULT_FILE
return 1
fi
}
@@ -244,6 +312,84 @@ function assert_task_success () {
function wait_for_task_completion () {
local OID=$1
- sleep 60 # TODO
+ local ATTEMPT=0
+ local MAX_ATTEMPTS=$2
+ local DELAY=$3
+
+ until [[ $ATTEMPT = $MAX_ATTEMPTS ]]; do
+ ATTEMPT=$((ATTEMPT+1))
+ echo "Waiting $DELAY seconds for task with oid $OID to finish (attempt $ATTEMPT) ..."
+ sleep $DELAY
+ get_object tasks $OID
+ TASK_EXECUTION_STATUS=$(xmllint --xpath "/*/*[local-name()='executionStatus']/text()" $TMPFILE) || (echo "Couldn't extract task status from task $OID" ; cat $TMPFILE ; rm $TMPFILE ; return 1)
+ if [[ $TASK_EXECUTION_STATUS = "suspended" ]] || [[ $TASK_EXECUTION_STATUS = "closed" ]]; then
+ echo "Task $OID is finished"
+ rm $TMPFILE
+ return 0
+ fi
+ done
+ rm $TMPFILE
+ echo Task with $OID did not finish in $(( $MAX_ATTEMPTS * $DELAY )) seconds
+ return 1
+}
+
+
+#search LDAP accout by uid
+function search_ldap_object_by_filter () {
+ local BASE_CONTEXT_FOR_SEARCH=$1
+ local FILTER="$2"
+ local LDAP_CONTAINER=$3
+ TMPFILE=$(mktemp /tmp/ldapsearch.XXXXXX)
+
+ docker exec $LDAP_CONTAINER ldapsearch -h localhost -p 389 -D "cn=Directory Manager" -w password -b "$BASE_CONTEXT_FOR_SEARCH" "($FILTER)" >$TMPFILE || (rm $TMPFILE ; return 1)
+ LDAPSEARCH_RESULT_FILE=$TMPFILE
return 0
}
+
+function check_ldap_account_by_user_name () {
+ local NAME="$1"
+ local LDAP_CONTAINER=$2
+ search_ldap_object_by_filter "ou=people,dc=internet2,dc=edu" "uid=$NAME" $LDAP_CONTAINER
+ search_objects_by_name users $NAME
+
+ local MP_FULL_NAME=$(xmllint --xpath "/*/*/*[local-name()='fullName']/text()" $SEARCH_RESULT_FILE) || (echo "Couldn't extract user fullName from file:" ; cat $SEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+ local MP_GIVEN_NAME=$(xmllint --xpath "/*/*/*[local-name()='givenName']/text()" $SEARCH_RESULT_FILE) || (echo "Couldn't extract user givenName from file:" ; cat $SEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+ local MP_FAMILY_NAME=$(xmllint --xpath "/*/*/*[local-name()='familyName']/text()" $SEARCH_RESULT_FILE) || (echo "Couldn't extract user familyName from file:" ; cat $SEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+
+ local LDAP_CN=$(grep -oP "cn: \K.*" $LDAPSEARCH_RESULT_FILE) || (echo "Couldn't extract user cn from file:" ; cat $LDAPSEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+ local LDAP_GIVEN_NAME=$(grep -oP "givenName: \K.*" $LDAPSEARCH_RESULT_FILE) || (echo "Couldn't extract user givenName from file:" ; cat $LDAPSEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+ local LDAP_SN=$(grep -oP "sn: \K.*" $LDAPSEARCH_RESULT_FILE) || (echo "Couldn't extract user sn from file:" ; cat $LDAPSEARCH_RESULT_FILE ; rm $SEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+
+ rm $SEARCH_RESULT_FILE
+ rm $LDAPSEARCH_RESULT_FILE
+
+ if [[ $MP_FULL_NAME = $LDAP_CN ]] && [[ $MP_GIVEN_NAME = $LDAP_GIVEN_NAME ]] && [[ $MP_FAMILY_NAME = $LDAP_SN ]]; then
+ return 0
+ fi
+
+ echo "User in Midpoint and LDAP Account with uid $NAME are not same"
+ return 1
+}
+
+function check_of_ldap_membership () {
+ local NAME_OF_USER="$1"
+ local NAME_OF_GROUP="$2"
+ local LDAP_CONTAINER=$3
+ search_ldap_object_by_filter "ou=people,dc=internet2,dc=edu" "uid=$NAME_OF_USER" $LDAP_CONTAINER
+
+ local LDAP_ACCOUNT_DN=$(grep -oP "dn: \K.*" $LDAPSEARCH_RESULT_FILE) || (echo "Couldn't extract user dn from file:" ; cat $LDAPSEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+
+ search_ldap_object_by_filter "ou=groups,dc=internet2,dc=edu" "cn=$NAME_OF_GROUP" $LDAP_CONTAINER
+
+ local LDAP_MEMBERS_DNS=$(grep -oP "uniqueMember: \K.*" $LDAPSEARCH_RESULT_FILE) || (echo "Couldn't extract user uniqueMember from file:" ; cat $LDAPSEARCH_RESULT_FILE ; rm $LDAPSEARCH_RESULT_FILE ; return 1)
+
+ rm $LDAPSEARCH_RESULT_FILE
+
+ if [[ $LDAP_MEMBERS_DNS =~ $LDAP_ACCOUNT_DN ]]; then
+ return 0
+ fi
+
+ echo "LDAP Account with uid $NAME_OF_USER is not member of LDAP Group $NAME_OF_GROUP"
+ return 1
+}
+