mirror of https://github.com/yandex/odyssey.git
mdb iamproxy auth support (#561)
This commit is contained in:
parent
ccd4dbf6e3
commit
0e44d13290
|
@ -49,7 +49,8 @@ set(od_src
|
|||
hashmap.c
|
||||
hba.c
|
||||
hba_reader.c
|
||||
hba_rule.c)
|
||||
hba_rule.c
|
||||
mdb_iamproxy.c)
|
||||
|
||||
if (PAM_FOUND)
|
||||
list(APPEND od_src pam.c)
|
||||
|
|
|
@ -67,6 +67,19 @@ static inline int od_auth_frontend_cleartext(od_client_t *client)
|
|||
|
||||
od_extention_t *extentions = client->global->extentions;
|
||||
|
||||
/* support mdb_iamproxy authentication */
|
||||
if (client->rule->enable_mdb_iamproxy_auth) {
|
||||
int authentication_result = mdb_iamproxy_authenticate_user(
|
||||
client->startup.user.value, client_token.password,
|
||||
instance, client);
|
||||
kiwi_password_free(&client_token);
|
||||
machine_msg_free(msg);
|
||||
if (authentication_result != OK_RESPONSE) {
|
||||
goto auth_failed; // refence at line 80, 100 and etc
|
||||
}
|
||||
return OK_RESPONSE;
|
||||
}
|
||||
|
||||
#ifdef LDAP_FOUND
|
||||
if (client->rule->ldap_endpoint_name) {
|
||||
od_debug(&instance->logger, "auth", client, NULL,
|
||||
|
|
|
@ -72,6 +72,9 @@ struct od_client {
|
|||
int ldap_storage_password_len;
|
||||
char *ldap_auth_dn;
|
||||
#endif
|
||||
|
||||
/* external_id for logging additional ifno about client */
|
||||
char *external_id;
|
||||
};
|
||||
|
||||
static const size_t OD_CLIENT_DEFAULT_HASHMAP_SZ = 420;
|
||||
|
@ -108,6 +111,7 @@ static inline void od_client_init(od_client_t *client)
|
|||
client->ldap_storage_password_len = 0;
|
||||
client->ldap_auth_dn = NULL;
|
||||
#endif
|
||||
client->external_id = NULL;
|
||||
|
||||
kiwi_be_startup_init(&client->startup);
|
||||
kiwi_vars_init(&client->vars);
|
||||
|
@ -146,6 +150,9 @@ static inline void od_client_free(od_client_t *client)
|
|||
if (client->prep_stmt_ids) {
|
||||
od_hashmap_free(client->prep_stmt_ids);
|
||||
}
|
||||
if (client->external_id) {
|
||||
free(client->external_id);
|
||||
}
|
||||
free(client);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,8 @@ typedef enum {
|
|||
OD_LAUTH_QUERY_USER,
|
||||
OD_LAUTH_LDAP_SERVICE,
|
||||
OD_LAUTH_PASSWORD_PASSTHROUGH,
|
||||
OD_LAUTH_MDB_IAMPROXY_ENABLE,
|
||||
OD_LAUTH_MDB_IAMPROXY_SOCKET_PATH,
|
||||
OD_LQUANTILES,
|
||||
OD_LMODULE,
|
||||
OD_LLDAP_ENDPOINT,
|
||||
|
@ -275,6 +277,9 @@ static od_keyword_t od_config_keywords[] = {
|
|||
od_keyword("password_passthrough", OD_LAUTH_PASSWORD_PASSTHROUGH),
|
||||
od_keyword("load_module", OD_LMODULE),
|
||||
od_keyword("hba_file", OD_LHBA_FILE),
|
||||
od_keyword("enable_mdb_iamproxy_auth", OD_LAUTH_MDB_IAMPROXY_ENABLE),
|
||||
od_keyword("mdb_iamproxy_socket_path",
|
||||
OD_LAUTH_MDB_IAMPROXY_SOCKET_PATH),
|
||||
|
||||
/* ldap */
|
||||
od_keyword("ldap_endpoint", OD_LLDAP_ENDPOINT),
|
||||
|
@ -1205,6 +1210,7 @@ static int od_config_reader_rule_settings(od_config_reader_t *reader,
|
|||
od_extention_t *extentions,
|
||||
od_storage_watchdog_t *watchdog)
|
||||
{
|
||||
rule->mdb_iamproxy_socket_path = NULL;
|
||||
for (;;) {
|
||||
od_token_t token;
|
||||
int rc;
|
||||
|
@ -1293,6 +1299,24 @@ static int od_config_reader_rule_settings(od_config_reader_t *reader,
|
|||
&rule->auth_module))
|
||||
return NOT_OK_RESPONSE;
|
||||
break;
|
||||
/* mdb_iamproxy authentication */
|
||||
case OD_LAUTH_MDB_IAMPROXY_ENABLE: {
|
||||
if (!od_config_reader_yes_no(
|
||||
reader, &rule->enable_mdb_iamproxy_auth))
|
||||
return NOT_OK_RESPONSE;
|
||||
if (rule->mdb_iamproxy_socket_path == NULL)
|
||||
rule->mdb_iamproxy_socket_path =
|
||||
"/var/run/iam-auth-proxy/iam-auth-proxy.sock";
|
||||
break;
|
||||
}
|
||||
case OD_LAUTH_MDB_IAMPROXY_SOCKET_PATH: {
|
||||
if (rule->mdb_iamproxy_socket_path != NULL)
|
||||
free(rule->mdb_iamproxy_socket_path);
|
||||
if (!od_config_reader_string(
|
||||
reader, &rule->mdb_iamproxy_socket_path))
|
||||
return NOT_OK_RESPONSE;
|
||||
break;
|
||||
}
|
||||
#ifdef PAM_FOUND
|
||||
/* auth_pam_service */
|
||||
case OD_LAUTH_PAM_SERVICE:
|
||||
|
|
|
@ -2340,4 +2340,4 @@ cleanup:
|
|||
od_router_unroute(router, client);
|
||||
/* close frontend connection */
|
||||
od_frontend_close(client);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,6 +215,17 @@ od_logger_format(od_logger_t *logger, od_logger_level_t level, char *context,
|
|||
if (od_unlikely(format_pos == format_end))
|
||||
break;
|
||||
switch (*format_pos) {
|
||||
/* external_id */
|
||||
case 'x': {
|
||||
if (client && client->external_id != NULL) {
|
||||
len = od_snprintf(dst_pos,
|
||||
dst_end - dst_pos,
|
||||
"%s",
|
||||
client->external_id);
|
||||
dst_pos += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* unixtime */
|
||||
case 'n': {
|
||||
time_t tm = time(NULL);
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
|
||||
/*
|
||||
* Odyssey.
|
||||
*
|
||||
* Scalable PostgreSQL connection pooler.
|
||||
*/
|
||||
|
||||
#include <odyssey.h>
|
||||
#include <machinarium.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <malloc.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/*CONNECTION CALLBACK TYPES*/
|
||||
#define MDB_IAMPROXY_CONN_ERROR -1
|
||||
#define MDB_IAMPROXY_CONN_TIMEOUT -1
|
||||
#define MDB_IAMPROXY_CONN_ACCEPTED 0
|
||||
#define MDB_IAMPROXY_CONN_DENIED -1
|
||||
|
||||
#define MDB_IAMPROXY_RES_ERROR -1
|
||||
#define MDB_IAMPROXY_RES_OK 0
|
||||
|
||||
/*AUTHENTICATION TIMEOUT LIMIT*/
|
||||
#define MDB_IAMPROXY_DEFAULT_HEADER_SIZE 8
|
||||
#define MDB_IAMPROXY_DEFAULT_CNT_CONNECTIONS 1
|
||||
#define MDB_IAMPROXY_MAX_MSG_BODY_SIZE 1048576 // 1 Mb
|
||||
|
||||
#define MDB_IAMPROXY_DEFAULT_CONNECTION_TIMEOUT 1000
|
||||
#define MDB_IAMPROXY_DEFAULT_RECEIVING_HEADER_TIMEOUT 4000
|
||||
#define MDB_IAMPROXY_DEFAULT_RECEIVING_BODY_TIMEOUT 1000
|
||||
#define MDB_IAMPROXY_DEFAULT_SENDING_TIMEOUT 1000
|
||||
|
||||
/*PAM SOCKET FILE*/
|
||||
#define MDB_IAMPROXY_DEFAULT_SOCKET_FILE \
|
||||
"/var/run/iam-auth-proxy/iam-auth-proxy.sock" // PAM SOCKET FILE place
|
||||
|
||||
void put_header(char dst[], uint64_t src)
|
||||
{
|
||||
for (int i = 0; i < MDB_IAMPROXY_DEFAULT_HEADER_SIZE; ++i) {
|
||||
dst[i] = (src & 0xFF);
|
||||
src >>= CHAR_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
void fetch_header(uint64_t *dst, char src[])
|
||||
{
|
||||
for (int i = 0; i < MDB_IAMPROXY_DEFAULT_HEADER_SIZE; ++i) {
|
||||
(*dst) |= (((uint64_t)src[i]) << (i * CHAR_BIT));
|
||||
}
|
||||
}
|
||||
|
||||
machine_msg_t *mdb_iamproxy_io_read(machine_io_t *io)
|
||||
{
|
||||
machine_msg_t *header;
|
||||
machine_msg_t *msg;
|
||||
|
||||
uint64_t body_size = 0;
|
||||
uint64_t received = 0;
|
||||
|
||||
/* RECEIVE HEADER */
|
||||
header = machine_read(io, MDB_IAMPROXY_DEFAULT_HEADER_SIZE,
|
||||
MDB_IAMPROXY_DEFAULT_RECEIVING_HEADER_TIMEOUT);
|
||||
if (header == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fetch_header(&body_size, (char *)machine_msg_data(header));
|
||||
machine_msg_free(header);
|
||||
|
||||
if (body_size > MDB_IAMPROXY_MAX_MSG_BODY_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
msg = machine_read(io, body_size,
|
||||
MDB_IAMPROXY_DEFAULT_RECEIVING_BODY_TIMEOUT);
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
int mdb_iamproxy_io_write(machine_io_t *io, machine_msg_t *msg)
|
||||
{
|
||||
/*GET COMMON MSG INFO AND ALLOCATE BUFFER*/
|
||||
int32_t send_result = MDB_IAMPROXY_RES_OK;
|
||||
uint64_t body_size = machine_msg_size(
|
||||
msg); // stores size of message (add one byte for 'c\0')
|
||||
|
||||
/* PREPARE HEADER BUFFER */
|
||||
machine_msg_t *header =
|
||||
machine_msg_create(MDB_IAMPROXY_DEFAULT_HEADER_SIZE);
|
||||
if (header == NULL) {
|
||||
send_result = MDB_IAMPROXY_RES_ERROR;
|
||||
goto free_end;
|
||||
}
|
||||
put_header((char *)machine_msg_data(header), body_size);
|
||||
|
||||
/*SEND HEADER TO SOCKET*/
|
||||
if (machine_write(io, header, MDB_IAMPROXY_DEFAULT_SENDING_TIMEOUT) <
|
||||
0) {
|
||||
send_result = MDB_IAMPROXY_RES_ERROR;
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
/*SEND MSG TO SOCKET*/
|
||||
if (machine_write(io, msg, MDB_IAMPROXY_DEFAULT_SENDING_TIMEOUT) < 0) {
|
||||
send_result = MDB_IAMPROXY_RES_ERROR;
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
free_end:
|
||||
return send_result;
|
||||
}
|
||||
|
||||
int mdb_iamproxy_authenticate_user(const char *username, const char *token,
|
||||
od_instance_t *instance, od_client_t *client)
|
||||
{
|
||||
int32_t authentication_result =
|
||||
MDB_IAMPROXY_CONN_DENIED; // stores authenticate status for user (default value: CONN_DENIED)
|
||||
int32_t correct_sending =
|
||||
MDB_IAMPROXY_CONN_ACCEPTED; // stores stutus of sending data to iam-auth-proxy
|
||||
char *auth_status_char;
|
||||
machine_msg_t *msg_username = NULL, *msg_token = NULL,
|
||||
*auth_status = NULL, *external_user = NULL;
|
||||
|
||||
/*SOCKET SETUP*/
|
||||
struct sockaddr *saddr;
|
||||
struct sockaddr_un
|
||||
exchange_socket; // socket for interprocceses connection
|
||||
memset(&exchange_socket, 0, sizeof(exchange_socket));
|
||||
exchange_socket.sun_family = AF_UNIX;
|
||||
saddr = (struct sockaddr *)&exchange_socket;
|
||||
od_snprintf(exchange_socket.sun_path, sizeof(exchange_socket.sun_path),
|
||||
"%s", MDB_IAMPROXY_DEFAULT_SOCKET_FILE);
|
||||
|
||||
/*SETUP IO*/
|
||||
machine_io_t *io;
|
||||
io = machine_io_create();
|
||||
if (io == NULL) {
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
/*CONNECT TO SOCKET*/
|
||||
int rc = machine_connect(io, saddr,
|
||||
MDB_IAMPROXY_DEFAULT_CONNECTION_TIMEOUT);
|
||||
if (rc == NOT_OK_RESPONSE) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to connect to %s", exchange_socket.sun_path);
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_end;
|
||||
}
|
||||
|
||||
/*COMMUNICATE WITH SOCKET*/
|
||||
msg_username = machine_msg_create(0);
|
||||
if (msg_username == NULL) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to allocate msg_username");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
if (machine_msg_write(msg_username, username, strlen(username) + 1) <
|
||||
0) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to send username to msg_username");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
|
||||
msg_token = machine_msg_create(0);
|
||||
if (msg_token == NULL) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to allocate msg_token");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
if (machine_msg_write(msg_token, token, strlen(token) + 1) < 0) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to write token to msg_token");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
|
||||
correct_sending = mdb_iamproxy_io_write(
|
||||
io, msg_username); // send USERNAME to socket
|
||||
if (correct_sending !=
|
||||
MDB_IAMPROXY_RES_OK) { // error during sending data to socket
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to send username to iam-auth-proxy");
|
||||
authentication_result = correct_sending;
|
||||
goto free_io;
|
||||
}
|
||||
correct_sending =
|
||||
mdb_iamproxy_io_write(io, msg_token); // send TOKEN to socket
|
||||
if (correct_sending !=
|
||||
MDB_IAMPROXY_RES_OK) { // error during sending data to socket
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to send token to iam-auth-proxy");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
|
||||
/*COMMUNUCATE WITH SOCKET*/
|
||||
auth_status =
|
||||
mdb_iamproxy_io_read(io); // recieve auth_status from socket
|
||||
if (auth_status == NULL) { // recieving is not completed successfully
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to receive auth_status from iam-auth-proxy");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_io;
|
||||
}
|
||||
|
||||
auth_status_char = (char *)machine_msg_data(auth_status);
|
||||
if ((unsigned)auth_status_char[0]) {
|
||||
authentication_result = MDB_IAMPROXY_CONN_ACCEPTED;
|
||||
} else {
|
||||
authentication_result = MDB_IAMPROXY_CONN_DENIED;
|
||||
}
|
||||
|
||||
external_user =
|
||||
mdb_iamproxy_io_read(io); // recieve subject_id from socket
|
||||
if (external_user == NULL) {
|
||||
od_error(&instance->logger, "auth", client, NULL,
|
||||
"failed to receive external_user from iam-auth-proxy");
|
||||
authentication_result = MDB_IAMPROXY_CONN_ERROR;
|
||||
goto free_auth_status;
|
||||
}
|
||||
|
||||
client->external_id = malloc(machine_msg_size(external_user));
|
||||
memcpy(client->external_id, (char *)machine_msg_data(external_user),
|
||||
machine_msg_size(external_user));
|
||||
|
||||
od_log(&instance->logger, "auth", client, NULL,
|
||||
"user '%s.%s', with client_id: %s was authenticated by iam with subject_id: %s",
|
||||
client->startup.database.value, client->startup.user.value,
|
||||
client->id.id, client->external_id);
|
||||
|
||||
/*FREE RESOURCES*/
|
||||
free_external_user:
|
||||
machine_msg_free(external_user);
|
||||
free_auth_status:
|
||||
machine_msg_free(auth_status);
|
||||
free_io:
|
||||
machine_io_free(io);
|
||||
free_end:
|
||||
/*RETURN RESULT*/
|
||||
return authentication_result;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef ODYSSEY_IAMPROXY_H
|
||||
#define ODYSSEY_IAMPROXY_H
|
||||
|
||||
/*
|
||||
* Odyssey.
|
||||
*
|
||||
* Scalable PostgreSQL connection pooler.
|
||||
*/
|
||||
|
||||
int mdb_iamproxy_authenticate_user(const char *username, const char *token,
|
||||
od_instance_t *instance,
|
||||
od_client_t *client);
|
||||
|
||||
#endif /* ODYSSEY_IAMPROXy_H */
|
|
@ -200,6 +200,8 @@ void od_rules_rule_free(od_rule_t *rule)
|
|||
free(rule->storage_password);
|
||||
if (rule->pool)
|
||||
od_rule_pool_free(rule->pool);
|
||||
if (rule->mdb_iamproxy_socket_path)
|
||||
free(rule->mdb_iamproxy_socket_path);
|
||||
|
||||
od_list_t *i, *n;
|
||||
od_list_foreach_safe(&rule->auth_common_names, i, n)
|
||||
|
|
|
@ -79,6 +79,9 @@ struct od_rule {
|
|||
od_list_t auth_common_names;
|
||||
int auth_common_names_count;
|
||||
|
||||
int enable_mdb_iamproxy_auth;
|
||||
char *mdb_iamproxy_socket_path;
|
||||
|
||||
#ifdef PAM_FOUND
|
||||
/* PAM parametrs */
|
||||
char *auth_pam_service;
|
||||
|
|
Loading…
Reference in New Issue