-
Notifications
You must be signed in to change notification settings - Fork 2
/
update-root-pass.sh
executable file
·199 lines (173 loc) · 6.42 KB
/
update-root-pass.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/bin/bash
# ANSI color codes
GREEN="\033[1;32m"
RED="\033[1;31m"
BLUE="\033[1;34m"
BOLD="\033[1m"
RESET="\033[0m"
# Initialize variables
PASSWORD=""
PASSWORD_HASH=""
OUTPUT_FILE=""
LIST_ONLY=0
MODE="search" # Default mode is search
HOSTS_INPUT=""
INVALID_OPTION=0
# Function to display help
function display_help() {
echo -e "${BOLD}Usage:${RESET} ${BLUE}$0 [options] [--hosts 'host1 host2'] <search-query>${RESET}\n"
echo -e "${BOLD}Description:${RESET} Lets you update the root passwords on multiple servers using Chef's knife tool. Search queries supported. Verifies that the password was changed. You need SSH access and sudo privileges on the servers.\n"
echo -e "${BOLD}Options:${RESET}"
echo -e " ${BLUE}-p${RESET} Specify the password in clear text (will be hashed)."
echo -e " ${BLUE}-h${RESET} Specify an existing password hash to use."
echo -e " ${BLUE}-o${RESET} Specify an output file to save the results."
echo -e " ${BLUE}-l${RESET} List the machines without changing passwords."
echo -e " ${BLUE}--hosts${RESET} Specify a list of hosts separated by space."
echo -e " ${BLUE}--help${RESET} Display this help message.\n"
echo -e "${BOLD}Example:${RESET}"
echo -e " ${BLUE}$0 -l -o results.txt 'platform:centos'${RESET} - List all CentOS machines without changing passwords and save the results to a file."
echo -e " ${BLUE}$0 -p 'myPassword123' --hosts 'host1 host2'${RESET} - Changes password on all hosts specified in the list."
echo -e " ${BLUE}$0 -p 'myPassword123' 'name:*'${RESET} - Changes password on all nodes in the Chef server matching the search query."
echo -e " ${BLUE}$0 -p 'myPassword123' -h '\$6\$saltsalt\$hashedpasswordhere' 'name:*'${RESET} - Changes password on all nodes in the Chef server matching the search query using the specified password hash."
}
check_dependencies() {
# Initialize an error flag
local error=0
# Check for knife
if ! command -v knife &> /dev/null; then
echo "knife is required but it's not installed. Please install it." >&2
error=1
fi
# Check for sshpass
if ! command -v sshpass &> /dev/null; then
echo "sshpass is required but it's not installed. Please install it." >&2
error=1
fi
# Check for openssl
if ! command -v openssl &> /dev/null; then
echo "openssl is required but it's not installed. Please install it." >&2
error=1
fi
# Return the error flag
return $error
}
if ! check_dependencies; then
echo "Some dependencies are missing. Please install them before proceeding." >&2
exit 1
fi
# Parse options
while [[ "$#" -gt 0 ]]; do
case $1 in
-p) PASSWORD="$2"; shift ;;
-h) PASSWORD_HASH="$2"; shift ;;
-o) OUTPUT_FILE="$2"; shift ;;
-l) LIST_ONLY=1 ;;
--hosts) HOSTS_INPUT="$2"; MODE="list"; shift ;;
--help) display_help; exit 0 ;;
*)
if [[ -n $1 && $1 != -* ]]; then
SEARCH_QUERY="$1"
else
echo -e "${RED}${BOLD}Invalid option:${RESET}${RED} $1${RESET}" >&2
INVALID_OPTION=1
fi ;;
esac
shift
done
# Check for invalid option
if [[ $INVALID_OPTION -eq 1 ]]; then
echo -e "\nUse ${BLUE}$0 --help${RESET} to display usage information."
exit 1
fi
# Check for required password or hash unless listing only
if { [ -z "$PASSWORD" ] && [ "$LIST_ONLY" -ne 1 ]; } || { [ -n "$PASSWORD_HASH" ] && [ -z "$PASSWORD" ]; }; then
echo -e "${RED}${BOLD}Error:${RESET}${RED} A password is required.${RESET}\n" >&2
echo -e "Use ${BLUE}$0 --help${RESET} to display usage information."
exit 1
fi
# If a clear text password is provided, and there is no hash, create a hash
if [ -n "$PASSWORD" ] && [ -z "$PASSWORD_HASH" ]; then
PASSWORD_HASH=$(openssl passwd -6 "$PASSWORD")
echo -e "${GREEN}Generated password hash:${RESET} $PASSWORD_HASH\n"
fi
# Encode PASSWORD_HASH to base64 (or it will most likely mess things up)
ENCODED_CHPASSWD_IN=$(echo -n "root:$PASSWORD_HASH" | base64 -w0)
main() {
# Use knife to get a list of nodes based on the search query
if [ "$MODE" = "search" ]; then
HOSTS=$(knife search node "$SEARCH_QUERY" -a name -F json | jq -r '.rows[] | to_entries[] | .key')
else
HOSTS=$HOSTS_INPUT
fi
# Initialize result arrays
SUCCESSFUL_HOSTS=()
FAILED_HOSTS=()
# Clear the output file if it exists
if [ -n "$OUTPUT_FILE" ]; then
> "$OUTPUT_FILE"
fi
if [ "$LIST_ONLY" -eq 1 ]; then
echo "Performing actions on the following nodes:"
fi
# Perform actions on nodes
for host in $HOSTS; do
if [ "$LIST_ONLY" -eq 1 ]; then
if [ -n "$OUTPUT_FILE" ]; then
echo "- $host" | tee -a "$OUTPUT_FILE"
else
echo "- $host"
fi
else
echo "- Updating password for root on $host"
# Update the password using knife ssh
knife ssh "name:$host" "echo $ENCODED_CHPASSWD_IN | base64 --decode | sudo /usr/sbin/chpasswd -e" -y
S=$?
case $S in
0) echo " - Sent new password" ;;
10) echo " - Host not found (did not match name registered in Chef?)"
FAILED_HOSTS+=("$host")
continue ;;
*) echo " - Failed"
FAILED_HOSTS+=("$host")
continue ;;
esac
echo " - Verifying password change"
# Verify the password change by attempting to SSH into the server using sshpass
if sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no -o PreferredAuthentications=password root@$host 'exit'; then
echo " - Success"
SUCCESSFUL_HOSTS+=("$host")
else
echo " - Failed"
FAILED_HOSTS+=("$host")
fi
fi
done
# Print the results
if [ "$LIST_ONLY" -ne 1 ]; then
if [ -n "${SUCCESSFUL_HOSTS[*]}" ]; then
echo
echo -e "${GREEN}${BOLD}Successful Hosts:${RESET}"
if [ -n "$OUTPUT_FILE" ]; then
echo -e "Successful Hosts:" >> "$OUTPUT_FILE"
printf '%s\n' "${SUCCESSFUL_HOSTS[@]}" | tee -a "$OUTPUT_FILE"
else
printf '%s\n' "${SUCCESSFUL_HOSTS[@]}"
fi
fi
if [ -n "$OUTPUT_FILE" ]; then
echo -e "" >> "$OUTPUT_FILE"
fi
if [ -n "${FAILED_HOSTS[*]}" ]; then
echo
echo -e "${RED}${BOLD}Failed Hosts:${RESET}"
if [ -n "$OUTPUT_FILE" ]; then
printf 'Failed Hosts:\n' | tee -a "$OUTPUT_FILE"
printf '%s\n' "${FAILED_HOSTS[@]}" | tee -a "$OUTPUT_FILE"
else
printf '%s\n' "${FAILED_HOSTS[@]}"
fi
fi
fi
}
# Execute the function
main