@@ -18,7 +18,12 @@ RED='\033[0;31m'
1818GREEN=' \033[0;32m'
1919NC=' \033[0m'
2020
21- # Function to print logs with color based on severity
21+ # Global variable to store the path of the temporary file.
22+ temp_file=" "
23+
24+ # Print logs with color based on severity.
25+ # :param severity: The severity level of the log (e.g., "INFO", "ERROR").
26+ # :param message: The message to log.
2227log () {
2328 local severity=$1
2429 local message=$2
@@ -37,12 +42,15 @@ log "INFO" "ANSIBLE_MODULE_UTILS: $ANSIBLE_MODULE_UTILS"
3742# Define the path to the vars.yaml file
3843VARS_FILE=" ${cmd_dir} /../vars.yaml"
3944
40- # Function to check if a command exists
45+ # Check if a command exists.
46+ # :param command: The command to check.
47+ # :return: None. Exits with a non-zero status if the command does not exist.
4148command_exists () {
4249 command -v " $1 " & > /dev/null
4350}
4451
45- # Function to validate input parameters from vars.yaml
52+ # Validate input parameters from vars.yaml.
53+ # :return: None. Exits with a non-zero status if validation fails.
4654validate_params () {
4755 local missing_params=()
4856 local params=(" TEST_TYPE" " SYSTEM_CONFIG_NAME" " sap_functional_test_type" " AUTHENTICATION_TYPE" )
@@ -71,18 +79,37 @@ validate_params() {
7179 fi
7280}
7381
74- # Function to check if a file exists
82+ # Check if a file exists.
83+ # :param file_path: The path to the file to check.
84+ # :param error_message: The error message to display if the file does not exist.
85+ # :return: None. Exits with a non-zero status if the file does not exist.
7586check_file_exists () {
7687 local file_path=$1
7788 local error_message=$2
78-
89+ log " INFO " " Checking if file exists: $file_path "
7990 if [[ ! -f " $file_path " ]]; then
8091 log " ERROR" " Error: $error_message "
8192 exit 1
8293 fi
8394}
8495
85- # Function to determine the playbook name based on the sap_functional_test_type
96+ # Extract the error message from a command's output.
97+ # :param error_output: The output containing the error message.
98+ # :return: The extracted error message or a default message if none is found.
99+ extract_error_message () {
100+ local error_output=$1
101+ local extracted_message
102+
103+ extracted_message=$( echo " $error_output " | grep -oP ' (?<=Message: ).*' | head -n 1)
104+ if [[ -z " $extracted_message " ]]; then
105+ extracted_message=" An unknown error occurred. See full error details above."
106+ fi
107+ echo " $extracted_message "
108+ }
109+
110+ # Determine the playbook name based on the sap_functional_test_type.
111+ # :param test_type: The type of SAP functional test.
112+ # :return: The name of the playbook.
86113get_playbook_name () {
87114 local test_type=$1
88115
@@ -100,24 +127,144 @@ get_playbook_name() {
100127 esac
101128}
102129
103- # Function to run the ansible playbook
130+ # Retrieve a secret from Azure Key Vault.
131+ # :param key_vault_id: The ID of the Key Vault.
132+ # :param secret_id: The ID of the secret in the Key Vault.
133+ # :param auth_type: The authentication type (e.g., "SSHKEY", "VMPASSWORD").
134+ # :return: None. Exits with a non-zero status if retrieval fails.
135+ retrieve_secret_from_key_vault () {
136+ local key_vault_id=$1
137+ local secret_id=$2
138+ local auth_type=$3 # Add auth_type as a parameter
139+
140+ subscription_id=$( echo " $key_vault_id " | awk -F' /' ' {for(i=1;i<=NF;i++){if($i=="subscriptions"){print $(i+1)}}}' )
141+
142+ if [[ -z " $key_vault_id " || -z " $secret_id " ]]; then
143+ log " ERROR" " Key Vault ID or secret ID is missing."
144+ exit 1
145+ fi
146+
147+ log " INFO" " Using Key Vault ID: $key_vault_id "
148+ log " INFO" " Using secret ID: $secret_id "
149+
150+ # Authenticate using MSI
151+ log " INFO" " Authenticating using MSI..."
152+ az login --identity
153+ az account set --subscription " $subscription_id "
154+ if [[ $? -ne 0 ]]; then
155+ log " ERROR" " Failed to authenticate using MSI."
156+ exit 1
157+ fi
158+
159+ # Attempt to retrieve the secret value and handle errors
160+ log " INFO" " Retrieving secret from Key Vault using resource ID..."
161+ set +e # Temporarily disable exit on error
162+ secret_value=$( az keyvault secret show --id " $secret_id " --query " value" -o tsv 2>&1 )
163+ az_exit_code=$? # Capture the exit code of the az command
164+ set -e # Re-enable exit on error
165+
166+ if [[ $az_exit_code -ne 0 || -z " $secret_value " ]]; then
167+ extracted_message=$( extract_error_message " $secret_value " )
168+ log " ERROR" " Failed to retrieve secret from Key Vault: $extracted_message "
169+ exit 1
170+ fi
171+
172+ log " INFO" " Successfully retrieved secret from Key Vault."
173+
174+ # Define a unique temporary file path based on auth_type
175+ if [[ " $auth_type " == " SSHKEY" ]]; then
176+ temp_file=$( mktemp --dry-run --suffix=.ppk)
177+ elif [[ " $auth_type " == " VMPASSWORD" ]]; then
178+ temp_file=$( mktemp --dry-run)
179+ else
180+ log " ERROR" " Unknown authentication type: $auth_type "
181+ exit 1
182+ fi
183+
184+ if [[ -f " $temp_file " ]]; then
185+ log " ERROR" " Temporary file already exists: $temp_file "
186+ exit 1
187+ fi
188+
189+ # Create the temporary file and write the secret value to it
190+ echo " $secret_value " > " $temp_file "
191+ chmod 600 " $temp_file " # Set the correct permissions for the file
192+ if [[ ! -s " $temp_file " ]]; then
193+ log " ERROR" " Failed to store the retrieved secret in the temporary file."
194+ exit 1
195+ fi
196+ log " INFO" " Temporary file created with secure permissions: $temp_file "
197+ }
198+
199+ # Run the ansible playbook.
200+ # :param playbook_name: The name of the playbook to run.
201+ # :param system_hosts: The path to the inventory file.
202+ # :param system_params: The path to the SAP parameters file.
203+ # :param auth_type: The authentication type (e.g., "SSHKEY", "VMPASSWORD").
204+ # :param system_config_folder: The path to the system configuration folder.
205+ # :return: None. Exits with the return code of the ansible-playbook command.
104206run_ansible_playbook () {
105207 local playbook_name=$1
106208 local system_hosts=$2
107209 local system_params=$3
108210 local auth_type=$4
109211 local system_config_folder=$5
110212
213+ # Set local secret_id and key_vault_id if defined
214+ local secret_id=$( grep " ^secret_id:" " $system_params " | awk ' {split($0,a,": "); print a[2]}' | xargs || true)
215+ local key_vault_id=$( grep " ^key_vault_id:" " $system_params " | awk ' {split($0,a,": "); print a[2]}' | xargs || true)
216+
217+ if [[ -n " $secret_id " ]]; then
218+ log " INFO" " Extracted secret_id: $secret_id "
219+ fi
220+
221+ if [[ -n " $key_vault_id " ]]; then
222+ log " INFO" " Extracted key_vault_id: $key_vault_id "
223+ fi
224+
111225 if [[ " $auth_type " == " SSHKEY" ]]; then
112- local ssh_key=" ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /ssh_key.ppk"
113- log " INFO" " Using SSH key: $ssh_key ."
114- command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts --private-key $ssh_key \
115- -e @$VARS_FILE -e @$system_params -e '_workspace_directory=$system_config_folder '"
226+ log " INFO" " Authentication type is SSHKEY."
227+
228+ if [[ -n " $key_vault_id " && -n " $secret_id " ]]; then
229+ log " INFO" " Key Vault ID and Secret ID are set. Retrieving SSH key from Key Vault."
230+ retrieve_secret_from_key_vault " $key_vault_id " " $secret_id " " SSHKEY"
231+
232+ check_file_exists " $temp_file " \
233+ " Temporary SSH key file not found. Please check the Key Vault secret ID."
234+ command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts --private-key $temp_file \
235+ -e @$VARS_FILE -e @$system_params -e '_workspace_directory=$system_config_folder '"
236+ else
237+ check_file_exists " ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /ssh_key.ppk" \
238+ " ssh_key.ppk not found in WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME directory."
239+ ssh_key=" ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /ssh_key.ppk"
240+ command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts --private-key $ssh_key \
241+ -e @$VARS_FILE -e @$system_params -e '_workspace_directory=$system_config_folder '"
242+ fi
243+
244+ elif [[ " $auth_type " == " VMPASSWORD" ]]; then
245+ log " INFO" " Authentication type is VMPASSWORD."
246+
247+ if [[ -n " $key_vault_id " && -n " $secret_id " ]]; then
248+ log " INFO" " Key Vault ID and Secret ID are set. Retrieving VM password from Key Vault."
249+ retrieve_secret_from_key_vault " $key_vault_id " " $secret_id " " VMPASSWORD"
250+
251+ check_file_exists " $temp_file " \
252+ " Temporary SSH key file not found. Please check the Key Vault secret ID."
253+ command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts \
254+ --extra-vars \" ansible_ssh_pass=$( cat $temp_file ) \" --extra-vars @$VARS_FILE -e @$system_params \
255+ -e '_workspace_directory=$system_config_folder '"
256+ else
257+ local password_file=" ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /password"
258+ check_file_exists " $password_file " \
259+ " password file not found in WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME directory."
260+ command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts \
261+ --extra-vars \" ansible_ssh_pass=$( cat $password_file ) \" --extra-vars @$VARS_FILE -e @$system_params \
262+ -e '_workspace_directory=$system_config_folder '"
263+ fi
264+
116265 else
117- log " INFO" " Using password authentication."
118- command=" ansible-playbook ${cmd_dir} /../src/$playbook_name .yml -i $system_hosts \
119- --extra-vars \" ansible_ssh_pass=$( cat ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /password) \" \
120- --extra-vars @$VARS_FILE -e @$system_params -e '_workspace_directory=$system_config_folder '"
266+ log " ERROR" " Unknown authentication type: $auth_type "
267+ exit 1
121268 fi
122269
123270 log " INFO" " Running ansible playbook..."
@@ -126,10 +273,17 @@ run_ansible_playbook() {
126273 return_code=$?
127274 log " INFO" " Ansible playbook execution completed with return code: $return_code "
128275
276+ # Clean up temporary file if it exists
277+ if [[ -n " $temp_file " && -f " $temp_file " ]]; then
278+ rm -f " $temp_file "
279+ log " INFO" " Temporary file deleted: $temp_file "
280+ fi
281+
129282 exit $return_code
130283}
131284
132- # Main script execution
285+ # Main script execution.
286+ # :return: None. Exits with a non-zero status if any step fails.
133287main () {
134288 log " INFO" " Activate the virtual environment..."
135289 set -e
@@ -152,19 +306,11 @@ main() {
152306 check_file_exists " $SYSTEM_PARAMS " \
153307 " sap-parameters.yaml not found in WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME directory."
154308
155- log " INFO" " Checking if the SSH key or password file exists..."
156- if [[ " $AUTHENTICATION_TYPE " == " SSHKEY" ]]; then
157- check_file_exists " ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /ssh_key.ppk" \
158- " ssh_key.ppk not found in WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME directory."
159- else
160- check_file_exists " ${cmd_dir} /../WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME /password" \
161- " password file not found in WORKSPACES/SYSTEM/$SYSTEM_CONFIG_NAME directory."
162- fi
163-
164309 playbook_name=$( get_playbook_name " $sap_functional_test_type " )
165310 log " INFO" " Using playbook: $playbook_name ."
166311
167312 run_ansible_playbook " $playbook_name " " $SYSTEM_HOSTS " " $SYSTEM_PARAMS " " $AUTHENTICATION_TYPE " " $SYSTEM_CONFIG_FOLDER "
313+
168314}
169315
170316# Execute the main function
0 commit comments