1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
// SPDX-License-Identifier: GPL-3.0-or-later
#include "claim.h"
#include "registry/registry_internals.h"
#include "aclk/aclk.h"
#include "aclk/aclk_proxy.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
"The CLI didn't work", // 5
"Wrong user", // 6
"Unknown HTTP error message", // 7
"invalid node id", // 8
"invalid node name", // 9
"invalid room id", // 10
"invalid public key", // 11
"token expired/token not found/invalid token", // 12
"already claimed", // 13
"processing claiming", // 14
"Internal Server Error", // 15
"Gateway Timeout", // 16
"Service Unavailable", // 17
"Agent Unique Id Not Readable" // 18
};
/* Retrieve the claim id for the agent.
* Caller owns the string.
*/
char *get_agent_claimid()
{
char *result;
rrdhost_aclk_state_lock(localhost);
result = (localhost->aclk_state.claimed_id == NULL) ? NULL : strdupz(localhost->aclk_state.claimed_id);
rrdhost_aclk_state_unlock(localhost);
return result;
}
#define CLAIMING_COMMAND_LENGTH 16384
#define CLAIMING_PROXY_LENGTH CLAIMING_COMMAND_LENGTH/4
extern struct registry registry;
/* rrd_init() and post_conf_load() must have been called before this function */
void claim_agent(char *claiming_arguments)
{
if (!netdata_cloud_setting) {
error("Refusing to claim agent -> cloud functionality has been disabled");
return;
}
#ifndef DISABLE_CLOUD
int exit_code;
pid_t command_pid;
char command_buffer[CLAIMING_COMMAND_LENGTH + 1];
FILE *fp_child_output, *fp_child_input;
// This is guaranteed to be set early in main via post_conf_load()
char *cloud_base_url = appconfig_get(&cloud_config, CONFIG_SECTION_GLOBAL, "cloud base url", NULL);
if (cloud_base_url == NULL)
fatal("Do not move the cloud base url out of post_conf_load!!");
const char *proxy_str;
ACLK_PROXY_TYPE proxy_type;
char proxy_flag[CLAIMING_PROXY_LENGTH] = "-noproxy";
proxy_str = aclk_get_proxy(&proxy_type);
if (proxy_type == PROXY_TYPE_SOCKS5 || proxy_type == PROXY_TYPE_HTTP)
snprintf(proxy_flag, CLAIMING_PROXY_LENGTH, "-proxy=\"%s\"", proxy_str);
snprintfz(command_buffer,
CLAIMING_COMMAND_LENGTH,
"exec netdata-claim.sh %s -hostname=%s -id=%s -url=%s -noreload %s",
proxy_flag,
netdata_configured_hostname,
localhost->machine_guid,
cloud_base_url,
claiming_arguments);
info("Executing agent claiming command 'netdata-claim.sh'");
fp_child_output = netdata_popen(command_buffer, &command_pid, &fp_child_input);
if(!fp_child_output) {
error("Cannot popen(\"%s\").", command_buffer);
return;
}
info("Waiting for claiming command to finish.");
while (fgets(command_buffer, CLAIMING_COMMAND_LENGTH, fp_child_output) != NULL) {;}
exit_code = netdata_pclose(fp_child_input, fp_child_output, command_pid);
info("Agent claiming command returned with code %d", exit_code);
if (0 == exit_code) {
load_claiming_state();
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]) - 1;
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]);
#else
UNUSED(claiming_arguments);
UNUSED(claiming_errors);
#endif
}
#ifdef ENABLE_ACLK
extern int aclk_connected, aclk_kill_link, aclk_disable_runtime;
#endif
/* Change the claimed state of the agent.
*
* This only happens when the user has explicitly requested it:
* - via the cli tool by reloading the claiming state
* - after spawning the claim because of a command-line argument
* If this happens with the ACLK active under an old claim then we MUST KILL THE LINK
*/
void load_claiming_state(void)
{
// --------------------------------------------------------------------
// Check if the cloud is enabled
#if defined( DISABLE_CLOUD ) || !defined( ENABLE_ACLK )
netdata_cloud_setting = 0;
#else
uuid_t uuid;
// Propagate into aclk and registry. Be kind of atomic...
appconfig_get(&cloud_config, CONFIG_SECTION_GLOBAL, "cloud base url", DEFAULT_CLOUD_BASE_URL);
rrdhost_aclk_state_lock(localhost);
if (localhost->aclk_state.claimed_id) {
if (aclk_connected)
localhost->aclk_state.prev_claimed_id = strdupz(localhost->aclk_state.claimed_id);
freez(localhost->aclk_state.claimed_id);
localhost->aclk_state.claimed_id = NULL;
}
if (aclk_connected)
{
info("Agent was already connected to Cloud - forcing reconnection under new credentials");
aclk_kill_link = 1;
}
aclk_disable_runtime = 0;
char filename[FILENAME_MAX + 1];
snprintfz(filename, FILENAME_MAX, "%s/cloud.d/claimed_id", netdata_configured_varlib_dir);
long bytes_read;
char *claimed_id = read_by_filename(filename, &bytes_read);
if(claimed_id && uuid_parse(claimed_id, uuid)) {
error("claimed_id \"%s\" doesn't look like valid UUID", claimed_id);
freez(claimed_id);
claimed_id = NULL;
}
if(claimed_id) {
localhost->aclk_state.claimed_id = mallocz(UUID_STR_LEN);
uuid_unparse_lower(uuid, localhost->aclk_state.claimed_id);
}
invalidate_node_instances(&localhost->host_uuid, claimed_id ? &uuid : NULL);
metaqueue_store_claim_id(&localhost->host_uuid, claimed_id ? &uuid : NULL);
rrdhost_aclk_state_unlock(localhost);
if (!claimed_id) {
info("Unable to load '%s', setting state to AGENT_UNCLAIMED", filename);
return;
}
freez(claimed_id);
info("File '%s' was found. Setting state to AGENT_CLAIMED.", filename);
netdata_cloud_setting = appconfig_get_boolean(&cloud_config, CONFIG_SECTION_GLOBAL, "enabled", 1);
#endif
}
struct config cloud_config = { .first_section = NULL,
.last_section = NULL,
.mutex = NETDATA_MUTEX_INITIALIZER,
.index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
.rwlock = AVL_LOCK_INITIALIZER } };
void load_cloud_conf(int silent)
{
char *filename;
errno = 0;
int ret = 0;
filename = strdupz_path_subpath(netdata_configured_varlib_dir, "cloud.d/cloud.conf");
ret = appconfig_load(&cloud_config, filename, 1, NULL);
if(!ret && !silent) {
info("CONFIG: cannot load cloud config '%s'. Running with internal defaults.", filename);
}
freez(filename);
}
|