ICS tests with istio and JWTs

Added support to create JWT in keycloak
Added support to configure ICS with JWT handling
Added support to configure auth with isto
Adapted test case to test ICS with auth

Issue-ID: NONRTRIC-738
Signed-off-by: BjornMagnussonXA <bjorn.magnusson@est.tech>
Change-Id: Ifc540778b84e5f4291876a90be78c838652ef8b3
diff --git a/test/common/api_curl.sh b/test/common/api_curl.sh
index e99f579..6058e08 100644
--- a/test/common/api_curl.sh
+++ b/test/common/api_curl.sh
@@ -159,12 +159,15 @@
         echo "-000"
         return 1
     fi
-
+	jwt=""
+	if [ ! -z "$KUBE_PROXY_CURL_JWT" ]; then
+		jwt=" -H "\""Authorization: Bearer $KUBE_PROXY_CURL_JWT"\"
+	fi
 	if [ $__ADAPTER_TYPE == "REST" ]; then
         url=" "${__ADAPTER}${input_url}
         oper=" -X "$oper
         curlString="curl -k $proxyflag "${oper}${timeout}${httpcode}${accept}${content}${url}${file}
-        echo " CMD: "$curlString >> $HTTPLOG
+        echo " CMD: $curlString $jwt" >> $HTTPLOG
 		if [ $# -gt 3 ]; then
 			echo " FILE: $(<$fname)" >> $HTTPLOG
 		fi
@@ -174,7 +177,11 @@
 		while [ $maxretries -ge 0 ]; do
 
 			let maxretries=maxretries-1
-			res=$($curlString)
+			if [ ! -z "$KUBE_PROXY_CURL_JWT" ]; then
+				res=$($curlString -H "Authorization: Bearer $KUBE_PROXY_CURL_JWT")
+			else
+				res=$($curlString)
+			fi
 			retcode=$?
 			if [ $retcode -ne 0 ]; then
 				echo " RETCODE: "$retcode >> $HTTPLOG
diff --git a/test/common/authsidecar_api_functions.sh b/test/common/authsidecar_api_functions.sh
new file mode 100644
index 0000000..594aa31
--- /dev/null
+++ b/test/common/authsidecar_api_functions.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# This is a script that contains container/service management functions
+# for AUTHSIDECAR
+
+################ Test engine functions ################
+
+# Create the image var used during the test
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__AUTHSIDECAR_imagesetup() {
+	__check_and_create_image_var AUTHSIDECAR "AUTHSIDECAR_IMAGE" "AUTHSIDECAR_IMAGE_BASE" "AUTHSIDECAR_IMAGE_TAG" $1 "$AUTHSIDECAR_DISPLAY_NAME"
+}
+
+# Pull image from remote repo or use locally built image
+# arg: <pull-policy-override> <pull-policy-original>
+# <pull-policy-override> Shall be used for images allowing overriding. For example use a local image when test is started to use released images
+# <pull-policy-original> Shall be used for images that does not allow overriding
+# Both var may contain: 'remote', 'remote-remove' or 'local'
+__AUTHSIDECAR_imagepull() {
+	__check_and_pull_image $1 "$AUTHSIDECAR_DISPLAY_NAME" $AUTHSIDECAR_APP_NAME AUTHSIDECAR_IMAGE
+}
+
+# Build image (only for simulator or interfaces stubs owned by the test environment)
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__AUTHSIDECAR_imagebuild() {
+	echo -e $RED"Image for app AUTHSIDECAR shall never be built"$ERED
+}
+
+# Generate a string for each included image using the app display name and a docker images format string
+# If a custom image repo is used then also the source image from the local repo is listed
+# arg: <docker-images-format-string> <file-to-append>
+__AUTHSIDECAR_image_data() {
+	echo -e "$AUTHSIDECAR_DISPLAY_NAME\t$(docker images --format $1 $AUTHSIDECAR_IMAGE)" >>   $2
+	if [ ! -z "$AUTHSIDECAR_IMAGE_SOURCE" ]; then
+		echo -e "-- source image --\t$(docker images --format $1 $AUTHSIDECAR_IMAGE_SOURCE)" >>   $2
+	fi
+}
+
+# Scale kubernetes resources to zero
+# All resources shall be ordered to be scaled to 0, if relevant. If not relevant to scale, then do no action.
+# This function is called for apps fully managed by the test script
+__AUTHSIDECAR_kube_scale_zero() {
+	:
+}
+
+# Scale kubernetes resources to zero and wait until this has been accomplished, if relevant. If not relevant to scale, then do no action.
+# This function is called for prestarted apps not managed by the test script.
+__AUTHSIDECAR_kube_scale_zero_and_wait() {
+	:
+}
+
+# Delete all kube resouces for the app
+# This function is called for apps managed by the test script.
+__AUTHSIDECAR_kube_delete_all() {
+	:
+}
+
+# Store docker logs
+# This function is called for apps managed by the test script.
+# args: <log-dir> <file-prexix>
+__AUTHSIDECAR_store_docker_logs() {
+	if [ $RUNMODE == "KUBE" ]; then
+		kubectl $KUBECONF  logs -l "autotest=AUTHSIDECAR" -A --tail=-1 > $1$2_authsidecar.log 2>&1
+	fi
+}
+
+# Initial setup of protocol, host and ports
+# This function is called for apps managed by the test script.
+# args: -
+__AUTHSIDECAR_initial_setup() {
+	:
+}
+
+# Set app short-name, app name and namespace for logging runtime statistics of kubernets pods or docker containers
+# For docker, the namespace shall be excluded
+# This function is called for apps managed by the test script as well as for prestarted apps.
+# args: -
+__AUTHSIDECAR_statisics_setup() {
+	echo ""
+}
+
+# Check application requirements, e.g. helm, the the test needs. Exit 1 if req not satisfied
+# args: -
+__AUTHSIDECAR_test_requirements() {
+	:
+}
+
+#######################################################
+
+# This app is intended as a sidecard container - no specific test functions
\ No newline at end of file
diff --git a/test/common/chartmus_api_functions.sh b/test/common/chartmus_api_functions.sh
index f7e268e..7c7a365 100644
--- a/test/common/chartmus_api_functions.sh
+++ b/test/common/chartmus_api_functions.sh
@@ -201,7 +201,7 @@
 
 		if [ $retcode_p -eq 0 ]; then
 			echo -e " Using existing $CHART_MUS_APP_NAME deployment and service"
-			echo " Setting RC replicas=1"
+			echo " Setting CHARTMUS replicas=1"
 			__kube_scale deployment $CHART_MUS_APP_NAME $KUBE_SIM_NAMESPACE 1
 		fi
 
diff --git a/test/common/clean_docker.sh b/test/common/clean_docker.sh
index 70e42da..7fe6c39 100755
--- a/test/common/clean_docker.sh
+++ b/test/common/clean_docker.sh
@@ -18,7 +18,7 @@
 
 # Script to clean all docker containers having the label 'nrttest_app', i.e started by autotest
 
-echo "Will stop and remove all docker containers with label 'nrttest_app'"
+echo "Stopping and removing all docker containers with label 'nrttest_app'"
 echo " Stopping containers..."
 docker stop $(docker ps -qa  --filter "label=nrttest_app") 2> /dev/null
 echo " Removing stopped containers..."
diff --git a/test/common/clean_kube.sh b/test/common/clean_kube.sh
index f25d52c..5997abc 100755
--- a/test/common/clean_kube.sh
+++ b/test/common/clean_kube.sh
@@ -86,7 +86,7 @@
 __kube_delete_all_resources() {
 	echo " Delete all in namespace $1 ..."
 	namespace=$1
-	resources="deployments replicaset statefulset services pods configmaps pvc serviceaccounts secrets"
+	resources="deployments replicaset statefulset services pods configmaps pvc serviceaccounts secrets authorizationpolicies requestauthentications"
 	for restype in $resources; do
 		result=$(kubectl $KUBECONF get $restype -n $namespace -o jsonpath='{.items[?(@.metadata.labels.autotest)].metadata.name}')
 		if [ $? -eq 0 ] && [ ! -z "$result" ]; then
diff --git a/test/common/ics_api_functions.sh b/test/common/ics_api_functions.sh
index 0df2ae4..2152de9 100644
--- a/test/common/ics_api_functions.sh
+++ b/test/common/ics_api_functions.sh
@@ -89,6 +89,7 @@
 # args: -
 __ICS_initial_setup() {
 	use_ics_rest_http
+	export ICS_SIDECAR_JWT_FILE=""
 }
 
 # Set app short-name, app name and namespace for logging runtime statistics of kubernets pods or docker containers
@@ -278,6 +279,10 @@
 			# Create app
 			input_yaml=$SIM_GROUP"/"$ICS_COMPOSE_DIR"/"app.yaml
 			output_yaml=$PWD/tmp/ics_app.yaml
+			if [ -z "$ICS_SIDECAR_JWT_FILE" ]; then
+				cat $input_yaml | sed  '/#ICS_JWT_START/,/#ICS_JWT_STOP/d' > $PWD/tmp/ics_app_tmp.yaml
+				input_yaml=$PWD/tmp/ics_app_tmp.yaml
+			fi
 			__kube_create_instance app $ICS_APP_NAME $input_yaml $output_yaml
 		fi
 
@@ -448,7 +453,7 @@
 # (Function for test scripts)
 set_ics_trace() {
 	echo -e $BOLD"Setting ics trace logging"$EBOLD
-	curlString="$ICS_SERVICE_PATH/actuator/loggers/org.oransc.information -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"trace\"}"
+	curlString="$ICS_SERVICE_PATH$ICS_ACTUATOR -X POST  -H Content-Type:application/json -d {\"configuredLevel\":\"trace\"}"
 	result=$(__do_curl "$curlString")
 	if [ $? -ne 0 ]; then
 		__print_err "Could not set trace mode" $@
@@ -2461,4 +2466,17 @@
 
 	__log_test_pass
 	return 0
+}
+
+# args: <realm> <client-name> <client-secret>
+ics_configure_sec() {
+	export ICS_CREDS_GRANT_TYPE="client_credentials"
+	export ICS_CREDS_CLIENT_SECRET=$3
+	export ICS_CREDS_CLIENT_ID=$2
+	export ICS_AUTH_SERVICE_URL=$KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$1/protocol/openid-connect/token
+	export ICS_SIDECAR_MOUNT="/token-cache"
+	export ICS_SIDECAR_JWT_FILE=$ICS_SIDECAR_MOUNT"/jwt.txt"
+
+	export AUTHSIDECAR_APP_NAME
+	export AUTHSIDECAR_DISPLAY_NAME
 }
\ No newline at end of file
diff --git a/test/common/istio_api_functions.sh b/test/common/istio_api_functions.sh
new file mode 100644
index 0000000..2afc3f9
--- /dev/null
+++ b/test/common/istio_api_functions.sh
@@ -0,0 +1,249 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2021 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# This is a script that contains function to handle helm on localhost
+
+
+################ Test engine functions ################
+
+# Create the image var used during the test
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__ISTIO_imagesetup() {
+	:
+}
+
+# Pull image from remote repo or use locally built image
+# arg: <pull-policy-override> <pull-policy-original>
+# <pull-policy-override> Shall be used for images allowing overriding. For example use a local image when test is started to use released images
+# <pull-policy-original> Shall be used for images that does not allow overriding
+# Both var may contain: 'remote', 'remote-remove' or 'local'
+__ISTIO_imagepull() {
+	:
+}
+
+# Build image (only for simulator or interfaces stubs owned by the test environment)
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__ISTIO_imagebuild() {
+	:
+}
+
+# Generate a string for each included image using the app display name and a docker images format string
+# If a custom image repo is used then also the source image from the local repo is listed
+# arg: <docker-images-format-string> <file-to-append>
+__ISTIO_image_data() {
+	:
+}
+
+# Scale kubernetes resources to zero
+# All resources shall be ordered to be scaled to 0, if relevant. If not relevant to scale, then do no action.
+# This function is called for apps fully managed by the test script
+__ISTIO_kube_scale_zero() {
+	:
+}
+
+# Scale kubernetes resources to zero and wait until this has been accomplished, if relevant. If not relevant to scale, then do no action.
+# This function is called for prestarted apps not managed by the test script.
+__ISTIO_kube_scale_zero_and_wait() {
+	:
+}
+
+# Delete all kube resouces for the app
+# This function is called for apps managed by the test script.
+__ISTIO_kube_delete_all() {
+	__kube_delete_all_resources $KUBE_NONRTRIC_NAMESPACE autotest ISTIO
+}
+
+# Store docker logs
+# This function is called for apps managed by the test script.
+# args: <log-dir> <file-prexix>
+__ISTIO_store_docker_logs() {
+	:
+}
+
+# Initial setup of protocol, host and ports
+# This function is called for apps managed by the test script.
+# args: -
+__ISTIO_initial_setup() {
+	# See jwt-info.txt in simulator-group/kubeproxy for detailed info
+	KUBE_PROXY_CURL_JWT=$ISTIO_GENERIC_JWT
+	KUBE_PROXY_ISTIO_JWKS_KEYS=$ISTIO_GENERIC_JWKS_KEY
+}
+
+# Set app short-name, app name and namespace for logging runtime statistics of kubernets pods or docker containers
+# For docker, the namespace shall be excluded
+# This function is called for apps managed by the test script as well as for prestarted apps.
+# args: -
+__ISTIO_statisics_setup() {
+	:
+}
+
+# Check application requirements, e.g. helm, the the test needs. Exit 1 if req not satisfied
+# args: -
+__ISTIO_test_requirements() {
+
+	kubectl $KUBECONF get requestauthentications -A &> /dev/null
+	if [ $? -ne 0 ]; then
+		echo $RED" Istio api: kubectl get requestauthentications is not installed"
+		exit 1
+	fi
+	kubectl $KUBECONF get authorizationpolicies -A &> /dev/null
+	if [ $? -ne 0 ]; then
+		echo $RED" Istio api: kubectl get authorizationpolicies is not installed"
+		exit 1
+	fi
+}
+
+#######################################################
+
+
+# Enable istio on namespace
+# arg: <namespace>
+istio_enable_istio_namespace() {
+	__log_conf_start $@
+    if [ $# -ne 1 ]; then
+        __print_err "<namespace>" $@
+        return 1
+    fi
+	__kube_create_namespace $1
+	__kube_label_non_ns_instance ns $1 "istio-injection=enabled"
+	__log_conf_ok
+	return 0
+}
+
+# Request authorization by jwksuri
+# args: <app> <namespace> <realm>
+istio_req_auth_by_jwksuri() {
+	__log_conf_start $@
+    if [ $# -ne 3 ]; then
+        __print_err "<app> <namespace> <realm>" $@
+        return 1
+    fi
+	name="ra-jwksuri-"$3"-"$1"-"$2
+	export  ISTIO_TEMPLATE_REPLACE_RA_NAME=$(echo $name | tr '[:upper:]' '[:lower:]')
+	export  ISTIO_TEMPLATE_REPLACE_RA_NS=$2
+	export  ISTIO_TEMPLATE_REPLACE_RA_APP_NAME=$1
+	export  ISTIO_TEMPLATE_REPLACE_RA_ISSUER=$KEYCLOAK_ISSUER_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$3
+	export  ISTIO_TEMPLATE_REPLACE_RA_JWKSURI=$KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$3/protocol/openid-connect/certs
+	inputfile=$SIM_GROUP/$ISTIO_COMPOSE_DIR/ra-jwksuri-template.yaml
+	outputfile=tmp/$ISTIO_TEMPLATE_REPLACE_RA_NAME".yaml"
+	envsubst < $inputfile > $outputfile
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot substitute yaml: $inputfile"
+		return 1
+	fi
+	kubectl $KUBECONF apply -f $outputfile &> tmp/kubeerr
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot apply yaml: $outputfile"
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+# Request authorization by jwks (inline keys)
+# args: <app> <namespace> <issuer> <key>
+istio_req_auth_by_jwks() {
+	__log_conf_start $@
+    if [ $# -ne 4 ]; then
+        __print_err "<app> <namespace> <issuer> <key>" $@
+        return 1
+    fi
+	name="ra-jwks-"$3"-"$1"-"$2
+	export  ISTIO_TEMPLATE_REPLACE_RA_NAME=$(echo $name | tr '[:upper:]' '[:lower:]')
+	export  ISTIO_TEMPLATE_REPLACE_RA_NS=$2
+	export  ISTIO_TEMPLATE_REPLACE_RA_APP_NAME=$1
+	export  ISTIO_TEMPLATE_REPLACE_RA_ISSUER=$3
+	export  ISTIO_TEMPLATE_REPLACE_RA_JWKS=$4
+	inputfile=$SIM_GROUP/$ISTIO_COMPOSE_DIR/ra-jwks-template.yaml
+	outputfile=tmp/$ISTIO_TEMPLATE_REPLACE_RA_NAME".yaml"
+	envsubst < $inputfile > $outputfile
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot substitute yaml: $inputfile"
+		return 1
+	fi
+	kubectl $KUBECONF apply -f $outputfile &> tmp/kubeerr
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot apply yaml: $outputfile"
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+# Authorization policy - by realm
+# args: <app> <namespace> <realam>
+istio_auth_policy_by_realm() {
+	__log_conf_start $@
+    if [ $# -ne 3 ]; then
+        __print_err "<app> <namespace> <realam>" $@
+        return 1
+    fi
+	name="ap-realm-"$3"-"$1"-"$2
+	export  ISTIO_TEMPLATE_REPLACE_AP_NAME=$(echo $name | tr '[:upper:]' '[:lower:]')
+	export  ISTIO_TEMPLATE_REPLACE_AP_NS=$2
+	export  ISTIO_TEMPLATE_REPLACE_AP_APP_NAME=$1
+	export  ISTIO_TEMPLATE_REPLACE_AP_PRINCIPAL="$KEYCLOAK_ISSUER_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$3/*"
+	inputfile=$SIM_GROUP/$ISTIO_COMPOSE_DIR/ap-principal-template.yaml
+	outputfile=tmp/$ISTIO_TEMPLATE_REPLACE_AP_NAME".yaml"
+	envsubst < $inputfile > $outputfile
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot substitute yaml: $inputfile"
+		return 1
+	fi
+	kubectl $KUBECONF apply -f $outputfile &> tmp/kubeerr
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot apply yaml: $outputfile"
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+# Authorization policy - by issuer
+# args: <app> <namespace> <issuer>
+istio_auth_policy_by_issuer() {
+	__log_conf_start $@
+    if [ $# -ne 3 ]; then
+        __print_err "<app> <namespace> <issuer>" $@
+        return 1
+    fi
+	name="ap-iss-"$3"-"$1"-"$2
+	export  ISTIO_TEMPLATE_REPLACE_AP_NAME=$(echo $name | tr '[:upper:]' '[:lower:]')
+	export  ISTIO_TEMPLATE_REPLACE_AP_NS=$2
+	export  ISTIO_TEMPLATE_REPLACE_AP_APP_NAME=$1
+	export  ISTIO_TEMPLATE_REPLACE_AP_PRINCIPAL="$3/*"
+	inputfile=$SIM_GROUP/$ISTIO_COMPOSE_DIR/ap-principal-template.yaml
+	outputfile=tmp/$ISTIO_TEMPLATE_REPLACE_AP_NAME".yaml"
+	envsubst < $inputfile > $outputfile
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot substitute yaml: $inputfile"
+		return 1
+	fi
+	kubectl $KUBECONF apply -f $outputfile &> tmp/kubeerr
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general "Cannot apply yaml: $outputfile"
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+
diff --git a/test/common/keycloak_api_functions.sh b/test/common/keycloak_api_functions.sh
new file mode 100644
index 0000000..828dcb3
--- /dev/null
+++ b/test/common/keycloak_api_functions.sh
@@ -0,0 +1,616 @@
+#!/bin/bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2021 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# This is a script that contains container/service management functions and test functions for Keycloak
+
+
+################ Test engine functions ################
+
+# Create the image var used during the test
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__KEYCLOAK_imagesetup() {
+	__check_and_create_image_var KEYCLOAK "KEYCLOAK_IMAGE" "KEYCLOAK_IMAGE_BASE" "KEYCLOAK_IMAGE_TAG" REMOTE_OTHER "$KEYCLOAK_DISPLAY_NAME"
+}
+
+# Pull image from remote repo or use locally built image
+# arg: <pull-policy-override> <pull-policy-original>
+# <pull-policy-override> Shall be used for images allowing overriding. For example use a local image when test is started to use released images
+# <pull-policy-original> Shall be used for images that does not allow overriding
+# Both var may contain: 'remote', 'remote-remove' or 'local'
+__KEYCLOAK_imagepull() {
+	__check_and_pull_image $2 "$KEYCLOAK_DISPLAY_NAME" $KEYCLOAK_APP_NAME KEYCLOAK_IMAGE
+}
+
+# Build image (only for simulator or interfaces stubs owned by the test environment)
+# arg: <image-tag-suffix> (selects staging, snapshot, release etc)
+# <image-tag-suffix> is present only for images with staging, snapshot,release tags
+__KEYCLOAK_imagebuild() {
+	echo -e $RED" Image for app KEYCLOAK shall never be built"$ERED
+}
+
+# Generate a string for each included image using the app display name and a docker images format string
+# If a custom image repo is used then also the source image from the local repo is listed
+# arg: <docker-images-format-string> <file-to-append>
+__KEYCLOAK_image_data() {
+	echo -e "$KEYCLOAK_DISPLAY_NAME\t$(docker images --format $1 $KEYCLOAK_IMAGE)" >>   $2
+	if [ ! -z "$KEYCLOAK_IMAGE_SOURCE" ]; then
+		echo -e "-- source image --\t$(docker images --format $1 $KEYCLOAK_IMAGE_SOURCE)" >>   $2
+	fi
+}
+
+# Scale kubernetes resources to zero
+# All resources shall be ordered to be scaled to 0, if relevant. If not relevant to scale, then do no action.
+# This function is called for apps fully managed by the test script
+__KEYCLOAK_kube_scale_zero() {
+	__kube_scale_all_resources $KUBE_KEYCLOAK_NAMESPACE autotest KEYCLOAK
+}
+
+# Scale kubernetes resources to zero and wait until this has been accomplished, if relevant. If not relevant to scale, then do no action.
+# This function is called for prestarted apps not managed by the test script.
+__KEYCLOAK_kube_scale_zero_and_wait() {
+	echo -e $RED" KEYCLOAK app is not scaled in this state"$ERED
+}
+
+# Delete all kube resouces for the app
+# This function is called for apps managed by the test script.
+__KEYCLOAK_kube_delete_all() {
+	__kube_delete_all_resources $KUBE_KEYCLOAK_NAMESPACE autotest KEYCLOAK
+}
+
+# Store docker logs
+# This function is called for apps managed by the test script.
+# args: <log-dir> <file-prexix>
+__KEYCLOAK_store_docker_logs() {
+	if [ $RUNMODE == "KUBE" ]; then
+		kubectl $KUBECONF  logs -l "autotest=KEYCLOAK" -n $KUBE_KEYCLOAK_NAMESPACE --tail=-1 > $1$2_keycloak.log 2>&1
+	else
+		docker logs $KEYCLOAK_APP_NAME > $1$2_keycloak.log 2>&1
+	fi
+}
+
+# Initial setup of protocol, host and ports
+# This function is called for apps managed by the test script.
+# args: -
+__KEYCLOAK_initial_setup() {
+	use_keycloak_http
+}
+
+# Set app short-name, app name and namespace for logging runtime statistics of kubernets pods or docker containers
+# For docker, the namespace shall be excluded
+# This function is called for apps managed by the test script as well as for prestarted apps.
+# args: -
+__KEYCLOAK_statisics_setup() {
+	if [ $RUNMODE == "KUBE" ]; then
+		echo "KEYCLOAK $KEYCLOAK_APP_NAME $KUBE_KEYCLOAK_NAMESPACE"
+	else
+		echo "KEYCLOAK $KEYCLOAK_APP_NAME"
+	fi
+}
+
+# Check application requirements, e.g. helm, the the test needs. Exit 1 if req not satisfied
+# args: -
+__KEYCLOAK_test_requirements() {
+	which jq > /dev/null
+	if [ $? -ne 0 ]; then
+		echo $RED" 'jq' is required to run tests. Pls install 'jq'"
+		return 1
+	fi
+}
+
+#######################################################
+
+# Set http as the protocol to use for all communication to the Keycloak
+# args: -
+# (Function for test scripts)
+use_keycloak_http() {
+	__keycloak_set_protocoll "http" $KEYCLOAK_INTERNAL_PORT $KEYCLOAK_EXTERNAL_PORT
+}
+
+# Set https as the protocol to use for all communication to the Keycloak
+# args: -
+# (Function for test scripts)
+use_keycloak_https() {
+	__keycloak_set_protocoll "https" $KEYCLOAK_INTERNAL_SECURE_PORT $KEYCLOAK_EXTERNAL_SECURE_PORT
+}
+
+# Setup paths to svc/container for internal and external access
+# args: <protocol> <internal-port> <external-port>
+__keycloak_set_protocoll() {
+	echo -e $BOLD"$KEYCLOAK_DISPLAY_NAME protocol setting"$EBOLD
+	echo -e " Using $BOLD $1 $EBOLD towards $KEYCLOAK_DISPLAY_NAME"
+
+	## Access to Keycloak
+
+	KEYCLOAK_SERVICE_PATH=$1"://"$KEYCLOAK_APP_NAME":"$2  # docker access, container->container and script->container via proxy
+	KEYCLOAK_SERVICE_PORT=$2
+	KEYCLOAK_SERVICE_HOST=$KEYCLOAK_APP_NAME
+	KEYCLOAK_ISSUER_PATH=$1"://"$KEYCLOAK_APP_NAME
+	if [ $RUNMODE == "KUBE" ]; then
+		KEYCLOAK_SERVICE_PATH=$1"://"$KEYCLOAK_APP_NAME.$KUBE_KEYCLOAK_NAMESPACE":"$3 # kube access, pod->svc and script->svc via proxy
+		KEYCLOAK_SERVICE_PORT=$3
+		KEYCLOAK_SERVICE_HOST=$KEYCLOAK_APP_NAME.$KUBE_KEYCLOAK_NAMESPACE
+		KEYCLOAK_ISSUER_PATH=$1"://"$KEYCLOAK_APP_NAME.$KUBE_KEYCLOAK_NAMESPACE
+	fi
+	KEYCLOAK_SERVICE_HTTPX=$1
+
+	echo ""
+}
+
+### Admin API functions Keycloak
+
+###########################
+### Keycloak functions
+###########################
+
+# Export env vars for config files, docker compose and kube resources
+# args:
+__keycloak_export_vars() {
+	export KEYCLOAK_APP_NAME
+	export KEYCLOAK_DISPLAY_NAME
+
+	export DOCKER_SIM_NWNAME
+	export KUBE_KEYCLOAK_NAMESPACE
+
+	export KEYCLOAK_IMAGE
+	export KEYCLOAK_INTERNAL_PORT
+	export KEYCLOAK_EXTERNAL_PORT
+
+	export KEYCLOAK_ADMIN_USER
+	export KEYCLOAK_ADMIN_PWD
+	export KEYCLOAK_KC_PROXY
+}
+
+
+# Start the Keycloak in the simulator group
+# args: -
+# (Function for test scripts)
+start_keycloak() {
+
+	echo -e $BOLD"Starting $KEYCLOAK_DISPLAY_NAME"$EBOLD
+
+	if [ $RUNMODE == "KUBE" ]; then
+
+		# Check if app shall be fully managed by the test script
+		__check_included_image "KEYCLOAK"
+		retcode_i=$?
+
+		# Check if app shall only be used by the testscipt
+		__check_prestarted_image "KEYCLOAK"
+		retcode_p=$?
+
+		if [ $retcode_i -ne 0 ] && [ $retcode_p -ne 0 ]; then
+			echo -e $RED"The $KEYCLOAK_NAME app is not included as managed nor prestarted in this test script"$ERED
+			echo -e $RED"The $KEYCLOAK_APP_NAME will not be started"$ERED
+			exit
+		fi
+		if [ $retcode_i -eq 0 ] && [ $retcode_p -eq 0 ]; then
+			echo -e $RED"The $KEYCLOAK_APP_NAME app is included both as managed and prestarted in this test script"$ERED
+			echo -e $RED"The $KEYCLOAK_APP_NAME will not be started"$ERED
+			exit
+		fi
+
+		if [ $retcode_p -eq 0 ]; then
+			echo -e " Using existing $KEYCLOAK_APP_NAME deployment and service"
+			echo " Setting keycloak replicas=1"
+			__kube_scale deployment $KEYCLOAK_APP_NAME $KUBE_KEYCLOAK_NAMESPACE 1
+		fi
+
+		if [ $retcode_i -eq 0 ]; then
+			echo -e " Creating $KEYCLOAK_APP_NAME deployment and service"
+
+            __kube_create_namespace $KUBE_KEYCLOAK_NAMESPACE
+
+			__keycloak_export_vars
+
+			# Create service and app
+			input_yaml=$SIM_GROUP"/"$KEYCLOAK_COMPOSE_DIR"/"svc_app.yaml
+			output_yaml=$PWD/tmp/keycloak_svc_app.yaml
+			__kube_create_instance "service/app" $KEYCLOAK_APP_NAME $input_yaml $output_yaml
+
+		fi
+
+		__check_service_start $KEYCLOAK_APP_NAME $KEYCLOAK_SERVICE_PATH$KEYCLOAK_ALIVE_URL
+	else
+
+		# Check if docker app shall be fully managed by the test script
+		__check_included_image 'KEYCLOAK'
+		if [ $? -eq 1 ]; then
+			echo -e $RED"The Keycloak app is not included as managed in this test script"$ERED
+			echo -e $RED"The Keycloak will not be started"$ERED
+			exit
+		fi
+
+		__keycloak_export_vars
+
+		__start_container $KEYCLOAK_COMPOSE_DIR "" NODOCKERARGS 1 $KEYCLOAK_APP_NAME
+
+        __check_service_start $KEYCLOAK_APP_NAME $KEYCLOAK_SERVICE_PATH$KEYCLOAK_ALIVE_URL
+	fi
+    echo ""
+    return 0
+}
+
+# Excute a curl cmd towards the keycloak and check the response code is 2XX.
+# args: <curl-cmd-string>
+# resp: <returned-payload> if return code is 0 otherwise <error-info>
+__execute_curl_to_keycloak() {
+
+	proxyflag=""
+	if [ ! -z "$KUBE_PROXY_PATH" ]; then
+		if [ $KUBE_PROXY_HTTPX == "http" ]; then
+			proxyflag=" --proxy $KUBE_PROXY_PATH"
+		else
+			proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
+		fi
+	fi
+	__cmd="curl -skw %{http_code} $proxyflag $1"
+	echo " CMD: $__cmd" >> $HTTPLOG
+	res=$($__cmd)
+	echo " RESP: $res" >> $HTTPLOG
+	retcode=$?
+    if [ $retcode -ne 0 ]; then
+        __log_conf_fail_general " Fatal error when executing curl, response: "$retcode
+        echo "$res"
+		return 1
+    fi
+    status=${res:${#res}-3}
+	if [ $status -lt 200 ] && [ $status -gt 299 ]; then
+		__log_conf_fail_status_code "2XX" $status
+		echo "$res"
+		return 1
+	fi
+	echo ${res:0:${#res}-3}
+	return 0
+}
+
+# # Excute a curl cmd towards the keycloak and check the response code is 2XX.
+# # args: <command-file>
+# # resp: <returned-payload> if return code is 0 otherwise <error-info>
+# __execute_curl_to_keycloak2() {
+
+#     # TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
+#     # echo "(${BASH_LINENO[0]}) - ${TIMESTAMP}: ${FUNCNAME[0]}" $@ >> $HTTPLOG
+# 	proxyflag=""
+# 	if [ ! -z "$KUBE_PROXY_PATH" ]; then
+# 		if [ $KUBE_PROXY_HTTPX == "http" ]; then
+# 			proxyflag=" --proxy $KUBE_PROXY_PATH"
+# 		else
+# 			proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
+# 		fi
+# 	fi
+# 	__cmd="curl -skw %{http_code} $proxyflag "$(< $1)
+# 	echo " CMD: $__cmd" >> $HTTPLOG
+# 	res=$(curl -skw %{http_code} $proxyflag $(< $1))
+# 	echo " RESP: $res" >> $HTTPLOG
+# 	retcode=$?
+#     if [ $retcode -ne 0 ]; then
+#         __log_conf_fail_general " Fatal error when executing curl, response: "$retcode
+#         echo "$res"
+# 		return 1
+#     fi
+#     status=${res:${#res}-3}
+# 	if [ $status -lt 200 ] && [ $status -gt 299 ]; then
+# 		__log_conf_fail_status_code "2XX" $status
+# 		echo "$res"
+# 		return 1
+# 	fi
+# 	echo ${res:0:${#res}-3}
+# 	return 0
+# }
+
+# Excute a curl cmd towards the keycloak and check the response code is 2XX.
+# args: <operation> <url> <token> <json>
+# resp: <returned-payload> if return code is 0 otherwise <error-info>
+__execute_curl_to_keycloak2() {
+	proxyflag=""
+	if [ ! -z "$KUBE_PROXY_PATH" ]; then
+		if [ $KUBE_PROXY_HTTPX == "http" ]; then
+			proxyflag=" --proxy $KUBE_PROXY_PATH"
+		else
+			proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
+		fi
+	fi
+	if [ $1 == "POST" ]; then
+		if [ $# -eq 3 ]; then
+			echo  curl -X POST -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3" >> $HTTPLOG
+			res=$(curl -X POST -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3")
+			retcode=$?
+		else
+			echo  curl -X POST -skw %{http_code} $proxyflag "$2" -H "Content-Type: application/json" -H "Authorization: Bearer $3" --data-binary "$4" >> $HTTPLOG
+			res=$(curl -X POST -skw %{http_code} $proxyflag "$2" -H "Content-Type: application/json" -H "Authorization: Bearer $3" --data-binary "$4")
+			retcode=$?
+		fi
+	elif [ $1 == "PUT" ]; then
+		if [ $# -eq 3 ]; then
+			echo  curl -X PUT -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3" >> $HTTPLOG
+			res=$(curl -X PUT -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3")
+			retcode=$?
+		else
+			echo  curl -X PUT -skw %{http_code} $proxyflag "$2" -H "Content-Type: application/json" -H "Authorization: Bearer $3" --data-binary "$4" >> $HTTPLOG
+			res=$(curl -X PUT -skw %{http_code} $proxyflag "$2" -H "Content-Type: application/json" -H "Authorization: Bearer $3" --data-binary "$4")
+			retcode=$?
+		fi
+	elif [ $1 == "GET" ]; then
+		echo  curl -X GET -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3" >> $HTTPLOG
+		res=$(curl -X GET -skw %{http_code} $proxyflag "$2" -H "Authorization: Bearer $3")
+		retcode=$?
+	fi
+	echo " RESP: $res" >> $HTTPLOG
+    if [ $retcode -ne 0 ]; then
+        __log_conf_fail_general " Fatal error when executing curl, response: "$retcode
+        echo "$res"
+		return 1
+    fi
+    status=${res:${#res}-3}
+	if [ $status -lt 200 ] && [ $status -gt 299 ]; then
+		__log_conf_fail_status_code "2XX" $status
+		echo "$res"
+		return 1
+	fi
+	echo ${res:0:${#res}-3}
+	return 0
+}
+
+# Extract JWT access token from json structure
+# args: <json>
+__keycloak_decode_jwt() {
+    echo $1 | jq -r .access_token | jq -R 'split(".") | .[1] | @base64d | fromjson'
+	return 0
+}
+
+# Get the admin token to use for subsequent rest calls to keycloak
+# args: -
+keycloak_api_obtain_admin_token() {
+	__log_conf_start $@
+	__curl_string="-X POST $KEYCLOAK_SERVICE_PATH$KEYCLOAK_ADMIN_URL_PREFIX/protocol/openid-connect/token     -H Content-Type:application/x-www-form-urlencoded     -d username="$KEYCLOAK_ADMIN_USER" -d password="$KEYCLOAK_ADMIN_PWD" -d grant_type=password -d client_id="$KEYCLOAK_ADMIN_CLIENT
+	__TMP_TOKEN=$(__execute_curl_to_keycloak "$__curl_string")
+	if [ $? -ne 0 ]; then
+        __log_conf_fail_general " Fatal error when executing curl, response: "$?
+        return 1
+	fi
+
+	__KEYCLOAK_ADMIN_TOKEN=$(echo "$__TMP_TOKEN" | jq  -r '.access_token')
+	if [ $? -ne 0 ]; then
+        __log_conf_fail_general " Fatal error when extracting token, response: "$?
+        return 1
+	fi
+
+	echo "Decoded token:" >> $HTTPLOG
+	__keycloak_decode_jwt "$__TMP_TOKEN" >> $HTTPLOG
+
+	__KEYCLOAK_ADMIN_TOKEN_EXP=$(echo "$__TMP_TOKEN" | jq  -r '.expires_in')
+	if [ $? -ne 0 ]; then
+        __log_conf_fail_general " Fatal error when extracting expiry time, response: "$?
+        return 1
+	fi
+	echo " Admin token obtained. Expires in $__KEYCLOAK_ADMIN_TOKEN_EXP seconds"
+
+	__log_conf_ok
+	return 0
+}
+
+# Create a realm, name, enabled, expiry-time
+# args: <realm-name> true|false <token-expiry>
+keycloak_api_create_realm() {
+	__log_conf_start $@
+	__json='{"realm":"'$1'","enabled":'$2',"accessTokenLifespan":'$3'}'
+	res=$(__execute_curl_to_keycloak2 POST "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX" "$__KEYCLOAK_ADMIN_TOKEN" "$__json")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when creating realm, response: "$?
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+# Update a realm, name, enabled, expiry-time
+# args: <realm-name> true|false <token-expiry>
+keycloak_api_update_realm() {
+	__log_conf_start $@
+	__json='{"realm":"'$1'","enabled":'$2',"accessTokenLifespan":'$3'}'
+	res=$(__execute_curl_to_keycloak2 PUT "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1" "$__KEYCLOAK_ADMIN_TOKEN" "$__json")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when updating realm, response: "$?
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+# Create a client
+# args: <realm-name> <client-name>
+keycloak_api_create_confidential_client() {
+	__log_conf_start $@
+	__json='{"clientId":"'$2'","publicClient":false,"serviceAccountsEnabled": true,"rootUrl":"https://example.com/example/","adminUrl":"https://example.com/example/"}'
+	res=$(__execute_curl_to_keycloak2 POST "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients" "$__KEYCLOAK_ADMIN_TOKEN" "$__json")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when ucreating client, response: "$?
+		return 1
+	fi
+	__log_conf_ok
+	return 0
+}
+
+__keycloak_api_get_client_id() {
+	TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
+	echo "(${BASH_LINENO[0]}) - ${TIMESTAMP}: ${FUNCNAME[0]}" $@ >> $HTTPLOG
+
+	res=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients?clientId=$2" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+	echo $res | jq -r '.[0].id'
+	return 0
+}
+
+__keycloak_api_get_service_account_id() {
+	TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
+	echo "(${BASH_LINENO[0]}) - ${TIMESTAMP}: ${FUNCNAME[0]}" $@ >> $HTTPLOG
+
+	res=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients$2/service-account-user" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+	echo $res | jq -r '.[0].id'
+	return 0
+}
+
+# Generate secret for client
+# args: <realm-name> <client-name>
+keycloak_api_generate_client_secret() {
+	__log_conf_start $@
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client id, response: "$?
+		return 1
+	fi
+	res=$(__execute_curl_to_keycloak2 POST "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when generating client secret, response: "$?
+		return 1
+	fi
+	__c_sec=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client secret, response: "$?
+		return 1
+	fi
+	__c_sec=$(echo $__c_sec | jq -r .value)
+	echo " Client id    : $__c_id"
+	echo " Client secret: $__c_sec"
+	__log_conf_ok
+	return 0
+}
+
+# Get secret for client
+# args: <realm-name> <client-name>
+keycloak_api_get_client_secret() {
+	__log_conf_start $@
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client id, response: "$?
+		return 1
+	fi
+	__c_sec=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client secret, response: "$?
+		return 1
+	fi
+	__c_sec=$(echo $__c_sec | jq -r .value)
+	echo " Client id    : $__c_id"
+	echo " Client secret: $__c_sec"
+	__log_conf_ok
+	return 0
+}
+
+# Create client roles
+# args: <realm-name> <client-name> <role>+
+keycloak_api_create_client_roles() {
+	__log_conf_start $@
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client id, response: "$?
+		return 1
+	fi
+	__realm=$1
+	shift; shift;
+    while [ $# -gt 0 ]; do
+		__json='{"name":"'$1'"}'
+		res=$(__execute_curl_to_keycloak2 POST "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$__realm/clients/$__c_id/roles" "$__KEYCLOAK_ADMIN_TOKEN" "$__json")
+		if [ $? -ne 0 ]; then
+			__log_conf_fail_general " Fatal error when creating client role, response: "$?
+			return 1
+		fi
+		shift
+	done
+	__log_conf_ok
+	return 0
+}
+
+# Get a client token
+# args: <realm-name> <client-name>
+keycloak_api_get_client_token() {
+	__log_conf_start $@
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client id, response: "$?
+		return 1
+	fi
+	__c_sec=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client secret, response: "$?
+		return 1
+	fi
+	__c_sec=$(echo $__c_sec | jq -r .value)
+	__curl_string="-X POST $KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$1/protocol/openid-connect/token     -H Content-Type:application/x-www-form-urlencoded     -d client_id="$2" -d client_secret="$__c_sec" -d grant_type=client_credentials"
+	__TMP_TOKEN=$(__execute_curl_to_keycloak "$__curl_string")
+	if [ $? -ne 0 ]; then
+		__log_conf_fail_general " Fatal error when getting client token, response: "$?
+		return 1
+	fi
+	echo $__TMP_TOKEN| jq -r .access_token
+	__log_conf_ok
+	return 0
+}
+
+# Read a client token
+# args: <realm-name> <client-name>
+keycloak_api_read_client_token() {
+	TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
+	echo "(${BASH_LINENO[0]}) - ${TIMESTAMP}: ${FUNCNAME[0]}" $@ >> $HTTPLOG
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		echo "<error-no-token>"
+		return 1
+	fi
+	__c_sec=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		echo "<error-no-token>"
+		return 1
+	fi
+	__c_sec=$(echo $__c_sec | jq -r .value)
+	__curl_string="-X POST $KEYCLOAK_SERVICE_PATH$KEYCLOAK_TOKEN_URL_PREFIX/$1/protocol/openid-connect/token     -H Content-Type:application/x-www-form-urlencoded     -d client_id="$2" -d client_secret="$__c_sec" -d grant_type=client_credentials"
+	__TMP_TOKEN=$(__execute_curl_to_keycloak "$__curl_string")
+	if [ $? -ne 0 ]; then
+		echo "<error-no-token>"
+		return 1
+	fi
+	echo $__TMP_TOKEN| jq -r .access_token
+	return 0
+}
+
+# Read secret for client
+# args: <realm-name> <client-name>
+keycloak_api_read_client_secret() {
+	TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
+	echo "(${BASH_LINENO[0]}) - ${TIMESTAMP}: ${FUNCNAME[0]}" $@ >> $HTTPLOG
+	__c_id=$(__keycloak_api_get_client_id $1 $2)
+	if [ $? -ne 0 ]; then
+		echo "<error-no-secret>"
+		return 1
+	fi
+	__c_sec=$(__execute_curl_to_keycloak2 GET "$KEYCLOAK_SERVICE_PATH$KEYCLOAK_REALM_URL_PREFIX/$1/clients/$__c_id/client-secret" "$__KEYCLOAK_ADMIN_TOKEN")
+	if [ $? -ne 0 ]; then
+		echo "<error-no-secret>"
+		return 1
+	fi
+	__c_sec=$(echo $__c_sec | jq -r .value)
+	echo $__c_sec
+	return 0
+}
\ No newline at end of file
diff --git a/test/common/kubeproxy_api_functions.sh b/test/common/kubeproxy_api_functions.sh
index 120fbb6..c66e63c 100644
--- a/test/common/kubeproxy_api_functions.sh
+++ b/test/common/kubeproxy_api_functions.sh
@@ -393,3 +393,4 @@
 	echo ""
 	return 0
 }
+
diff --git a/test/common/prodstub_api_functions.sh b/test/common/prodstub_api_functions.sh
index 9af00d8..7dbef77 100644
--- a/test/common/prodstub_api_functions.sh
+++ b/test/common/prodstub_api_functions.sh
@@ -274,8 +274,14 @@
 			proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
 		fi
 	fi
-	echo " CMD: $3 $proxyflag" >> $HTTPLOG
-	res="$($3 $proxyflag)"
+	if [ ! -z "$KUBE_PROXY_CURL_JWT" ]; then
+		jwt="-H "\""Authorization: Bearer $KUBE_PROXY_CURL_JWT"\"
+		echo " CMD: $3 $proxyflag $jwt" >> $HTTPLOG
+		res=$($3 $proxyflag -H "Authorization: Bearer $KUBE_PROXY_CURL_JWT")
+	else
+		echo " CMD: $3 $proxyflag" >> $HTTPLOG
+		res="$($3 $proxyflag)"
+	fi
 	echo " RESP: $res" >> $HTTPLOG
 	retcode=$?
     if [ $retcode -ne 0 ]; then
diff --git a/test/common/pvccleaner_api_functions.sh b/test/common/pvccleaner_api_functions.sh
index 26bee7b..4ffb522 100644
--- a/test/common/pvccleaner_api_functions.sh
+++ b/test/common/pvccleaner_api_functions.sh
@@ -79,7 +79,7 @@
 # args: <log-dir> <file-prexix>
 __PVCCLEANER_store_docker_logs() {
 	if [ $RUNMODE == "KUBE" ]; then
-		kubectl $KUBECONF  logs -l "autotest=PRODSTUB" -A --tail=-1 > $1$2_pvs_cleaner.log 2>&1
+		kubectl $KUBECONF  logs -l "autotest=PVCCLEANER" -A --tail=-1 > $1$2_pvs_cleaner.log 2>&1
 	fi
 }
 
diff --git a/test/common/ricsim_api_functions.sh b/test/common/ricsim_api_functions.sh
index 4623563..b8af532 100644
--- a/test/common/ricsim_api_functions.sh
+++ b/test/common/ricsim_api_functions.sh
@@ -241,7 +241,7 @@
 			export RIC_SIM_INTERNAL_PORT
 			export RIC_SIM_INTERNAL_SECURE_PORT
 
-			echo -e " Creating $A1PMS_APP_NAME app and expose service"
+			echo -e " Creating $RIC_SIM_PREFIX app and expose service"
 
 			#Check if nonrtric namespace exists, if not create it
 			__kube_create_namespace $KUBE_A1SIM_NAMESPACE
diff --git a/test/common/test_env-onap-jakarta.sh b/test/common/test_env-onap-jakarta.sh
index 0824cc1..33ac6ac 100644
--- a/test/common/test_env-onap-jakarta.sh
+++ b/test/common/test_env-onap-jakarta.sh
@@ -215,7 +215,7 @@
 ICS_APP_NAME_ALIAS="information-service-container"       # Alias name, name used by the control panel
 ICS_HOST_MNT_DIR="./mnt"                                 # Mounted dir, relative to compose file, on the host
 ICS_CONTAINER_MNT_DIR="/var/information-coordinator-service" # Mounted dir in the container
-ICS_ACTUATOR="/actuator/loggers/org.oransc.information"  # Url for trace/debug
+ICS_ACTUATOR="/actuator/loggers/org.oransc.ics"          # Url for trace/debug
 ICS_CERT_MOUNT_DIR="./cert"
 ICS_ALIVE_URL="/status"                                  # Base path for alive check
 ICS_COMPOSE_DIR="ics"                                    # Dir in simulator_group for docker-compose
diff --git a/test/common/test_env-oran-e-release.sh b/test/common/test_env-oran-e-release.sh
index dbddca1..4e57ac5 100755
--- a/test/common/test_env-oran-e-release.sh
+++ b/test/common/test_env-oran-e-release.sh
@@ -214,7 +214,7 @@
 KAFKAPC_IMAGE_TAG_LOCAL="latest"
 #No local image for pvc cleaner, remote image always used
 
-#PVC Cleaner remote image and tag
+#Chartmusem remote image and tag
 CHART_MUS_IMAGE_BASE="ghcr.io/helm/chartmuseum"
 CHART_MUS_IMAGE_TAG_REMOTE_OTHER="v0.13.1"
 #No local image for chart museum, remote image always used
@@ -290,7 +290,7 @@
 ICS_APP_NAME_ALIAS="information-service-container"       # Alias name, name used by the control panel
 ICS_HOST_MNT_DIR="./mnt"                                 # Mounted db dir, relative to compose file, on the host
 ICS_CONTAINER_MNT_DIR="/var/information-coordinator-service" # Mounted dir in the container
-ICS_ACTUATOR="/actuator/loggers/org.oransc.information"  # Url for trace/debug
+ICS_ACTUATOR="/actuator/loggers/org.oransc.ics"          # Url for trace/debug
 ICS_CERT_MOUNT_DIR="./cert"
 ICS_ALIVE_URL="/status"                                  # Base path for alive check
 ICS_COMPOSE_DIR="ics"                                    # Dir in simulator_group for docker-compose
diff --git a/test/common/test_env-oran-f-release.sh b/test/common/test_env-oran-f-release.sh
index eb26634..4beddd1 100755
--- a/test/common/test_env-oran-f-release.sh
+++ b/test/common/test_env-oran-f-release.sh
@@ -150,6 +150,13 @@
 HELM_MANAGER_IMAGE_TAG_REMOTE="1.2.0"
 HELM_MANAGER_IMAGE_TAG_REMOTE_RELEASE="1.2.0"
 
+# Auth sidecar
+AUTHSIDECAR_IMAGE_BASE="o-ran-sc/nonrtric-auth-token-fetch"
+AUTHSIDECAR_IMAGE_TAG_LOCAL="1.0.0-SNAPSHOT"
+AUTHSIDECAR_IMAGE_TAG_REMOTE_SNAPSHOT="1.0.0-SNAPSHOT"
+AUTHSIDECAR_IMAGE_TAG_REMOTE="1.0.0"
+AUTHSIDECAR_IMAGE_TAG_REMOTE_RELEASE="1.0.0"
+
 #MR stub image and tag
 MRSTUB_IMAGE_BASE="mrstub"
 MRSTUB_IMAGE_TAG_LOCAL="latest"
@@ -202,13 +209,18 @@
 KAFKAPC_IMAGE_TAG_LOCAL="latest"
 #No local image for pvc cleaner, remote image always used
 
-#PVC Cleaner remote image and tag
+#Chartmusem remote image and tag
 CHART_MUS_IMAGE_BASE="ghcr.io/helm/chartmuseum"
 CHART_MUS_IMAGE_TAG_REMOTE_OTHER="v0.13.1"
 #No local image for chart museum, remote image always used
 
+#Keycloak remote image and tag
+KEYCLOAK_IMAGE_BASE="quay.io/keycloak/keycloak"
+KEYCLOAK_IMAGE_TAG_REMOTE_OTHER="17.0.0"
+#No local image for chart museum, remote image always used
+
 # List of app short names produced by the project
-PROJECT_IMAGES_APP_NAMES="A1PMS ICS CP RC RICSIM NGW DMAAPADP DMAAPMED HELMMANAGER"  # Add SDNC here if oran image is used
+PROJECT_IMAGES_APP_NAMES="A1PMS ICS CP RC RICSIM NGW DMAAPADP DMAAPMED HELMMANAGER AUTHSIDECAR"  # Add SDNC here if oran image is used
 
 # List of app short names which images pulled from ORAN
 ORAN_IMAGES_APP_NAMES=""  # Not used
@@ -241,6 +253,7 @@
 KUBE_A1SIM_NAMESPACE="a1-sim"                            # Namespace for a1-p simulators (RICSIM)
 KUBE_ONAP_NAMESPACE="onap"                               # Namespace for onap (only message router)
 KUBE_SDNC_NAMESPACE="onap"                               # Namespace for sdnc
+KUBE_KEYCLOAK_NAMESPACE="keycloak"                       # Namespace for keycloak
 
 A1PMS_EXTERNAL_PORT=8081                                   # A1PMS container external port (host -> container)
 A1PMS_INTERNAL_PORT=8081                                   # A1PMS container internal port (container -> container)
@@ -278,7 +291,7 @@
 ICS_APP_NAME_ALIAS="information-service-container"       # Alias name, name used by the control panel
 ICS_HOST_MNT_DIR="./mnt"                                 # Mounted db dir, relative to compose file, on the host
 ICS_CONTAINER_MNT_DIR="/var/information-coordinator-service" # Mounted dir in the container
-ICS_ACTUATOR="/actuator/loggers/org.oransc.information"  # Url for trace/debug
+ICS_ACTUATOR="/actuator/loggers/org.oransc.ics"          # Url for trace/debug
 ICS_CERT_MOUNT_DIR="./cert"
 ICS_ALIVE_URL="/status"                                  # Base path for alive check
 ICS_COMPOSE_DIR="ics"                                    # Dir in simulator_group for docker-compose
@@ -547,6 +560,29 @@
 HELM_MANAGER_COMPOSE_DIR="helmmanager"                   # Dir in simulator_group for docker-compose
 HELM_MANAGER_USER="helmadmin"
 HELM_MANAGER_PWD="itisasecret"
+
+KEYCLOAK_APP_NAME="keycloak"                             # Name for the keycloak app
+KEYCLOAK_DISPLAY_NAME="Keycloak"
+KEYCLOAK_EXTERNAL_PORT=80                                # keycloak container external port (host -> container)
+KEYCLOAK_INTERNAL_PORT=8080                              # keycloak container internal port (container -> container)
+KEYCLOAK_ADMIN_URL_PREFIX="/realms/master"
+KEYCLOAK_REALM_URL_PREFIX="/admin/realms"
+KEYCLOAK_TOKEN_URL_PREFIX="/realms"
+KEYCLOAK_ALIVE_URL="/realms/master"                      # Base path for alive check
+KEYCLOAK_COMPOSE_DIR="keycloak"
+KEYCLOAK_ADMIN_USER="admin"
+KEYCLOAK_ADMIN_PWD="admin"
+KEYCLOAK_ADMIN_CLIENT="admin-cli"
+KEYCLOAK_KC_PROXY="edge"
+
+ISTIO_COMPOSE_DIR="istio"
+
+# See jwt-info.txt in simulator-group/kubeproxy for detailed info
+ISTIO_GENERIC_JWKS_KEY='{ "keys":[{"kty":"RSA","e":"AQAB","kid":"dc1b272d-124e-417f-b6e3-eda9c0e29509","n":"u1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0_IzW7yWR7QkrmBL7jTKEn5u-qKhbwKfBstIs-bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW_VDL5AaWTg0nLVkjRo9z-40RQzuVaE8AkAFmxZzow3x-VJYKdjykkJ0iT9wCS0DRTXu269V264Vf_3jvredZiKRkgwlL9xNAwxXFg0x_XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC-9aGVd-Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmw"}]}'
+ISTIO_GENERIC_JWT="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJkb21haW4iLCJpc3MiOiJLVUJFUFJPWFkifQ.T5p9ip8yBRAYpArajFGhUlpfnV0HAbA7dPsSojYx1BNo6nwt_cpt6xJ8x66XwV-KqHud_S8hlnixLBYRtUiU8v7lWdk8RhBwW7w4CJs6n8ByvKsjJU8se18RWbSqsi-IQRsdkMiHz5fKosfCGVj6hI214S_yY988ICV7kl9anQhaD8zUPQQvso2zaAkT1qTgC5pxpZc3lB5526DvzsmYr_gaeE-GcbKW9hFoYppOhItL74IRVqRBs_pbaAauUg-9v_bRaJc5yOo3UMFDNiI2HCB6mdgJTLNb8bsT5qExgcbCRpUnOCF0I6PrvVlGft4zZkvz7I0I-8emVn4m-PV-BA"
+
+AUTHSIDECAR_APP_NAME="authsidecar"
+AUTHSIDECAR_DISPLAY_NAME="Authentication Token Fetcher"
 ########################################
 # Setting for common curl-base function
 ########################################
diff --git a/test/common/testcase_common.sh b/test/common/testcase_common.sh
index 5ebc9d3..1c77eda 100755
--- a/test/common/testcase_common.sh
+++ b/test/common/testcase_common.sh
@@ -30,7 +30,7 @@
 	echo "      [--repo-policy local|remote] [--cluster-timeout <timeout-in seconds>] [--print-stats]"
 	echo "      [--override <override-environment-filename>] [--pre-clean] [--gen-stats] [--delete-namespaces]"
 	echo "      [--delete-containers] [--endpoint-stats] [--kubeconfig <config-file>] [--host-path-dir <local-host-dir>]"
-	echo "      [--kubecontext <context-name>]"
+	echo "      [--kubecontext <context-name>] [--docker-host <docker-host-url>] [--docker-proxy <host-or-ip>]"
 }
 
 if [ $# -eq 1 ] && [ "$1" == "help" ]; then
@@ -68,6 +68,8 @@
 	echo "--kubeconfig          -  Configure kubectl to use cluster specific cluster config file"
 	echo "--host-path-dir       -  (Base-)path on local-hostmounted to all VMs (nodes), for hostpath volumes in kube"
 	echo "--kubecontext         -  Configure kubectl to use a certain context, e.g 'minikube'"
+	echo "--docker-host         -  Configure docker to use docker in e.g. a VM"
+	echo "--docker-proxy        -  Configure ip/host to docker when docker is running in a VM"
 	echo ""
 	echo "List of app short names supported: "$APP_SHORT_NAMES
 	exit 0
@@ -268,6 +270,14 @@
 #Var to configure kubectl from a config file or context
 KUBECONF=""
 
+#Localhost, may be set to another host/ip by cmd parameter
+LOCALHOST_NAME="localhost"
+
+#Reseting vars related to token/keys used by kubeproxy when istio is enabled
+#The vars are populated if istio is used in the testcase
+KUBE_PROXY_CURL_JWT=""
+KUBE_PROXY_ISTIO_JWKS_KEYS=""
+
 #Var pointing to dir mounted to each kubernetes node (master and workers)
 #Persistent volumes using "hostpath" are allocated beneath the point.
 #Typically it is a dir on local host mounted to each VM running the master and worker.
@@ -883,6 +893,55 @@
 				fi
 			else
 				HOST_PATH_BASE_DIR=$1
+				echo "Option set - Host path for kube set to: "$1
+				shift
+				foundparm=0
+			fi
+		fi
+	fi
+	if [ $paramerror -eq 0 ]; then
+		if [ "$1" == "--docker-host" ]; then
+			shift;
+			if [ -z "$1" ]; then
+				paramerror=1
+				if [ -z "$paramerror_str" ]; then
+					paramerror_str="No url found for : '--docker-host'"
+				fi
+			else
+				export DOCKER_HOST="$1"
+				echo "Option set - DOCKER_HOST set to: "$1
+				shift
+				foundparm=0
+			fi
+		fi
+	fi
+	if [ $paramerror -eq 0 ]; then
+		if [ "$1" == "--docker-host" ]; then
+			shift;
+			if [ -z "$1" ]; then
+				paramerror=1
+				if [ -z "$paramerror_str" ]; then
+					paramerror_str="No url found for : '--docker-host'"
+				fi
+			else
+				export DOCKER_HOST="$1"
+				echo "Option set - DOCKER_HOST set to: "$1
+				shift
+				foundparm=0
+			fi
+		fi
+	fi
+	if [ $paramerror -eq 0 ]; then
+		if [ "$1" == "--docker-proxy" ]; then
+			shift;
+			if [ -z "$1" ]; then
+				paramerror=1
+				if [ -z "$paramerror_str" ]; then
+					paramerror_str="No ip/host found for : '--docker-proxy'"
+				fi
+			else
+				export LOCALHOST_NAME=$1
+				echo "Option set - docker proxy set to: "$1
 				shift
 				foundparm=0
 			fi
@@ -905,11 +964,6 @@
 	exit 1
 fi
 
-#Localhost constants
-LOCALHOST_NAME="localhost"
-# if [ ! -z "$DOCKER_HOST" ]; then
-# 	LOCALHOST_NAME=$(echo $DOCKER_HOST | awk -F[/:] '{print $4}' )
-# fi
 LOCALHOST_HTTP="http://$LOCALHOST_NAME"
 LOCALHOST_HTTPS="https://$LOCALHOST_NAME"
 
@@ -2293,7 +2347,7 @@
 	namespace=$1
 	labelname=$2
 	labelid=$3
-	resources="deployments replicaset statefulset services pods configmaps persistentvolumeclaims persistentvolumes serviceaccounts clusterrolebindings secrets"
+	resources="deployments replicaset statefulset services pods configmaps persistentvolumeclaims persistentvolumes serviceaccounts clusterrolebindings secrets authorizationpolicies requestauthentications"
 	deleted_resourcetypes=""
 	for restype in $resources; do
 		ns_flag="-n $namespace"
@@ -2409,7 +2463,7 @@
 	return 0
 }
 
-# Removes a namespace
+# Removes and re-create a namespace
 # args: <namespace>
 # (Not for test scripts)
 clean_and_create_namespace() {
@@ -2427,7 +2481,22 @@
 	if [ $? -ne 0 ]; then
 		return 1
 	fi
+}
 
+# Add/remove label on non-namespaced kube object
+# args: <api> <instance> <label>
+# (Not for test scripts)
+__kube_label_non_ns_instance() {
+	kubectl $KUBECONF label $1 $2 "$3" 1> /dev/null 2> ./tmp/kubeerr
+	return $?
+}
+
+# Add/remove label on namespaced kube object
+# args: <api> <instance> <namespace> <label>
+# (Not for test scripts)
+__kube_label_ns_instance() {
+	kubectl $KUBECONF label $1 $2 -n $3 "$4" 1> /dev/null 2> ./tmp/kubeerr
+	return $?
 }
 
 # Find the host ip of an app (using the service resource)
@@ -3010,10 +3079,19 @@
 			proxyflag=" --proxy-insecure --proxy $KUBE_PROXY_PATH"
 		fi
 	fi
-	curlString="curl -skw %{http_code} $proxyflag $@"
-	echo " CMD: $curlString" >> $HTTPLOG
-	res=$($curlString)
-	retcode=$?
+
+	if [ ! -z "$KUBE_PROXY_CURL_JWT" ]; then
+		jwt="-H "\""Authorization: Bearer $KUBE_PROXY_CURL_JWT"\"
+		curlString="curl -skw %{http_code} $proxyflag $@"
+		echo " CMD: $curlString $jwt" >> $HTTPLOG
+		res=$($curlString -H "Authorization: Bearer $KUBE_PROXY_CURL_JWT")
+		retcode=$?
+	else
+		curlString="curl -skw %{http_code} $proxyflag $@"
+		echo " CMD: $curlString" >> $HTTPLOG
+		res=$($curlString)
+		retcode=$?
+	fi
 	echo " RESP: $res" >> $HTTPLOG
 	echo " RETCODE: $retcode" >> $HTTPLOG
 	if [ $retcode -ne 0 ]; then
@@ -3041,6 +3119,7 @@
 
 		return 0
 	fi
+
 }
 
 # Generic curl function, assumes all 200-codes are ok
diff --git a/test/common/testengine_config.sh b/test/common/testengine_config.sh
index 367ad68..77b8ee0 100644
--- a/test/common/testengine_config.sh
+++ b/test/common/testengine_config.sh
@@ -18,13 +18,13 @@
 #
 
 # List of short names for all supported apps, including simulators etc
-APP_SHORT_NAMES="A1PMS ICS SDNC CP NGW RC RICSIM HTTPPROXY CBS CONSUL DMAAPMR MR CR PRODSTUB KUBEPROXY DMAAPMED DMAAPADP PVCCLEANER KAFKAPC CHARTMUS HELMMANAGER LOCALHELM"
+APP_SHORT_NAMES="A1PMS ICS SDNC CP NGW RC RICSIM HTTPPROXY CBS CONSUL DMAAPMR MR CR PRODSTUB KUBEPROXY DMAAPMED DMAAPADP PVCCLEANER KAFKAPC CHARTMUS HELMMANAGER LOCALHELM KEYCLOAK ISTIO AUTHSIDECAR"
 
 # List of available apps that built and released of the project
-PROJECT_IMAGES="A1PMS ICS SDNC CP NGW RICSIM RC DMAAPMED DMAAPADP HELMMANAGER"
+PROJECT_IMAGES="A1PMS ICS SDNC CP NGW RICSIM RC DMAAPMED DMAAPADP HELMMANAGER AUTHSIDECAR"
 
 # List of available apps to override with local or remote staging/snapshot/release image
-AVAILABLE_IMAGES_OVERRIDE="A1PMS ICS SDNC CP NGW RICSIM RC DMAAPMED DMAAPADP HELMMANAGER"
+AVAILABLE_IMAGES_OVERRIDE="A1PMS ICS SDNC CP NGW RICSIM RC DMAAPMED DMAAPADP HELMMANAGER AUTHSIDECAR"
 
 # List of available apps where the image is built by the test environment
 LOCAL_IMAGE_BUILD="MR CR PRODSTUB KUBEPROXY HTTPPROXY KAFKAPC"