diff --git a/bin/saml.sh b/bin/saml.sh index 034639c..33165db 100644 --- a/bin/saml.sh +++ b/bin/saml.sh @@ -3,6 +3,50 @@ CONFIG_DIR="$HOME/.saml-auth" CONFIG_FILE="$CONFIG_DIR/saml_profile.config" VERSION="v7.0.0" +REGIONS=( + "eu-west-1" + "eu-central-1" +) + +########################################### +############ HELPER FUNCTIONS ############# +########################################### +is_number() { + local input="$1" + [[ "$input" =~ ^[0-9]+$ ]] +} + +is_comma_separated_numbers() { + local input="$1" + [[ "$input" =~ ^[0-9]+(,[0-9]+)*$ ]] +} + +is_valid_index() { + local index="$1" + local array_size="$2" + if is_number "$index" && (( index >= 1 && index <= array_size )); then + return 0 + else + return 1 + fi +} + +print_numbered_list() { + local array_name=$1 + local header=$2 + + echo "$header" + local i=1 + eval "local arr=(\"\${${array_name}[@]}\")" + for item in "${arr[@]}"; do + echo "$i) $item" + ((i++)) + done +} + +########################################### +############ MAIN FUNCTIONS ############### +########################################### # Function to load profiles from the configuration file load_profiles() { @@ -12,6 +56,11 @@ load_profiles() { else profiles=() fi + + if [ ${#profiles[@]} -eq 0 ]; then + echo "No profiles found. Please run 'saml config' to configure profiles." + exit 1 + fi } # Function to save profiles to the configuration file @@ -37,32 +86,209 @@ config_profiles() { echo "Profiles saved to $CONFIG_FILE" } +# Function to read saved credentials if they exist +read_credentials() { + # Email + if [ -z "$email" ]; then + read -r -p "Enter the email: " email + else + echo "Email set to: $email" + read -r -p "Press Enter to confirm or enter a new email: " new_email + if [ -n "$new_email" ]; then + email="$new_email" + fi + fi + export SAML_EMAIL="$email" + + # Password + if [ -z "$SAML_PASSWORD" ]; then + read -s -p "Enter the password: " SAML_PASSWORD + export SAML_PASSWORD + fi +} + +# Function to replace profile in ~/.saml2aws and log in +login_with_profile() { + local profile=$1 + echo "Replacing aws_profile with '$profile' in ~/.saml2aws configuration file" + sed -i '' '/aws_profile/d' ~/.saml2aws + echo "aws_profile = $profile" >> ~/.saml2aws + + echo "Logging in with profile '$profile'" + + read_credentials + # Execute saml2aws login using the current profile + saml2aws login --force --username="$SAML_EMAIL" --password="$SAML_PASSWORD" --skip-prompt + + echo "---------------------------------------------" +} + +# Function to get array of all kubeconfig contexts +get_all_kubeconfig_contexts() { + kubectl config get-contexts -o name +} + +# Function to switch kubeconfig context based on selected profile and cluster +switch_context_from_profile() { + local selected_profile="$1" + + if [ -z "$selected_profile" ]; then + echo "No profile provided to switch_context function." + return 1 + fi + + echo "Validating authentication for profile: $selected_profile" + aws sts get-caller-identity --profile "$selected_profile" > /dev/null 2>&1 + + if [ $? -ne 0 ]; then + echo "❌ Failed to validate authentication for profile $selected_profile, Triggering 'saml login'." + login_with_profile "$profile" + fi + + while true; do + echo "Fetching EKS clusters for profile: $selected_profile" + clusters=() + for region in "${REGIONS[@]}"; do + region_clusters=$(aws eks list-clusters --output text --profile "$selected_profile" --region "$region" | awk '{print $2}') + + while read -r cluster; do + if [ -n "$cluster" ]; then + clusters+=("$cluster|$region") + fi + done <<< "$region_clusters" + done + + if [ ${#clusters[@]} -eq 0 ]; then + echo "No clusters found for profile $selected_profile." + return 1 + fi + + echo "Available EKS Clusters:" + i=1 + for entry in "${clusters[@]}"; do + cluster_name="${entry%%|*}" + cluster_region="${entry##*|}" + echo "$i) $cluster_name (Region: $cluster_region)" + ((i++)) + done + + read -r -p "Enter the number of the cluster you want to switch to: " cluster_index + + # Validate Input + if ! is_number "$cluster_index"; then + echo "Invalid input. Please enter a number." + continue + fi + + if ! is_valid_index "$cluster_index" "${#clusters[@]}"; then + echo "Invalid selection. Please choose a number between 1 and ${#clusters[@]}." + continue + fi + + selected_entry="${clusters[$((cluster_index-1))]}" + selected_cluster="${selected_entry%%|*}" + selected_region="${selected_entry##*|}" + + if aws eks update-kubeconfig --region "$selected_region" --name "$selected_cluster" --profile "$selected_profile" --alias $selected_cluster > /dev/null 2>&1; then + echo "✅ Switched kubeconfig context to cluster '$selected_cluster' in region '$selected_region' using profile '$selected_profile'" + break + else + echo "❌ Failed to switch context." + fi + done +} + +switch_context_from_kubeconfig() { + local context="$1" + kubectl config use-context "$context" > /dev/null 2>&1 + + if [ $? -eq 0 ]; then + echo "✅ Switched kubeconfig context to '$context'" + else + echo "❌ Failed to switch kubeconfig context to '$context'" + fi +} + +function update_kubeconfig() { + local profile="$1" + for region in "${REGIONS[@]}"; do + # Get a list of available EKS clusters for the current profile and region + clusters=$(aws eks list-clusters --output text --profile "$profile" --region "$region" | awk '{print $2}') + + # Iterate over each cluster + while read -r cluster; do + # Execute the update-kubeconfig command + if aws eks update-kubeconfig --region "$region" --name "$cluster" --profile "$profile" --alias $cluster > /dev/null 2>&1; then + echo "Updated kubeconfig for cluster $cluster in region $region using profile $profile" + else + echo "Failed to update kubeconfig for cluster $cluster in region $region using profile $profile" + fi + done <<< "$clusters" + done +} + +function whitelist_profiles() { + # Add a note about Production Accounts as a banner + echo "############################################################" + echo "# #" + echo "# Note: This step is only for Production Accounts as #" + echo "# Lower accounts are opened by default to 0.0.0.0/0. #" + echo "# #" + echo "############################################################" + + # Prompt the user to proceed with whitelisting IP to EKS clusters + read -r -p "Do you want to proceed with whitelisting your IP to EKS Clusters? (yes/no): " proceed + + if [ "$proceed" == "yes" ]; then + # Run the eks.sh script + "eks" + else + echo "Whitelisting operation was canceled." + fi +} + # Function to display help information display_help() { cat < /dev/null; then + echo "❌ Required command '$cmd' not found. Please install it." + exit 1 fi -fi - -# Call the function to read the password -read_password "Enter the password: " - -# Display the list of profiles and prompt user to choose profiles -echo "Available AWS Accounts:" -i=1 -for profile in "${profiles[@]}"; do - echo "$i) $profile" - ((i++)) done -read -r -p "Enter the numbers of the profiles you want to use, separated by commas (e.g., 1,3,5): " selected_profiles +# Read selected profiles from the user input +if [ "$1" == "context" ]; then + ############ Handle Context Switching ################ -# Convert the selection to an array of indices -IFS=',' read -ra profile_indices <<< "$selected_profiles" + actions=("Select context from current kubeconfig" "Select context from profile") + print_numbered_list actions "Available actions:" + read -r -p "Choose an option to select a context: " switch_context_action -# Function to replace profile in ~/.saml2aws and log in -login_with_profile() { - local profile=$1 - echo "Replacing aws_profile with '$profile' in ~/.saml2aws configuration file" - sed -i '' '/aws_profile/d' ~/.saml2aws - echo "aws_profile = $profile" >> ~/.saml2aws - - echo "Logging in with profile '$profile'" - - # Execute saml2aws login using the current profile - saml2aws login --force --username="$SAML_EMAIL" --password="$password" --skip-prompt - - echo "---------------------------------------------" -} - -# Loop through each selected profile and log in -for index in "${profile_indices[@]}"; do - profile=${profiles[$((index-1))]} - if [ -n "$profile" ]; then - login_with_profile "$profile" + if [ "$switch_context_action" == "1" ]; then + switch_context_profile=$(get_all_kubeconfig_contexts | fzf --prompt="Select kube context: ") + switch_context_from_kubeconfig $switch_context_profile else - echo "Invalid profile selection: $index. Skipping." + # Load profiles from the configuration file + load_profiles + + # Display the list of profiles and prompt user to choose profiles + print_numbered_list profiles "Available AWS Accounts:" + + read -r -p "Enter the numbers of the profile you want to use (Only One): " switch_context_profile + + # Validate Input + if ! is_number "$switch_context_profile"; then + echo "Invalid input. Please enter a number." + exit 1 + fi + + profile=${profiles[$((switch_context_profile-1))]} + if [ -n "$profile" ]; then + switch_context_from_profile "$profile" + else + echo "Invalid profile selection: $switch_context_profile." + exit 1 + fi fi -done -echo "Completed replacing all selected profiles and logging in." +else + ############ Handle Login ################ -# Clear the password variable after use -unset password + # Load profiles from the configuration file + load_profiles -regions=( - "eu-west-1" - "eu-central-1" -) + # Display the list of profiles and prompt user to choose profiles + print_numbered_list profiles "Available AWS Accounts:" -# Iterate over each region and selected profile -for region in "${regions[@]}"; do + read -r -p "Enter the numbers of the profiles you want to use, separated by commas (e.g., 1,3,5): " login_profiles + + # Validate Input + if ! is_comma_separated_numbers "$login_profiles"; then + echo "Invalid input. Please enter a comma seperated number." + exit 1 + fi + + # Convert the selection to an array of indices + IFS=',' read -ra profile_indices <<< "$login_profiles" + + # Loop through each selected profile and log in for index in "${profile_indices[@]}"; do profile=${profiles[$((index-1))]} if [ -n "$profile" ]; then - # Get a list of available EKS clusters for the current profile and region - clusters=$(aws eks list-clusters --output text --profile "$profile" --region "$region" | awk '{print $2}') - - # Iterate over each cluster - while read -r cluster; do - # Execute the update-kubeconfig command - if aws eks update-kubeconfig --region "$region" --name "$cluster" --profile "$profile"; then - echo "Updated kubeconfig for cluster $cluster in region $region using profile $profile" - else - echo "Failed to update kubeconfig for cluster $cluster in region $region using profile $profile" - fi - done <<< "$clusters" + login_with_profile "$profile" + update_kubeconfig "$profile" + else + echo "Invalid profile selection: $index. Skipping." fi done -done - -# Add a note about Production Accounts as a banner -echo "############################################################" -echo "# #" -echo "# Note: This step is only for Production Accounts as #" -echo "# Lower accounts are opened by default to 0.0.0.0/0. #" -echo "# #" -echo "############################################################" - -# Prompt the user to proceed with whitelisting IP to EKS clusters -read -r -p "Do you want to proceed with whitelisting your IP to EKS Clusters? (yes/no): " proceed - -if [ "$proceed" == "yes" ]; then - # Run the eks.sh script - "eks" -else - echo "Whitelisting operation was canceled." -fi +fi \ No newline at end of file