Skip to content

Instantly share code, notes, and snippets.

@patricknelson
Last active August 12, 2024 14:50
Show Gist options
  • Save patricknelson/95761f807a4ba231b57d6bcb9fe5eb11 to your computer and use it in GitHub Desktop.
Save patricknelson/95761f807a4ba231b57d6bcb9fe5eb11 to your computer and use it in GitHub Desktop.
kubectl-sure: Provide confirmation when in sensitive contexts

kubectl-sure: Provide confirmation when in sensitive contexts

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).

Demo

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

Installation

  1. Place the code below in your .bash_profile
  2. Configure options:
    • Edit the SENSITIVE_CONTEXTS variable to contain the list of contexts you want to help protect
    • Set ALWAYS_ANNOUNCE_CONTEXT to false 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 to 0 to confirm every time
  3. 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
  4. 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. even kubectl 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).

Code

##
## 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
}

Limitation of Liability

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment