Skip to content

Commit

Permalink
[#378] Vault Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ashu3103 committed Mar 14, 2024
1 parent d9f9253 commit 716b22c
Show file tree
Hide file tree
Showing 30 changed files with 1,961 additions and 529 deletions.
2 changes: 1 addition & 1 deletion AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ Nikita Bugrovsky <[email protected]>
Lawrence Wu <[email protected]>
Yongting You <[email protected]>
Ashutosh Sharma <[email protected]>
Henrique de Carvalho <[email protected]>
Henrique de Carvalho <[email protected]>
1 change: 1 addition & 0 deletions doc/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ The available keys and their accepted values are reported in the table below.
| log_disconnections | `off` | Bool | No | Log disconnects |
| blocking_timeout | 30 | Int | No | The number of seconds the process will be blocking for a connection (disable = 0) |
| idle_timeout | 0 | Int | No | The number of seconds a connection is been kept alive (disable = 0) |
| rotate_frontend_password_timeout | 0 | Int | No | The number of seconds after which the passwords of frontend users updated periodically (disable = 0) |
| max_connection_age | 0 | Int | No | The maximum number of seconds that a connection will live (disable = 0) |
| validation | `off` | String | No | Should connection validation be performed. Valid options: `off`, `foreground` and `background` |
| background_interval | 300 | Int | No | The interval between background validation scans in seconds |
Expand Down
59 changes: 59 additions & 0 deletions doc/VAULT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# pgagroal-vault configuration

The configuration which is mandatory is loaded from either the path specified by the `-c` flag or `/etc/pgagroal/pgagroal_vault.conf`.

The configuration of `pgagroal-vault` is split into sections using the `[` and `]` characters.

The pgagroal-vault section, called `[pgagroal-vault]`, is where you configure the overall properties of the vault's server.

The other section provide configuration for the management port of pgagroal. For now there can be only one pgagroal management port to connect.
This section don't have any requirements to their naming so you can give them
meaningful names but generally named as `[main]`.

All properties within a section are in the format `key = value`.

The characters `#` and `;` can be used for comments. A line is totally ignored if the
very first non-space character is a comment one, but it is possible to put a comment at the end of a line.
The `Bool` data type supports the following values: `on`, `yes`, `1`, `true`, `off`, `no`, `0` and `false`.

See a more complete [sample](./etc/pgagroal_vault.conf) configuration for running `pgagroal-vault` on `localhost`.

## [pgagroal-vault]

This section is mandatory and the pooler will refuse to start if the configuration file does not specify one and only one. Usually this section is place on top of the configuration file, but its position within the file does not really matter.
The available keys and their accepted values are reported in the table below.

| Property | Default | Unit | Required | Description |
|----------|---------|------|----------|-------------|
| host | | String | Yes | The bind address for pgagroal-vault |
| port | | Int | Yes | The bind port for pgagroal-vault |
| log_type | console | String | No | The logging type (console, file, syslog) |
| log_level | info | String | No | The logging level, any of the (case insensitive) strings `FATAL`, `ERROR`, `WARN`, `INFO` and `DEBUG` (that can be more specific as `DEBUG1` thru `DEBUG5`). Debug level greater than 5 will be set to `DEBUG5`. Not recognized values will make the log_level be `INFO` |
| log_path | pgagroal.log | String | No | The log file location. Can be a strftime(3) compatible string. |
| log_rotation_age | 0 | String | No | The age that will trigger a log file rotation. If expressed as a positive number, is managed as seconds. Supports suffixes: 'S' (seconds, the default), 'M' (minutes), 'H' (hours), 'D' (days), 'W' (weeks). A value of `0` disables. |
| log_rotation_size | 0 | String | No | The size of the log file that will trigger a log rotation. Supports suffixes: 'B' (bytes), the default if omitted, 'K' or 'KB' (kilobytes), 'M' or 'MB' (megabytes), 'G' or 'GB' (gigabytes). A value of `0` (with or without suffix) disables. |
| log_line_prefix | %Y-%m-%d %H:%M:%S | String | No | A strftime(3) compatible string to use as prefix for every log line. Must be quoted if contains spaces. |
| log_mode | append | String | No | Append to or create the log file (append, create) |
| log_connections | `off` | Bool | No | Log connects |
| log_disconnections | `off` | Bool | No | Log disconnects |
| tls | `off` | Bool | No | Enable Transport Layer Security (TLS) |
| tls_cert_file | | String | No | Certificate file for TLS. This file must be owned by either the user running pgagroal-vault or root. |
| tls_key_file | | String | No | Private key file for TLS. This file must be owned by either the user running pgagroal-vault or root. Additionally permissions must be at least `0640` when owned by root or `0600` otherwise. |
| tls_ca_file | | String | No | Certificate Authority (CA) file for TLS. This file must be owned by either the user running pgagroal-vault or root. |


## [main]

The section with a name different from `pgagroal-vault` will be treated as an main section.

| Property | Default | Unit | Required | Description |
|----------|---------|------|----------|-------------|
| host | | String | Yes | The address of the pgagroal running the management server |
| port | | Int | Yes | The management port of pgagroal |
| user | | String | Yes | The admin user of the pgagroal remote management service |
| tls | `off` | Bool | No | Enable Transport Layer Security (TLS) support (Experimental - no pooling) |
| tls_cert_file | | String | No | Certificate file for TLS. This file must be owned by either the user running pgagroal or root. |
| tls_key_file | | String | No | Private key file for TLS. This file must be owned by either the user running pgagroal or root. Additionally permissions must be at least `0640` when owned by root or `0600` otherwise. |
| tls_ca_file | | String | No | Certificate Authority (CA) file for TLS. This file must be owned by either the user running pgagroal or root. |

Note: For `pgagroal-vault` to function and connect properly to pgagroal, the remote server for management of the `pgagroal` should be enabled i.e. `management` should be greater than 0.
16 changes: 16 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -321,3 +321,19 @@ target_link_libraries(pgagroal-admin-bin pgagroal)

install(TARGETS pgagroal-admin-bin DESTINATION ${CMAKE_INSTALL_BINDIR})



#
# Build pgagroal-vault
#
add_executable(pgagroal-vault-bin vault.c ${RESOURCE_OBJECT})
if (CMAKE_C_LINK_PIE_SUPPORTED)
set_target_properties(pgagroal-vault-bin PROPERTIES LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE TRUE OUTPUT_NAME pgagroal-vault)
else()
set_target_properties(pgagroal-vault-bin PROPERTIES LINKER_LANGUAGE C POSITION_INDEPENDENT_CODE FALSE OUTPUT_NAME pgagroal-vault)
endif()
target_link_libraries(pgagroal-vault-bin pgagroal)

install(TARGETS pgagroal-vault-bin DESTINATION ${CMAKE_INSTALL_BINDIR})


56 changes: 15 additions & 41 deletions src/admin.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,18 @@
#include <sys/stat.h>
#include <err.h>

#define DEFAULT_PASSWORD_LENGTH 64
#define MIN_PASSWORD_LENGTH 8

#define ACTION_UNKNOWN 0
#define ACTION_MASTER_KEY 1
#define ACTION_ADD_USER 2
#define ACTION_UPDATE_USER 3
#define ACTION_REMOVE_USER 4
#define ACTION_LIST_USERS 5

static char CHARS[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', '\\', '|', ';', ':',
'\'', '\"', ',', '<', '.', '>', '/', '?'};

static int master_key(char* password, bool generate_pwd, int pwd_length);
static int add_user(char* users_path, char* username, char* password, bool generate_pwd, int pwd_length);
static int update_user(char* users_path, char* username, char* password, bool generate_pwd, int pwd_length);
static int remove_user(char* users_path, char* username);
static int list_users(char* users_path);
static char* generate_password(int pwd_length);

static void
version(void)
Expand Down Expand Up @@ -359,8 +349,11 @@ master_key(char* password, bool generate_pwd, int pwd_length)
}
else
{
password = generate_password(pwd_length);
do_free = false;
if (pgagroal_generate_password(pwd_length, &password))
{
do_free = false;
goto error;
}
}
}
else
Expand Down Expand Up @@ -481,7 +474,11 @@ add_user(char* users_path, char* username, char* password, bool generate_pwd, in
password:
if (generate_pwd)
{
password = generate_password(pwd_length);
if (pgagroal_generate_password(pwd_length, &password))
{
do_free = false;
goto error;
}
do_verify = false;
printf("Password : %s", password);
}
Expand Down Expand Up @@ -655,7 +652,11 @@ update_user(char* users_path, char* username, char* password, bool generate_pwd,
password:
if (generate_pwd)
{
password = generate_password(pwd_length);
if (pgagroal_generate_password(pwd_length, &password))
{
do_free = false;
goto error;
}
do_verify = false;
printf("Password : %s", password);
}
Expand Down Expand Up @@ -903,30 +904,3 @@ list_users(char* users_path)

return 1;
}

static char*
generate_password(int pwd_length)
{
char* pwd;
size_t s;
time_t t;

s = pwd_length + 1;

pwd = calloc(1, s);
if (pwd == NULL)
{
pgagroal_log_fatal("Couldn't allocate memory while generating password");
return NULL;
}

srand((unsigned)time(&t));

for (int i = 0; i < s; i++)
{
*((char*)(pwd + i)) = CHARS[rand() % sizeof(CHARS)];
}
*((char*)(pwd + pwd_length)) = '\0';

return pwd;
}
28 changes: 14 additions & 14 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ main(int argc, char** argv)
char* database = NULL;
char un[MAX_USERNAME_LENGTH];
char* server = NULL;
struct configuration* config = NULL;
struct main_configuration* config = NULL;
bool remote_connection = false;
long l_port;
char* config_key = NULL; /* key for a configuration setting */
Expand Down Expand Up @@ -288,7 +288,7 @@ main(int argc, char** argv)
exit(1);
}

