Last active
August 8, 2024 16:02
-
-
Save markjacksonfishing/96403920f74432ff405b463b90dea8d2 to your computer and use it in GitHub Desktop.
backstage-k8s-debug.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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