Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 52 additions & 87 deletions static/scripts/license_usage_offline.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@
set -euo pipefail
IFS=$'\n\t'

# Debug mode
if [[ "${DEBUG:-false}" == "true" ]]; then
set -x # Enable command tracing
echo "Debug mode enabled"
echo "Running in directory: $(pwd)"
echo "Script arguments: $*"
env | grep -E 'JWT_FILE|NIM_IP|USERNAME|PASSWORD|USE_CASE'
fi

# Set timeouts for operations
CURL_TIMEOUT=${CURL_TIMEOUT:-30}
API_POLL_TIMEOUT=${API_POLL_TIMEOUT:-60}

# Function to log with timestamp
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}

log "Script started"

# Function to display usage
usage() {
echo "Usage: $0 -j <JWT file> -i <NIM IP> -u <username> -p <password> -s <initial|telemetry>"
Expand Down Expand Up @@ -44,7 +64,6 @@ if [ ! -d "/tmp" ]; then
mkdir -p /tmp || { echo "Failed to create /tmp directory. Exiting."; exit 1; }
fi


# Read JWT contents
if [ ! -f "$JWT_FILE" ]; then
echo -e "JWT file '$JWT_FILE' not found.$" >&2
Expand Down Expand Up @@ -84,25 +103,29 @@ is_ipv4() {
return 1
fi
}
echo "Checking connectivity to NGINX Instance Manager using Curl ..."
if ! curl -sk --output /dev/null --silent --fail --max-time $CURL_TIMEOUT "https://$NIM_IP"; then
echo -e "The NGINX Instance Manager UI is not reachable on $NIM_IP"
exit 1
fi
echo "Checking connectivity to F5 licensing server..."
SERVER_RESPONSE=$(curl -v --max-time $CURL_TIMEOUT https://product.apis.f5.com 2>&1)

if is_ipv4 "$NIM_IP"; then
check_ping "$NIM_IP"
# Check if the server is reachable by verifying connection was established
if echo "$SERVER_RESPONSE" | grep -q "Connected to product.apis.f5.com" && echo "$SERVER_RESPONSE" | grep -q "server accepted"; then
echo -e "The licensing server is reachable on product.apis.f5.com"
else
echo "Checking connectivity to NGINX Instance Manager using Curl ..."
if ! curl -sk --output /dev/null --silent --fail "https://$NIM_IP"; then
echo -e "The NGINX Instance Manager UI is not reachable on $NIM_IP"
exit 1
fi
fi
check_ping "product.apis.f5.com"
echo -e "The licensing server is not reachable on product.apis.f5.com"
echo -e "Connection details: $SERVER_RESPONSE"
exit 1
fi

# NGINX Instance Manager Version check
VERSION_JSON=$(curl -sk -X GET "https://$NIM_IP/api/platform/v1/modules/versions" \
--header "Content-Type: application/json" \
--header "Authorization: Basic $AUTH_HEADER")
NIM_VER=$(echo "$VERSION_JSON" | sed -E 's/.*"nim"[ \t]*:[ \t]*"([0-9]+\.[0-9]+)(\.[0-9]+)?".*/\1/')
echo "Current version of NGINX Instance Manager is $NIM_VER"
JWT_CONTENT=$(<"$JWT_FILE")

# Construct JSON payload
JSON_PAYLOAD=$(cat <<EOF
Expand Down Expand Up @@ -145,16 +168,9 @@ fi
ORIGIN="https://$NIM_IP"
REFERER="$ORIGIN/ui/settings/license"



if [[ "$USE_CASE" == "initial" ]]; then
# Read JWT content
if [ ! -f "$JWT_FILE" ]; then
echo -e "JWT file '$JWT_FILE' not found." >&2
exit 1
fi
# Step 1: Apply JWT license (only if use case is 'initial' or 'intial_only')
echo "Applying JWT license"
sleep 5
RESPONSE=$(curl -sS -k --max-time 10 -w "\n%{http_code}" -X POST "https://$NIM_IP/api/platform/v1/license?telemetry=true" \
-H "Origin: $ORIGIN" \
-H "Referer: $REFERER" \
Expand All @@ -165,12 +181,9 @@ if [[ "$USE_CASE" == "initial" ]]; then
HTTP_BODY=$(echo "$RESPONSE" | sed '$d')
HTTP_STATUS=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_STATUS" -ne 202 ]; then
echo -e "HTTP request failed with status code $HTTP_STATUS.
Response: $HTTP_BODY$" >&2
echo -e "HTTP request failed with status code $HTTP_STATUS.\nResponse: $HTTP_BODY$" >&2
if echo "$HTTP_BODY" | jq -r '.message' | grep -q "failed to register token. already registered"; then
echo -e "NGINX Instance Manager already registered and licensed.
If needed, terminate the current license manually in the NGINX Instance Manager UI and re-run the script with the correct license.
https://docs.nginx.com/nginx-instance-manager/disconnected/add-license-disconnected-deployment/"
echo -e "NGINX Instance Manager already registered and licensed.\nIf needed, terminate the current license manually in the NGINX Instance Manager UI and re-run the script with the correct license.\nhttps://docs.nginx.com/nginx-instance-manager/disconnected/add-license-disconnected-deployment/"
fi
exit 1
fi
Expand All @@ -179,12 +192,11 @@ fi
if [[ "$NIM_VER" < "2.18" ]]; then
echo "NGINX Instance Manager version $NIM_VER is not supported by this script. Please use NGINX Instance Manager 2.18 or later"
exit 1

elif [[ "$NIM_VER" == "2.18" ]] || [[ "$NIM_VER" == "2.19" ]]; then
echo "NGINX Instance Manager version $NIM_VER detected."
ORIGIN="https://$NIM_IP"

# Send the PUT request and separate body and status code
# Send the PUT request and separate body and status code
PUT_RESPONSE_CODE=$(curl -k -s -w "%{http_code}" -o /tmp/put_response.json --location --request PUT "https://$NIM_IP/api/platform/v1/license?telemetry=true" \
--header "Origin: $ORIGIN" \
--header "Referer: https://$NIM_IP/ui/settings/license" \
Expand Down Expand Up @@ -223,7 +235,6 @@ elif [[ "$NIM_VER" == "2.18" ]] || [[ "$NIM_VER" == "2.19" ]]; then
fi

if [[ "$USE_CASE" != "telemetry" ]]; then

RESPONSE=$(curl -sS -k --max-time 10 -w "\n%{http_code}" -X POST "https://$NIM_IP/api/platform/v1/license?telemetry=true" \
-H "Origin: $ORIGIN" \
-H "Referer: $REFERER" \
Expand All @@ -237,15 +248,10 @@ if [[ "$USE_CASE" != "telemetry" ]]; then
echo -e "License applied successfully in DISCONNECTED mode."
fi



# Continue with further steps for version >= 2.20...
echo "Executing telemetry tasks "
# Step 2: Download the usage report
echo "Downloading usage report from NGINX Instance Manager at $NIM_IP..."
sleep 5
echo "Executing telemetry tasks"
if [[ "$NIM_VER" == "2.18" ]] || [[ "$NIM_VER" == "2.19" ]]; then
if [[ "$USE_CASE" == "initial" ]]; then
# Perform the request and capture the status code and output
HTTP_RESPONSE=$(curl -k -sS -w "\n%{http_code}" --location "https://$NIM_IP/api/platform/v1/report/download?format=zip&reportType=initial" \
--header "accept: application/json" \
--header "authorization: Basic $AUTH_HEADER" \
Expand All @@ -263,143 +269,114 @@ if [[ "$NIM_VER" == "2.18" ]] || [[ "$NIM_VER" == "2.19" ]]; then
--header 'accept: */*' \
--header 'authorization: Basic $AUTH_HEADER' \
--output \"$report_save_path\""

if [ "$USE_CASE" == "telemetry" ]; then
echo "Running telemetry stage: "

# Run the saved command and store the response
response=$(eval $prepare_usage_command)

sleep 2
# Validate if the response contains "Report generation in progress"
if echo "$response" | grep -q '"telemetry":"Report generation in progress"'; then
if echo "$response" | grep -q '"telemetry":"Report generation in progress"'; then
echo -e "Success: Report generation is in progress."
else
echo -e "Failure: Report generation not in progress or unexpected response."
exit 1
fi

echo "Running command: $download_usage_command"
eval $download_usage_command
else
echo "Running command: $download_usage_command"
eval $download_usage_command
fi
fi
echo "Running command: $download_usage_command"
eval $download_usage_command
else
echo "Running command: $download_usage_command"
eval $download_usage_command
fi
fi
else
# Perform the request and capture the status code and output
HTTP_RESPONSE=$(curl -k -sS -w "\n%{http_code}" --location "https://$NIM_IP/api/platform/v1/report/download?format=zip" \
--header "accept: application/json" \
--header "authorization: Basic $AUTH_HEADER" \
--header "content-type: application/json" \
--header "origin: https://$NIM_IP" \
--output /tmp/response.zip)
# Extract the HTTP status code (last line)
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tail -n1)

# Check the status code
HTTP_STATUS=$(echo "$HTTP_RESPONSE" | tail -n1)
if [ "$HTTP_STATUS" -ne 200 ]; then
echo -e "Failed to download usage report from NGINX Instance Manager. HTTP Status Code: $HTTP_STATUS" >&2
echo "Please verify that NGINX Instance Manager is reachable and the credentials are correct." >&2
echo "(or) Verify that NGINX Instance Manager is licensed before using the 'telemetry' flag (run it with 'initial' first)."
# Optionally, remove the partial or corrupt file
rm -f /tmp/response.zip
exit 1
fi
fi

echo -e "Usage report downloaded successfully as '/tmp/response.zip'."

# Step 3: Upload the usage report to F5 server
echo "Uploading the usage report to F5 Licensing server"

TEEM_UPLOAD_URL="https://product.apis.f5.com/ee/v1/entitlements/telemetry/bulk"

# Capture both response body and status code
UPLOAD_RESULT=$(curl -sS -w "\n%{http_code}" --location "$TEEM_UPLOAD_URL" \
--header "Authorization: Bearer $JWT_CONTENT" \
--form "file=@/tmp/response.zip")

# Extract HTTP status code and body
UPLOAD_STATUS=$(echo "$UPLOAD_RESULT" | tail -n1)
UPLOAD_BODY=$(echo "$UPLOAD_RESULT" | sed '$d')

# Validate HTTP status code
if [ "$UPLOAD_STATUS" -ne 202 ]; then
echo -e "Usage report upload failed. HTTP Status: $UPLOAD_STATUS$" >&2
echo "Response Body: $UPLOAD_BODY" >&2
exit 1
fi

# Check if response is valid JSON
if ! echo "$UPLOAD_BODY" | jq empty >/dev/null 2>&1; then
echo -e "Upload response is not valid JSON. Response: $UPLOAD_BODY$" >&2
exit 1
fi

# Extract the statusLink
STATUS_LINK=$(echo "$UPLOAD_BODY" | jq -r '.statusLink // empty')

if [ -z "$STATUS_LINK" ]; then
echo -e "Failed to extract statusLink from the upload response. Response: $UPLOAD_BODY$" >&2
exit 1
fi

echo "StatusLink extracted: $STATUS_LINK"

# Extract the unique status ID from the statusLink
STATUS_ID=$(echo "$STATUS_LINK" | sed 's|/ee/v1/entitlements/telemetry/bulk/status/||')

# Step 4: Validate the submit report status
echo "Validating the report status"
echo "Validating report status using status ID: $STATUS_LINK"

STATUS_URL="https://product.apis.f5.com/ee/v1/entitlements/telemetry/bulk/status/$STATUS_ID"

# Get the response from F5 status endpoint
sleep 5
STATUS_RESPONSE=$(curl -k -sS -w "\n%{http_code}" --location "$STATUS_URL" \
--header "Authorization: Bearer $JWT_CONTENT")

# Separate body and HTTP status code
STATUS_BODY=$(echo "$STATUS_RESPONSE" | sed '$d')
STATUS_CODE=$(echo "$STATUS_RESPONSE" | tail -n1)

# Validate HTTP status
if [ "$STATUS_CODE" -ne 200 ]; then
echo -e "Status check failed. HTTP Status: $STATUS_CODE$" >&2
echo "Response Body: $STATUS_BODY" >&2
exit 1
fi

# Validate that it's valid JSON
if ! echo "$STATUS_BODY" | jq empty >/dev/null 2>&1; then
echo -e "Invalid JSON in status body: $STATUS_BODY$" >&2
exit 1
fi

# Now safely extract values
PERCENTAGE_COMPLETE=$(echo "$STATUS_BODY" | jq -r '.percentageComplete')
PERCENTAGE_SUCCESSFUL=$(echo "$STATUS_BODY" | jq -r '.percentageSuccessful')
READY_FOR_DOWNLOAD=$(echo "$STATUS_BODY" | jq -r '.readyForDownload')

# Set a time limit (in seconds)
TIME_LIMIT=30 # 30 sec for example
TIME_LIMIT=30
START_TIME=$(date +%s)

# Function to calculate elapsed time
elapsed_time() {
echo $(($(date +%s) - $START_TIME))
}

# Keep checking until conditions are met or time limit is reached
while true; do
# Validate all required conditions
if [ "$PERCENTAGE_COMPLETE" -eq "100" ] && [ "$READY_FOR_DOWNLOAD" == "true" ]; then
echo -e "Validating Report."
break
fi

# Check if we've exceeded the time limit
if [ $(elapsed_time) -ge "$TIME_LIMIT" ]; then
echo -e "Time limit exceeded. Report validation failed."
echo " percentageComplete: $PERCENTAGE_COMPLETE"
Expand All @@ -410,28 +387,22 @@ while true; do
exit 1
fi

# Print current validation status
echo -e "Report validation failed. Waiting for conditions to be met...$"
echo " percentageComplete: $PERCENTAGE_COMPLETE"
echo " percentageSuccessful: $PERCENTAGE_SUCCESSFUL"
echo " readyForDownload: $READY_FOR_DOWNLOAD"

# Sleep for some time before checking again (e.g., 30 seconds)
sleep 5
done

echo -e "Report validated successfully. All conditions met."

# Step 5: Download the report from F5

echo "Downloading report from F5 License server..."

DOWNLOAD_URL="https://product.apis.f5.com/ee/v1/entitlements/telemetry/bulk/download/$STATUS_ID"
DOWNLOAD_RESPONSE=$(curl -sS -w "%{http_code}" --location "$DOWNLOAD_URL" \
--header "Authorization: Bearer $JWT_CONTENT" \
--output /tmp/response_teem.zip)

# Check HTTP status code
HTTP_STATUS=$(echo "$DOWNLOAD_RESPONSE" | tail -n1)
if [ "$HTTP_STATUS" -ne 200 ]; then
echo -e "Failed to download the report from F5. HTTP Status Code: $HTTP_STATUS$" >&2
Expand All @@ -440,31 +411,25 @@ fi

echo -e "Report downloaded successfully from F5 as '/tmp/response_teem.zip'."

# Step 6: Upload the acknowledgement report to NGINX Instance Manager
echo "Uploading the license acknowledgement to NGINX Instance Manager..."

UPLOAD_URL="https://$NIM_IP/api/platform/v1/report/upload"
UPLOAD_RESPONSE=$(curl -k -sS --location "$UPLOAD_URL" \
--header "Authorization: Basic $AUTH_HEADER" \
--form "file=@/tmp/response_teem.zip" \
-w "%{http_code}" -o /tmp/temp_response.json)

# Extract the HTTP status code
HTTP_STATUS=$(echo "$UPLOAD_RESPONSE" | tail -n1)

# Extract the message from the response body (temp_response.json)
UPLOAD_MESSAGE=$(cat /tmp/temp_response.json | jq -r '.message')

# Ensure HTTP_STATUS is a valid integer
if ! [[ "$HTTP_STATUS" =~ ^[0-9]+$ ]]; then
echo -e "Invalid HTTP status code. Response: $UPLOAD_RESPONSE$" >&2
exit 1
fi

# Check if the upload response contains the success message and validate the status code
if [ "$UPLOAD_MESSAGE" != "Report uploaded successfully." ] || [ "$HTTP_STATUS" -ne 200 ]; then
echo -e "Upload failed. Response: $UPLOAD_RESPONSE$" >&2
exit 1
fi
echo -e "Acknowledgement uploaded successfully to NGINX Instance Manager."


Loading