From cc5ffa5e599c974c426e93faa821b342e96b916d Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Mon, 11 Nov 2024 12:46:27 +0100 Subject: [PATCH 1/2] aws.sh: chmod 600 $TOKEN_FILE, add get_instance_id() with DMI support, and use get_instance_id() in AWS agents --- heartbeat/aws-vpc-move-ip | 2 +- heartbeat/aws.sh | 30 +++++++++++++++++++++++++++--- heartbeat/awseip | 2 +- heartbeat/awsvip | 2 +- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip index 3aa9ceb02..09ae68b57 100755 --- a/heartbeat/aws-vpc-move-ip +++ b/heartbeat/aws-vpc-move-ip @@ -269,7 +269,7 @@ ec2ip_validate() { TOKEN=$(get_token) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC - EC2_INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id") + EC2_INSTANCE_ID=$(get_instance_id) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC if [ -z "${EC2_INSTANCE_ID}" ]; then diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh index c77f93b91..9cd343c16 100644 --- a/heartbeat/aws.sh +++ b/heartbeat/aws.sh @@ -9,8 +9,8 @@ . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs # Defaults -OCF_RESKEY_curl_retries_default="3" -OCF_RESKEY_curl_sleep_default="1" +OCF_RESKEY_curl_retries_default="4" +OCF_RESKEY_curl_sleep_default="3" : ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}} : ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}} @@ -20,11 +20,13 @@ OCF_RESKEY_curl_sleep_default="1" TOKEN_FILE="${HA_RSCTMP}/.aws_imds_token" TOKEN_LIFETIME=21600 # Token lifetime in seconds (6 hours) TOKEN_EXPIRY_THRESHOLD=3600 # Renew token if less than 60 minutes (1 hour) remaining +DMI_FILE="/sys/devices/virtual/dmi/id/board_asset_tag" # Only supported on nitro-based instances. # Function to fetch a new token fetch_new_token() { TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: $TOKEN_LIFETIME'" "http://169.254.169.254/latest/api/token") echo "$TOKEN $(date +%s)" > "$TOKEN_FILE" + chmod 600 "$TOKEN_FILE" echo "$TOKEN" } @@ -43,4 +45,26 @@ get_token() { fi # Fetch a new token if not valid fetch_new_token -} \ No newline at end of file +} + +get_instance_id() { + local INSTANCE_ID + + # Try to get the EC2 instance ID from DMI first before falling back to IMDS. + ocf_log debug "EC2: Attempt to get EC2 Instance ID from local file." + if [ -r "$DMI_FILE" ] && [ -s "$DMI_FILE" ]; then + INSTANCE_ID="$(cat "$DMI_FILE")" + case "$INSTANCE_ID" in + i-0*) echo "$INSTANCE_ID"; return "$OCF_SUCCESS" ;; + esac + fi + + INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id") + if [ $? -ne 0 ]; then + ocf_exit_reason "Failed to get EC2 Instance ID" + exit $OCF_ERR_GENERIC + fi + + echo "$INSTANCE_ID" + return "$OCF_SUCCESS" +} diff --git a/heartbeat/awseip b/heartbeat/awseip index 4b1c3bc6a..7f38376dc 100755 --- a/heartbeat/awseip +++ b/heartbeat/awseip @@ -305,7 +305,7 @@ ALLOCATION_ID="${OCF_RESKEY_allocation_id}" PRIVATE_IP_ADDRESS="${OCF_RESKEY_private_ip_address}" TOKEN=$(get_token) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC -INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id") +INSTANCE_ID=$(get_instance_id) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC case $__OCF_ACTION in diff --git a/heartbeat/awsvip b/heartbeat/awsvip index 8c71e7fac..0856ac5e4 100755 --- a/heartbeat/awsvip +++ b/heartbeat/awsvip @@ -265,7 +265,7 @@ fi SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}" TOKEN=$(get_token) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC -INSTANCE_ID=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/instance-id") +INSTANCE_ID=$(get_instance_id) [ $? -ne 0 ] && exit $OCF_ERR_GENERIC MAC_ADDRESS=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -s -H 'X-aws-ec2-metadata-token: $TOKEN'" "http://169.254.169.254/latest/meta-data/mac") [ $? -ne 0 ] && exit $OCF_ERR_GENERIC From b8d3ecc6a8ce4baf4b28d02978dd573728ccf5fa Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Mon, 18 Nov 2024 11:10:42 +0100 Subject: [PATCH 2/2] aws.sh/ocf-shellfuncs: add ability to fresh token if it's invalid --- heartbeat/aws.sh | 1 + heartbeat/ocf-shellfuncs.in | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh index 9cd343c16..64f2e13a7 100644 --- a/heartbeat/aws.sh +++ b/heartbeat/aws.sh @@ -18,6 +18,7 @@ OCF_RESKEY_curl_sleep_default="3" # Function to enable reusable IMDS token retrieval for efficient repeated access # File to store the token and timestamp TOKEN_FILE="${HA_RSCTMP}/.aws_imds_token" +TOKEN_FUNC="fetch_new_token" # Used by curl_retry() if saved token is invalid TOKEN_LIFETIME=21600 # Token lifetime in seconds (6 hours) TOKEN_EXPIRY_THRESHOLD=3600 # Renew token if less than 60 minutes (1 hour) remaining DMI_FILE="/sys/devices/virtual/dmi/id/board_asset_tag" # Only supported on nitro-based instances. diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in index 922c6ea45..8e51fa3c8 100644 --- a/heartbeat/ocf-shellfuncs.in +++ b/heartbeat/ocf-shellfuncs.in @@ -697,6 +697,15 @@ curl_retry() ocf_log debug "result: $result" [ $rc -eq 0 ] && break + if [ -n "$TOKEN" ] && [ -n "$TOKEN_FILE" ] && \ + [ -f "$TOKEN_FILE" ] && [ -n "$TOKEN_FUNC" ] && \ + echo "$result" | grep -q "The requested URL returned error: 401$"; then + local OLD_TOKEN="$TOKEN" + ocf_log err "Token invalid. Getting new token." + TOKEN=$($TOKEN_FUNC) + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + args=$(echo "$args" | sed "s/$OLD_TOKEN/$TOKEN/") + fi sleep $sleep done @@ -1110,4 +1119,4 @@ ocf_is_true "$OCF_TRACE_RA" && ocf_start_trace # pacemaker sets HA_use_logd, some others use HA_LOGD :/ if ocf_is_true "$HA_use_logd"; then : ${HA_LOGD:=yes} -fi \ No newline at end of file +fi