Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions doc/samples/keepalived.conf.HTTP_GET.auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
! Configuration File for keepalived - HTTP_GET with authentication
! This sample demonstrates HTTP basic authentication for HTTP_GET checks

global_defs {
notification_email {
acassen
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}

vrrp_instance VI_1 {
interface lo
virtual_router_id 50
nopreempt
priority 100
advert_int 1
virtual_ipaddress {
127.0.0.1
}
}

virtual_server 10.10.10.2 1358 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP

sorry_server 192.168.200.200 1358

real_server 192.168.200.2 1358 {
weight 1
HTTP_GET {
url {
path /testurl3/test.jsp
username myuser
password mypassword
status_code 200
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}

real_server 192.168.200.3 1358 {
weight 1
SSL_GET {
url {
path /secure/test.jsp
username admin
password secret123
status_code 200
tls_compliant
}
connect_timeout 5
retry 3
delay_before_retry 3
}
}
}
51 changes: 51 additions & 0 deletions doc/samples/keepalived.conf.HTTP_GET.auth.simple
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
! Simple configuration to test HTTP_GET authentication
! This tests only the HTTP check parsing without VRRP

global_defs {
notification_email {
acassen
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}

virtual_server 10.10.10.2 1358 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP

real_server 127.0.0.1 1358 {
weight 1
HTTP_GET {
url {
path /testurl3/test.jsp
username myuser
password mypassword
status_code 200
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}

real_server 127.0.0.1 1359 {
weight 1
SSL_GET {
url {
path /secure/test.jsp
username admin
password secret123
status_code 200
tls_compliant
}
connect_timeout 5
retry 3
delay_before_retry 3
}
}
}
56 changes: 56 additions & 0 deletions keepalived/check/check_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,14 @@ static const char *request_template =
"GET %s HTTP/1.%d\r\n"
"User-Agent: KeepAliveClient\r\n"
"%s"
"%s"
"Host: %s%s\r\n\r\n";

static const char *request_template_ipv6 =
"GET %s HTTP/1.%d\r\n"
"User-Agent: KeepAliveClient\r\n"
"%s"
"%s"
"Host: [%s]%s\r\n\r\n";

/* Output delimiters */
Expand Down Expand Up @@ -177,6 +179,8 @@ free_url(url_t *url)
FREE_CONST_PTR(url->path);
FREE_CONST_PTR(url->digest);
FREE_CONST_PTR(url->virtualhost);
FREE_CONST_PTR(url->username);
FREE_CONST_PTR(url->password);
#ifdef _WITH_REGEX_CHECK_
if (url->regex) {
if (!--url->regex->refcnt) {
Expand Down Expand Up @@ -259,6 +263,8 @@ dump_url(FILE *fp, bool is_ssl, const url_t *url)

if (url->virtualhost)
conf_write(fp, " Virtual host = %s", url->virtualhost);
if (url->username && url->password)
conf_write(fp, " Auth = %s:%s", url->username, url->password);
if (url->last_ssl_error)
conf_write(fp, " Last SSL error = 0x%lx", url->last_ssl_error);

Expand Down Expand Up @@ -412,6 +418,14 @@ compare_http_check(const checker_t *old_c, checker_t *new_c)
return false;
if (u1->virtualhost && strcmp(u1->virtualhost, u2->virtualhost))
return false;
if (!u1->username != !u2->username)
return false;
if (u1->username && strcmp(u1->username, u2->username))
return false;
if (!u1->password != !u2->password)
return false;
if (u1->password && strcmp(u1->password, u2->password))
return false;
#ifdef _WITH_REGEX_CHECK_
if (!u1->regex != !u2->regex)
return false;
Expand Down Expand Up @@ -617,6 +631,28 @@ url_virtualhost_handler(const vector_t *strvec)
set_string(&current_url->virtualhost, strvec, "url virtualhost");
}

static void
url_username_handler(const vector_t *strvec)
{
if (vector_size(strvec) < 2) {
report_config_error(CONFIG_GENERAL_ERROR, "Missing HTTP_GET username");
return;
}

set_string(&current_url->username, strvec, "url username");
}

static void
url_password_handler(const vector_t *strvec)
{
if (vector_size(strvec) < 2) {
report_config_error(CONFIG_GENERAL_ERROR, "Missing HTTP_GET password");
return;
}

set_string(&current_url->password, strvec, "url password");
}

static void
url_tls_compliant_handler(const vector_t *strvec)
{
Expand Down Expand Up @@ -962,6 +998,8 @@ install_http_ssl_check_keyword(const char *keyword)
install_keyword("digest", &digest_handler);
install_keyword("status_code", &status_code_handler);
install_keyword("virtualhost", &url_virtualhost_handler);
install_keyword("username", &url_username_handler);
install_keyword("password", &url_password_handler);
#ifdef _WITH_REGEX_CHECK_
install_keyword("regex", &regex_handler);
install_keyword("regex_no_match", &regex_no_match_handler);
Expand Down Expand Up @@ -1642,6 +1680,8 @@ http_request(thread_ref_t thread)
const char *request_host;
char request_host_port[7]; /* ":" [0-9][0-9][0-9][0-9][0-9] "\0" */
char *str_request;
const char *auth_header = "";
char auth_buf[512];
url_t *fetched_url;
int ret = 0;

Expand All @@ -1650,6 +1690,21 @@ http_request(thread_ref_t thread)

fetched_url = fetch_next_url(http_get_check);

/* Create Authorization header if username and password are provided */
if (fetched_url->username && fetched_url->password) {
char credentials[128];
char encoded[256];
int len;

snprintf(credentials, sizeof(credentials), "%s:%s", fetched_url->username, fetched_url->password);
len = EVP_EncodeBlock((unsigned char *)encoded, (unsigned char *)credentials, strlen(credentials));
if (len > 0) {
encoded[len] = '\0';
snprintf(auth_buf, sizeof(auth_buf), "Authorization: Basic %s\r\n", encoded);
auth_header = auth_buf;
}
}

if (fetched_url->virtualhost)
vhost = fetched_url->virtualhost;
else if (http_get_check->virtualhost)
Expand Down Expand Up @@ -1677,6 +1732,7 @@ http_request(thread_ref_t thread)
fetched_url->path,
http_get_check->http_protocol == HTTP_PROTOCOL_1_1 ? 1 : 0,
http_get_check->http_protocol == HTTP_PROTOCOL_1_0C || http_get_check->http_protocol == HTTP_PROTOCOL_1_1 ? "Connection: close\r\n" : "",
auth_header,
request_host, request_host_port);

#ifdef _CHECKER_DEBUG_
Expand Down
2 changes: 2 additions & 0 deletions keepalived/include/check_http.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ typedef struct _url {
const uint8_t *digest;
unsigned long status_code[(HTTP_STATUS_CODE_MAX - HTTP_STATUS_CODE_MIN + 1 - 1) / (sizeof(unsigned long) * CHAR_BIT) + 1];
const char *virtualhost;
const char *username;
const char *password;
ssize_t len_mismatch;
bool tls_compliant;
unsigned long last_ssl_error;
Expand Down