diff --git a/RHEL-66293-1-aws-agents-reuse-imds-token-until-it-expires.patch b/RHEL-66293-1-aws-agents-reuse-imds-token-until-it-expires.patch new file mode 100644 index 0000000..b81a105 --- /dev/null +++ b/RHEL-66293-1-aws-agents-reuse-imds-token-until-it-expires.patch @@ -0,0 +1,455 @@ +From 61cec34a754017537c61e79cd1212f2688c32429 Mon Sep 17 00:00:00 2001 +From: harshkiprofile <83770157+harshkiprofile@users.noreply.github.com> +Date: Mon, 4 Nov 2024 12:19:10 +0530 +Subject: [PATCH 1/7] Introduce a new shell function to reuse IMDS token + +--- + heartbeat/ocf-shellfuncs.in | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in +index 5c4bb3264..0c4632cf9 100644 +--- a/heartbeat/ocf-shellfuncs.in ++++ b/heartbeat/ocf-shellfuncs.in +@@ -1111,3 +1111,34 @@ ocf_is_true "$OCF_TRACE_RA" && ocf_start_trace + if ocf_is_true "$HA_use_logd"; then + : ${HA_LOGD:=yes} + fi ++ ++# File to store the token and timestamp ++TOKEN_FILE="/tmp/.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 ++ ++# Function to fetch a new token ++fetch_new_token() { ++ TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: $TOKEN_LIFETIME") ++ echo "$TOKEN $(date +%s)" > "$TOKEN_FILE" ++ echo "$TOKEN" ++} ++ ++# Function to retrieve or renew the token ++get_token() { ++ if [[ -f "$TOKEN_FILE" ]]; then ++ read -r STORED_TOKEN STORED_TIMESTAMP < "$TOKEN_FILE" ++ CURRENT_TIME=$(date +%s) ++ ELAPSED_TIME=$((CURRENT_TIME - STORED_TIMESTAMP)) ++ ++ if (( ELAPSED_TIME < (TOKEN_LIFETIME - TOKEN_EXPIRY_THRESHOLD) )); then ++ # Token is still valid ++ echo "$STORED_TOKEN" ++ return ++ fi ++ fi ++ # Fetch a new token if not valid ++ fetch_new_token ++} ++ ++ + +From 00629fa44cb7a8dd1045fc8cad755e1d0c808476 Mon Sep 17 00:00:00 2001 +From: harshkiprofile <83770157+harshkiprofile@users.noreply.github.com> +Date: Mon, 4 Nov 2024 12:21:18 +0530 +Subject: [PATCH 2/7] Utilize the get_token function to reuse the token + +--- + heartbeat/aws-vpc-move-ip | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip +index 6115e5ba8..fbeb2ee64 100755 +--- a/heartbeat/aws-vpc-move-ip ++++ b/heartbeat/aws-vpc-move-ip +@@ -270,7 +270,7 @@ ec2ip_validate() { + fi + fi + +- TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token") ++ 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") + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + +From 36126cdcb90ad617ecfce03d986550907732aa4f Mon Sep 17 00:00:00 2001 +From: harshkiprofile <83770157+harshkiprofile@users.noreply.github.com> +Date: Mon, 4 Nov 2024 12:22:16 +0530 +Subject: [PATCH 3/7] Utilize to get_token function to reuse the token + +--- + heartbeat/awsvip | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/heartbeat/awsvip b/heartbeat/awsvip +index f2b238a0f..ca19ac086 100755 +--- a/heartbeat/awsvip ++++ b/heartbeat/awsvip +@@ -266,7 +266,7 @@ if [ -n "${OCF_RESKEY_region}" ]; then + AWSCLI_CMD="$AWSCLI_CMD --region ${OCF_RESKEY_region}" + fi + SECONDARY_PRIVATE_IP="${OCF_RESKEY_secondary_private_ip}" +-TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token") ++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") + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + +From dcd0050df5ba94905bc71d38b05cbb93f5687b61 Mon Sep 17 00:00:00 2001 +From: harshkiprofile +Date: Mon, 4 Nov 2024 20:05:33 +0530 +Subject: [PATCH 4/7] Move token renewal function to aws.sh for reuse in AWS + agent scripts + +--- + heartbeat/Makefile.am | 1 + + heartbeat/aws-vpc-move-ip | 1 + + heartbeat/aws-vpc-route53.in | 3 ++- + heartbeat/aws.sh | 46 ++++++++++++++++++++++++++++++++++++ + heartbeat/awseip | 3 ++- + heartbeat/awsvip | 1 + + heartbeat/ocf-shellfuncs.in | 33 +------------------------- + 7 files changed, 54 insertions(+), 34 deletions(-) + create mode 100644 heartbeat/aws.sh + +diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am +index 409847970..655740f14 100644 +--- a/heartbeat/Makefile.am ++++ b/heartbeat/Makefile.am +@@ -218,6 +218,7 @@ ocfcommon_DATA = ocf-shellfuncs \ + ocf-rarun \ + ocf-distro \ + apache-conf.sh \ ++ aws.sh \ + http-mon.sh \ + sapdb-nosha.sh \ + sapdb.sh \ +diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip +index fbeb2ee64..f4b0492f2 100755 +--- a/heartbeat/aws-vpc-move-ip ++++ b/heartbeat/aws-vpc-move-ip +@@ -33,6 +33,7 @@ + + : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} + . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ++. ${OCF_FUNCTIONS_DIR}/aws.sh + + # Defaults + OCF_RESKEY_awscli_default="/usr/bin/aws" +diff --git a/heartbeat/aws-vpc-route53.in b/heartbeat/aws-vpc-route53.in +index eba2ed95c..f7e756782 100644 +--- a/heartbeat/aws-vpc-route53.in ++++ b/heartbeat/aws-vpc-route53.in +@@ -43,6 +43,7 @@ + + : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} + . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ++. ${OCF_FUNCTIONS_DIR}/aws.sh + + # Defaults + OCF_RESKEY_awscli_default="/usr/bin/aws" +@@ -377,7 +378,7 @@ r53_monitor() { + _get_ip() { + case $OCF_RESKEY_ip in + local|public) +- TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token") ++ TOKEN=$(get_token) + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + IPADDRESS=$(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/${OCF_RESKEY_ip}-ipv4") + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC +diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh +new file mode 100644 +index 000000000..fc557109c +--- /dev/null ++++ b/heartbeat/aws.sh +@@ -0,0 +1,46 @@ ++#!/bin/sh ++# ++# ++# AWS Helper Scripts ++# ++# ++ ++: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} ++. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ++ ++# Defaults ++OCF_RESKEY_curl_retries_default="3" ++OCF_RESKEY_curl_sleep_default="1" ++ ++: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}} ++: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}} ++ ++# Function to enable reusable IMDS token retrieval for efficient repeated access ++# File to store the token and timestamp ++TOKEN_FILE="/tmp/.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 ++ ++# 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" ++ echo "$TOKEN" ++} ++ ++# Function to retrieve or renew the token ++get_token() { ++ if [ -f "$TOKEN_FILE" ]; then ++ read -r STORED_TOKEN STORED_TIMESTAMP < "$TOKEN_FILE" ++ CURRENT_TIME=$(date +%s) ++ ELAPSED_TIME=$((CURRENT_TIME - STORED_TIMESTAMP)) ++ ++ if (( ELAPSED_TIME < (TOKEN_LIFETIME - TOKEN_EXPIRY_THRESHOLD) )); then ++ # Token is still valid ++ echo "$STORED_TOKEN" ++ return ++ fi ++ fi ++ # Fetch a new token if not valid ++ fetch_new_token ++} +\ No newline at end of file +diff --git a/heartbeat/awseip b/heartbeat/awseip +index ffb6223a1..049c2e566 100755 +--- a/heartbeat/awseip ++++ b/heartbeat/awseip +@@ -38,6 +38,7 @@ + + : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} + . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ++. ${OCF_FUNCTIONS_DIR}/aws.sh + + ####################################################################### + +@@ -306,7 +307,7 @@ fi + ELASTIC_IP="${OCF_RESKEY_elastic_ip}" + ALLOCATION_ID="${OCF_RESKEY_allocation_id}" + PRIVATE_IP_ADDRESS="${OCF_RESKEY_private_ip_address}" +-TOKEN=$(curl_retry "$OCF_RESKEY_curl_retries" "$OCF_RESKEY_curl_sleep" "--show-error -sX PUT -H 'X-aws-ec2-metadata-token-ttl-seconds: 21600'" "http://169.254.169.254/latest/api/token") ++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") + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC +diff --git a/heartbeat/awsvip b/heartbeat/awsvip +index ca19ac086..de67981d8 100755 +--- a/heartbeat/awsvip ++++ b/heartbeat/awsvip +@@ -37,6 +37,7 @@ + + : ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat} + . ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs ++. ${OCF_FUNCTIONS_DIR}/aws.sh + + ####################################################################### + +diff --git a/heartbeat/ocf-shellfuncs.in b/heartbeat/ocf-shellfuncs.in +index 0c4632cf9..922c6ea45 100644 +--- a/heartbeat/ocf-shellfuncs.in ++++ b/heartbeat/ocf-shellfuncs.in +@@ -1110,35 +1110,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 +- +-# File to store the token and timestamp +-TOKEN_FILE="/tmp/.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 +- +-# Function to fetch a new token +-fetch_new_token() { +- TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: $TOKEN_LIFETIME") +- echo "$TOKEN $(date +%s)" > "$TOKEN_FILE" +- echo "$TOKEN" +-} +- +-# Function to retrieve or renew the token +-get_token() { +- if [[ -f "$TOKEN_FILE" ]]; then +- read -r STORED_TOKEN STORED_TIMESTAMP < "$TOKEN_FILE" +- CURRENT_TIME=$(date +%s) +- ELAPSED_TIME=$((CURRENT_TIME - STORED_TIMESTAMP)) +- +- if (( ELAPSED_TIME < (TOKEN_LIFETIME - TOKEN_EXPIRY_THRESHOLD) )); then +- # Token is still valid +- echo "$STORED_TOKEN" +- return +- fi +- fi +- # Fetch a new token if not valid +- fetch_new_token +-} +- +- ++fi +\ No newline at end of file + +From 9f7be201923c8eab1b121f2067ed74a69841cf8a Mon Sep 17 00:00:00 2001 +From: harshkiprofile +Date: Tue, 5 Nov 2024 19:12:34 +0530 +Subject: [PATCH 5/7] Refactor to use common temp path and update shell syntax + +--- + heartbeat/Makefile.am | 2 +- + heartbeat/aws.sh | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/heartbeat/Makefile.am b/heartbeat/Makefile.am +index 655740f14..8352f3a3d 100644 +--- a/heartbeat/Makefile.am ++++ b/heartbeat/Makefile.am +@@ -218,7 +218,7 @@ ocfcommon_DATA = ocf-shellfuncs \ + ocf-rarun \ + ocf-distro \ + apache-conf.sh \ +- aws.sh \ ++ aws.sh \ + http-mon.sh \ + sapdb-nosha.sh \ + sapdb.sh \ +diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh +index fc557109c..c77f93b91 100644 +--- a/heartbeat/aws.sh ++++ b/heartbeat/aws.sh +@@ -17,7 +17,7 @@ OCF_RESKEY_curl_sleep_default="1" + + # Function to enable reusable IMDS token retrieval for efficient repeated access + # File to store the token and timestamp +-TOKEN_FILE="/tmp/.imds_token" ++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 + +@@ -35,7 +35,7 @@ get_token() { + CURRENT_TIME=$(date +%s) + ELAPSED_TIME=$((CURRENT_TIME - STORED_TIMESTAMP)) + +- if (( ELAPSED_TIME < (TOKEN_LIFETIME - TOKEN_EXPIRY_THRESHOLD) )); then ++ if [ "$ELAPSED_TIME" -lt "$((TOKEN_LIFETIME - TOKEN_EXPIRY_THRESHOLD))" ]; then + # Token is still valid + echo "$STORED_TOKEN" + return + +From 4f61048064d1df3bebdb5c1441cf0020f213c01b Mon Sep 17 00:00:00 2001 +From: harshkiprofile +Date: Tue, 5 Nov 2024 19:30:15 +0530 +Subject: [PATCH 6/7] Consolidate curl_retry and curl_sleep variable to a + single location in aws.sh + +--- + heartbeat/aws-vpc-move-ip | 4 ---- + heartbeat/aws-vpc-route53.in | 4 ---- + heartbeat/awseip | 4 ---- + heartbeat/awsvip | 4 ---- + 4 files changed, 16 deletions(-) + +diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip +index f4b0492f2..3aa9ceb02 100755 +--- a/heartbeat/aws-vpc-move-ip ++++ b/heartbeat/aws-vpc-move-ip +@@ -48,8 +48,6 @@ OCF_RESKEY_interface_default="eth0" + OCF_RESKEY_iflabel_default="" + OCF_RESKEY_monapi_default="false" + OCF_RESKEY_lookup_type_default="InstanceId" +-OCF_RESKEY_curl_retries_default="3" +-OCF_RESKEY_curl_sleep_default="1" + + : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} + : ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}} +@@ -63,8 +61,6 @@ OCF_RESKEY_curl_sleep_default="1" + : ${OCF_RESKEY_iflabel=${OCF_RESKEY_iflabel_default}} + : ${OCF_RESKEY_monapi=${OCF_RESKEY_monapi_default}} + : ${OCF_RESKEY_lookup_type=${OCF_RESKEY_lookup_type_default}} +-: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}} +-: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}} + ####################################################################### + + +diff --git a/heartbeat/aws-vpc-route53.in b/heartbeat/aws-vpc-route53.in +index f7e756782..85c8de3c1 100644 +--- a/heartbeat/aws-vpc-route53.in ++++ b/heartbeat/aws-vpc-route53.in +@@ -54,8 +54,6 @@ OCF_RESKEY_hostedzoneid_default="" + OCF_RESKEY_fullname_default="" + OCF_RESKEY_ip_default="local" + OCF_RESKEY_ttl_default=10 +-OCF_RESKEY_curl_retries_default="3" +-OCF_RESKEY_curl_sleep_default="1" + + : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} + : ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}} +@@ -65,8 +63,6 @@ OCF_RESKEY_curl_sleep_default="1" + : ${OCF_RESKEY_fullname:=${OCF_RESKEY_fullname_default}} + : ${OCF_RESKEY_ip:=${OCF_RESKEY_ip_default}} + : ${OCF_RESKEY_ttl:=${OCF_RESKEY_ttl_default}} +-: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}} +-: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}} + + usage() { + cat <<-EOT +diff --git a/heartbeat/awseip b/heartbeat/awseip +index 049c2e566..4b1c3bc6a 100755 +--- a/heartbeat/awseip ++++ b/heartbeat/awseip +@@ -50,16 +50,12 @@ OCF_RESKEY_auth_type_default="key" + OCF_RESKEY_profile_default="default" + OCF_RESKEY_region_default="" + OCF_RESKEY_api_delay_default="3" +-OCF_RESKEY_curl_retries_default="3" +-OCF_RESKEY_curl_sleep_default="1" + + : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} + : ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}} + : ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} + : ${OCF_RESKEY_region=${OCF_RESKEY_region_default}} + : ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}} +-: ${OCF_RESKEY_curl_retries=${OCF_RESKEY_curl_retries_default}} +-: ${OCF_RESKEY_curl_sleep=${OCF_RESKEY_curl_sleep_default}} + + meta_data() { + cat < +Date: Tue, 5 Nov 2024 20:50:24 +0530 +Subject: [PATCH 7/7] aws.sh needs to added to be symlinkstargets in + doc/man/Makefile.am + +--- + doc/man/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am +index ef7639bff..447f5cba3 100644 +--- a/doc/man/Makefile.am ++++ b/doc/man/Makefile.am +@@ -42,7 +42,7 @@ radir = $(abs_top_builddir)/heartbeat + # required for out-of-tree build + symlinkstargets = \ + ocf-distro ocf.py ocf-rarun ocf-returncodes \ +- findif.sh apache-conf.sh http-mon.sh mysql-common.sh \ ++ findif.sh apache-conf.sh aws.sh http-mon.sh mysql-common.sh \ + nfsserver-redhat.sh openstack-common.sh ora-common.sh + + preptree: diff --git a/RHEL-66293-2-aws-agents-reuse-imds-token-improvements.patch b/RHEL-66293-2-aws-agents-reuse-imds-token-improvements.patch new file mode 100644 index 0000000..2ba9acf --- /dev/null +++ b/RHEL-66293-2-aws-agents-reuse-imds-token-improvements.patch @@ -0,0 +1,161 @@ +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 diff --git a/RHEL-68740-awsvip-add-interface-parameter.patch b/RHEL-68740-awsvip-add-interface-parameter.patch new file mode 100644 index 0000000..c7bf67f --- /dev/null +++ b/RHEL-68740-awsvip-add-interface-parameter.patch @@ -0,0 +1,184 @@ +From 392d40048a25d7cb73ec5b5e9f7a5862f7a3fd48 Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 11 Nov 2024 12:22:27 +0100 +Subject: [PATCH 1/2] aws.sh: add get_interface_mac() + +--- + heartbeat/aws.sh | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh +index 64f2e13a7..ebb4eb1f4 100644 +--- a/heartbeat/aws.sh ++++ b/heartbeat/aws.sh +@@ -69,3 +69,24 @@ get_instance_id() { + echo "$INSTANCE_ID" + return "$OCF_SUCCESS" + } ++ ++get_interface_mac() { ++ local MAC_FILE MAC_ADDR rc ++ MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address" ++ if [ -f "$MAC_FILE" ]; then ++ cmd="cat ${MAC_FILE}" ++ else ++ cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3" ++ fi ++ ocf_log debug "executing command: $cmd" ++ MAC_ADDR="$(eval $cmd)" ++ rc=$? ++ if [ $rc != 0 ]; then ++ ocf_log warn "command failed, rc: $rc" ++ return $OCF_ERR_GENERIC ++ fi ++ ocf_log debug "MAC address associated with interface ${OCF_RESKEY_interface}: ${MAC_ADDR}" ++ ++ echo $MAC_ADDR ++ return $OCF_SUCCESS ++} + +From 87337ac4da931d5a53c83d53d4bab17ee123ba9f Mon Sep 17 00:00:00 2001 +From: Oyvind Albrigtsen +Date: Mon, 11 Nov 2024 12:26:38 +0100 +Subject: [PATCH 2/2] awsvip: let user specify which interface to use, and make + the parameter optional in aws-vpc-move-ip + +--- + heartbeat/aws-vpc-move-ip | 20 ++++---------------- + heartbeat/aws.sh | 4 +++- + heartbeat/awsvip | 24 +++++++++++++++++------- + 3 files changed, 24 insertions(+), 24 deletions(-) + +diff --git a/heartbeat/aws-vpc-move-ip b/heartbeat/aws-vpc-move-ip +index 09ae68b57..2afc0ba53 100755 +--- a/heartbeat/aws-vpc-move-ip ++++ b/heartbeat/aws-vpc-move-ip +@@ -157,7 +157,7 @@ Role to use to query/update the route table + + + +- ++ + + Name of the network interface, i.e. eth0 + +@@ -321,7 +321,7 @@ ec2ip_monitor() { + ocf_log debug "monitor: Enhanced Monitoring disabled - omitting API call" + fi + +- cmd="ip addr show to $OCF_RESKEY_ip up" ++ cmd="ip addr show dev $OCF_RESKEY_interface to $OCF_RESKEY_ip up" + ocf_log debug "executing command: $cmd" + RESULT=$($cmd | grep "$OCF_RESKEY_ip") + if [ -z "$RESULT" ]; then +@@ -331,7 +331,7 @@ ec2ip_monitor() { + level="info" + fi + +- ocf_log "$level" "IP $OCF_RESKEY_ip not assigned to running interface" ++ ocf_log "$level" "IP $OCF_RESKEY_ip not assigned to interface $OCF_RESKEY_interface" + return $OCF_NOT_RUNNING + fi + +@@ -369,19 +369,7 @@ ec2ip_drop() { + } + + ec2ip_get_instance_eni() { +- MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address" +- if [ -f $MAC_FILE ]; then +- cmd="cat ${MAC_FILE}" +- else +- cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3" +- fi +- ocf_log debug "executing command: $cmd" +- MAC_ADDR="$(eval $cmd)" +- rc=$? +- if [ $rc != 0 ]; then +- ocf_log warn "command failed, rc: $rc" +- return $OCF_ERR_GENERIC +- fi ++ MAC_ADDR=$(get_interface_mac) + ocf_log debug "MAC address associated with interface ${OCF_RESKEY_interface}: ${MAC_ADDR}" + + cmd="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/network/interfaces/macs/${MAC_ADDR}/interface-id\"" +diff --git a/heartbeat/aws.sh b/heartbeat/aws.sh +index ebb4eb1f4..216033afe 100644 +--- a/heartbeat/aws.sh ++++ b/heartbeat/aws.sh +@@ -73,7 +73,9 @@ get_instance_id() { + get_interface_mac() { + local MAC_FILE MAC_ADDR rc + MAC_FILE="/sys/class/net/${OCF_RESKEY_interface}/address" +- if [ -f "$MAC_FILE" ]; then ++ if [ -z "$OCF_RESKEY_interface" ]; then ++ cmd="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\"" ++ elif [ -f "$MAC_FILE" ]; then + cmd="cat ${MAC_FILE}" + else + cmd="ip -br link show dev ${OCF_RESKEY_interface} | tr -s ' ' | cut -d' ' -f3" +diff --git a/heartbeat/awsvip b/heartbeat/awsvip +index 0856ac5e4..015180d5a 100755 +--- a/heartbeat/awsvip ++++ b/heartbeat/awsvip +@@ -49,12 +49,14 @@ OCF_RESKEY_auth_type_default="key" + OCF_RESKEY_profile_default="default" + OCF_RESKEY_region_default="" + OCF_RESKEY_api_delay_default="3" ++OCF_RESKEY_interface_default="" + + : ${OCF_RESKEY_awscli=${OCF_RESKEY_awscli_default}} + : ${OCF_RESKEY_auth_type=${OCF_RESKEY_auth_type_default}} + : ${OCF_RESKEY_profile=${OCF_RESKEY_profile_default}} + : ${OCF_RESKEY_region=${OCF_RESKEY_region_default}} + : ${OCF_RESKEY_api_delay=${OCF_RESKEY_api_delay_default}} ++: ${OCF_RESKEY_interface=${OCF_RESKEY_interface_default}} + + meta_data() { + cat < + + ++ ++ ++Name of the network interface, i.e. eth0 ++ ++network interface name ++ ++ ++ + + + curl retries before failing +@@ -207,16 +217,16 @@ awsvip_stop() { + } + + awsvip_monitor() { +- $AWSCLI_CMD ec2 describe-instances \ +- --instance-id "${INSTANCE_ID}" \ +- --query 'Reservations[].Instances[].NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress[]' \ ++ $AWSCLI_CMD ec2 describe-network-interfaces \ ++ --network-interface-ids "${NETWORK_ID}" \ ++ --query 'NetworkInterfaces[].PrivateIpAddresses[].PrivateIpAddress[]' \ + --output text | \ + grep -qE "(^|\s)${SECONDARY_PRIVATE_IP}(\s|$)" +- RET=$? +- +- if [ $RET -ne 0 ]; then ++ if [ $? -ne 0 ]; then ++ [ "$__OCF_ACTION" = "monitor" ] && ! ocf_is_probe && ocf_log error "IP $SECONDARY_PRIVATE_IP not assigned to interface ${NETWORK_ID}" + return $OCF_NOT_RUNNING + fi ++ + return $OCF_SUCCESS + } + +@@ -267,7 +277,7 @@ TOKEN=$(get_token) + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + 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") ++MAC_ADDRESS=$(get_interface_mac) + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC + NETWORK_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/network/interfaces/macs/${MAC_ADDRESS}/interface-id") + [ $? -ne 0 ] && exit $OCF_ERR_GENERIC diff --git a/resource-agents.spec b/resource-agents.spec index dfc4655..1d39462 100644 --- a/resource-agents.spec +++ b/resource-agents.spec @@ -20,7 +20,7 @@ # %global upstream_prefix ClusterLabs-resource-agents -%global upstream_version a6ccb93a +%global upstream_version 56e76b01 # Whether this platform defaults to using systemd as an init system # (needs to be evaluated prior to BuildRequires being enumerated and @@ -44,12 +44,15 @@ Name: resource-agents Summary: Open Source HA Reusable Cluster Resource Scripts -Version: 4.15.1 -Release: 1%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist}.1 +Version: 4.16.0 +Release: 1%{?rcver:%{rcver}}%{?numcomm:.%{numcomm}}%{?alphatag:.%{alphatag}}%{?dirty:.%{dirty}}%{?dist} License: GPL-2.0-or-later AND LGPL-2.1-or-later URL: https://github.com/ClusterLabs/resource-agents Source0: %{upstream_prefix}-%{upstream_version}.tar.gz Patch0: pgsqlms-ra.patch +Patch1: RHEL-66293-1-aws-agents-reuse-imds-token-until-it-expires.patch +Patch2: RHEL-66293-2-aws-agents-reuse-imds-token-improvements.patch +Patch3: RHEL-68740-awsvip-add-interface-parameter.patch # bundled ha-cloud-support libs Patch500: ha-cloud-support-aliyun.patch @@ -118,7 +121,7 @@ Requires: /sbin/fsck %endif Requires: /usr/sbin/fsck.ext2 /usr/sbin/fsck.ext3 /usr/sbin/fsck.ext4 Requires: /usr/sbin/fsck.xfs -%if 0%{?suse_version} +%if 0%{?fedora} > 40 || 0%{?centos} > 9 || 0%{?rhel} > 9 || 0%{?suse_version} Requires: /usr/sbin/mount.nfs /usr/sbin/mount.nfs4 %else Requires: /sbin/mount.nfs /sbin/mount.nfs4 @@ -138,7 +141,7 @@ Requires: /sbin/ip Requires: /usr/sbin/lvm # nfsserver / netfs.sh -%if 0%{?suse_version} +%if 0%{?fedora} > 40 || 0%{?centos} > 9 || 0%{?rhel} > 9 || 0%{?suse_version} Requires: /usr/sbin/rpc.statd %else Requires: /sbin/rpc.statd @@ -148,6 +151,9 @@ Requires: /usr/sbin/rpc.nfsd /usr/sbin/rpc.mountd # ocf.py Requires: python3 +# ethmonitor +Requires: bc + # rgmanager %if %{with rgmanager} # ip.sh @@ -204,6 +210,9 @@ exit 1 %endif %setup -q -n %{upstream_prefix}-%{upstream_version} %patch -p1 -P 0 +%patch -p1 -P 1 +%patch -p1 -P 2 +%patch -p1 -P 3 # bundled ha-cloud-support libs %patch -p1 -P 500 @@ -507,6 +516,8 @@ rm -rf %{buildroot}/usr/share/doc/resource-agents %{_mandir}/man7/*gcp-* /usr/lib/ocf/resource.d/heartbeat/powervs-subnet %{_mandir}/man7/*powervs-subnet* +%exclude /usr/lib/ocf/resource.d/heartbeat/azure-events +%exclude %{_mandir}/man7/*azure-events.7* %exclude /usr/lib/ocf/resource.d/heartbeat/gcp-vpc-move-ip %exclude %{_mandir}/man7/*gcp-vpc-move-ip* %endif @@ -520,6 +531,15 @@ rm -rf %{buildroot}/usr/share/doc/resource-agents %{_usr}/lib/ocf/lib/heartbeat/OCF_*.pm %changelog +* Tue Nov 26 2024 Oyvind Albrigtsen - 4.16.0-1 +- Rebase to resource-agents 4.16.0 upstream release +- AWS agents: reuse IMDS token until it expires +- awsvip: add interface parameter +- ethmonitor: add bc dependency +- build: use /usr/sbin path for nfs-utils dependencies + + Resolves: RHEL-65331, RHEL-66293, RHEL-68740, RHEL-53615, RHEL-68840 + * Tue Oct 29 2024 Troy Dawson - 4.15.1-1.1 - Bump release for October 2024 mass rebuild: Resolves: RHEL-64018 diff --git a/sources b/sources index 99c0d03..cc83394 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (ClusterLabs-resource-agents-a6ccb93a.tar.gz) = 3ea92f051f16efbd0845d193cc7d2e7d8e9f66ba8e2bbba3a7b8d093ceff3103f8077b93037067dee8962a7d5c1ad0a0b5642acbaf385b0619cef96f18928911 +SHA512 (ClusterLabs-resource-agents-56e76b01.tar.gz) = 14fded6bebcc9ada33c0c3db4fee45d6efc5d33865c52c1cf76b4485180cf9a76bae3456d84ba32635a2214ed1ee4010ca8704c844cebf4093ebc0843081919e