This bash function provides an extra failsafe that may help prevent you from accidentally running kubectl
commands in the wrong context (or in
contexts which could cause issues, such as shared or even production clusters).
Running kubectl
in prod
on accident:
$ kubectl apply -f deployment.yml
You are in a sensitive context: prod
Are you SURE you want to proceed? Type 'YES' to confirm: oops
Confirmation not received. Aborting command.
Running kubectl
in prod
on purpose:
$ kubectl apply -f deployment.yml
You are in a sensitive context: prod
Are you SURE you want to proceed? Type 'YES' to confirm: YES
Confirmation received. Proceeding with the command...
deployment.apps/app-deployment configured
Subsequent runs within CONFIRM_AFTER_SECONDS
:
$ kubectl apply -f deployment.yml
deployment.apps/app-deployment configured
- Place the code below in your
.bash_profile
- Configure options:
- Edit the
SENSITIVE_CONTEXTS
variable to contain the list of contexts you want to help protect - Set
ALWAYS_ANNOUNCE_CONTEXT
tofalse
if you don't want to be annoyed when NOT in a sensitive context - Change
CONFIRM_AFTER_SECONDS
to the number of seconds to wait before confirming again, or set to0
to confirm every time
- Edit the
- Close your current shell and log back in to load the function
- Tip: Remember to always do this after each change to the
SENSITIVE_CONTEXTS
variable
- Tip: Remember to always do this after each change to the
- Test it out by running
kubectl get pods
while in a context
Note:
- Absolutely every invocation of
kubectl
will receive a confirmation when currently in a sensitive context (e.g. evenkubectl config set-context ...
). This script is not yet feature rich to detect operations which could potentially make changes. - All output from this script is sent to error output (
STDERR
) to prevent being mixed into standard output (STDOUT
).
##
## This function wraps the 'kubectl' command to provide a confirmation prompt when running in sensitive contexts.
##
function kubectl() {
##
## Configuration
##
# Define a list of sensitive contexts, e.g.: ("prod" "staging")
local SENSITIVE_CONTEXTS=("prod" "staging")
# Set to false to disable the confirmation prompt for all contexts
local ALWAYS_ANNOUNCE_CONTEXT=true
# Number of seconds to wait before asking for confirmation again. Set to 0 to ask every time.
local CONFIRM_AFTER_SECONDS=60
##
## No need to edit below this line
##
# ANSI escape codes for some extra pizazz.
local RED='\033[0;31m'
local GREEN='\033[0;32m'
local NC='\033[0m' # No Color
# Check if input is piped
local INPUT=""
if [ ! -t 0 ]; then # Check if stdin is from a terminal or piped
INPUT=$(cat)
fi
local CURRENT_CONTEXT=$(command kubectl config current-context)
# Check if the current context is in the list of sensitive contexts
if [[ " ${SENSITIVE_CONTEXTS[@]} " =~ " ${CURRENT_CONTEXT} " ]]; then
local CONFIRMATION_TIMESTAMP_FILE="/tmp/kubectl-confirmation.timestamp"
local CURRENT_TIME=$(date +%s)
if [ ! -f "$CONFIRMATION_TIMESTAMP_FILE" ] || [ $(($CURRENT_TIME - $(cat "$CONFIRMATION_TIMESTAMP_FILE"))) -ge $CONFIRM_AFTER_SECONDS ]; then
echo -e "You are in a sensitive context: ${RED}$CURRENT_CONTEXT${NC}" 1>&2
# Use file descriptor 3 for reading user input, linked to the terminal
exec 3</dev/tty
echo -n "Are you SURE you want to proceed? Type 'YES' to confirm: " 1>&2
read -u 3 CONFIRMATION
exec 3<&- # Close the file descriptor when done
if [[ $CONFIRMATION != "YES" ]]; then
echo "Confirmation not received. Aborting command." 1>&2
return 1
fi
echo "$CURRENT_TIME" >"$CONFIRMATION_TIMESTAMP_FILE"
echo "Confirmation received. Proceeding with the command..." 1>&2
echo "" 1>&2
fi
else
if [[ "$ALWAYS_ANNOUNCE_CONTEXT" == true ]]; then
echo -e "Running in context: ${GREEN}$CURRENT_CONTEXT${NC}" 1>&2
echo "" 1>&2
fi
fi
# Execute the original kubectl command with all arguments passed to the function
if [[ -n "$INPUT" ]]; then
echo "$INPUT" | command kubectl "$@"
else
command kubectl "$@"
fi
}
TL;DR: Be sure to test the code before actually using it in a production environment! Use at your own risk.
This code is provided "as is," with all faults, defects, bugs, and errors. I make no warranties or representations of any kind concerning the performance, operation, or use of the code. Under no circumstances shall I be liable for any incidental, special, indirect, or consequential damages or loss, including, without limitation, lost profits or revenues, costs of replacement goods, loss or damage to data arising out of the use or inability to use this code or any associated service, damages resulting from use of or reliance on the code, even if I have been advised of the possibility of such damages.