0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-10 08:07:34 +00:00

Claim on Windows ()

This commit is contained in:
thiagoftsm 2024-08-29 21:12:43 +00:00 committed by GitHub
parent aa5d16dee6
commit f4531bc522
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 498 additions and 28 deletions

View file

@ -118,6 +118,10 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN" OR "${CMAKE_SYSTEM_NAME}" STREQU
endif()
set(BINDIR usr/bin)
set(CMAKE_RC_COMPILER_INIT windres)
ENABLE_LANGUAGE(RC)
SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
add_definitions(-D_GNU_SOURCE)
if($ENV{CLION_IDE})
@ -1296,6 +1300,13 @@ set(CLAIM_PLUGIN_FILES
src/claim/cloud-status.h
)
set(CLAIM_WINDOWS_FILES
src/claim/netdata_claim.c
src/claim/netdata_claim.h
src/claim/netdata_claim_window.c
src/claim/netdata_claim_window.h
)
set(ACLK_ALWAYS_BUILD
src/aclk/aclk_rrdhost_state.h
src/aclk/aclk_proxy.c
@ -2238,6 +2249,13 @@ add_executable(netdata
"$<$<BOOL:${ENABLE_EXPORTER_PROMETHEUS_REMOTE_WRITE}>:${PROMETHEUS_REMOTE_WRITE_EXPORTING_FILES}>"
)
if(OS_WINDOWS)
set(NETDATA_CLAIM_RES_FILES "packaging/windows/resources/netdata_claim.rc")
add_executable(netdata_claim ${CLAIM_WINDOWS_FILES} ${NETDATA_CLAIM_RES_FILES})
target_link_libraries(netdata_claim shell32;gdi32;msftedit)
endif()
target_compile_definitions(netdata PRIVATE
"$<$<BOOL:${ENABLE_ML}>:DLIB_NO_GUI_SUPPORT>"
)
@ -2426,6 +2444,13 @@ install(PROGRAMS
COMPONENT netdata
DESTINATION "${BINDIR}")
if(OS_WINDOWS)
install(PROGRAMS
${CMAKE_BINARY_DIR}/netdata_claim.exe
COMPONENT netdata
DESTINATION "${BINDIR}")
endif()
#
# We don't check ENABLE_PLUGIN_CGROUP_NETWORK because rpm builds assume
# the files exists unconditionally.

View file

@ -34,8 +34,14 @@ var startMsys
var hCloudToken
var cloudToken
var hCloudRoom
var cloudRoom
var hCloudRooms
var cloudRooms
var hProxy
var proxy
var hInsecure
var insecure
var avoidClaim
Function .onInit
nsExec::ExecToLog '$SYSDIR\sc.exe stop Netdata'
@ -46,6 +52,8 @@ Function .onInit
${EndIf}
StrCpy $startMsys ${BST_UNCHECKED}
StrCpy $insecure ${BST_UNCHECKED}
StrCpy $avoidClaim ${BST_UNCHECKED}
FunctionEnd
Function NetdataConfigPage
@ -57,40 +65,76 @@ Function NetdataConfigPage
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 12u "Enter your Token and Cloud Room."
IfFileExists "$INSTDIR\etc\netdata\claim.conf" NotNeeded
${NSD_CreateLabel} 0 0 100% 12u "Enter your Token and Cloud Room(s)."
${NSD_CreateLabel} 0 15% 100% 12u "Optionally, you can open a terminal to execute additional commands."
${NSD_CreateLabel} 0 35% 20% 10% "Token"
${NSD_CreateLabel} 0 30% 20% 10% "Token"
Pop $0
${NSD_CreateText} 21% 35% 79% 10% ""
${NSD_CreateText} 21% 30% 79% 10% ""
Pop $hCloudToken
${NSD_CreateLabel} 0 55% 20% 10% "Room"
${NSD_CreateLabel} 0 45% 20% 10% "Room(s)"
Pop $0
${NSD_CreateText} 21% 55% 79% 10% ""
Pop $hCloudRoom
${NSD_CreateText} 21% 45% 79% 10% ""
Pop $hCloudRooms
${NSD_CreateCheckbox} 0 70% 100% 10u "Open terminal"
${NSD_CreateLabel} 0 60% 20% 10% "Proxy"
Pop $0
${NSD_CreateText} 21% 60% 79% 10% ""
Pop $hProxy
${NSD_CreateCheckbox} 0 75% 100% 10u "Insecure connection"
Pop $hInsecure
${NSD_CreateCheckbox} 0 90% 100% 10u "Open terminal"
Pop $hStartMsys
Goto EndDialogDraw
NotNeeded:
StrCpy $avoidClaim ${BST_CHECKED}
${NSD_CreateLabel} 0 0 100% 12u "Your host has already been claimed. You can proceed with the update."
EndDialogDraw:
nsDialogs::Show
FunctionEnd
Function NetdataConfigLeave
${NSD_GetText} $hCloudToken $cloudToken
${NSD_GetText} $hCloudRoom $cloudRoom
${NSD_GetState} $hStartMsys $startMsys
${If} $avoidClaim == ${BST_UNCHECKED}
${NSD_GetText} $hCloudToken $cloudToken
${NSD_GetText} $hCloudRooms $cloudRooms
${NSD_GetText} $hProxy $proxy
${NSD_GetState} $hStartMsys $startMsys
${NSD_GetState} $hInsecure $insecure
StrLen $0 $cloudToken
StrLen $1 $cloudRoom
${If} $0 == 125
${AndIf} $0 == 36
# We should start our new claiming software here
MessageBox MB_OK "$cloudToken | $cloudRoom | $startMsys"
StrLen $0 $cloudToken
StrLen $1 $cloudRooms
${If} $0 == 0
${OrIf} $1 == 0
Goto runMsys
${EndIf}
${If} $0 == 135
${AndIf} $1 >= 36
nsExec::ExecToLog '$INSTDIR\usr\bin\netdata_claim.exe /T $cloudToken /R $cloudRooms /P $proxy /I $insecure'
pop $0
${Else}
MessageBox MB_OK "The Cloud information does not have the expected length."
${EndIf}
runMsys:
${If} $startMsys == ${BST_CHECKED}
nsExec::ExecToLog '$INSTDIR\msys2.exe'
pop $0
${EndIf}
${EndIf}
${If} $startMsys == 1
nsExec::ExecToLog '$INSTDIR\msys2.exe'
pop $0
ClearErrors
nsExec::ExecToLog '$SYSDIR\sc.exe start Netdata'
pop $0
${If} $0 != 0
MessageBox MB_OK "Warning: Failed to start Netdata service."
${EndIf}
FunctionEnd
@ -152,13 +196,6 @@ Section "Install Netdata"
DetailPrint "Warning: Failed to add Netdata service description."
${EndIf}
ClearErrors
nsExec::ExecToLog '$SYSDIR\sc.exe start Netdata'
pop $0
${If} $0 != 0
DetailPrint "Warning: Failed to start Netdata service."
${EndIf}
WriteUninstaller "$INSTDIR\Uninstall.exe"
Call NetdataUninstallRegistry

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.99.0.0"
processorArchitecture="*"
name="netdata_claim"
type="win32"/>
<description>Netdata Claim!</description>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View file

@ -0,0 +1,3 @@
#include "winuser.h"
1 RT_MANIFEST "netdata_claim.manifest"
11 ICON "../NetdataWhite.ico"

250
src/claim/netdata_claim.c Normal file
View file

@ -0,0 +1,250 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <shellapi.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "netdata_claim.h"
LPWSTR token = NULL;
LPWSTR room = NULL;
LPWSTR proxy = NULL;
LPWSTR *argv = NULL;
char *aToken = NULL;
char *aRoom = NULL;
char *aProxy = NULL;
int insecure = 0;
LPWSTR netdata_claim_get_formatted_message(LPWSTR pMessage, ...)
{
LPWSTR pBuffer = NULL;
va_list args = NULL;
va_start(args, pMessage);
FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, pMessage, 0, 0, (LPWSTR)&pBuffer,
0, &args);
va_end(args);
return pBuffer;
}
// Common Functions
void netdata_claim_error_exit(wchar_t *function)
{
DWORD error = GetLastError();
LPWSTR pMessage = L"The function %1 failed with error %2.";
LPWSTR pBuffer = netdata_claim_get_formatted_message(pMessage, function, error);
if (pBuffer) {
MessageBoxW(NULL, pBuffer, L"Error", MB_OK|MB_ICONERROR);
LocalFree(pBuffer);
}
ExitProcess(error);
}
/**
* Parse Args
*
* Parse arguments identifying necessity to make a window
*
* @param argc number of arguments
* @param argv A pointer for all arguments given
*
* @return it return the number of arguments parsed.
*/
int nd_claim_parse_args(int argc, LPWSTR *argv)
{
int i;
for (i = 1 ; i < argc; i++) {
// We are working with Microsoft, thus it does not make sense wait for only smallcase
if(wcscasecmp(L"/T", argv[i]) == 0) {
if (argc <= i + 1)
continue;
i++;
token = argv[i];
}
if(wcscasecmp(L"/R", argv[i]) == 0) {
if (argc <= i + 1)
continue;
i++;
room = argv[i];
}
if(wcscasecmp(L"/P", argv[i]) == 0) {
if (argc <= i + 1)
continue;
i++;
// Minimum IPV4
if(wcslen(argv[i]) >= 8) {
proxy = argv[i];
}
}
if(wcscasecmp(L"/I", argv[i]) == 0) {
if (argc <= i + 1)
continue;
i++;
size_t length = wcslen(argv[i]);
char *tmp = calloc(sizeof(char), length);
if (!tmp)
ExitProcess(1);
netdata_claim_convert_str(tmp, argv[i], length - 1);
if (i < argc)
insecure = atoi(tmp);
else
insecure = 1;
free(tmp);
}
}
if (!token || !room)
return 0;
return argc;
}
static int netdata_claim_prepare_strings()
{
if (!token || !room)
return -1;
size_t length = wcslen(token) + 1;
aToken = calloc(sizeof(char), length);
if (!aToken)
return -1;
netdata_claim_convert_str(aToken, token, length - 1);
length = wcslen(room) + 1;
aRoom = calloc(sizeof(char), length - 1);
if (!aRoom)
return -1;
netdata_claim_convert_str(aRoom, room, length - 1);
if (proxy) {
length = wcslen(proxy) + 1;
aProxy = calloc(sizeof(char), length - 1);
if (!aProxy)
return -1;
netdata_claim_convert_str(aProxy, proxy, length - 1);
}
return 0;
}
static void netdata_claim_exit_callback(int signal)
{
(void)signal;
if (aToken)
free(aToken);
if (aRoom)
free(aRoom);
if (aProxy)
free(aProxy);
if (argv)
LocalFree(argv);
}
static inline int netdata_claim_prepare_data(char *out, size_t length)
{
char *proxyLabel = (aProxy) ? "proxy = " : "# proxy = ";
char *proxyValue = (aProxy) ? aProxy : "";
return snprintf(out,
length,
"[global]\n url = https://app.netdata.cloud\n token = %s\n rooms = %s\n %s%s\n insecure = %s",
aToken,
aRoom,
proxyLabel,
proxyValue,
(insecure) ? "YES" : "NO"
);
}
static int netdata_claim_get_path(char *path)
{
char *usrPath = { "\\usr\\bin" };
DWORD length = GetCurrentDirectoryA(WINDOWS_MAX_PATH, path);
if (!length) {
return -1;
}
if (strstr(path, usrPath)) {
length -= 7;
path[length] = '\0';
}
return 0;
}
static void netdata_claim_write_config(char *path)
{
char configPath[WINDOWS_MAX_PATH + 1];
char data[WINDOWS_MAX_PATH + 1];
snprintf(configPath, WINDOWS_MAX_PATH - 1, "%s\\etc\\netdata\\claim.conf", path);
HANDLE hf = CreateFileA(configPath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hf == INVALID_HANDLE_VALUE)
netdata_claim_error_exit(L"CreateFileA");
DWORD length = netdata_claim_prepare_data(data, WINDOWS_MAX_PATH);
DWORD written = 0;
BOOL ret = WriteFile(hf, data, length, &written, NULL);
if (!ret) {
CloseHandle(hf);
netdata_claim_error_exit(L"WriteFileA");
}
if (length != written)
MessageBoxW(NULL, L"Cannot write claim.conf.", L"Error", MB_OK|MB_ICONERROR);
CloseHandle(hf);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
signal(SIGABRT, netdata_claim_exit_callback);
signal(SIGINT, netdata_claim_exit_callback);
signal(SIGTERM, netdata_claim_exit_callback);
int argc;
LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argc)
argc = nd_claim_parse_args(argc, argv);
// When no data is given, user must to use graphic mode
int ret = 0;
if (!argc) {
ret = netdata_claim_window_loop(hInstance, nCmdShow);
} else {
if (netdata_claim_prepare_strings()) {
goto exit_claim;
}
char basePath[WINDOWS_MAX_PATH];
if (!netdata_claim_get_path(basePath)) {
netdata_claim_write_config(basePath);
}
}
exit_claim:
netdata_claim_exit_callback(0);
return ret;
}

19
src/claim/netdata_claim.h Normal file
View file

@ -0,0 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NETDATA_CLAIM_H_
# define NETDATA_CLAIM_H_ 1
#include <wchar.h>
#include "netdata_claim_window.h"
extern LPWSTR token;
extern LPWSTR room;
extern LPWSTR proxy;
void netdata_claim_error_exit(wchar_t *function);
static inline void netdata_claim_convert_str(char *dst, wchar_t *src, size_t len) {
size_t copied = wcstombs(dst, src, len);
dst[copied] = '\0';
}
#endif //NETDATA_CLAIM_H_

View file

@ -0,0 +1,108 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#define UNICODE
#define _UNICODE
#include <windows.h>
#include "richedit.h"
#include "tchar.h"
#include "netdata_claim.h"
static LPCTSTR szWindowClass = _T("DesktopApp");
static HINSTANCE hInst;
static HWND hToken;
static HWND hRoom;
LRESULT CALLBACK WndProc(HWND hNetdatawnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
LPCTSTR topMsg[] = { L" Help",
L" ",
L"In this initial version of the software, there are no fields for data",
L" entry. To claim your agent, you must use the following options:",
L" ",
L"/T TOKEN: The cloud token;",
L"/R ROOMS: A list of rooms to claim;",
L"/P PROXY: The proxy information;",
L"/I : Use insecure connection;"
};
switch (message)
{
case WM_PAINT: {
hdc = BeginPaint(hNetdatawnd, &ps);
int i;
for (i = 0; i < sizeof(topMsg) / sizeof(LPCTSTR); i++) {
TextOut(hdc, 5, 5 + 15*i, topMsg[i], wcslen(topMsg[i]));
}
EndPaint(hNetdatawnd, &ps);
break;
}
case WM_COMMAND:
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default: {
return DefWindowProc(hNetdatawnd, message, wParam, lParam);
break;
}
}
return 0;
}
int netdata_claim_window_loop(HINSTANCE hInstance, int nCmdShow)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(wcex.hInstance, MAKEINTRESOURCEW(11));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex)) {
MessageBoxW(NULL, L"Call to RegisterClassEx failed!", L"Error", 0);
return 1;
}
hInst = hInstance;
HWND hNetdatawnd = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
szWindowClass,
L"Netdata Claim",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
460, 220,
NULL,
NULL,
hInstance,
NULL
);
if (!hNetdatawnd) {
MessageBoxW(NULL, L"Call to CreateWindow failed!", L"Error", 0);
return 1;
}
ShowWindow(hNetdatawnd, nCmdShow);
UpdateWindow(hNetdatawnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}

View file

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef NETDATA_CLAIM_WINDOW_H_
# define NETDATA_CLAIM_WINDOW_H_ 1
// https://learn.microsoft.com/en-us/troubleshoot/windows-client/shell-experience/command-line-string-limitation
// https://sourceforge.net/p/mingw/mailman/mingw-users/thread/4C8FD4EB.4050503@xs4all.nl/
#define WINDOWS_MAX_PATH 8191
int netdata_claim_window_loop(HINSTANCE hInstance, int nCmdShow);
#endif //NETDATA_CLAIM_WINDOW_H_