#!/bin/bash # Version: 1.2.2 # Author: Tomi Eckert # A script to interactively manage SAP HANA hdbuserstore keys, with testing. # --- Style Definitions --- COLOR_BLUE='\033[1;34m' COLOR_GREEN='\033[1;32m' COLOR_YELLOW='\033[1;33m' COLOR_RED='\033[1;31m' COLOR_NC='\033[0m' # No Color # --- Configuration --- # Adjust these paths if your HANA client is installed elsewhere. HDB_CLIENT_PATH="/usr/sap/hdbclient" HDB_USERSTORE_EXEC="${HDB_CLIENT_PATH}/hdbuserstore" HDB_SQL_EXEC="${HDB_CLIENT_PATH}/hdbsql" # --- Function: Test Key Connection --- # @param $1: The key name to test. # @return: 0 for success, 1 for failure. test_key() { local key_to_test=$1 if [ -z "$key_to_test" ]; then echo -e "${COLOR_RED} โŒ Error: No key name provided for testing.${COLOR_NC}" return 1 fi echo -e "\n${COLOR_YELLOW}๐Ÿงช Testing connection for key '${key_to_test}'...${COLOR_NC}" # Execute hdbsql, capturing both stdout and stderr. # The query is simple and lightweight, designed just to validate the connection. test_output=$("$HDB_SQL_EXEC" -U "$key_to_test" "SELECT 'Connection successful' FROM DUMMY" 2>&1) local exit_code=$? if [ $exit_code -eq 0 ] && [[ "$test_output" == *"Connection successful"* ]]; then echo -e "${COLOR_GREEN} โœ… Connection test successful!${COLOR_NC}" return 0 else echo -e "${COLOR_RED} โŒ Connection test failed for key '${key_to_test}'.${COLOR_NC}" echo -e "${COLOR_RED} Error details:${COLOR_NC}" # Indent the error message for better readability. echo "$test_output" | sed 's/^/ /' return 1 fi } # --- Function: Create New Key --- create_new_key() { current_hostname=$(hostname) echo -e "\n${COLOR_BLUE}๐Ÿ”‘ --- Create New Secure Key ---${COLOR_NC}" read -p "Enter the Key Name [CRONKEY]: " key_name read -p "Enter the HANA Host [${current_hostname}]: " hdb_host read -p "Enter the Instance Number [00]: " hdb_instance # Ask if connecting to SYSTEMDB to format the connection string correctly. read -p "Is this for the SYSTEMDB tenant? (y/n) [n]: " is_systemdb # Set default values for prompts key_name=${key_name:-"CRONKEY"} hdb_host=${hdb_host:-$current_hostname} hdb_instance=${hdb_instance:-"00"} is_systemdb=${is_systemdb:-"n"} # Conditionally build the connection string if [[ "$is_systemdb" =~ ^[Yy]$ ]]; then CONNECTION_STRING="${hdb_host}:3${hdb_instance}13" echo -e "${COLOR_YELLOW}๐Ÿ’ก Connecting to SYSTEMDB. Tenant name will be omitted from the connection string.${COLOR_NC}" else read -p "Enter the Tenant DB [NDB]: " hdb_tenant hdb_tenant=${hdb_tenant:-"NDB"} CONNECTION_STRING="${hdb_host}:3${hdb_instance}15@${hdb_tenant}" fi read -p "Enter the Database User [SYSTEM]: " hdb_user read -sp "Enter the Database Password: " hdb_pass echo "" hdb_user=${hdb_user:-"SYSTEM"} echo -e "\n${COLOR_YELLOW}๐Ÿ“ Review the command below (password is hidden):" echo "------------------------------------------------------" printf "${HDB_USERSTORE_EXEC} SET \"%s\" \"%s\" \"%s\" \"\"\n" "$key_name" "$CONNECTION_STRING" "$hdb_user" echo -e "------------------------------------------------------${COLOR_NC}" read -p "โ“ Execute this command? (y/n): " execute_now if [[ "$execute_now" =~ ^[Yy]$ ]]; then echo -e "\n${COLOR_GREEN}โš™๏ธ Executing command...${COLOR_NC}" # Create the key first if "$HDB_USERSTORE_EXEC" SET "$key_name" "$CONNECTION_STRING" "$hdb_user" "$hdb_pass"; then echo -e "${COLOR_GREEN} โœ… Success! Key '${key_name}' stored locally.${COLOR_NC}" # Immediately test the new key if ! test_key "$key_name"; then # If the test fails, roll back by deleting the key echo -e "\n${COLOR_YELLOW} ๋กค Rolling back: Deleting the newly created key '${key_name}' due to connection failure.${COLOR_NC}" if "$HDB_USERSTORE_EXEC" DELETE "$key_name"; then echo -e "${COLOR_GREEN} โœ… Key '${key_name}' successfully deleted.${COLOR_NC}" else echo -e "${COLOR_RED} โŒ Error: Failed to automatically delete the key '${key_name}'. Please remove it manually.${COLOR_NC}" fi fi else echo -e "${COLOR_RED} โŒ Error: Failed to store key '${key_name}'. Please check details and credentials.${COLOR_NC}" fi else echo -e "\n${COLOR_YELLOW}๐Ÿ›‘ Execution aborted by user.${COLOR_NC}" fi } # --- Function: Delete Key --- delete_key() { echo -e "\n${COLOR_BLUE}๐Ÿ—‘๏ธ --- Delete Existing Secure Key ---${COLOR_NC}" keys=$("$HDB_USERSTORE_EXEC" list 2>/dev/null | tail -n +3 | grep '^KEY ' | awk '{print $2}') if [ -z "$keys" ]; then echo -e "${COLOR_YELLOW}๐Ÿคท No keys found to delete.${COLOR_NC}" return fi PS3=$'\nPlease select a key to delete (or Ctrl+C to cancel): ' select key_to_delete in $keys; do if [ -n "$key_to_delete" ]; then read -p "โ“ PERMANENTLY delete the key '$key_to_delete'? (y/n): " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then echo -e "\n${COLOR_GREEN}โš™๏ธ Deleting key '$key_to_delete'...${COLOR_NC}" if "$HDB_USERSTORE_EXEC" DELETE "$key_to_delete"; then echo -e "${COLOR_GREEN} โœ… Success! Key '$key_to_delete' has been deleted.${COLOR_NC}" else echo -e "${COLOR_RED} โŒ Error: Failed to delete the key.${COLOR_NC}" fi else echo -e "\n${COLOR_YELLOW}๐Ÿ›‘ Deletion aborted by user.${COLOR_NC}" fi break else echo -e "${COLOR_RED}โŒ Invalid selection. Try again.${COLOR_NC}" fi done } # --- Function: List and Test a Key --- list_and_test_key() { echo -e "\n${COLOR_BLUE}๐Ÿงช --- Test an Existing Secure Key ---${COLOR_NC}" keys=$("$HDB_USERSTORE_EXEC" list 2>/dev/null | tail -n +3 | grep '^KEY ' | awk '{print $2}') if [ -z "$keys" ]; then echo -e "${COLOR_YELLOW}๐Ÿคท No keys found to test.${COLOR_NC}" return fi PS3=$'\nPlease select a key to test (or Ctrl+C to cancel): ' select key_to_test in $keys; do if [ -n "$key_to_test" ]; then test_key "$key_to_test" break else echo -e "${COLOR_RED}โŒ Invalid selection. Try again.${COLOR_NC}" fi done } # --- Main Menu --- while true; do echo -e "\n${COLOR_BLUE}๐Ÿ” ========== SAP HANA Secure User Store Key Manager ==========${COLOR_NC}" echo "1) Create a New Key" echo "2) Delete an Existing Key" echo "3) Test an Existing Key" echo "4) Exit" read -p $'\nPlease select an option: ' choice case $choice in 1) create_new_key ;; 2) delete_key ;; 3) list_and_test_key ;; 4) echo "๐Ÿ‘‹ Exiting." exit 0 ;; *) echo -e "${COLOR_RED}โŒ Invalid option '$choice'. Please try again.${COLOR_NC}" ;; esac done