From ffeabfe12c4f17479fb0d401c403f58338083e43 Mon Sep 17 00:00:00 2001 From: Carter McKinnon Date: Thu, 17 Aug 2023 09:43:05 -0700 Subject: [PATCH] Fetch new IMDS token for every request --- files/bin/imds | 51 ++++++----------------- files/bootstrap.sh | 2 + scripts/cleanup.sh | 3 +- test/cases/imds-token-refresh.sh | 69 -------------------------------- 4 files changed, 16 insertions(+), 109 deletions(-) delete mode 100755 test/cases/imds-token-refresh.sh diff --git a/files/bin/imds b/files/bin/imds index 061c8b070..2e87c00d8 100755 --- a/files/bin/imds +++ b/files/bin/imds @@ -5,20 +5,13 @@ set -o pipefail set -o nounset if [ "$#" -ne 1 ]; then - echo >&2 "usage: imds API_PATH" + echo >&2 "usage: imds token|API_PATH" exit 1 fi -# leading slashes will be removed -API_PATH="${1#/}" - -CURRENT_TIME=$(date '+%s') - IMDS_DEBUG="${IMDS_DEBUG:-false}" # default ttl is 15 minutes IMDS_TOKEN_TTL_SECONDS=${IMDS_TOKEN_TTL_SECONDS:-900} -# max ttl is 6 hours, see: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html -IMDS_MAX_TOKEN_TTL_SECONDS=${IMDS_MAX_TOKEN_TTL_SECONDS:-21600} IMDS_RETRIES=${IMDS_RETRIES:-10} IMDS_RETRY_DELAY_SECONDS=${IMDS_RETRY_DELAY_SECONDS:-1} IMDS_ENDPOINT=${IMDS_ENDPOINT:-169.254.169.254} @@ -49,43 +42,25 @@ function imdscurl() { } function get-token() { - local TOKEN_DIR="/tmp/imds-tokens/$(whoami)" - mkdir -p -m 0600 $TOKEN_DIR - - # cleanup expired tokens - local DELETED_TOKENS=0 - for TOKEN_FILE in $(ls $TOKEN_DIR | awk '$0 < '$(($CURRENT_TIME - $IMDS_MAX_TOKEN_TTL_SECONDS))); do - rm $TOKEN_DIR/$TOKEN_FILE - DELETED_TOKENS=$(($DELETED_TOKENS + 1)) - done - if [ "$DELETED_TOKENS" -gt 0 ]; then - log "🗑ī¸ Deleted $DELETED_TOKENS expired IMDS token(s)." - fi - - local TOKEN_FILE=$(ls $TOKEN_DIR | awk '$0 > '$CURRENT_TIME | sort -n -r | head -n 1) - - if [ "$TOKEN_FILE" = "" ]; then - TOKEN_FILE=$(($CURRENT_TIME + $IMDS_TOKEN_TTL_SECONDS)) - local TOKEN=$(imdscurl \ - -H "X-aws-ec2-metadata-token-ttl-seconds: $IMDS_TOKEN_TTL_SECONDS" \ - -X PUT \ - "http://$IMDS_ENDPOINT/latest/api/token") - echo "$TOKEN" > "$TOKEN_DIR/$TOKEN_FILE" - chmod 0600 "$TOKEN_DIR/$TOKEN_FILE" - log "🔑 Retrieved a fresh IMDS token that will expire in $IMDS_TOKEN_TTL_SECONDS seconds." - else - log "ℹī¸ Using cached IMDS token that expires in $(($TOKEN_FILE - $CURRENT_TIME)) seconds." - fi - cat "$TOKEN_DIR/$TOKEN_FILE" + imdscurl \ + -H "X-aws-ec2-metadata-token-ttl-seconds: $IMDS_TOKEN_TTL_SECONDS" \ + -X PUT \ + "http://$IMDS_ENDPOINT/latest/api/token" } function get-with-token() { local API_PATH="$1" imdscurl \ - -H "X-aws-ec2-metadata-token: $(get-token)" \ + -H "X-aws-ec2-metadata-token: ${IMDS_TOKEN:-$(get-token)}" \ "http://$IMDS_ENDPOINT/$API_PATH" } log "ℹī¸ Talking to IMDS at $IMDS_ENDPOINT" -get-with-token "$API_PATH" +if [ "$1" = "token" ]; then + get-token +else + # leading slashes will be removed + API_PATH="${1#/}" + get-with-token "$API_PATH" +fi diff --git a/files/bootstrap.sh b/files/bootstrap.sh index a073ce646..7d2ce8098 100755 --- a/files/bootstrap.sh +++ b/files/bootstrap.sh @@ -175,6 +175,8 @@ set -- "${POSITIONAL[@]}" # restore positional parameters CLUSTER_NAME="$1" set -u +export IMDS_TOKEN=$(imds token) + KUBELET_VERSION=$(kubelet --version | grep -Eo '[0-9]\.[0-9]+\.[0-9]+') log "INFO: Using kubelet version $KUBELET_VERSION" diff --git a/scripts/cleanup.sh b/scripts/cleanup.sh index a1b223d62..61c399fee 100644 --- a/scripts/cleanup.sh +++ b/scripts/cleanup.sh @@ -24,7 +24,6 @@ sudo rm -rf \ /var/log/secure \ /var/log/wtmp \ /var/log/messages \ - /var/log/audit/* \ - /tmp/imds-tokens + /var/log/audit/* sudo touch /etc/machine-id diff --git a/test/cases/imds-token-refresh.sh b/test/cases/imds-token-refresh.sh deleted file mode 100755 index 76af2c460..000000000 --- a/test/cases/imds-token-refresh.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash - -set -o nounset -set -o errexit -set -o pipefail - -echo "--> Should refresh IMDS token on configured interval" -exit_code=0 -TOKEN_DIR=/tmp/imds-tokens/$(whoami) -TTL=5 -export IMDS_TOKEN_TTL_SECONDS=$TTL -export IMDS_DEBUG=true -imds /latest/meta-data/instance-id || exit_code=$? - -if [[ ${exit_code} -ne 0 ]]; then - echo "❌ Test Failed: expected a non-zero exit code but got '${exit_code}'" - exit 1 -elif [[ $(ls $TOKEN_DIR | wc -l) -ne 1 ]]; then - echo "❌ Test Failed: expected one token to be present after first IMDS call but got '$(ls $TOKEN_DIR)'" - exit 1 -fi - -imds /latest/meta-data/instance-id || exit_code=$? - -if [[ ${exit_code} -ne 0 ]]; then - echo "❌ Test Failed: expected a non-zero exit code but got '${exit_code}'" - exit 1 -elif [[ $(ls $TOKEN_DIR | wc -l) -ne 1 ]]; then - echo "❌ Test Failed: expected one token to be present after second IMDS call but got '$(ls $TOKEN_DIR)'" - exit 1 -fi - -sleep $(($TTL + 1)) - -imds /latest/meta-data/instance-id || exit_code=$? - -if [[ ${exit_code} -ne 0 ]]; then - echo "❌ Test Failed: expected a non-zero exit code but got '${exit_code}'" - exit 1 -elif [[ $(ls $TOKEN_DIR | wc -l) -ne 2 ]]; then - echo "❌ Test Failed: expected two tokens to be present after third IMDS call but got '$(ls $TOKEN_DIR)'" - exit 1 -fi - -sleep $(($TTL + 1)) - -# both tokens are now expired, but only one should be garbage-collected with a window of $TTL - -IMDS_MAX_TOKEN_TTL_SECONDS=$TTL imds /latest/meta-data/instance-id || exit_code=$? - -if [[ ${exit_code} -ne 0 ]]; then - echo "❌ Test Failed: expected a non-zero exit code but got '${exit_code}'" - exit 1 -elif [[ $(ls $TOKEN_DIR | wc -l) -ne 2 ]]; then - echo "❌ Test Failed: expected two tokens to be present after first garbage-collection but got '$(ls $TOKEN_DIR)'" - exit 1 -fi - -# the other expired token should be removed with a window of 0 - -IMDS_MAX_TOKEN_TTL_SECONDS=0 imds /latest/meta-data/instance-id || exit_code=$? - -if [[ ${exit_code} -ne 0 ]]; then - echo "❌ Test Failed: expected a non-zero exit code but got '${exit_code}'" - exit 1 -elif [[ $(ls $TOKEN_DIR | wc -l) -ne 1 ]]; then - echo "❌ Test Failed: expected one token to be present after second garbage-collection but got '$(ls $TOKEN_DIR)'" - exit 1 -fi