size = sizeof(struct configuration);
size = sizeof(struct main_configuration);
if (pgagroal_create_shared_memory(size, HUGEPAGE_OFF, &shmem))
{
errx(1, "Error creating shared memory");
Expand All @@ -309,19 +309,19 @@ main(int argc, char** argv)

if (logfile)
{
config = (struct configuration*)shmem;
config = (struct main_configuration*)shmem;

config->log_type = PGAGROAL_LOGGING_TYPE_FILE;
memset(&config->log_path[0], 0, MISC_LENGTH);
memcpy(&config->log_path[0], logfile, MIN(MISC_LENGTH - 1, strlen(logfile)));
config->conf.log_type = PGAGROAL_LOGGING_TYPE_FILE;
memset(&config->conf.log_path[0], 0, MISC_LENGTH);
memcpy(&config->conf.log_path[0], logfile, MIN(MISC_LENGTH - 1, strlen(logfile)));
}

if (pgagroal_start_logging())
{
errx(1, "Cannot start the logging subsystem");
}

config = (struct configuration*)shmem;
config = (struct main_configuration*)shmem;
}
else
{
Expand All @@ -339,19 +339,19 @@ main(int argc, char** argv)

if (logfile)
{
config = (struct configuration*)shmem;
config = (struct main_configuration*)shmem;

config->log_type = PGAGROAL_LOGGING_TYPE_FILE;
memset(&config->log_path[0], 0, MISC_LENGTH);
memcpy(&config->log_path[0], logfile, MIN(MISC_LENGTH - 1, strlen(logfile)));
config->conf.log_type = PGAGROAL_LOGGING_TYPE_FILE;
memset(&config->conf.log_path[0], 0, MISC_LENGTH);
memcpy(&config->conf.log_path[0], logfile, MIN(MISC_LENGTH - 1, strlen(logfile)));
}

if (pgagroal_start_logging())
{
errx(1, "Cannot start the logging subsystem");
}

config = (struct configuration*)shmem;
config = (struct main_configuration*)shmem;
}
}

