#!/bin/bash
# Version: 1.2.3
# 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.
# Define potential HDB client paths
HDB_CLIENT_PATH_1="/usr/sap/hdbclient"
HDB_CLIENT_PATH_2="/usr/sap/NDB/HDB00/exe"

# Check which path exists and set HDB_CLIENT_PATH accordingly
if [ -d "$HDB_CLIENT_PATH_1" ]; then
    HDB_CLIENT_PATH="$HDB_CLIENT_PATH_1"
elif [ -d "$HDB_CLIENT_PATH_2" ]; then
    HDB_CLIENT_PATH="$HDB_CLIENT_PATH_2"
else
    echo -e "${COLOR_RED}❌ Error: Neither '$HDB_CLIENT_PATH_1' nor '$HDB_CLIENT_PATH_2' found.${COLOR_NC}"
    echo -e "${COLOR_RED}Please install the SAP HANA client or adjust the paths in the script.${COLOR_NC}"
    exit 1
fi
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\" \"<password>\"\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

