From ce9f70d7b3696a54f099628f3337f5c4d5bd1407 Mon Sep 17 00:00:00 2001 From: Markos Fountoulakis <44345837+mfundul@users.noreply.github.com> Date: Thu, 19 Dec 2019 11:01:59 +0200 Subject: [PATCH] Agent claiming (#7525) Initial infrastructure support for agent claiming. This feature is not currently enabled as we are still finalizing the details of the cloud infrastructure w.r.t. agent claiming. The feature will be enabled when we are ready to release it. --- .gitignore | 1 + BUILD.md | 1 - CMakeLists.txt | 6 + Makefile.am | 7 + claim/Makefile.am | 21 ++ claim/README.md | 72 +++++++ claim/claim.c | 103 ++++++++++ claim/claim.h | 14 ++ claim/netdata-claim.sh.in | 216 +++++++++++++++++++++ cli/README.md | 2 + configure.ac | 1 + daemon/commands.c | 21 +- daemon/commands.h | 1 + daemon/common.h | 3 + daemon/daemon.c | 6 + daemon/main.c | 15 ++ netdata-installer.sh | 10 + packaging/installer/netdata-uninstaller.sh | 1 + 18 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 claim/Makefile.am create mode 100644 claim/README.md create mode 100644 claim/claim.c create mode 100644 claim/claim.h create mode 100755 claim/netdata-claim.sh.in diff --git a/.gitignore b/.gitignore index 284fcda506..f94c5603a3 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ daemon/anonymous-statistics.sh daemon/get-kubernetes-labels.sh health/notifications/alarm-notify.sh +claim/netdata-claim.sh collectors/cgroups.plugin/cgroup-name.sh collectors/tc.plugin/tc-qos-helper.sh collectors/charts.d.plugin/charts.d.plugin diff --git a/BUILD.md b/BUILD.md index e22e6a2fff..5ad4bdbaef 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,4 +1,3 @@ - # The build system We are currently migrating from `autotools` to `CMake` as a build-system. This document diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ff64b1c38..fe221b9b0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -601,6 +601,11 @@ set(BACKENDS_PLUGIN_FILES backends/prometheus/backend_prometheus.h ) +set(CLAIM_PLUGIN_FILES + claim/claim.c + claim/claim.h + ) + set(EXPORTING_ENGINE_FILES exporting/exporting_engine.c exporting/exporting_engine.h @@ -667,6 +672,7 @@ set(NETDATA_FILES ${STATSD_PLUGIN_FILES} ${STREAMING_PLUGIN_FILES} ${WEB_PLUGIN_FILES} + ${CLAIM_PLUGIN_FILES} ) set(NETDATACLI_FILES diff --git a/Makefile.am b/Makefile.am index 1158cf073d..0a8c3e8800 100644 --- a/Makefile.am +++ b/Makefile.am @@ -99,6 +99,7 @@ SUBDIRS += \ registry \ streaming \ web \ + claim \ $(NULL) @@ -454,6 +455,11 @@ BACKENDS_PLUGIN_FILES = \ backends/prometheus/backend_prometheus.h \ $(NULL) +CLAIM_PLUGIN_FILES = \ + claim/claim.c \ + claim/claim.h \ + $(NULL) + EXPORTING_ENGINE_FILES = \ exporting/exporting_engine.c \ exporting/exporting_engine.h \ @@ -521,6 +527,7 @@ NETDATA_FILES = \ $(STREAMING_PLUGIN_FILES) \ $(STATSD_PLUGIN_FILES) \ $(WEB_PLUGIN_FILES) \ + $(CLAIM_PLUGIN_FILES) \ $(NULL) if FREEBSD diff --git a/claim/Makefile.am b/claim/Makefile.am new file mode 100644 index 0000000000..c838db9b66 --- /dev/null +++ b/claim/Makefile.am @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +CLEANFILES = \ + netdata-claim.sh \ + $(NULL) + +include $(top_srcdir)/build/subst.inc +SUFFIXES = .in + +sbin_SCRIPTS = \ + netdata-claim.sh \ + $(NULL) + +dist_noinst_DATA = \ + netdata-claim.sh.in \ + README.md \ + $(NULL) + diff --git a/claim/README.md b/claim/README.md new file mode 100644 index 0000000000..05de636155 --- /dev/null +++ b/claim/README.md @@ -0,0 +1,72 @@ +# Agent claiming + +Agent claiming is part of the onboarding process when creating a workspace in Netdata Cloud. Each workspace gets its own +common invitation mechanism, which begins with the administrators of the workspace creating a **claiming-token**. They, +or other users is their organization, can then use the claiming-token to add an agent to their workspace. + +To claim a Netdata agent, you first send a claiming request to Netdata Cloud (from the agent node). Once the +Netdata Cloud validates the claiming request of the agent (based on the claiming token), and returns a successful +result, the node is considered claimed. + +## Claiming script + +The user can claim an agent by directly calling the `netdata-claim.sh` script **as the netdata user** and passing the +following arguments: + +```sh +-token=TOKEN + where TOKEN is the workspace claiming-token. +-rooms=ROOM1,ROOM2,... + where ROOMX is the workspace war-room to join. This list is optional. +-url=URL_BASE + where URL_BASE is the Netdata Cloud endpoint base URL. By default, this is https://netdata.cloud. +-id=AGENT_ID + where AGENT_ID is the unique identifier of the agent. This is the agent's MACHINE_GUID by default. +-hostname=HOSTNAME + where HOSTNAME is the result of the hostname command by default. +``` + +For example, the following command claims an agent and adds it to rooms `room1` and `room2`: + +```sh +netdata-claim.sh -token=MYTOKEN1234567 -rooms=room1,room2 +``` + +You should then update the `netdata` service about the result with `netdatacli`: + +```sh +netdatacli reload-claiming-state +``` + +This reloads the agent claiming state from disk. + +## Netdata agent command line + +The user can trigger agent claiming by calling the `netdata` service binary with the additional command line parameters: + +```sh +-W "claim -token=TOKEN -rooms=ROOM1,ROOM2" +``` + +For example: + +```sh +/usr/sbin/netdata -D -W "claim -token=MYTOKEN1234567 -rooms=room1,room2" +``` + +If need be, the user can override the agent's defaults by providing additional arguments like those described +[here](#claiming-script). + +## Claiming directory + +Netdata stores the agent claiming-related state in the user configuration directory under `claim.d`, e.g. in +`/etc/netdata/claim.d`. The user can put files in this directory to provide defaults to the `-token` and `-rooms` +arguments. These files should be owned **by the `netdata` user**. + +The `claim.d/token` file should contain the claiming-token and the `claim.d/rooms` file should contain the list of +war-rooms. + +The user can also put the Cloud endpoint's full certificate chain in `claim.d/cloud_fullchain.pem` so that the agent +can trust the endpoint if necessary. + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fclaim%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)](<>) diff --git a/claim/claim.c b/claim/claim.c new file mode 100644 index 0000000000..75f0a437d6 --- /dev/null +++ b/claim/claim.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "claim.h" +#include "../registry/registry_internals.h" + +char *claiming_pending_arguments = NULL; + +static char *claiming_errors[] = { + "Agent claimed successfully", // 0 + "Unknown argument", // 1 + "Problems with claiming working directory", // 2 + "Missing dependencies", // 3 + "Failure to connect to endpoint", // 4 + "Unknown HTTP error message", // 5 + "invalid agent id", // 6 + "invalid public key", // 7 + "token has expired", // 8 + "invalid token", // 9 + "duplicate agent id", // 10 + "claimed in another workspace", // 11 + "internal server error" // 12 +}; + +#define AGENT_UNCLAIMED 0 +#define AGENT_CLAIMED 1 +static uint8_t claiming_status = AGENT_UNCLAIMED; + +uint8_t is_agent_claimed(void) +{ + return (AGENT_CLAIMED == claiming_status); +} + +#define CLAIMING_COMMAND_LENGTH 16384 + +extern struct registry registry; + +/* rrd_init() must have been called before this function */ +void claim_agent(char *claiming_arguments) +{ + info("The claiming feature is under development and still subject to change before the next release"); + return; + + int exit_code; + pid_t command_pid; + char command_buffer[CLAIMING_COMMAND_LENGTH + 1]; + FILE *fp; + + snprintfz(command_buffer, + CLAIMING_COMMAND_LENGTH, + "exec netdata-claim.sh -hostname=%s -id=%s -url=%s %s", + netdata_configured_hostname, + localhost->machine_guid, + registry.cloud_base_url, + claiming_arguments); + + info("Executing agent claiming command 'netdata-claim.sh'"); + fp = mypopen(command_buffer, &command_pid); + if(!fp) { + error("Cannot popen(\"%s\").", command_buffer); + return; + } + info("Waiting for claiming command to finish."); + while (fgets(command_buffer, CLAIMING_COMMAND_LENGTH, fp) != NULL) {;} + exit_code = mypclose(fp, command_pid); + info("Agent claiming command returned with code %d", exit_code); + if (0 == exit_code) { + claiming_status = AGENT_CLAIMED; + info("Agent successfully claimed."); + return; + } + if (exit_code < 0) { + error("Agent claiming command failed to complete its run."); + return; + } + errno = 0; + unsigned maximum_known_exit_code = sizeof(claiming_errors) / sizeof(claiming_errors[0]); + + if ((unsigned)exit_code > maximum_known_exit_code) { + error("Agent failed to be claimed with an unknown error."); + return; + } + error("Agent failed to be claimed with the following error message:"); + error("\"%s\"", claiming_errors[exit_code]); +} + +void load_claiming_state(void) +{ + info("The claiming feature is under development and still subject to change before the next release"); + return; + + char filename[FILENAME_MAX + 1]; + struct stat statbuf; + + snprintfz(filename, FILENAME_MAX, "%s/claim.d/is_claimed", netdata_configured_user_config_dir); + // check if the file exists + if (lstat(filename, &statbuf) != 0) { + info("File '%s' was not found. Setting state to AGENT_UNCLAIMED.", filename); + claiming_status = AGENT_UNCLAIMED; + } else { + info("File '%s' was found. Setting state to AGENT_CLAIMED.", filename); + claiming_status = AGENT_CLAIMED; + } +} diff --git a/claim/claim.h b/claim/claim.h new file mode 100644 index 0000000000..3b2b867434 --- /dev/null +++ b/claim/claim.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_CLAIM_H +#define NETDATA_CLAIM_H 1 + +#include "../daemon/common.h" + +extern char *claiming_pending_arguments; + +void claim_agent(char *claiming_arguments); +uint8_t is_agent_claimed(void); +void load_claiming_state(void); + +#endif //NETDATA_CLAIM_H diff --git a/claim/netdata-claim.sh.in b/claim/netdata-claim.sh.in new file mode 100755 index 0000000000..e565e3de28 --- /dev/null +++ b/claim/netdata-claim.sh.in @@ -0,0 +1,216 @@ +#!/usr/bin/env bash +# netdata +# real-time performance and health monitoring, done right! +# (C) 2017 Costa Tsaousis +# 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 +# +# OK: Agent claimed successfully +# HTTP Status code: 200 +# Exit code: 0 +# +# Error: The agent id is invalid; it does not fulfill the constraints +# HTTP Status code: 422 +# Error message: "invalid agent id" +# Exit code: 6 +# +# Error: Invalid public key; the public key is empty or not present +# HTTP Status code: 422 +# Error message: "invalid public key" +# Exit code: 7 +# +# Error: Expired token +# HTTP Status code: 403 +# Error message: "token has expired" +# Exit code: 8 +# +# Error: Invalid claiming token; missing, undecryptable, invalid payload... +# HTTP Status code: 422 +# Error message: "invalid token" +# Exit code: 9 +# +# Error: Duplicate agent id; an agent with the same id but a different public key is already registered in the cloud +# HTTP Status code: 409 +# Error message: "duplicate agent id" +# Exit code: 10 +# +# Error: Already claimed in another workspace; +# this agent (same id, same public key) already belongs to another workspace +# HTTP Status code: 403 +# Error message: "claimed in another workspace" +# Exit code: 11 +# +# Error: Internal server error. Any other unexpected error (DB problems, etc.) +# HTTP Status code: 500 +# Error message: "internal server error" +# Exit code: 12 + +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 neither is 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" + +# 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} ;; + *) echo >&2 "Unknown argument ${arg}" + exit 1 ;; + esac + shift 1 +done + +echo >&2 "Token: ****************" +echo >&2 "Base URL: $URL_BASE" +echo >&2 "Id: $ID" +echo >&2 "Rooms: $ROOMS" +echo >&2 "Hostname: $HOSTNAME" + +# 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/workspaces/agents/${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" <&2 "Failed to connect to ${URL_BASE}" + rm -f "${CLAIMING_DIR}/tmpout.txt" + exit 4 +fi + +HTTP_STATUS_CODE=$(grep "HTTP" "${CLAIMING_DIR}/tmpout.txt" | awk -F " " '{print $2}') +if [ "${HTTP_STATUS_CODE}" -ne 200 ] ; then + ERROR_MESSAGE=$(grep "\"error\":" "${CLAIMING_DIR}/tmpout.txt" | awk -F "error\":\"" '{print $2}' | sed s'/"}//g') + case ${ERROR_MESSAGE} in + "invalid agent id") EXIT_CODE=6 ;; + "invalid public key") EXIT_CODE=7 ;; + "token has expired") EXIT_CODE=8 ;; + "invalid token") EXIT_CODE=9 ;; + "duplicate agent id") EXIT_CODE=10 ;; + "claimed in another workspace") EXIT_CODE=11 ;; + "internal server error") EXIT_CODE=12 ;; + *) EXIT_CODE=5 ;; + esac + echo >&2 "Failed to claim agent." + rm -f "${CLAIMING_DIR}/tmpout.txt" + exit $EXIT_CODE +fi + +rm -f "${CLAIMING_DIR}/tmpout.txt" +touch "${CLAIMING_DIR}/is_claimed" +rm -f "${CLAIMING_DIR}/token" +echo >&2 "Agent was successfully claimed." \ No newline at end of file diff --git a/cli/README.md b/cli/README.md index 3872dac1c1..d39198f26d 100644 --- a/cli/README.md +++ b/cli/README.md @@ -19,6 +19,8 @@ shutdown-agent Cleanup and exit the netdata agent. fatal-agent Log the state and halt the netdata agent. +reload-claiming-state + Reload agent claiming state from disk. ``` Those commands are the same that can be sent to netdata via [signals](../daemon#command-line-options). diff --git a/configure.ac b/configure.ac index 6fcb3baeba..ad35aa61cc 100644 --- a/configure.ac +++ b/configure.ac @@ -1282,6 +1282,7 @@ AC_CONFIG_FILES([ web/gui/Makefile web/server/Makefile web/server/static/Makefile + claim/Makefile ]) AC_OUTPUT diff --git a/daemon/commands.c b/daemon/commands.c index 5eb22a6693..b12c19216b 100644 --- a/daemon/commands.c +++ b/daemon/commands.c @@ -40,6 +40,7 @@ static cmd_status_t cmd_save_database_execute(char *args, char **message); static cmd_status_t cmd_reopen_logs_execute(char *args, char **message); static cmd_status_t cmd_exit_execute(char *args, char **message); static cmd_status_t cmd_fatal_execute(char *args, char **message); +static cmd_status_t cmd_reload_claiming_state_execute(char *args, char **message); static cmd_status_t cmd_reload_labels_execute(char *args, char **message); static command_info_t command_info_array[] = { @@ -49,6 +50,7 @@ static command_info_t command_info_array[] = { {"reopen-logs", cmd_reopen_logs_execute, CMD_TYPE_ORTHOGONAL}, // Close and reopen log files {"shutdown-agent", cmd_exit_execute, CMD_TYPE_EXCLUSIVE}, // exit cleanly {"fatal-agent", cmd_fatal_execute, CMD_TYPE_HIGH_PRIORITY}, // exit with fatal error + {"reload-claiming-state", cmd_reload_claiming_state_execute, CMD_TYPE_ORTHOGONAL}, // reload claiming state {"reload-labels", cmd_reload_labels_execute, CMD_TYPE_ORTHOGONAL}, // reload the labels }; @@ -108,7 +110,9 @@ static cmd_status_t cmd_help_execute(char *args, char **message) "shutdown-agent\n" " Cleanup and exit the netdata agent.\n" "fatal-agent\n" - " Log the state and halt the netdata agent.\n", + " Log the state and halt the netdata agent.\n" + "reload-claiming-state\n" + " Reload agent claiming state from disk.\n", MAX_COMMAND_LENGTH - 1); return CMD_STATUS_SUCCESS; } @@ -176,6 +180,21 @@ static cmd_status_t cmd_fatal_execute(char *args, char **message) return CMD_STATUS_SUCCESS; } +static cmd_status_t cmd_reload_claiming_state_execute(char *args, char **message) +{ + (void)args; + (void)message; + + info("The claiming feature is still in development and subject to change before the next release"); + return CMD_STATUS_FAILURE; + + error_log_limit_unlimited(); + info("COMMAND: Reloading Agent Claiming configuration."); + load_claiming_state(); + error_log_limit_reset(); + return CMD_STATUS_SUCCESS; +} + static cmd_status_t cmd_reload_labels_execute(char *args, char **message) { (void)args; diff --git a/daemon/commands.h b/daemon/commands.h index 6de4084217..cb879c2a8c 100644 --- a/daemon/commands.h +++ b/daemon/commands.h @@ -19,6 +19,7 @@ typedef enum cmd { CMD_REOPEN_LOGS, CMD_EXIT, CMD_FATAL, + CMD_RELOAD_CLAIMING_STATE, CMD_RELOAD_LABELS, CMD_TOTAL_COMMANDS } cmd_t; diff --git a/daemon/common.h b/daemon/common.h index 5202a53082..6ac3cb3c87 100644 --- a/daemon/common.h +++ b/daemon/common.h @@ -60,6 +60,9 @@ // netdata unit tests #include "unit_test.h" +// netdata agent claiming +#include "claim/claim.h" + // the netdata deamon #include "daemon.h" #include "main.h" diff --git a/daemon/daemon.c b/daemon/daemon.c index 4ad082b95e..77448c0e73 100644 --- a/daemon/daemon.c +++ b/daemon/daemon.c @@ -4,6 +4,7 @@ #include char pidfile[FILENAME_MAX + 1] = ""; +char claimingdirectory[FILENAME_MAX + 1]; static void chown_open_file(int fd, uid_t uid, gid_t gid) { if(fd == -1) return; @@ -50,6 +51,7 @@ int become_user(const char *username, int pid_fd) { create_needed_dir(netdata_configured_cache_dir, uid, gid); create_needed_dir(netdata_configured_varlib_dir, uid, gid); + create_needed_dir(claimingdirectory, uid, gid); if(pidfile[0]) { if(chown(pidfile, uid, gid) == -1) @@ -434,6 +436,9 @@ int become_daemon(int dont_fork, const char *user) // never become a problem sched_setscheduler_set(); + // Set claiming directory based on user config directory with correct ownership + snprintfz(claimingdirectory, FILENAME_MAX, "%s/claim.d", netdata_configured_user_config_dir); + if(user && *user) { if(become_user(user, pidfd) != 0) { error("Cannot become user '%s'. Continuing as we are.", user); @@ -443,6 +448,7 @@ int become_daemon(int dont_fork, const char *user) else { create_needed_dir(netdata_configured_cache_dir, getuid(), getgid()); create_needed_dir(netdata_configured_varlib_dir, getuid(), getgid()); + create_needed_dir(claimingdirectory, getuid(), getgid()); } if(pidfd != -1) diff --git a/daemon/main.c b/daemon/main.c index b00de00628..1dcdb6edd2 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -351,6 +351,8 @@ int help(int exitcode) { " set netdata.conf option from the command line.\n\n" " -W simple-pattern pattern string\n" " Check if string matches pattern and exit.\n\n" + " -W \"claim -token=TOKEN -rooms=ROOM1,ROOM2\"\n" + " Claim the agent to the workspace rooms pointed to by TOKEN and ROOM*.\n\n" ); fprintf(stream, "\n Signals netdata handles:\n\n" @@ -926,6 +928,7 @@ int main(int argc, char **argv) { { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; + char* claim_string = "claim"; #ifdef ENABLE_DBENGINE char* createdataset_string = "createdataset="; char* stresstest_string = "stresstest="; @@ -1086,6 +1089,10 @@ int main(int argc, char **argv) { printf("%s\n", value); return 0; } + else if(strncmp(optarg, claim_string, strlen(claim_string)) == 0) { + /* will trigger a claiming attempt when the agent is initialized */ + claiming_pending_arguments = optarg + strlen(claim_string); + } else { fprintf(stderr, "Unknown -W parameter '%s'\n", optarg); return help(1); @@ -1271,6 +1278,14 @@ int main(int argc, char **argv) { get_system_info(system_info); rrd_init(netdata_configured_hostname, system_info); + + // ------------------------------------------------------------------------ + // Claim netdata agent to a cloud endpoint + + if (claiming_pending_arguments) + claim_agent(claiming_pending_arguments); + load_claiming_state(); + // ------------------------------------------------------------------------ // enable log flood protection diff --git a/netdata-installer.sh b/netdata-installer.sh index 442b28e87e..e6affc36e5 100755 --- a/netdata-installer.sh +++ b/netdata-installer.sh @@ -617,6 +617,7 @@ NETDATA_LOG_DIR="$(config_option "global" "log directory" "${NETDATA_PREFIX}/var NETDATA_USER_CONFIG_DIR="$(config_option "global" "config directory" "${NETDATA_PREFIX}/etc/netdata")" NETDATA_STOCK_CONFIG_DIR="$(config_option "global" "stock config directory" "${NETDATA_PREFIX}/usr/lib/netdata/conf.d")" NETDATA_RUN_DIR="${NETDATA_PREFIX}/var/run" +NETDATA_CLAIMING_DIR="${NETDATA_USER_CONFIG_DIR}/claim.d" cat <&2 "Creating directory '${NETDATA_CLAIMING_DIR}'" + run mkdir -p "${NETDATA_CLAIMING_DIR}" || exit 1 +fi +run chown -R "${NETDATA_USER}:${NETDATA_GROUP}" "${NETDATA_CLAIMING_DIR}" +run chmod 770 "${NETDATA_CLAIMING_DIR}" + # --- plugins ---- if [ "${UID}" -eq 0 ]; then diff --git a/packaging/installer/netdata-uninstaller.sh b/packaging/installer/netdata-uninstaller.sh index 424367b595..dc3a0eabb0 100755 --- a/packaging/installer/netdata-uninstaller.sh +++ b/packaging/installer/netdata-uninstaller.sh @@ -313,6 +313,7 @@ if [ -n "${NETDATA_PREFIX}" ] && [ -d "${NETDATA_PREFIX}" ]; then else rm_file "/usr/sbin/netdata" rm_file "/usr/sbin/netdatacli" + rm_file "/usr/sbin/netdata-claim.sh" rm_dir "/usr/share/netdata" rm_dir "/usr/libexec/netdata" rm_dir "/var/lib/netdata"