Expand Down Expand Up @@ -485,7 +485,7 @@ main(int argc, char** argv)
else
{
/* Remote connection */
if (pgagroal_connect(host, atoi(port), &socket))
if (pgagroal_connect(host, atoi(port), &socket, config->keep_alive, config->non_blocking, &config->buffer_size, config->nodelay))
{
/* Remote connection */

Expand All @@ -504,7 +504,7 @@ main(int argc, char** argv)
goto done;
}

if (pgagroal_connect(host, (int)l_port, &socket))
if (pgagroal_connect(host, (int)l_port, &socket, config->keep_alive, config->non_blocking, &config->buffer_size, config->nodelay))
{
warnx("No route to host: %s:%ld\n", host, l_port);
goto done;
Expand Down
75 changes: 74 additions & 1 deletion src/include/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ extern "C" {
* configuration file.
*/
#define PGAGROAL_MAIN_INI_SECTION "pgagroal"
/*
* The main section that must be present in the `pgagroal_vault.conf`
* configuration file.
*/
#define PGAGROAL_VAULT_INI_SECTION "pgagroal-vault"

/*
* The following constants are used to clearly identify
Expand Down Expand Up @@ -70,6 +75,14 @@ extern "C" {
int
pgagroal_init_configuration(void* shmem);

/**
* Initialize the vault configuration structure
* @param shmem The shared memory segment
* @return 0 upon success, otherwise 1
*/
int
pgagroal_vault_init_configuration(void* shmem);

/**
* Read the configuration from a file
* @param shmem The shared memory segment
Expand All @@ -96,6 +109,30 @@ pgagroal_read_configuration(void* shmem, char* filename, bool emitWarnings);
int
pgagroal_validate_configuration(void* shmem, bool has_unix_socket, bool has_main_sockets);

/**
* Read the configuration of vault from a file
* @param shmem The shared memory segment
* @param filename The file name
* @param emitWarnings true if unknown parameters have to
* reported on stderr
* @return 0 (i.e, PGAGROAL_CONFIGURATION_STATUS_OK) upon success, otherwise
* - PGAGROAL_CONFIGURATION_STATUS_FILE_NOT_FOUND if the file does not exists
* - PGAGROAL_CONFIGURATION_STATUS_FILE_TOO_BIG if the file contains too many sections
* - a positive value to indicate how many errors (with regard to sections) have been found
* - PGAGROAL_CONFIGURATION_STATUS_KO if the file has generic errors, most notably it lacks
* a [pgagroal-vault] section
*/
int
pgagroal_vault_read_configuration(void* shmem, char* filename, bool emitWarnings);

/**
* Validate the configuration of vault
* @param shmem The shared memory segment
* @return 0 upon success, otherwise 1
*/
int
pgagroal_vault_validate_configuration(void* shmem);

/**
* Read the HBA configuration from a file
* @param shmem The shared memory segment
Expand Down Expand Up @@ -193,6 +230,19 @@ pgagroal_validate_frontend_users_configuration(void* shmem);
int
pgagroal_read_admins_configuration(void* shmem, char* filename);

/**
* Read the USERS configuration of vault from a file
* @param shmem The shared memory segment
* @param filename The file name
* @return 0 (i.e, PGAGROAL_CONFIGURATION_STATUS_OK) upon success, otherwise
* - PGAGROAL_CONFIGURATION_STATUS_FILE_NOT_FOUND if the file does not exists
* - PGAGROAL_CONFIGURATION_STATUS_FILE_TOO_BIG if the file contains too many users
* (i.e., more users than the number defined in the limits)
* - PGAGROAL_CONFIGURATION_STATUS_CANNOT_DECRYPT to indicate a problem reading the content of the file
*/
int
pgagroal_vault_read_users_configuration(void* shmem, char* filename);

/**
* Validate the ADMINS configuration from a file
* @param shmem The shared memory segment
Expand Down Expand Up @@ -317,12 +367,35 @@ pgagroal_write_config_value(char* buffer, char* config_key, size_t buffer_size);
* pgagroal_apply_main_configuration( config, NULL, PGAGROAL_MAIN_INI_SECTION, "log_level", "info" );
*/
int
pgagroal_apply_main_configuration(struct configuration* config,
pgagroal_apply_main_configuration(struct main_configuration* config,
struct server* srv,
char* section,
char* key,
char* value);

/**
* Function to apply a single configuration parameter.
*
* This is the backbone function used when parsing the main configuration file
* and is used to set any of the allowed parameters.
*
* @param config the configuration to apply values onto
* @param srv the server to which the configuration parameter refers to, if needed
* @param section the section of the file, main or server
* @param key the parameter name of the configuration
* @param value the value of the configuration
* @return 0 on success
*
* Examples of usage:
* pgagroal_apply_vault_configuration( config, NULL, PGAGROAL_VAULT_INI_SECTION, "log_level", "info" );
*/
int
pgagroal_apply_vault_configuration(struct vault_configuration* config,
struct vault_server* srv,
char* section,
char* key,
char* value);

/**
* Function to set a configuration value.
*
Expand Down
Loading

0 comments on commit 716b22c

Please sign in to comment.