mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
[MINOR] checks: add support for LDAPv3 health checks
This patch provides a new "option ldap-check" statement to enable server health checks based on LDAPv3 bind requests. (cherry picked from commit b76b44c6fed8a7ba6f0f565dd72a9cb77aaeca7c)
This commit is contained in:
parent
b824b002cd
commit
b4c81e4c81
@ -898,6 +898,7 @@ option httpclose (*) X X X X
|
|||||||
option httplog X X X X
|
option httplog X X X X
|
||||||
option http_proxy (*) X X X X
|
option http_proxy (*) X X X X
|
||||||
option independant-streams (*) X X X X
|
option independant-streams (*) X X X X
|
||||||
|
option ldap-check X - X X
|
||||||
option log-health-checks (*) X - X X
|
option log-health-checks (*) X - X X
|
||||||
option log-separate-errors (*) X X X -
|
option log-separate-errors (*) X X X -
|
||||||
option logasap (*) X X X -
|
option logasap (*) X X X -
|
||||||
@ -3120,6 +3121,29 @@ no option independant-streams
|
|||||||
See also : "timeout client" and "timeout server"
|
See also : "timeout client" and "timeout server"
|
||||||
|
|
||||||
|
|
||||||
|
option ldap-check
|
||||||
|
Use LDAPv3 health checks for server testing
|
||||||
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
|
yes | no | yes | yes
|
||||||
|
Arguments : none
|
||||||
|
|
||||||
|
It is possible to test that the server correctly talks LDAPv3 instead of just
|
||||||
|
testing that it accepts the TCP connection. When this option is set, an
|
||||||
|
LDAPv3 anonymous simple bind message is sent to the server, and the response
|
||||||
|
is analyzed to find an LDAPv3 bind response message.
|
||||||
|
|
||||||
|
The server is considered valid only when the LDAP response contains success
|
||||||
|
resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9).
|
||||||
|
|
||||||
|
Logging of bind requests is server dependent see your documentation how to
|
||||||
|
configure it.
|
||||||
|
|
||||||
|
Example :
|
||||||
|
option ldap-check
|
||||||
|
|
||||||
|
See also : "option httpchk"
|
||||||
|
|
||||||
|
|
||||||
option log-health-checks
|
option log-health-checks
|
||||||
no option log-health-checks
|
no option log-health-checks
|
||||||
Enable or disable logging of health checks
|
Enable or disable logging of health checks
|
||||||
|
@ -118,6 +118,7 @@
|
|||||||
#define DEF_RISETIME 2
|
#define DEF_RISETIME 2
|
||||||
#define DEF_CHECK_REQ "OPTIONS / HTTP/1.0\r\n"
|
#define DEF_CHECK_REQ "OPTIONS / HTTP/1.0\r\n"
|
||||||
#define DEF_SMTP_CHECK_REQ "HELO localhost\r\n"
|
#define DEF_SMTP_CHECK_REQ "HELO localhost\r\n"
|
||||||
|
#define DEF_LDAP_CHECK_REQ "\x30\x0c\x02\x01\x01\x60\x07\x02\x01\x03\x04\x00\x80\x00"
|
||||||
|
|
||||||
#define DEF_HANA_ONERR HANA_ONERR_FAILCHK
|
#define DEF_HANA_ONERR HANA_ONERR_FAILCHK
|
||||||
#define DEF_HANA_ERRLIMIT 10
|
#define DEF_HANA_ERRLIMIT 10
|
||||||
|
@ -139,6 +139,7 @@
|
|||||||
#define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */
|
#define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */
|
||||||
#define PR_O2_SSL3_CHK 0x00100000 /* use SSLv3 CLIENT_HELLO packets for server health */
|
#define PR_O2_SSL3_CHK 0x00100000 /* use SSLv3 CLIENT_HELLO packets for server health */
|
||||||
#define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with server eventhough we close */
|
#define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with server eventhough we close */
|
||||||
|
#define PR_O2_LDAP_CHK 0x00400000 /* use LDAP check for server health */
|
||||||
/* end of proxy->options2 */
|
/* end of proxy->options2 */
|
||||||
|
|
||||||
/* bits for sticking rules */
|
/* bits for sticking rules */
|
||||||
|
@ -2748,6 +2748,7 @@ stats_error_parsing:
|
|||||||
curproxy->options &= ~PR_O_SMTP_CHK;
|
curproxy->options &= ~PR_O_SMTP_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_LDAP_CHK;
|
||||||
curproxy->options |= PR_O_HTTP_CHK;
|
curproxy->options |= PR_O_HTTP_CHK;
|
||||||
if (!*args[2]) { /* no argument */
|
if (!*args[2]) { /* no argument */
|
||||||
curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
|
curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
|
||||||
@ -2779,6 +2780,7 @@ stats_error_parsing:
|
|||||||
curproxy->options &= ~PR_O_HTTP_CHK;
|
curproxy->options &= ~PR_O_HTTP_CHK;
|
||||||
curproxy->options &= ~PR_O_SMTP_CHK;
|
curproxy->options &= ~PR_O_SMTP_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_LDAP_CHK;
|
||||||
curproxy->options2 |= PR_O2_SSL3_CHK;
|
curproxy->options2 |= PR_O2_SSL3_CHK;
|
||||||
}
|
}
|
||||||
else if (!strcmp(args[1], "smtpchk")) {
|
else if (!strcmp(args[1], "smtpchk")) {
|
||||||
@ -2788,6 +2790,7 @@ stats_error_parsing:
|
|||||||
curproxy->options &= ~PR_O_HTTP_CHK;
|
curproxy->options &= ~PR_O_HTTP_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_LDAP_CHK;
|
||||||
curproxy->options |= PR_O_SMTP_CHK;
|
curproxy->options |= PR_O_SMTP_CHK;
|
||||||
|
|
||||||
if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
|
if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
|
||||||
@ -2814,8 +2817,23 @@ stats_error_parsing:
|
|||||||
curproxy->options &= ~PR_O_HTTP_CHK;
|
curproxy->options &= ~PR_O_HTTP_CHK;
|
||||||
curproxy->options &= ~PR_O_SMTP_CHK;
|
curproxy->options &= ~PR_O_SMTP_CHK;
|
||||||
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_LDAP_CHK;
|
||||||
curproxy->options2 |= PR_O2_MYSQL_CHK;
|
curproxy->options2 |= PR_O2_MYSQL_CHK;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(args[1], "ldap-check")) {
|
||||||
|
/* use LDAP request to check servers' health */
|
||||||
|
free(curproxy->check_req);
|
||||||
|
curproxy->check_req = NULL;
|
||||||
|
curproxy->options &= ~PR_O_HTTP_CHK;
|
||||||
|
curproxy->options &= ~PR_O_SMTP_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_SSL3_CHK;
|
||||||
|
curproxy->options2 &= ~PR_O2_MYSQL_CHK;
|
||||||
|
curproxy->options2 |= PR_O2_LDAP_CHK;
|
||||||
|
|
||||||
|
curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
|
||||||
|
memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
|
||||||
|
curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
|
||||||
|
}
|
||||||
else if (!strcmp(args[1], "forwardfor")) {
|
else if (!strcmp(args[1], "forwardfor")) {
|
||||||
int cur_arg;
|
int cur_arg;
|
||||||
|
|
||||||
|
58
src/checks.c
58
src/checks.c
@ -743,7 +743,8 @@ static int event_srv_chk_w(int fd)
|
|||||||
if ((s->proxy->options & PR_O_HTTP_CHK) ||
|
if ((s->proxy->options & PR_O_HTTP_CHK) ||
|
||||||
(s->proxy->options & PR_O_SMTP_CHK) ||
|
(s->proxy->options & PR_O_SMTP_CHK) ||
|
||||||
(s->proxy->options2 & PR_O2_SSL3_CHK) ||
|
(s->proxy->options2 & PR_O2_SSL3_CHK) ||
|
||||||
(s->proxy->options2 & PR_O2_MYSQL_CHK)) {
|
(s->proxy->options2 & PR_O2_MYSQL_CHK) ||
|
||||||
|
(s->proxy->options2 & PR_O2_LDAP_CHK)) {
|
||||||
int ret;
|
int ret;
|
||||||
const char *check_req = s->proxy->check_req;
|
const char *check_req = s->proxy->check_req;
|
||||||
int check_len = s->proxy->check_len;
|
int check_len = s->proxy->check_len;
|
||||||
@ -866,6 +867,7 @@ static int event_srv_chk_r(int fd)
|
|||||||
struct server *s = t->context;
|
struct server *s = t->context;
|
||||||
char *desc;
|
char *desc;
|
||||||
int done;
|
int done;
|
||||||
|
unsigned short msglen;
|
||||||
|
|
||||||
if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) {
|
if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) {
|
||||||
/* in case of TCP only, this tells us if the connection failed */
|
/* in case of TCP only, this tells us if the connection failed */
|
||||||
@ -1024,6 +1026,60 @@ static int event_srv_chk_r(int fd)
|
|||||||
set_server_check_status(s, HCHK_STATUS_L7STS, desc);
|
set_server_check_status(s, HCHK_STATUS_L7STS, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (s->proxy->options2 & PR_O2_LDAP_CHK) {
|
||||||
|
if (!done && s->check_data_len < 14)
|
||||||
|
goto wait_more_data;
|
||||||
|
|
||||||
|
/* Check if the server speaks LDAP (ASN.1/BER)
|
||||||
|
* http://en.wikipedia.org/wiki/Basic_Encoding_Rules
|
||||||
|
* http://tools.ietf.org/html/rfc4511
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc4511#section-4.1.1
|
||||||
|
* LDAPMessage: 0x30: SEQUENCE
|
||||||
|
*/
|
||||||
|
if ((s->check_data_len < 14) || (*(s->check_data) != '\x30')) {
|
||||||
|
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* size of LDAPMessage */
|
||||||
|
msglen = (*(s->check_data + 1) & 0x80) ? (*(s->check_data + 1) & 0x7f) : 0;
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc4511#section-4.2.2
|
||||||
|
* messageID: 0x02 0x01 0x01: INTEGER 1
|
||||||
|
* protocolOp: 0x61: bindResponse
|
||||||
|
*/
|
||||||
|
if ((msglen > 2) ||
|
||||||
|
(memcmp(s->check_data + 2 + msglen, "\x02\x01\x01\x61", 4) != 0)) {
|
||||||
|
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
|
||||||
|
|
||||||
|
goto out_wakeup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* size of bindResponse */
|
||||||
|
msglen += (*(s->check_data + msglen + 6) & 0x80) ? (*(s->check_data + msglen + 6) & 0x7f) : 0;
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
|
||||||
|
* ldapResult: 0x0a 0x01: ENUMERATION
|
||||||
|
*/
|
||||||
|
if ((msglen > 4) ||
|
||||||
|
(memcmp(s->check_data + 7 + msglen, "\x0a\x01", 2) != 0)) {
|
||||||
|
set_server_check_status(s, HCHK_STATUS_L7RSP, "Not LDAPv3 protocol");
|
||||||
|
|
||||||
|
goto out_wakeup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://tools.ietf.org/html/rfc4511#section-4.1.9
|
||||||
|
* resultCode
|
||||||
|
*/
|
||||||
|
s->check_code = *(s->check_data + msglen + 9);
|
||||||
|
if (s->check_code) {
|
||||||
|
set_server_check_status(s, HCHK_STATUS_L7STS, "See RFC: http://tools.ietf.org/html/rfc4511#section-4.1.9");
|
||||||
|
} else {
|
||||||
|
set_server_check_status(s, HCHK_STATUS_L7OKD, "Success");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* other checks are valid if the connection succeeded anyway */
|
/* other checks are valid if the connection succeeded anyway */
|
||||||
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
|
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user