Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save markjacksonfishing/96403920f74432ff405b463b90dea8d2 to your computer and use it in GitHub Desktop.
Save markjacksonfishing/96403920f74432ff405b463b90dea8d2 to your computer and use it in GitHub Desktop.
backstage-k8s-debug.sh
#!/bin/bash -e
# --------------------------------------------------------------
# Backstage Kubernetes Debug Script
# --------------------------------------------------------------
# This script helps troubleshoot and validate the integration
# between a Backstage app and a Kubernetes cluster (AKS). It:
# 1. Checks if the required command-line tools (Azure CLI and kubectl) are installed.
# 2. Verifies Azure login status.
# 3. Assigns the necessary RBAC role to a specified service principal or user.
# 4. Checks Kubernetes RBAC configuration.
# 5. Tests access to the Kubernetes API using the service account token.
# 6. Validates and automatically corrects the Backstage `app-config.yaml` for necessary fields and configuration correctness.
# 7. Logs all operations and errors to a file named `debug.log`.
# 8. Restarts Backstage automatically if configurations were changed.
#
# Usage Instructions:
# 1. Save this script to a file, for example: `backstage-k8s-debug.sh`.
# 2. Make the script executable:
# chmod +x backstage-k8s-debug.sh
# 3. Run the script:
# ./backstage-k8s-debug.sh
# 4. Follow the prompts and review the log file `debug.log` for detailed output.
#
# All rights reserved © Anuclei 2024
# --------------------------------------------------------------
# Log file
LOGFILE="debug.log"
: > "$LOGFILE"
# Function to log and display messages
log() {
echo "$1"
echo "$(date): $1" >> "$LOGFILE"
}
# Function to handle errors
error_exit() {
log "Error: $1"
exit 1
}
# Function to check command existence
check_command() {
if ! command -v "$1" &> /dev/null; then
error_exit "$1 is not installed. Please install it before running this script."
else
log "$1 is installed."
fi
}
# Function to verify if a file contains specific fields
verify_config_fields() {
local config_file=$1
shift
local fields=("$@")
for field in "${fields[@]}"; do
if grep -q "$field" "$config_file"; then
log "Field '$field' found in $config_file."
else
log "Field '$field' NOT found in $config_file. Automatically adding it."
echo " $field: ADD_DEFAULT_VALUE" >> "$config_file"
RESTART_NEEDED=true
fi
done
}
# Function to automatically update authProvider to serviceAccount
ensure_auth_provider_is_service_account() {
local config_file=$1
local cluster_name=$2
if grep -q "authProvider: \"serviceAccount\"" "$config_file"; then
log "authProvider is already set to 'serviceAccount'."
else
log "authProvider is NOT set to 'serviceAccount'. Automatically updating it."
sed -i "/- name: \"$cluster_name\"/a \ \ \ \ authProvider: \"serviceAccount\"" "$config_file"
log "authProvider set to 'serviceAccount' in $config_file."
RESTART_NEEDED=true
fi
}
# Function to validate and correct Kubernetes API server URL
validate_and_correct_k8s_api_url() {
local api_url=$1
if [[ $api_url =~ ^https:// ]]; then
log "Kubernetes API server URL appears valid."
else
log "Kubernetes API server URL may be incorrect. Automatically correcting it."
read -p "Enter the correct Kubernetes API server URL: " new_url
sed -i "s|$api_url|$new_url|g" "$APP_CONFIG_PATH"
log "Kubernetes API server URL updated to '$new_url' in $APP_CONFIG_PATH."
RESTART_NEEDED=true
fi
}
# Prompting user inputs
read -p "Enter your Azure Subscription ID: " SUBSCRIPTION_ID
read -p "Enter your Resource Group Name: " RESOURCE_GROUP
read -p "Enter your AKS Cluster Name: " AKS_CLUSTER_NAME
read -p "Enter your Service Principal or User ID for role assignment: " ASSIGNEE_ID
read -p "Enter the path to your app-config.yaml file (default: ./app-config.yaml): " APP_CONFIG_PATH
APP_CONFIG_PATH=${APP_CONFIG_PATH:-./app-config.yaml}
# Checking for required tools
log "Checking required command-line tools..."
check_command "az"
check_command "kubectl"
# Verifying Azure login status
log "Checking Azure login status..."
if ! az account show &> /dev/null; then
error_exit "Not logged in to Azure. Please login using 'az login'."
else
log "Azure login verified."
fi
# Assigning role to Service Principal/User
log "Assigning 'Azure Kubernetes Service RBAC Cluster Admin' role..."
az role assignment create \
--assignee "$ASSIGNEE_ID" \
--role "Azure Kubernetes Service RBAC Cluster Admin" \
--scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.ContainerService/managedClusters/$AKS_CLUSTER_NAME" &>> "$LOGFILE"
if [ $? -eq 0 ]; then
log "Role assignment successful."
else
error_exit "Role assignment failed. Please check the provided inputs."
fi
# Checking Kubernetes RBAC configuration
log "Checking Kubernetes RBAC configuration for cluster '$AKS_CLUSTER_NAME'..."
if kubectl get clusterrolebinding | grep -q "$ASSIGNEE_ID"; then
log "Kubernetes RBAC configuration appears correct."
else
log "Kubernetes RBAC configuration might be missing. Please check manually."
fi
# Extracting service account token from app-config.yaml
log "Extracting service account token from $APP_CONFIG_PATH..."
SERVICE_ACCOUNT_TOKEN=$(grep -Po '(?<=serviceAccountToken:\s)\S+' "$APP_CONFIG_PATH")
if [ -z "$SERVICE_ACCOUNT_TOKEN" ]; then
error_exit "Service account token not found in $APP_CONFIG_PATH. Please ensure it's correctly configured."
else
log "Service account token extracted successfully."
fi
# Checking access to Kubernetes API using the service account token
log "Testing access to Kubernetes API using the service account token..."
if kubectl --token="$SERVICE_ACCOUNT_TOKEN" get nodes &>> "$LOGFILE"; then
log "Access to Kubernetes API using the service account token is working."
else
error_exit "Access to Kubernetes API using the service account token failed. Please check the token's permissions and configuration."
fi
# Verifying Backstage Kubernetes plugin configuration
log "Checking Backstage Kubernetes plugin configuration in $APP_CONFIG_PATH..."
if [ -f "$APP_CONFIG_PATH" ]; then
log "app-config.yaml file found."
# Define required fields and verify them
REQUIRED_FIELDS=("kubernetes" "clusters" "serviceAccountToken" "baseUrl")
verify_config_fields "$APP_CONFIG_PATH" "${REQUIRED_FIELDS[@]}"
# Additional checks for specific configurations
if grep -q "kubernetes" "$APP_CONFIG_PATH"; then
log "Kubernetes configuration detected in app-config.yaml."
# Validate and correct Kubernetes API server URL
K8S_API_URL=$(grep -Po '(?<=url:\s)\S+' "$APP_CONFIG_PATH")
validate_and_correct_k8s_api_url "$K8S_API_URL"
# Ensure authProvider is set to serviceAccount
ensure_auth_provider_is_service_account "$APP_CONFIG_PATH" "$AKS_CLUSTER_NAME"
# Check for potential misconfigurations
if grep -q "localhost" "$APP_CONFIG_PATH"; then
log "Warning: 'localhost' found in app-config.yaml. Automatically correcting it."
read -p "Enter the correct Kubernetes API server URL: " correct_url
sed -i "s|localhost|$correct_url|g" "$APP_CONFIG_PATH"
log "Kubernetes API server URL updated from 'localhost' to '$correct_url' in $APP_CONFIG_PATH."
RESTART_NEEDED=true
fi
else
error_exit "Kubernetes configuration not found in app-config.yaml. Please ensure it's correctly configured."
fi
else
error_exit "app-config.yaml file not found at '$APP_CONFIG_PATH'. Please ensure the path is correct."
fi
# Restart Backstage if any changes were made
if [ "$RESTART_NEEDED" = true ]; then
log "Changes were made to the configuration. Restarting Backstage..."
# Replace with your actual Backstage restart command
if systemctl is-active --quiet backstage; then
sudo systemctl restart backstage
elif command -v docker-compose &> /dev/null; then
docker-compose restart backstage
elif command -v pm2 &> /dev/null; then
pm2 restart backstage
else
log "No suitable restart method found. Please restart Backstage manually."
fi
log "Backstage restarted successfully."
else
log "No restart needed."
fi
log "Script execution completed. Please review the log file '$LOGFILE' for details."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment