Last active
April 29, 2025 14:27
-
-
Save tsallou/bb4a3156a55e03c675d1be5b27be846f to your computer and use it in GitHub Desktop.
Gcloud PAM TUI
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 | |
# Define project list and folder mapping (ID -> Display Name) | |
projects=("project_id_a" "project_id_b" "project_id_c") | |
declare -A folders | |
folders=( | |
["folder_id_1"]="Folder 1" | |
["folder_id_2"]="Folder 2" | |
) | |
# Function to display a menu and return the selected item | |
select_from_list() { | |
local prompt="$1" | |
shift | |
local options=("$@") | |
local menu_items=() | |
for i in "${!options[@]}"; do | |
menu_items+=("$i" "${options[i]}") | |
done | |
dialog --clear --menu "$prompt" 15 50 10 "${menu_items[@]}" 3>&1 1>&2 2>&3 | |
} | |
# Function to map folder display name back to folder ID | |
get_folder_id() { | |
local display_name="$1" | |
for folder_id in "${!folders[@]}"; do | |
if [[ "${folders[$folder_id]}" == "$display_name" ]]; then | |
echo "$folder_id" | |
return | |
fi | |
done | |
} | |
# Ensure dialog is installed | |
if ! command -v dialog &> /dev/null; then | |
echo "Error: 'dialog' is not installed. Please install it and try again." | |
echo "For example, on Debian/Ubuntu: sudo apt-get install dialog" | |
exit 1 | |
fi | |
# Prepare the combined selection list | |
scopes_list=("${projects[@]}") | |
for folder_id in "${!folders[@]}"; do | |
scopes_list+=("${folders[$folder_id]}") | |
done | |
# Let the user select a project or folder | |
scope_index=$(select_from_list "Select a Project or Folder:" "${scopes_list[@]}") | |
selected_scope="${scopes_list[$scope_index]}" | |
# Determine scope type and internal scope | |
if [[ " ${projects[*]} " =~ " ${selected_scope} " ]]; then | |
scope_type="project" | |
internal_scope="$selected_scope" | |
else | |
scope_type="folder" | |
internal_scope=$(get_folder_id "$selected_scope") | |
fi | |
scopes="$scope_type/$internal_scope" | |
# Fetch roles dynamically using gcloud command and suppress stderr | |
roles_output=$(gcloud pam entitlements search --location=global --caller-access-type=grant-requester --$scope_type="$internal_scope" --format="value(privilegedAccess.gcpIamAccess.roleBindings[].role, name.segment(5))" 2>/dev/null) | |
# Handle empty output | |
if [[ -z "$roles_output" ]]; then | |
dialog --msgbox "No roles found for the selected $scope_type: $selected_scope" 10 50 | |
clear | |
exit 1 | |
fi | |
# Parse roles and sort by role names alphabetically | |
IFS=$'\n' | |
read -r -d '' -a roles <<< "$roles_output" | |
sorted_roles=$(printf "%s\n" "${roles[@]}" | sort) | |
role_names=() | |
entitlement_ids=() | |
while IFS= read -r role; do | |
role_names+=("$(echo "$role" | awk '{print $1}')") # First field: role name | |
entitlement_ids+=("$(echo "$role" | awk '{print $2}')") # Second field: entitlement ID | |
done <<< "$sorted_roles" | |
# Select a role | |
role_index=$(select_from_list "Select a Role for $scope_type: $selected_scope" "${role_names[@]}") | |
selected_role="${role_names[$role_index]}" | |
selected_entitlement="${entitlement_ids[$role_index]}" | |
# Input duration and justification | |
duration_minutes=$(dialog --clear --inputbox "Enter Duration (in minutes):" 8 50 30 3>&1 1>&2 2>&3) | |
duration_seconds=$((duration_minutes * 60)) | |
justification=$(dialog --clear --inputbox "Enter Justification:" 8 50 "" 3>&1 1>&2 2>&3) | |
# Confirm the selections | |
dialog --msgbox "Selected Scope: $scopes\nSelected Role: $selected_role\nDuration: $duration_seconds seconds\nJustification: $justification" 10 50 | |
# Construct and execute the gcloud command | |
gcloud_command="gcloud pam grants create --entitlement=$selected_entitlement --$scope_type=$internal_scope --location=global --requested-duration=${duration_seconds}s --justification=\"$justification\"" | |
command_output=$(eval "$gcloud_command" 2>&1) | |
command_status=$? | |
# Display the result | |
if [[ $command_status -eq 0 ]]; then | |
dialog --msgbox "Command executed successfully:\n$gcloud_command" 15 50 | |
else | |
dialog --msgbox "Command execution failed with status $command_status:\n\nLogs:\n$command_output" 15 60 | |
fi | |
# Cleanup and exit | |
clear |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment