0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-02 20:48:06 +00:00

Fix parsing SSL ACL along with others ()

* sslstream: ACL parser

It was noticed in the issue 6457 that the some ACLs were not parsing
correctly when they were along SSL acl, this commit fixes this'

* sslstream: remove comments

This commit removes the comments that were present while I was testing the code

* sslstream: Tests

This commit adds ACL tests to check the Netdata response to them

* sslstream: Tests

Fix the extension to upload the files

* sslstream: more tests

In this commit I am bringing more tests, including the ssl tests'

* sslstream: leading space

Remove leading space from variable that was creating problem with shellcheck

* sslstream: glob

Remove special character from script

* sslstream: Makefile

The Makefile diretives were pointed to wrong files

* sslstream: Missing stream encrypt

This commit solves the problem of the stream not be encrypted, but
it is not the final solution, because the parser made is incomplete.

* sslstream: Finish encrypt channel

This commit brings the step that I was missing, the complete encryptation
in the communication between Master and Slave

* sslstream: Fix argument in script

After the latest tests, it was verified that two arguments given to a function
inside the script were not correct, with this PR I am fixing this!

* sslstream: Fix argument in info

Instead to call a function to deliver an integer I was passing a size_t value.
Only cmake showed this, but not in my clion! :/

* sslstream: Fix redirect

When we were having different SSL configuration, the system were not applying
the option for all

* sslstream: Update documentation

Our documentation was not clear about the rules according our code
so I am updating the text to explain for the users

* sslstream: Adjust script

With this last commit, I am adjusting the tests to avoid false positive

* sslstream: Missing elif

The previous commit had a missing elif in the shell script

* sslstream: Split ports

Before this commit Netdata was having SSL as a global option, now it has as a real ACL.

* sslstream: reduce context

The stream variable will not be affected in the master side, it is only necessary
on the slave side, so I am reducing the context of it

* sslstream: Force SSL

When the user has certificate and he does not set any SSL flag, it is necessary
to append the SSL=force flag

* sslstream: Default flag

It is necessary to have a default flag when the SSL flags are not SET

* sslstream: remove comments

Remove comments from the scrip

* sslstream: moving flag

It is better the flag to be set inside socket instead everytime there is a new connection

* sslstream: documentation

Fix a sentence in the web/server/README.md
This commit is contained in:
thiagoftsm 2019-07-25 16:43:04 +00:00 committed by Chris Akritidis
parent d95912af08
commit 2f7962c9e1
14 changed files with 399 additions and 37 deletions

1
.gitignore vendored
View file

@ -166,6 +166,7 @@ callgrind.out.*
gmon.out
gmon.txt
sitespeed-result/
tests/acls/acl.sh
tests/urls/request.sh
# tests and temp files

View file

@ -117,6 +117,103 @@ inline int pluginsd_split_words(char *str, char **words, int max_words) {
return quoted_strings_splitter(str, words, max_words, pluginsd_space);
}
#ifdef ENABLE_HTTPS
/**
* Update Buffer
*
* Update the temporary buffer used to parse data received from slave
*
* @param output is a pointer to the vector where I will store the data
* @param ssl is the connection pointer with the server
*
* @return it returns the total of bytes read on success and a negative number otherwise
*/
int pluginsd_update_buffer(char *output, SSL *ssl) {
ERR_clear_error();
int bytesleft = SSL_read(ssl, output, PLUGINSD_LINE_MAX_SSL_READ);
if(bytesleft <= 0) {
int sslerrno = SSL_get_error(ssl, bytesleft);
switch(sslerrno) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
{
break;
}
default:
{
u_long err;
char buf[256];
int counter = 0;
while ((err = ERR_get_error()) != 0) {
ERR_error_string_n(err, buf, sizeof(buf));
info("%d SSL Handshake error (%s) on socket %d ", counter++, ERR_error_string((long)SSL_get_error(ssl, bytesleft), NULL), SSL_get_fd(ssl));
}
}
}
} else {
output[bytesleft] = '\0';
}
return bytesleft;
}
/**
* Get from Buffer
*
* Get data to process from buffer
*
* @param output is the output vector that will be used to parse the string.
* @param bytesread the amount of bytes read in the previous iteration.
* @param input the input vector where there are data to process
* @param ssl a pointer to the connection with the server
* @param src the first address of the input, because sometime will be necessary to restart the addr with it.
*
* @return It returns a pointer for the next iteration on success and NULL otherwise.
*/
char * pluginsd_get_from_buffer(char *output, int *bytesread, char *input, SSL *ssl, char *src) {
int copying = 1;
char *endbuffer;
size_t length;
while(copying) {
if(*bytesread > 0) {
endbuffer = strchr(input, '\n');
if(endbuffer) {
copying = 0;
endbuffer++; //Advance due the fact I wanna copy '\n'
length = endbuffer - input;
*bytesread -= length;
memcpy(output, input, length);
output += length;
*output = '\0';
input += length;
}else {
length = strlen(input);
memcpy(output, input, length);
output += length;
input = src;
*bytesread = pluginsd_update_buffer(input, ssl);
if(*bytesread <= 0) {
input = NULL;
copying = 0;
}
}
}else {
//reduce sample of bytes read, print the length
*bytesread = pluginsd_update_buffer(input, ssl);
if(*bytesread <= 0) {
input = NULL;
copying = 0;
}
}
}
return input;
}
#endif
inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int trust_durations) {
int enabled = cd->enabled;
@ -149,10 +246,43 @@ inline size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp, int
goto cleanup;
}
#ifdef ENABLE_HTTPS
int bytesleft = 0;
char tmpbuffer[PLUGINSD_LINE_MAX];
char *readfrom;
#endif
while(!ferror(fp)) {
if(unlikely(netdata_exit)) break;
char *r = fgets(line, PLUGINSD_LINE_MAX, fp);
char *r;
#ifdef ENABLE_HTTPS
int normalread = 1;
if(netdata_srv_ctx) {
if(host->ssl.conn && !host->ssl.flags) {
if(!bytesleft) {
r = line;
readfrom = tmpbuffer;
bytesleft = pluginsd_update_buffer(readfrom, host->ssl.conn);
if(bytesleft <= 0) {
break;
}
}
readfrom = pluginsd_get_from_buffer(line, &bytesleft, readfrom, host->ssl.conn, tmpbuffer);
if(!readfrom) {
r = NULL;
}
normalread = 0;
}
}
if(normalread) {
r = fgets(line, PLUGINSD_LINE_MAX, fp);
}
#else
r = fgets(line, PLUGINSD_LINE_MAX, fp);
#endif
if(unlikely(!r)) {
if(feof(fp))
error("read failed: end of file");

View file

@ -31,6 +31,7 @@
#define PLUGINSD_KEYWORD_VARIABLE "VARIABLE"
#define PLUGINSD_LINE_MAX 1024
#define PLUGINSD_LINE_MAX_SSL_READ 512
#define PLUGINSD_MAX_WORDS 20
#define PLUGINSD_MAX_DIRECTORIES 20

View file

@ -7,8 +7,6 @@ SSL_CTX *netdata_client_ctx=NULL;
SSL_CTX *netdata_srv_ctx=NULL;
const char *security_key=NULL;
const char *security_cert=NULL;
int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
int netdata_use_ssl_on_http = NETDATA_SSL_FORCE; //We force SSL due safety reasons
int netdata_validate_server = NETDATA_SSL_VALID_CERTIFICATE;
/**
@ -176,6 +174,9 @@ void security_start_ssl(int selector) {
}
case NETDATA_SSL_CONTEXT_STREAMING: {
netdata_client_ctx = security_initialize_openssl_client();
//This is necessary for the stream, because it is working sometimes with nonblock socket.
//It returns the bitmask afte to change, there is not any description of errors in the documentation
SSL_CTX_set_mode(netdata_client_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |SSL_MODE_AUTO_RETRY);
break;
}
case NETDATA_SSL_CONTEXT_OPENTSDB: {
@ -206,6 +207,17 @@ void security_clean_openssl() {
#endif
}
/**
* Process accept
*
* Process the SSL handshake with the client case it is necessary.
*
* @param ssl is a pointer for the SSL structure
* @param msg is a copy of the first 8 bytes of the initial message received
*
* @return it returns 0 case it performs the handshake, 8 case it is clean connection
* and another integer power of 2 otherwise.
*/
int security_process_accept(SSL *ssl,int msg) {
int sock = SSL_get_fd(ssl);
int test;
@ -250,7 +262,7 @@ int security_process_accept(SSL *ssl,int msg) {
debug(D_WEB_CLIENT_ACCESS,"SSL Handshake finished %s errno %d on socket fd %d", ERR_error_string((long)SSL_get_error(ssl, test), NULL), errno, sock);
}
return 0;
return NETDATA_SSL_HANDSHAKE_COMPLETE;
}
int security_test_certificate(SSL *ssl) {

View file

@ -25,7 +25,7 @@
struct netdata_ssl{
SSL *conn; //SSL connection
int flags;
int flags; //The flags for SSL connection
};
extern SSL_CTX *netdata_opentsdb_ctx;
@ -33,8 +33,6 @@ extern SSL_CTX *netdata_client_ctx;
extern SSL_CTX *netdata_srv_ctx;
extern const char *security_key;
extern const char *security_cert;
extern int netdata_use_ssl_on_stream;
extern int netdata_use_ssl_on_http;
extern int netdata_validate_server;
void security_openssl_library();

View file

@ -301,39 +301,47 @@ void listen_sockets_close(LISTEN_SOCKETS *sockets) {
sockets->failed = 0;
}
WEB_CLIENT_ACL socket_ssl_acl(char *ssl) {
/*
* SSL ACL
*
* Search the SSL acl and apply it case it is set.
*
* @param acl is the acl given by the user.
*/
WEB_CLIENT_ACL socket_ssl_acl(char *acl) {
char *ssl = strchr(acl,'^');
if(ssl) {
//Due the format of the SSL command it is always the last command,
//we finish it here to avoid problems with the ACLs
*ssl = '\0';
#ifdef ENABLE_HTTPS
if (!strcmp(ssl,"optional")) {
netdata_use_ssl_on_http = NETDATA_SSL_OPTIONAL;
return WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
}
else if (!strcmp(ssl,"force")) {
netdata_use_ssl_on_stream = NETDATA_SSL_FORCE;
return WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
}
ssl++;
if (!strncmp("SSL=",ssl,4)) {
ssl += 4;
if (!strcmp(ssl,"optional")) {
return WEB_CLIENT_ACL_SSL_OPTIONAL;
}
else if (!strcmp(ssl,"force")) {
return WEB_CLIENT_ACL_SSL_FORCE;
}
}
#endif
}
return WEB_CLIENT_ACL_NONE;
}
WEB_CLIENT_ACL read_acl(char *st) {
char *ssl = strchr(st,'^');
if (ssl) {
ssl++;
if (!strncmp("SSL=",ssl,4)) {
ssl += 4;
}
socket_ssl_acl(ssl);
}
WEB_CLIENT_ACL ret = socket_ssl_acl(st);
if (!strcmp(st,"dashboard")) return WEB_CLIENT_ACL_DASHBOARD;
if (!strcmp(st,"registry")) return WEB_CLIENT_ACL_REGISTRY;
if (!strcmp(st,"badges")) return WEB_CLIENT_ACL_BADGE;
if (!strcmp(st,"management")) return WEB_CLIENT_ACL_MGMT;
if (!strcmp(st,"streaming")) return WEB_CLIENT_ACL_STREAMING;
if (!strcmp(st,"netdata.conf")) return WEB_CLIENT_ACL_NETDATACONF;
if (!strcmp(st,"dashboard")) ret |= WEB_CLIENT_ACL_DASHBOARD;
if (!strcmp(st,"registry")) ret |= WEB_CLIENT_ACL_REGISTRY;
if (!strcmp(st,"badges")) ret |= WEB_CLIENT_ACL_BADGE;
if (!strcmp(st,"management")) ret |= WEB_CLIENT_ACL_MGMT;
if (!strcmp(st,"streaming")) ret |= WEB_CLIENT_ACL_STREAMING;
if (!strcmp(st,"netdata.conf")) ret |= WEB_CLIENT_ACL_NETDATACONF;
return socket_ssl_acl(st);
return ret;
}
static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition, uint16_t default_port, int listen_backlog) {
@ -375,7 +383,7 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
error("LISTENER: Cannot create unix socket '%s'", path);
sockets->failed++;
} else {
acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING | WEB_CLIENT_ACL_SSL_DEFAULT;
listen_sockets_add(sockets, fd, AF_UNIX, socktype, protocol_str, path, 0, acl_flags);
added++;
}
@ -425,7 +433,13 @@ static inline int bind_to_this(LISTEN_SOCKETS *sockets, const char *definition,
}
acl_flags |= read_acl(portconfig);
} else {
acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING;
acl_flags = WEB_CLIENT_ACL_DASHBOARD | WEB_CLIENT_ACL_REGISTRY | WEB_CLIENT_ACL_BADGE | WEB_CLIENT_ACL_MGMT | WEB_CLIENT_ACL_NETDATACONF | WEB_CLIENT_ACL_STREAMING | WEB_CLIENT_ACL_SSL_DEFAULT;
}
//Case the user does not set the option SSL in the "bind to", but he has
//the certificates, I must redirect, so I am assuming here the default option
if(!(acl_flags & WEB_CLIENT_ACL_SSL_OPTIONAL) && !(acl_flags & WEB_CLIENT_ACL_SSL_FORCE)) {
acl_flags |= WEB_CLIENT_ACL_SSL_DEFAULT;
}
uint32_t scope_id = 0;

View file

@ -17,7 +17,10 @@ typedef enum web_client_acl {
WEB_CLIENT_ACL_BADGE = 1 << 2,
WEB_CLIENT_ACL_MGMT = 1 << 3,
WEB_CLIENT_ACL_STREAMING = 1 << 4,
WEB_CLIENT_ACL_NETDATACONF = 1 << 5
WEB_CLIENT_ACL_NETDATACONF = 1 << 5,
WEB_CLIENT_ACL_SSL_OPTIONAL = 1 << 6,
WEB_CLIENT_ACL_SSL_FORCE = 1 << 7,
WEB_CLIENT_ACL_SSL_DEFAULT = 1 << 8
} WEB_CLIENT_ACL;
#define web_client_can_access_dashboard(w) ((w)->acl & WEB_CLIENT_ACL_DASHBOARD)
@ -26,6 +29,9 @@ typedef enum web_client_acl {
#define web_client_can_access_mgmt(w) ((w)->acl & WEB_CLIENT_ACL_MGMT)
#define web_client_can_access_stream(w) ((w)->acl & WEB_CLIENT_ACL_STREAMING)
#define web_client_can_access_netdataconf(w) ((w)->acl & WEB_CLIENT_ACL_NETDATACONF)
#define web_client_is_using_ssl_optional(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_OPTIONAL)
#define web_client_is_using_ssl_force(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_FORCE)
#define web_client_is_using_ssl_default(w) ((w)->port_acl & WEB_CLIENT_ACL_SSL_DEFAULT)
typedef struct listen_sockets {
struct config *config; // the config file to use

View file

@ -48,6 +48,7 @@ unsigned int default_rrdpush_enabled = 0;
char *default_rrdpush_destination = NULL;
char *default_rrdpush_api_key = NULL;
char *default_rrdpush_send_charts_matching = NULL;
int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
static void load_stream_conf() {
errno = 0;
@ -801,7 +802,17 @@ void *rrdpush_sender_thread(void *ptr) {
rrdpush_buffer_lock(host);
debug(D_STREAM, "STREAM: Sending data, starting from %zu, size %zu...", begin, buffer_strlen(host->rrdpush_sender_buffer));
ssize_t ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
ssize_t ret;
#ifdef ENABLE_HTTPS
SSL *conn = host->ssl.conn ;
if(conn && !host->ssl.flags) {
ret = SSL_write(conn,&host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin);
} else {
ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
}
#else
ret = send(host->rrdpush_sender_socket, &host->rrdpush_sender_buffer->buffer[begin], buffer_strlen(host->rrdpush_sender_buffer) - begin, MSG_DONTWAIT);
#endif
if (unlikely(ret == -1)) {
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
debug(D_STREAM, "STREAM: Send failed - closing socket...");
@ -1059,6 +1070,8 @@ static int rrdpush_receive(int fd
info("STREAM %s [receive from [%s]:%s]: initializing communication...", host->hostname, client_ip, client_port);
#ifdef ENABLE_HTTPS
host->ssl.conn = ssl->conn;
host->ssl.flags = ssl->flags;
if(send_timeout(ssl,fd, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT), 0, 60) != strlen(START_STREAMING_PROMPT)) {
#else
if(send_timeout(fd, START_STREAMING_PROMPT, strlen(START_STREAMING_PROMPT), 0, 60) != strlen(START_STREAMING_PROMPT)) {

View file

@ -5,7 +5,11 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
CLEANFILES = \
health_mgmtapi/health-cmdapi-test.sh \
<<<<<<< HEAD
acls/acl.sh \
=======
urls/request.sh \
>>>>>>> 63a4cadd346df71255d2350128eebcf317e81d0f
$(NULL)
include $(top_srcdir)/build/subst.inc
@ -23,11 +27,13 @@ dist_noinst_DATA = \
node.d/fronius.process.spec.js \
node.d/fronius.validation.spec.js \
health_mgmtapi/health-cmdapi-test.sh.in \
acls/acl.sh.in \
urls/request.sh.in \
$(NULL)
dist_plugins_SCRIPTS = \
health_mgmtapi/health-cmdapi-test.sh \
acls/acl.sh \
urls/request.sh \
$(NULL)

119
tests/acls/acl.sh.in Normal file
View file

@ -0,0 +1,119 @@
#!/bin/bash -x
# SPDX-License-Identifier: GPL-3.0-or-later
BASICURL="http://127.0.0.1"
BASICURLS="https://127.0.0.1"
NETDATA_VARLIB_DIR="/var/lib/netdata"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;43m'
#change the previous acl file and with a new
#and store it on a new file
change_file(){
sed "s/$1/$2/g" netdata.cfg > "$4"
}
change_ssl_file(){
KEYROW="ssl key = $3/key.pem"
CERTROW="ssl certificate = $3/cert.pem"
sed "s@ssl key =@$KEYROW@g" netdata.ssl.cfg > tmp
sed "s@ssl certificate =@$CERTROW@g" tmp > tmp2
sed "s/$1/$2/g" tmp2 > "$4"
}
run_acl_tests() {
#Give a time for netdata start properly
sleep 2
curl -v -k --tls-max 1.2 --create-dirs -o index.html "$2" 2> log_index.txt
curl -v -k --tls-max 1.2 --create-dirs -o netdata.txt "$2/netdata.conf" 2> log_nc.txt
curl -v -k --tls-max 1.2 --create-dirs -o badge.csv "$2/api/v1/badge.svg?chart=cpu.cpu0_interrupts" 2> log_badge.txt
curl -v -k --tls-max 1.2 --create-dirs -o info.txt "$2/api/v1/info" 2> log_info.txt
curl -H "X-Auth-Token: $1" -v -k --tls-max 1.2 --create-dirs -o health.csv "$2/api/v1/manage/health?cmd=LIST" 2> log_health.txt
TOT=$(grep -c "HTTP/1.1 301" log_*.txt | cut -d: -f2| grep -c 1)
if [ "$TOT" -ne "$4" ]; then
echo -e "${RED}I got a wrong number of redirects($TOT) when SSL is activated, It was expected $4"
rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt
killall netdata
exit 1
elif [ "$TOT" -eq "$4" ] && [ "$4" -ne "0" ]; then
echo -e "${YELLOW}I got the correct number of redirects($4) when SSL is activated and I try to access with HTTP."
return
fi
TOT=$(grep -c "HTTP/1.1 200 OK" log_* | cut -d: -f2| grep -c 1)
if [ "$TOT" -ne "$3" ]; then
echo -e "${RED}I got a wrong number of \"200 OK\" from the queries, it was expected $3."
killall netdata
rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt
exit 1
fi
echo -e "${GREEN}ACLs were applied correctly"
}
CONF=$(grep "bind" netdata.cfg)
MUSER=$(grep run netdata.cfg | cut -d= -f2|sed 's/^[ \t]*//')
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -sha512 -subj "/C=US/ST=Denied/L=Somewhere/O=Dis/CN=www.example.com" -keyout key.pem -out cert.pem
chown "$MUSER" key.pem cert.pem
CWD=$(pwd)
if [ -f "${NETDATA_VARLIB_DIR}/netdata.api.key" ] ;then
read -r TOKEN < "${NETDATA_VARLIB_DIR}/netdata.api.key"
else
TOKEN="NULL"
fi
change_file "$CONF" " bind to = *" "$CWD" "netdata.conf.test0"
netdata -c "netdata.conf.test0"
run_acl_tests $TOKEN "$BASICURL:19999" 5 0
killall netdata
change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management *:20001=dashboard|registry|netdata.conf^SSL=optional *:20002=dashboard|registry" "$CWD" "netdata.conf.test1"
netdata -c "netdata.conf.test1"
run_acl_tests $TOKEN "$BASICURL:19999" 5 5
run_acl_tests $TOKEN "$BASICURLS:19999" 5 0
run_acl_tests $TOKEN "$BASICURL:20000" 4 5
run_acl_tests $TOKEN "$BASICURLS:20000" 4 0
run_acl_tests $TOKEN "$BASICURL:20001" 4 0
run_acl_tests $TOKEN "$BASICURLS:20001" 4 0
run_acl_tests $TOKEN "$BASICURL:20002" 3 5
run_acl_tests $TOKEN "$BASICURLS:20002" 3 0
killall netdata
change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management *:20001=dashboard|registry|netdata.conf^SSL=force *:20002=dashboard|registry" "$CWD" "netdata.conf.test2"
netdata -c "netdata.conf.test2"
run_acl_tests $TOKEN "$BASICURL:19999" 5 5
run_acl_tests $TOKEN "$BASICURLS:19999" 5 0
run_acl_tests $TOKEN "$BASICURL:20000" 4 5
run_acl_tests $TOKEN "$BASICURLS:20000" 4 0
run_acl_tests $TOKEN "$BASICURL:20001" 4 5
run_acl_tests $TOKEN "$BASICURLS:20001" 4 0
run_acl_tests $TOKEN "$BASICURL:20002" 3 5
run_acl_tests $TOKEN "$BASICURLS:20002" 3 0
killall netdata
change_ssl_file "$CONF" " bind to = *=dashboard|registry|badges|management|netdata.conf *:20000=dashboard|registry|badges|management^SSL=optional *:20001=dashboard|registry|netdata.conf^SSL=force" "$CWD" "netdata.conf.test3"
netdata -c "netdata.conf.test3"
run_acl_tests $TOKEN "$BASICURL:19999" 5 5
run_acl_tests $TOKEN "$BASICURLS:19999" 5 0
run_acl_tests $TOKEN "$BASICURL:20000" 4 0
run_acl_tests $TOKEN "$BASICURLS:20000" 4 0
run_acl_tests $TOKEN "$BASICURL:20001" 4 5
run_acl_tests $TOKEN "$BASICURLS:20001" 4 0
killall netdata
rm log_* netdata.conf.test* netdata.txt health.csv index.html badge.csv tmp* key.pem cert.pem info.txt
echo "All the tests were successful"

20
tests/acls/netdata.cfg Normal file
View file

@ -0,0 +1,20 @@
# netdata configuration
#
# You can download the latest version of this file, using:
#
# wget -O /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
# or
# curl -o /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
#
# You can uncomment and change any of the options below.
# The value shown in the commented settings, is the default value.
#
[global]
run as user = netdata
# the default database size - 1 hour
history = 3600
# by default do not expose the netdata port
bind to = localhost

View file

@ -0,0 +1,24 @@
# netdata configuration
#
# You can download the latest version of this file, using:
#
# wget -O /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
# or
# curl -o /etc/netdata/netdata.conf http://localhost:19999/netdata.conf
#
# You can uncomment and change any of the options below.
# The value shown in the commented settings, is the default value.
#
[global]
run as user = netdata
# the default database size - 1 hour
history = 3600
# by default do not expose the netdata port
bind to = localhost
[web]
ssl key =
ssl certificate =

View file

@ -112,6 +112,20 @@ Example:
For information how to configure the slaves to use TLS, check [securing the communication](../../streaming#securing-streaming-communications) in the streaming documentation. There you will find additional details on the expected behavior for client and server nodes, when their respective TLS options are enabled.
When we define the use of SSL in a Netdata agent for different ports, Netdata will apply the behavior specified on each port. For example, using the configuration line below:
```
[web]
bind to = *=dashboard|registry|badges|management|streaming|netdata.conf^SSL=force *:20000=netdata.conf^SSL=optional *:20001=dashboard|registry
```
Netdata will:
- Force all HTTP requests to the default port to be redirected to HTTPS (same port).
- Refuse unencrypted streaming connections from slaves on the default port.
- Allow both HTTP and HTTPS requests to port 20000 for netdata.conf
- Force HTTP requests to port 20001 to be redirected to HTTPS (same port). Only allow requests for the dashboard, the read API and the registry on port 20001.
#### TLS/SSL errors
When you start using Netdata with TLS, you may find errors in the Netdata log, which is stored at `/var/log/netdata/error.log` by default.

View file

@ -835,7 +835,11 @@ static inline char *web_client_valid_method(struct web_client *w, char *s) {
s = &s[7];
#ifdef ENABLE_HTTPS
if ( (w->ssl.flags) && (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE)){
if (w->ssl.flags && web_client_is_using_ssl_force(w)){
w->header_parse_tries = 0;
w->header_parse_last_size = 0;
web_client_disable_wait_receive(w);
char hostname[256];
char *copyme = strstr(s,"hostname=");
if ( copyme ){
@ -1065,7 +1069,7 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
}
#ifdef ENABLE_HTTPS
if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (netdata_use_ssl_on_http & NETDATA_SSL_FORCE) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (web_client_is_using_ssl_force(w) || web_client_is_using_ssl_default(w)) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
w->header_parse_tries = 0;
w->header_parse_last_size = 0;
web_client_disable_wait_receive(w);