123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- #!/usr/bin/env bash
- # netdata
- # real-time performance and health monitoring, done right!
- # (C) 2017 Costa Tsaousis <costa@tsaousis.gr>
- # SPDX-License-Identifier: GPL-3.0-or-later
- # Exit code: 0 - Success
- # Exit code: 1 - Unknown argument
- # Exit code: 2 - Problems with claiming working directory
- # Exit code: 3 - Missing dependencies
- # Exit code: 4 - Failure to connect to endpoint
- # Exit code: 5 - Unknown HTTP error message
- # Exit code: 6 - The CLI didn't work
- # Exit code: 7 - Wrong user
- #
- # OK: Agent claimed successfully
- # HTTP Status code: 204
- # Exit code: 0
- #
- # Error: The agent id is invalid; it does not fulfill the constraints
- # HTTP Status code: 422
- # Error key: "ErrInvalidNodeID"
- # Error message: "invalid node id"
- # Exit code: 6
- # Error: The agent hostname is invalid; it does not fulfill the constraints
- # HTTP Status code: 422
- # Error key: "ErrInvalidNodeName"
- # Error message: "invalid node name"
- # Exit code: 7
- #
- # Error: At least one of the given rooms ids is invalid; it does not fulfill the constraints
- # HTTP Status code: 422
- # Error key: "ErrInvalidRoomID"
- # Error message: "invalid room id"
- # Exit code: 8
- #
- # Error: Invalid public key; the public key is empty or not present
- # HTTP Status code: 422
- # Error key: "ErrInvalidPublicKey"
- # Error message: "invalid public key"
- # Exit code: 9
- #
- # Error: Expired, missing or invalid token
- # HTTP Status code: 403
- # Error key: "ErrForbidden"
- # Error message: "token expired" | "token not found" | "invalid token"
- # Exit code: 10
- #
- # Error: Duplicate agent id; an agent with the same id is already registered in the cloud
- # HTTP Status code: 409
- # Error key: "ErrAlreadyClaimed"
- # Error message: "already claimed"
- # Exit code: 11
- #
- # Error: The node claiming process is still in progress.
- # HTTP Status code: 102
- # Error key: "ErrProcessingClaim"
- # Error message: "processing claiming"
- # Exit code: 12
- #
- # Error: Internal server error. Any other unexpected error (DB problems, etc.)
- # HTTP Status code: 500
- # Error key: "ErrInternalServerError"
- # Error message: "Internal Server Error"
- # Exit code: 13
- #
- # Error: There was a timout processing the claim.
- # HTTP Status code: 504
- # Error key: "ErrGatewayTimeout"
- # Error message: "Gateway Timeout"
- # Exit code: 14
- #
- # Error: The service cannot handle the claiming request at this time.
- # HTTP Status code: 503
- # Error key: "ErrServiceUnavailable"
- # Error message: "Service Unavailable"
- # Exit code: 15
- if command -v curl >/dev/null 2>&1 ; then
- URLTOOL="curl"
- elif command -v wget >/dev/null 2>&1 ; then
- URLTOOL="wget"
- else
- echo >&2 "I need curl or wget to proceed, but neither is available on this system."
- exit 3
- fi
- if ! command -v openssl >/dev/null 2>&1 ; then
- echo >&2 "I need openssl to proceed, but it is not available on this system."
- exit 3
- fi
- # -----------------------------------------------------------------------------
- # defaults to allow running this script by hand
- [ -z "${NETDATA_USER_CONFIG_DIR}" ] && NETDATA_USER_CONFIG_DIR="@configdir_POST@"
- MACHINE_GUID_FILE="@registrydir_POST@/netdata.public.unique.id"
- CLAIMING_DIR="${NETDATA_USER_CONFIG_DIR}/claim.d"
- TOKEN="unknown"
- URL_BASE="https://netdata.cloud"
- ID="unknown"
- ROOMS=""
- HOSTNAME=$(hostname)
- CLOUD_CERTIFICATE_FILE="${CLAIMING_DIR}/cloud_fullchain.pem"
- VERBOSE=0
- INSECURE=0
- RELOAD=1
- NETDATA_USER=netdata
- [ -z "$EUID" ] && EUID="$(id -u)"
- CONF_USER=$(grep '^[ #]*run as user[ ]*=' "${NETDATA_USER_CONFIG_DIR}/netdata.conf" 2>/dev/null)
- if [ -n "$CONF_USER" ]; then
- NETDATA_USER=$(echo "$CONF_USER" | sed 's/^[^=]*=[ \t]*//' | sed 's/[ \t]*$//')
- fi
- # get the MACHINE_GUID by default
- if [ -r "${MACHINE_GUID_FILE}" ]; then
- ID="$(cat "${MACHINE_GUID_FILE}")"
- fi
- # get token from file
- if [ -r "${CLAIMING_DIR}/token" ]; then
- TOKEN="$(cat "${CLAIMING_DIR}/token")"
- fi
- # get rooms from file
- if [ -r "${CLAIMING_DIR}/rooms" ]; then
- ROOMS="$(cat "${CLAIMING_DIR}/rooms")"
- fi
- for arg in "$@"
- do
- case $arg in
- -token=*) TOKEN=${arg:7} ;;
- -url=*) URL_BASE=${arg:5} ;;
- -id=*) ID=${arg:4} ;;
- -rooms=*) ROOMS=${arg:7} ;;
- -hostname=*) HOSTNAME=${arg:10} ;;
- -verbose) VERBOSE=1 ;;
- -insecure) INSECURE=1 ;;
- -proxy=*) PROXY=${arg:7} ;;
- -noproxy) NOPROXY=yes ;;
- -noreload) RELOAD=0 ;;
- -user=*) NETDATA_USER=${arg:6} ;;
- *) echo >&2 "Unknown argument ${arg}"
- exit 1 ;;
- esac
- shift 1
- done
- if [ "$EUID" != "0" ] && [ "$(whoami)" != "$NETDATA_USER" ]; then
- echo >&2 "This script must be run by the $NETDATA_USER user account"
- exit 7
- fi
- # if curl not installed give warning SOCKS can't be used
- if [[ "${URLTOOL}" != "curl" && "${PROXY:0:5}" = socks ]] ; then
- echo >&2 "wget doesn't support SOCKS. Please install curl or disable SOCKS proxy."
- exit 1
- fi
- echo >&2 "Token: ****************"
- echo >&2 "Base URL: $URL_BASE"
- echo >&2 "Id: $ID"
- echo >&2 "Rooms: $ROOMS"
- echo >&2 "Hostname: $HOSTNAME"
- echo >&2 "Proxy: $PROXY"
- echo >&2 "Netdata user: $NETDATA_USER"
- # create the claiming directory for this user
- if [ ! -d "${CLAIMING_DIR}" ] ; then
- mkdir -p "${CLAIMING_DIR}" && chmod 0770 "${CLAIMING_DIR}"
- # shellcheck disable=SC2181
- if [ $? -ne 0 ] ; then
- echo >&2 "Failed to create claiming working directory ${CLAIMING_DIR}"
- exit 2
- fi
- fi
- if [ ! -w "${CLAIMING_DIR}" ] ; then
- echo >&2 "No write permission in claiming working directory ${CLAIMING_DIR}"
- exit 2
- fi
- if [ ! -f "${CLAIMING_DIR}/private.pem" ] ; then
- echo >&2 "Generating private/public key for the first time."
- if ! openssl genrsa -out "${CLAIMING_DIR}/private.pem" 2048 ; then
- echo >&2 "Failed to generate private/public key pair."
- exit 2
- fi
- fi
- if [ ! -f "${CLAIMING_DIR}/public.pem" ] ; then
- echo >&2 "Extracting public key from private key."
- if ! openssl rsa -in "${CLAIMING_DIR}/private.pem" -outform PEM -pubout -out "${CLAIMING_DIR}/public.pem" ; then
- echo >&2 "Failed to extract public key."
- exit 2
- fi
- fi
- TARGET_URL="${URL_BASE%/}/api/v1/spaces/nodes/${ID}"
- # shellcheck disable=SC2002
- KEY=$(cat "${CLAIMING_DIR}/public.pem" | tr '\n' '!' | sed -e 's/!/\\n/g')
- # shellcheck disable=SC2001
- [ -n "$ROOMS" ] && ROOMS=\"$(echo "$ROOMS" | sed s'/,/", "/g')\"
- cat > "${CLAIMING_DIR}/tmpin.txt" <<EMBED_JSON
- {
- "node": {
- "id": "$ID",
- "hostname": "$HOSTNAME"
- },
- "token": "$TOKEN",
- "rooms" : [ $ROOMS ],
- "publicKey" : "$KEY"
- }
- EMBED_JSON
- if [ "${VERBOSE}" == 1 ] ; then
- echo "Request to server:"
- cat "${CLAIMING_DIR}/tmpin.txt"
- fi
- if [ "${URLTOOL}" = "curl" ] ; then
- URLCOMMAND="curl --connect-timeout 5 --retry 0 -s -i -X PUT -d \"@${CLAIMING_DIR}/tmpin.txt\""
- if [ "${NOPROXY}" = "yes" ] ; then
- URLCOMMAND="${URLCOMMAND} -x \"\""
- elif [ -n "${PROXY}" ] ; then
- URLCOMMAND="${URLCOMMAND} -x \"${PROXY}\""
- fi
- else
- URLCOMMAND="wget -T 15 -O - -q --save-headers --content-on-error=on --method=PUT \
- --body-file=\"${CLAIMING_DIR}/tmpin.txt\""
- if [ "${NOPROXY}" = "yes" ] ; then
- URLCOMMAND="${URLCOMMAND} --no-proxy"
- elif [ "${PROXY:0:4}" = http ] ; then
- URLCOMMAND="export http_proxy=${PROXY}; ${URLCOMMAND}"
- fi
- fi
- if [ "${INSECURE}" == 1 ] ; then
- if [ "${URLTOOL}" = "curl" ] ; then
- URLCOMMAND="${URLCOMMAND} --insecure"
- else
- URLCOMMAND="${URLCOMMAND} --no-check-certificate"
- fi
- fi
- if [ -r "${CLOUD_CERTIFICATE_FILE}" ] ; then
- if [ "${URLTOOL}" = "curl" ] ; then
- URLCOMMAND="${URLCOMMAND} --cacert \"${CLOUD_CERTIFICATE_FILE}\""
- else
- URLCOMMAND="${URLCOMMAND} --ca-certificate \"${CLOUD_CERTIFICATE_FILE}\""
- fi
- fi
- if [ "${VERBOSE}" == 1 ]; then
- echo "${URLCOMMAND} \"${TARGET_URL}\""
- fi
- eval "${URLCOMMAND} \"${TARGET_URL}\"" >"${CLAIMING_DIR}/tmpout.txt"
- URLCOMMAND_EXIT_CODE=$?
- if [ "${URLTOOL}" = "wget" ] && [ "${URLCOMMAND_EXIT_CODE}" -eq 8 ] ; then
- # We consider the server issuing an error response a successful attempt at communicating
- URLCOMMAND_EXIT_CODE=0
- fi
- rm -f "${CLAIMING_DIR}/tmpin.txt"
- # Check if URLCOMMAND connected and received reply
- if [ "${URLCOMMAND_EXIT_CODE}" -ne 0 ] ; then
- echo >&2 "Failed to connect to ${URL_BASE}, return code ${URLCOMMAND_EXIT_CODE}"
- rm -f "${CLAIMING_DIR}/tmpout.txt"
- exit 4
- fi
- if [ "${VERBOSE}" == 1 ] ; then
- echo "Response from server:"
- cat "${CLAIMING_DIR}/tmpout.txt"
- fi
- HTTP_STATUS_CODE=$(grep "HTTP" "${CLAIMING_DIR}/tmpout.txt" | awk -F " " '{print $2}')
- if [ "${HTTP_STATUS_CODE}" = "204" ] ; then
- rm -f "${CLAIMING_DIR}/tmpout.txt"
- echo -n "${ID}" >"${CLAIMING_DIR}/claimed_id" || (echo >&2 "Claiming failed"; set -e; exit 2)
- rm -f "${CLAIMING_DIR}/token" || (echo >&2 "Claiming failed"; set -e; exit 2)
- if [ "$EUID" == "0" ]; then
- chown -R "${NETDATA_USER}:${NETDATA_USER}" ${CLAIMING_DIR} || (echo >&2 "Claiming failed"; set -e; exit 2)
- fi
- if [ "${RELOAD}" == "0" ] ; then
- exit 0
- fi
- netdatacli reload-claiming-state && echo >&2 "Node was successfully claimed." && exit 0
- echo "The claim was successful but the agent could not be notified ($?)- it requires a restart to connect to the cloud"
- exit 6
- fi
- ERROR_MESSAGE=$(grep "\"errorMsgKey\":" "${CLAIMING_DIR}/tmpout.txt" | awk -F "errorMsgKey\":\"" '{print $2}' | awk -F "\"" '{print $1}')
- case ${ERROR_MESSAGE} in
- "ErrInvalidNodeID") EXIT_CODE=6 ;;
- "ErrInvalidNodeName") EXIT_CODE=7 ;;
- "ErrInvalidRoomID") EXIT_CODE=8 ;;
- "ErrInvalidPublicKey") EXIT_CODE=9 ;;
- "ErrForbidden") EXIT_CODE=10 ;;
- "ErrAlreadyClaimed") EXIT_CODE=11 ;;
- "ErrProcessingClaim") EXIT_CODE=12 ;;
- "ErrInternalServerError") EXIT_CODE=13 ;;
- "ErrGatewayTimeout") EXIT_CODE=14 ;;
- "ErrServiceUnavailable") EXIT_CODE=15 ;;
- *) EXIT_CODE=5 ;;
- esac
- echo >&2 "Failed to claim node."
- rm -f "${CLAIMING_DIR}/tmpout.txt"
- exit $EXIT_CODE
|