From 87344060a4d0fb0d5503aa95c9b4236ceee70d04 Mon Sep 17 00:00:00 2001 From: Seokho Son Date: Tue, 16 Jul 2024 19:47:50 +0900 Subject: [PATCH 1/5] Add encryption decryption script for credentials --- scripts/init/decCredential.sh | 60 +++++++++++++++++++++++++ scripts/init/encCredential.sh | 84 +++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100755 scripts/init/decCredential.sh create mode 100755 scripts/init/encCredential.sh diff --git a/scripts/init/decCredential.sh b/scripts/init/decCredential.sh new file mode 100755 index 00000000..4d2ecd57 --- /dev/null +++ b/scripts/init/decCredential.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +CRED_FILE_NAME="credentials.yaml" +CRED_PATH="$HOME/.cloud-barista" +FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" +ENCRYPTED_FILE="$FILE_PATH.enc" +TEMP_DECRYPTED_FILE="$FILE_PATH.tmp" + +# Check if OpenSSL is installed +if ! command -v openssl &> /dev/null; then + echo "OpenSSL is not installed. Installation guide:" + echo "Ubuntu/Debian: sudo apt-get install openssl" + echo "CentOS/RHEL: sudo yum install openssl" + echo "Fedora: sudo dnf install openssl" + echo "Arch Linux: sudo pacman -S openssl" + exit 1 +fi + +# Check if the file is already decrypted +if [ -f "$FILE_PATH" ]; then + echo "The file is already decrypted." + exit 0 +fi + +# Check if the encrypted file exists +if [ ! -f "$ENCRYPTED_FILE" ]; then + echo "The encrypted file does not exist: $ENCRYPTED_FILE" + exit 1 +fi + +# Prompt for password or use the environment variable +if [ -z "$TB_CRED_DECRYPT_KEY" ]; then + read -sp "Enter the password: " PASSWORD + echo + + if [ -z "$PASSWORD" ]; then + echo "Password is required." + exit 1 + fi + + # Set the environment variable for the decryption key + TB_CRED_DECRYPT_KEY=$PASSWORD +else + echo "Using key from environment variable TB_CRED_DECRYPT_KEY" +fi + +# Decrypt the file to a temporary file, suppressing OpenSSL error messages +DECRYPT_OUTPUT=$(openssl enc -aes-256-cbc -d -pbkdf2 -in "$ENCRYPTED_FILE" -out "$TEMP_DECRYPTED_FILE" -pass pass:"$TB_CRED_DECRYPT_KEY" 2>&1) + +# Check if decryption was successful +if [ $? -eq 0 ]; then + mv "$TEMP_DECRYPTED_FILE" "$FILE_PATH" + rm "$ENCRYPTED_FILE" + echo "File successfully decrypted: $FILE_PATH" + echo "Encrypted file deleted: $ENCRYPTED_FILE" +else + echo "Failed to decrypt the file. Exiting." + rm -f "$TEMP_DECRYPTED_FILE" # Remove the temporary file if decryption failed + exit 1 +fi diff --git a/scripts/init/encCredential.sh b/scripts/init/encCredential.sh new file mode 100755 index 00000000..99d6234f --- /dev/null +++ b/scripts/init/encCredential.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +CRED_FILE_NAME="credentials.yaml" +CRED_PATH="$HOME/.cloud-barista" +FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" +ENCRYPTED_FILE="$FILE_PATH.enc" +TEMP_DECRYPTED_FILE="$FILE_PATH.tmp.dec" + +# Check if OpenSSL is installed +if ! command -v openssl &> /dev/null; then + echo "OpenSSL is not installed. Installation guide:" + echo "Ubuntu/Debian: sudo apt-get install openssl" + echo "CentOS/RHEL: sudo yum install openssl" + echo "Fedora: sudo dnf install openssl" + echo "Arch Linux: sudo pacman -S openssl" + exit 1 +fi + +# Check if the file is already encrypted +if [ -f "$ENCRYPTED_FILE" ]; then + echo "The file is already encrypted." + exit 0 +fi + +# Check if the file to be encrypted exists +if [ ! -f "$FILE_PATH" ]; then + echo "The file to be encrypted does not exist: $FILE_PATH" + exit 1 +fi + +# Prompt to proceed with encryption +read -p "Do you want to encrypt the file $FILE_PATH? (y/n): " CONFIRM +if [ "$CONFIRM" != "y" ]; then + echo "Encryption process aborted." + exit 0 +fi + +# Prompt for password +read -sp "Enter a password (press enter to generate a random key): " PASSWORD +echo +if [ -n "$PASSWORD" ]; then + read -sp "Confirm the password: " PASSWORD_CONFIRM + echo + if [ "$PASSWORD" != "$PASSWORD_CONFIRM" ]; then + echo "Passwords do not match. Encryption aborted." + exit 1 + fi +fi + +if [ -z "$PASSWORD" ]; then + # Generate a random key + TB_CRED_DECRYPT_KEY=$(openssl rand -base64 64 | tr -d '\n') +else + TB_CRED_DECRYPT_KEY=$PASSWORD +fi + +# Encrypt the file +openssl enc -aes-256-cbc -salt -pbkdf2 -in "$FILE_PATH" -out "$ENCRYPTED_FILE" -pass pass:"$TB_CRED_DECRYPT_KEY" + +if [ $? -eq 0 ]; then + # Verify encryption by decrypting the file to a temporary file + openssl enc -aes-256-cbc -d -pbkdf2 -in "$ENCRYPTED_FILE" -out "$TEMP_DECRYPTED_FILE" -pass pass:"$TB_CRED_DECRYPT_KEY" + if [ $? -eq 0 ] && cmp -s "$FILE_PATH" "$TEMP_DECRYPTED_FILE"; then + rm "$TEMP_DECRYPTED_FILE" + rm "$FILE_PATH" + echo "File successfully encrypted: $ENCRYPTED_FILE" + echo "Original file deleted: $FILE_PATH" + if [ -z "$PASSWORD" ]; then + echo "Your encryption key is: $TB_CRED_DECRYPT_KEY" + echo "To decrypt the file, export the key as an environment variable:" + echo "export TB_CRED_DECRYPT_KEY=\"$TB_CRED_DECRYPT_KEY\"" + fi + else + echo "Encryption verification failed." + if [ $? -ne 0 ]; then + echo "Decryption failed during verification." + else + echo "File comparison failed during verification." + fi + rm "$TEMP_DECRYPTED_FILE" + fi +else + echo "Failed to encrypt the file." +fi From 44e7048ba3414421e3ea7e9330f269424b9aa091 Mon Sep 17 00:00:00 2001 From: Seokho Son Date: Mon, 22 Jul 2024 21:29:00 +0900 Subject: [PATCH 2/5] Force encrypted credential file for init.py --- scripts/init/decCredential.sh | 43 +++++++++++------- scripts/init/encCredential.sh | 83 +++++++++++++++++++++++------------ scripts/init/init.py | 66 ++++++++++++++++++++++------ 3 files changed, 133 insertions(+), 59 deletions(-) diff --git a/scripts/init/decCredential.sh b/scripts/init/decCredential.sh index 4d2ecd57..f7f0c456 100755 --- a/scripts/init/decCredential.sh +++ b/scripts/init/decCredential.sh @@ -1,47 +1,56 @@ #!/bin/bash +# Define colors for output +RED='\033[0;31m' +LGREEN='\033[1;32m' +PURPLE='\033[0;35m' +NC='\033[0m' # No Color +CYAN='\033[0;36m' +YELLOW='\033[1;33m' + CRED_FILE_NAME="credentials.yaml" CRED_PATH="$HOME/.cloud-barista" FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" ENCRYPTED_FILE="$FILE_PATH.enc" TEMP_DECRYPTED_FILE="$FILE_PATH.tmp" +KEY_FILE="$CRED_PATH/cred_key" # Check if OpenSSL is installed if ! command -v openssl &> /dev/null; then - echo "OpenSSL is not installed. Installation guide:" - echo "Ubuntu/Debian: sudo apt-get install openssl" - echo "CentOS/RHEL: sudo yum install openssl" - echo "Fedora: sudo dnf install openssl" - echo "Arch Linux: sudo pacman -S openssl" + echo -e "\n${RED}OpenSSL is not installed. Installation guide:${NC}" + echo -e "${LGREEN}Ubuntu/Debian:${NC} sudo apt-get install openssl" + echo -e "${LGREEN}CentOS/RHEL:${NC} sudo yum install openssl" + echo -e "${LGREEN}Fedora:${NC} sudo dnf install openssl" + echo -e "${LGREEN}Arch Linux:${NC} sudo pacman -S openssl\n" exit 1 fi # Check if the file is already decrypted if [ -f "$FILE_PATH" ]; then - echo "The file is already decrypted." + echo -e "\n${RED}The file is already decrypted.${NC}\n" exit 0 fi # Check if the encrypted file exists if [ ! -f "$ENCRYPTED_FILE" ]; then - echo "The encrypted file does not exist: $ENCRYPTED_FILE" + echo -e "\n${RED}The encrypted file does not exist: ${CYAN}$ENCRYPTED_FILE${NC}\n" exit 1 fi -# Prompt for password or use the environment variable -if [ -z "$TB_CRED_DECRYPT_KEY" ]; then +# Prompt for password or use the key file +if [ -f "$KEY_FILE" ]; then + TB_CRED_DECRYPT_KEY=$(cat "$KEY_FILE") +else read -sp "Enter the password: " PASSWORD echo if [ -z "$PASSWORD" ]; then - echo "Password is required." + echo -e "\n${RED}Password is required.${NC}\n" exit 1 fi - # Set the environment variable for the decryption key + # Use the entered password TB_CRED_DECRYPT_KEY=$PASSWORD -else - echo "Using key from environment variable TB_CRED_DECRYPT_KEY" fi # Decrypt the file to a temporary file, suppressing OpenSSL error messages @@ -51,10 +60,12 @@ DECRYPT_OUTPUT=$(openssl enc -aes-256-cbc -d -pbkdf2 -in "$ENCRYPTED_FILE" -out if [ $? -eq 0 ]; then mv "$TEMP_DECRYPTED_FILE" "$FILE_PATH" rm "$ENCRYPTED_FILE" - echo "File successfully decrypted: $FILE_PATH" - echo "Encrypted file deleted: $ENCRYPTED_FILE" + echo -e "\n${LGREEN}File successfully decrypted: ${CYAN}$FILE_PATH${NC}" + echo -e "(Encrypted file deleted: $ENCRYPTED_FILE)\n" else - echo "Failed to decrypt the file. Exiting." + echo -e "\n${RED}Failed to decrypt the file. Exiting.${NC}\n" + echo -e "${RED}log: ${DECRYPT_OUTPUT}${NC}\n" rm -f "$TEMP_DECRYPTED_FILE" # Remove the temporary file if decryption failed exit 1 fi + diff --git a/scripts/init/encCredential.sh b/scripts/init/encCredential.sh index 99d6234f..a929f4b0 100755 --- a/scripts/init/encCredential.sh +++ b/scripts/init/encCredential.sh @@ -1,39 +1,61 @@ #!/bin/bash +# Define colors for output +RED='\033[0;31m' +LGREEN='\033[1;32m' +PURPLE='\033[0;35m' +NC='\033[0m' # No Color +CYAN='\033[0;36m' +YELLOW='\033[1;33m' + CRED_FILE_NAME="credentials.yaml" CRED_PATH="$HOME/.cloud-barista" FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" ENCRYPTED_FILE="$FILE_PATH.enc" TEMP_DECRYPTED_FILE="$FILE_PATH.tmp.dec" +KEY_FILE="$CRED_PATH/cred_key" +SCRIPT_DIR=$(dirname "$(realpath "$0")") +DECRYPT_SCRIPT_PATH="$SCRIPT_DIR/decCredential.sh" # Check if OpenSSL is installed if ! command -v openssl &> /dev/null; then - echo "OpenSSL is not installed. Installation guide:" - echo "Ubuntu/Debian: sudo apt-get install openssl" - echo "CentOS/RHEL: sudo yum install openssl" - echo "Fedora: sudo dnf install openssl" - echo "Arch Linux: sudo pacman -S openssl" + echo -e "\n${RED}OpenSSL is not installed. Installation guide:${NC}" + echo -e "${LGREEN}Ubuntu/Debian:${NC} sudo apt-get install openssl" + echo -e "${LGREEN}CentOS/RHEL:${NC} sudo yum install openssl" + echo -e "${LGREEN}Fedora:${NC} sudo dnf install openssl" + echo -e "${LGREEN}Arch Linux:${NC} sudo pacman -S openssl\n" exit 1 fi # Check if the file is already encrypted if [ -f "$ENCRYPTED_FILE" ]; then - echo "The file is already encrypted." + echo -e "\n${RED}The file is already encrypted.${NC}\n" exit 0 fi # Check if the file to be encrypted exists if [ ! -f "$FILE_PATH" ]; then - echo "The file to be encrypted does not exist: $FILE_PATH" + echo -e "\n${RED}The file to be encrypted does not exist: ${CYAN}$FILE_PATH${NC}\n" exit 1 fi # Prompt to proceed with encryption -read -p "Do you want to encrypt the file $FILE_PATH? (y/n): " CONFIRM -if [ "$CONFIRM" != "y" ]; then - echo "Encryption process aborted." - exit 0 -fi +while true; do + echo -e "\nDo you want to encrypt the file ${CYAN}$FILE_PATH${NC}? (y/n): \c" + read -e CONFIRM + case $CONFIRM in + [Yy]* ) + break + ;; + [Nn]* ) + echo -e "\n${RED}Encryption process aborted.${NC}\n" + exit 0 + ;; + * ) + echo -e "\n${RED}Please answer yes or no.${NC}\n" + ;; + esac +done # Prompt for password read -sp "Enter a password (press enter to generate a random key): " PASSWORD @@ -42,16 +64,21 @@ if [ -n "$PASSWORD" ]; then read -sp "Confirm the password: " PASSWORD_CONFIRM echo if [ "$PASSWORD" != "$PASSWORD_CONFIRM" ]; then - echo "Passwords do not match. Encryption aborted." + echo -e "\n${RED}Passwords do not match. Encryption aborted.${NC}\n" exit 1 fi -fi - -if [ -z "$PASSWORD" ]; then + TB_CRED_DECRYPT_KEY=$PASSWORD + # Delete the existing key file if any + if [ -f "$KEY_FILE" ]; then + rm "$KEY_FILE" + fi + echo -e "\n${YELLOW}Remember the password you have entered. You will need it to decrypt the file.${NC}\n" +else # Generate a random key TB_CRED_DECRYPT_KEY=$(openssl rand -base64 64 | tr -d '\n') -else - TB_CRED_DECRYPT_KEY=$PASSWORD + echo "$TB_CRED_DECRYPT_KEY" > "$KEY_FILE" + echo -e "\n${YELLOW}A random encryption key was generated and saved to ${CYAN}$KEY_FILE${NC}" + echo -e "${YELLOW}This file should be used temporarily. Please store the key securely.${NC}\n" fi # Encrypt the file @@ -63,22 +90,20 @@ if [ $? -eq 0 ]; then if [ $? -eq 0 ] && cmp -s "$FILE_PATH" "$TEMP_DECRYPTED_FILE"; then rm "$TEMP_DECRYPTED_FILE" rm "$FILE_PATH" - echo "File successfully encrypted: $ENCRYPTED_FILE" - echo "Original file deleted: $FILE_PATH" - if [ -z "$PASSWORD" ]; then - echo "Your encryption key is: $TB_CRED_DECRYPT_KEY" - echo "To decrypt the file, export the key as an environment variable:" - echo "export TB_CRED_DECRYPT_KEY=\"$TB_CRED_DECRYPT_KEY\"" - fi + echo -e "\n${LGREEN}File successfully encrypted: ${CYAN}$ENCRYPTED_FILE${NC}" + echo -e "${LGREEN}Original file deleted: ${CYAN}$FILE_PATH${NC}\n" + echo -e "${YELLOW}To edit the credentials,${NC}" + echo -e "Use ${CYAN}$DECRYPT_SCRIPT_PATH${NC} to decrypt the file" + echo -e "Then edit ${CYAN}$FILE_PATH${NC}\n" else - echo "Encryption verification failed." + echo -e "\n${RED}Encryption verification failed.${NC}\n" if [ $? -ne 0 ]; then - echo "Decryption failed during verification." + echo -e "${RED}Decryption failed during verification.${NC}\n" else - echo "File comparison failed during verification." + echo -e "${RED}File comparison failed during verification.${NC}\n" fi rm "$TEMP_DECRYPTED_FILE" fi else - echo "Failed to encrypt the file." + echo -e "\n${RED}Failed to encrypt the file.${NC}\n" fi diff --git a/scripts/init/init.py b/scripts/init/init.py index bc2b5e2a..32dd61d2 100755 --- a/scripts/init/init.py +++ b/scripts/init/init.py @@ -7,11 +7,12 @@ import argparse import threading from concurrent.futures import ThreadPoolExecutor, as_completed - +import subprocess import requests import yaml from tqdm import tqdm from colorama import Fore, init +from getpass import getpass parser = argparse.ArgumentParser(description="Automatically proceed without confirmation.") parser.add_argument('-y', '--yes', action='store_true', help='Automatically answer yes to prompts and proceed.') @@ -21,14 +22,16 @@ init(autoreset=True) # Configuration -TUMBLEBUG_SERVER = os.getenv('TUMBLEBUG_SERVER', 'localhost:1323') +TUMBLEBUG_SERVER = os.getenv('TUMBLEBUG_SERVER', 'localhost:1323') API_USERNAME = os.getenv('API_USERNAME', 'default') API_PASSWORD = os.getenv('API_PASSWORD', 'default') AUTH = f"Basic {base64.b64encode(f'{API_USERNAME}:{API_PASSWORD}'.encode()).decode()}" HEADERS = {'Authorization': AUTH, 'Content-Type': 'application/json'} -CRED_FILE_NAME = "credentials.yaml" +CRED_FILE_NAME_ENC = "credentials.yaml.enc" CRED_PATH = os.path.join(os.path.expanduser('~'), '.cloud-barista') +ENC_FILE_PATH = os.path.join(CRED_PATH, CRED_FILE_NAME_ENC) +KEY_FILE = os.path.join(CRED_PATH, "cred_key") expected_completion_time_seconds = 240 @@ -36,8 +39,47 @@ if not os.path.exists(CRED_PATH): print(Fore.RED + "Error: CRED_PATH does not exist. Please run scripts/genCredential.sh first.") sys.exit(1) -elif not os.path.isfile(os.path.join(CRED_PATH, CRED_FILE_NAME)): - print(Fore.RED + "Error: CRED_FILE_NAME does not exist. Please check if it has been generated.") +elif not os.path.isfile(ENC_FILE_PATH): + print(Fore.RED + f"Error: {CRED_FILE_NAME_ENC} does not exist. Please check if it has been generated.") + print(Fore.RED + f"- This script does not accept 'credentials.yaml'. For your security, it only accepts an encrypted file.") + print(Fore.RED + f"- Please generate '{CRED_FILE_NAME_ENC}' using 'scripts/init/encCredential.sh'.") + sys.exit(1) + + +# Decrypt credentials.yaml.enc +def decrypt_credentials(enc_file_path, key): + try: + result = subprocess.run( + ['openssl', 'enc', '-aes-256-cbc', '-d', '-pbkdf2', '-in', enc_file_path, '-pass', f'pass:{key}'], + check=True, + capture_output=True + ) + if result.returncode != 0: + return None, "Decryption failed." + return result.stdout.decode('utf-8'), None + except subprocess.CalledProcessError as e: + return None, f"Decryption error: {e.stderr.decode('utf-8')}" + +def get_decryption_key(): + # Try using the key from the key file + if os.path.isfile(KEY_FILE): + with open(KEY_FILE, 'r') as kf: + key = kf.read().strip() + print(Fore.YELLOW + f"Using key from {KEY_FILE} to decrypt the credentials file.") + decrypted_content, error = decrypt_credentials(ENC_FILE_PATH, key) + if error is None: + return decrypted_content + print(Fore.RED + error) + + # Prompt for password up to 3 times if the key file is not used or fails + for attempt in range(3): + password = getpass(f"Enter the password to decrypt the credentials file (attempt {attempt + 1}/3): ") + decrypted_content, error = decrypt_credentials(ENC_FILE_PATH, password) + if error is None: + return decrypted_content + print(Fore.RED + error) + + print(Fore.RED + "Failed to decrypt the file after 3 attempts. Exiting.") sys.exit(1) # Print the current configuration @@ -46,7 +88,7 @@ print(" - " + Fore.CYAN + "API_USERNAME:" + Fore.RESET + f" {API_USERNAME[0]}**********") print(" - " + Fore.CYAN + "API_PASSWORD:" + Fore.RESET + f" {API_PASSWORD[0]}**********") print(" - " + Fore.CYAN + "CRED_PATH:" + Fore.RESET + f" {CRED_PATH}") -print(" - " + Fore.CYAN + "CRED_FILE_NAME:" + Fore.RESET + f" {CRED_FILE_NAME}") +print(" - " + Fore.CYAN + "CRED_FILE_NAME:" + Fore.RESET + f" {CRED_FILE_NAME_ENC}") print(" - " + Fore.CYAN + "expected completion time:" + Fore.RESET + f" {expected_completion_time_seconds} seconds\n") # Check server health before proceeding @@ -63,7 +105,6 @@ print(Fore.RED + f"Failed to connect to server. Check the server address and try again.") sys.exit(1) - # Wait for user input to proceed print(Fore.YELLOW + "Registering credentials and Loading common Specs and Images takes time") if not args.yes: @@ -72,10 +113,9 @@ print(Fore.GREEN + "See you soon. :)") sys.exit(0) -# Load credentials from YAML file -with open(os.path.join(CRED_PATH, CRED_FILE_NAME), 'r') as file: - cred_data = yaml.safe_load(file)['credentialholder']['admin'] - +# Get the decryption key and decrypt the credentials file +decrypted_content = get_decryption_key() +cred_data = yaml.safe_load(decrypted_content)['credentialholder']['admin'] print(Fore.YELLOW + f"\nRegistering all valid credentials for all cloud regions...") @@ -123,7 +163,6 @@ def load_resources(): finally: event.set() # Signal that the request is complete regardless of success or failure - # Start time start_time = time.time() @@ -144,7 +183,6 @@ def load_resources(): # Wait for the thread to complete thread.join() - # Calculate duration end_time = time.time() duration = end_time - start_time @@ -178,4 +216,4 @@ def load_resources(): print(Fore.RESET + "Registered Common images") print(Fore.GREEN + f"- Successful: {successful_images}" + Fore.RESET + f", Failed: {failed_images}") else: - print(Fore.RED + "No data returned from the API.") \ No newline at end of file + print(Fore.RED + "No data returned from the API.") From 0c1fa0edb02dceb0c462f0011990e885a397275c Mon Sep 17 00:00:00 2001 From: Seokho Son Date: Mon, 22 Jul 2024 22:18:55 +0900 Subject: [PATCH 3/5] Describe how encryption works --- README.md | 13 +++++++++++++ scripts/init/README.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/README.md b/README.md index 1bade24b..39980a51 100644 --- a/README.md +++ b/README.md @@ -317,6 +317,19 @@ To provisioning multi-cloud infrastructures with CB-TB, it is necessary to regis ClientSecret: ... ``` + - Encrypt `credentials.yaml` into `credentials.yaml.enc` + To protect sensitive information, `credentials.yaml` is not used directly. Instead, it must be encrypted using `encCredential.sh`. The encrypted file `credentials.yaml.enc` is then used by `init.py`. This approach ensures that sensitive credentials are not stored in plain text. + + If you need to update your credentials, decrypt the encrypted file using `decCredential.sh`, make the necessary changes to `credentials.yaml`, and then re-encrypt it. + - Encrypting Credentials + ```bash + scripts/init/encCredential.sh + ``` + - Decrypting Credentials + ```bash + scripts/init/decCredential.sh + ``` + - Register all multi-cloud connection information and common resources - How to register diff --git a/scripts/init/README.md b/scripts/init/README.md index c8e98dfd..12d63975 100644 --- a/scripts/init/README.md +++ b/scripts/init/README.md @@ -15,6 +15,18 @@ The `init.py` script is designed to automate the process of registering credenti - The `python3-venv` package should be installed for running the script using `init.sh`. ## Usage + +### Encrypting Credentials +Before running `init.py`, you must encrypt your `credentials.yaml` file to ensure the security of your sensitive information. + +1. Use the `encCredential.sh` script to encrypt your `credentials.yaml` file: +```bash +scripts/init/encCredential.sh +``` + +The `init.py` script will decrypt the `credentials.yaml.enc` file as needed to read the credentials. You may need to provide a password if the decryption key is not stored. + + ### Direct Execution ```bash pip3 install -r requirements.txt @@ -42,9 +54,25 @@ Before running the script, ensure the following environment variables are set ac - `API_USERNAME`: Username for API authentication. - `API_PASSWORD`: Password for API authentication. +## Security Considerations +To protect sensitive information, `credentials.yaml` is not used directly. Instead, it must be encrypted using `encCredential.sh`. The encrypted file `credentials.yaml.enc` is then used by `init.py`. This approach ensures that sensitive credentials are not stored in plain text. + +If you need to update your credentials, decrypt the encrypted file using `decCredential.sh`, make the necessary changes to `credentials.yaml`, and then re-encrypt it. + +### Encrypting Credentials +```bash +scripts/init/encCredential.sh +``` + +### Decrypting Credentials +```bash +scripts/init/decCredential.sh +``` ## Related Files - `init.py`: Main Python script. - `requirements.txt`: Contains all Python dependencies. - `init.sh`: Bash script for setting up a Python virtual environment and running `init.py`. - `credentials.yaml`: Contains the credentials data to be registered with the Tumblebug server. +- `encCredential.sh`: Script to encrypt `credentials.yaml`. +- `decCredential.sh`: Script to decrypt `credentials.yaml.enc`. \ No newline at end of file From b1653571bbcf6874d09a7cc962ffce406ee89041 Mon Sep 17 00:00:00 2001 From: Seokho Son Date: Tue, 23 Jul 2024 20:44:43 +0900 Subject: [PATCH 4/5] Add warning message about using temporal key file --- scripts/init/decCredential.sh | 5 +++++ scripts/init/encCredential.sh | 35 +++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/scripts/init/decCredential.sh b/scripts/init/decCredential.sh index f7f0c456..ac325d8d 100755 --- a/scripts/init/decCredential.sh +++ b/scripts/init/decCredential.sh @@ -40,6 +40,8 @@ fi # Prompt for password or use the key file if [ -f "$KEY_FILE" ]; then TB_CRED_DECRYPT_KEY=$(cat "$KEY_FILE") + echo -e "\n${YELLOW}Using the temporary key file for decryption: ${CYAN}$KEY_FILE${NC}" + echo -e "${RED}Warning: It is not recommended to use temporary key file continuously. Please manage the key securely and delete the file after use.${NC}" else read -sp "Enter the password: " PASSWORD echo @@ -64,6 +66,9 @@ if [ $? -eq 0 ]; then echo -e "(Encrypted file deleted: $ENCRYPTED_FILE)\n" else echo -e "\n${RED}Failed to decrypt the file. Exiting.${NC}\n" + if [ -f "$KEY_FILE" ]; then + echo -e "${RED}Failed to decrypt the file using the key file. Please delete the key file and retry with manual password input.${NC}" + fi echo -e "${RED}log: ${DECRYPT_OUTPUT}${NC}\n" rm -f "$TEMP_DECRYPTED_FILE" # Remove the temporary file if decryption failed exit 1 diff --git a/scripts/init/encCredential.sh b/scripts/init/encCredential.sh index a929f4b0..06ff8dd8 100755 --- a/scripts/init/encCredential.sh +++ b/scripts/init/encCredential.sh @@ -58,7 +58,8 @@ while true; do done # Prompt for password -read -sp "Enter a password (press enter to generate a random key): " PASSWORD +echo -e "Enter a password (press ${YELLOW}enter${NC} to generate a random key): \c" +read -sp "" PASSWORD echo if [ -n "$PASSWORD" ]; then read -sp "Confirm the password: " PASSWORD_CONFIRM @@ -76,9 +77,31 @@ if [ -n "$PASSWORD" ]; then else # Generate a random key TB_CRED_DECRYPT_KEY=$(openssl rand -base64 64 | tr -d '\n') - echo "$TB_CRED_DECRYPT_KEY" > "$KEY_FILE" - echo -e "\n${YELLOW}A random encryption key was generated and saved to ${CYAN}$KEY_FILE${NC}" - echo -e "${YELLOW}This file should be used temporarily. Please store the key securely.${NC}\n" + echo -e "${YELLOW}A random key has been generated for encryption.${NC}\n" + while true; do + echo -e "Do you want to ${YELLOW}save${NC} the key to a temporary file or ${LGREEN}print${NC} it to stdout? (${YELLOW}s${NC}/${LGREEN}p${NC}): \c" + read -e OUTPUT_OPTION + case $OUTPUT_OPTION in + s ) + echo "$TB_CRED_DECRYPT_KEY" > "$KEY_FILE" + echo -e "\n${LGREEN}The encryption key has been saved to: ${CYAN}$KEY_FILE${NC}" + echo -e "${RED}Warning: It is not recommended to use this temporary file continuously. Please manage the key securely and delete the file after use.${NC}" + break + ;; + p ) + echo -e "\n${LGREEN}Encryption Key: ${CYAN}$TB_CRED_DECRYPT_KEY${NC}" + echo -e "${RED}Warning: Please copy and manage the key securely. This key will not be shown again.${NC}" + # Delete the existing key file if any + if [ -f "$KEY_FILE" ]; then + rm "$KEY_FILE" + fi + break + ;; + * ) + echo -e "${RED}Please answer 's' for save or 'p' for print.${NC}" + ;; + esac + done fi # Encrypt the file @@ -90,8 +113,8 @@ if [ $? -eq 0 ]; then if [ $? -eq 0 ] && cmp -s "$FILE_PATH" "$TEMP_DECRYPTED_FILE"; then rm "$TEMP_DECRYPTED_FILE" rm "$FILE_PATH" - echo -e "\n${LGREEN}File successfully encrypted: ${CYAN}$ENCRYPTED_FILE${NC}" - echo -e "${LGREEN}Original file deleted: ${CYAN}$FILE_PATH${NC}\n" + echo -e "\n${YELLOW}File successfully encrypted${NC}: ${CYAN}$ENCRYPTED_FILE${NC}" + echo -e "(Original file deleted: ${CYAN}$FILE_PATH${NC})\n" echo -e "${YELLOW}To edit the credentials,${NC}" echo -e "Use ${CYAN}$DECRYPT_SCRIPT_PATH${NC} to decrypt the file" echo -e "Then edit ${CYAN}$FILE_PATH${NC}\n" From 275d5a800bd398d30efafe7dfcf1a483fd6e478a Mon Sep 17 00:00:00 2001 From: Seokho Son Date: Tue, 23 Jul 2024 20:54:21 +0900 Subject: [PATCH 5/5] Change tmp key file name --- scripts/init/decCredential.sh | 2 +- scripts/init/encCredential.sh | 2 +- scripts/init/init.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/init/decCredential.sh b/scripts/init/decCredential.sh index ac325d8d..01b1f98d 100755 --- a/scripts/init/decCredential.sh +++ b/scripts/init/decCredential.sh @@ -13,7 +13,7 @@ CRED_PATH="$HOME/.cloud-barista" FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" ENCRYPTED_FILE="$FILE_PATH.enc" TEMP_DECRYPTED_FILE="$FILE_PATH.tmp" -KEY_FILE="$CRED_PATH/cred_key" +KEY_FILE="$CRED_PATH/.tmp_enc_key" # Check if OpenSSL is installed if ! command -v openssl &> /dev/null; then diff --git a/scripts/init/encCredential.sh b/scripts/init/encCredential.sh index 06ff8dd8..4c12be1e 100755 --- a/scripts/init/encCredential.sh +++ b/scripts/init/encCredential.sh @@ -13,7 +13,7 @@ CRED_PATH="$HOME/.cloud-barista" FILE_PATH="$CRED_PATH/$CRED_FILE_NAME" ENCRYPTED_FILE="$FILE_PATH.enc" TEMP_DECRYPTED_FILE="$FILE_PATH.tmp.dec" -KEY_FILE="$CRED_PATH/cred_key" +KEY_FILE="$CRED_PATH/.tmp_enc_key" SCRIPT_DIR=$(dirname "$(realpath "$0")") DECRYPT_SCRIPT_PATH="$SCRIPT_DIR/decCredential.sh" diff --git a/scripts/init/init.py b/scripts/init/init.py index 32dd61d2..882c2538 100755 --- a/scripts/init/init.py +++ b/scripts/init/init.py @@ -31,7 +31,7 @@ CRED_FILE_NAME_ENC = "credentials.yaml.enc" CRED_PATH = os.path.join(os.path.expanduser('~'), '.cloud-barista') ENC_FILE_PATH = os.path.join(CRED_PATH, CRED_FILE_NAME_ENC) -KEY_FILE = os.path.join(CRED_PATH, "cred_key") +KEY_FILE = os.path.join(CRED_PATH, ".tmp_enc_key") expected_completion_time_seconds = 240