YARN-4245. Generalize config file handling in container-executor. Contributed by Sidharta Seethana.
This commit is contained in:
parent
e51a8c1056
commit
8ed2e060e8
@ -34,34 +34,22 @@
|
|||||||
|
|
||||||
#define MAX_SIZE 10
|
#define MAX_SIZE 10
|
||||||
|
|
||||||
struct confentry {
|
|
||||||
const char *key;
|
|
||||||
const char *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct configuration {
|
|
||||||
int size;
|
|
||||||
struct confentry **confdetails;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct configuration config={.size=0, .confdetails=NULL};
|
|
||||||
|
|
||||||
//clean up method for freeing configuration
|
//clean up method for freeing configuration
|
||||||
void free_configurations() {
|
void free_configurations(struct configuration *cfg) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0; i < config.size; i++) {
|
for (i = 0; i < cfg->size; i++) {
|
||||||
if (config.confdetails[i]->key != NULL) {
|
if (cfg->confdetails[i]->key != NULL) {
|
||||||
free((void *)config.confdetails[i]->key);
|
free((void *)cfg->confdetails[i]->key);
|
||||||
}
|
}
|
||||||
if (config.confdetails[i]->value != NULL) {
|
if (cfg->confdetails[i]->value != NULL) {
|
||||||
free((void *)config.confdetails[i]->value);
|
free((void *)cfg->confdetails[i]->value);
|
||||||
}
|
}
|
||||||
free(config.confdetails[i]);
|
free(cfg->confdetails[i]);
|
||||||
}
|
}
|
||||||
if (config.size > 0) {
|
if (cfg->size > 0) {
|
||||||
free(config.confdetails);
|
free(cfg->confdetails);
|
||||||
}
|
}
|
||||||
config.size = 0;
|
cfg->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,8 +121,8 @@ int check_configuration_permissions(const char* file_name) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//function used to load the configurations present in the secure config
|
|
||||||
void read_config(const char* file_name) {
|
void read_config(const char* file_name, struct configuration *cfg) {
|
||||||
FILE *conf_file;
|
FILE *conf_file;
|
||||||
char *line;
|
char *line;
|
||||||
char *equaltok;
|
char *equaltok;
|
||||||
@ -152,9 +140,9 @@ void read_config(const char* file_name) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//allocate space for ten configuration items.
|
//allocate space for ten configuration items.
|
||||||
config.confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
|
cfg->confdetails = (struct confentry **) malloc(sizeof(struct confentry *)
|
||||||
* MAX_SIZE);
|
* MAX_SIZE);
|
||||||
config.size = 0;
|
cfg->size = 0;
|
||||||
conf_file = fopen(file_name, "r");
|
conf_file = fopen(file_name, "r");
|
||||||
if (conf_file == NULL) {
|
if (conf_file == NULL) {
|
||||||
fprintf(ERRORFILE, "Invalid conf file provided : %s \n", file_name);
|
fprintf(ERRORFILE, "Invalid conf file provided : %s \n", file_name);
|
||||||
@ -196,9 +184,9 @@ void read_config(const char* file_name) {
|
|||||||
free(line);
|
free(line);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
config.confdetails[config.size] = (struct confentry *) malloc(
|
cfg->confdetails[cfg->size] = (struct confentry *) malloc(
|
||||||
sizeof(struct confentry));
|
sizeof(struct confentry));
|
||||||
if(config.confdetails[config.size] == NULL) {
|
if(cfg->confdetails[cfg->size] == NULL) {
|
||||||
fprintf(LOGFILE,
|
fprintf(LOGFILE,
|
||||||
"Failed allocating memory for single configuration item\n");
|
"Failed allocating memory for single configuration item\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -208,10 +196,10 @@ void read_config(const char* file_name) {
|
|||||||
fprintf(LOGFILE, "read_config : Adding conf key : %s \n", equaltok);
|
fprintf(LOGFILE, "read_config : Adding conf key : %s \n", equaltok);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(config.confdetails[config.size], 0, sizeof(struct confentry));
|
memset(cfg->confdetails[cfg->size], 0, sizeof(struct confentry));
|
||||||
config.confdetails[config.size]->key = (char *) malloc(
|
cfg->confdetails[cfg->size]->key = (char *) malloc(
|
||||||
sizeof(char) * (strlen(equaltok)+1));
|
sizeof(char) * (strlen(equaltok)+1));
|
||||||
strcpy((char *)config.confdetails[config.size]->key, equaltok);
|
strcpy((char *)cfg->confdetails[cfg->size]->key, equaltok);
|
||||||
equaltok = strtok_r(NULL, "=", &temp_equaltok);
|
equaltok = strtok_r(NULL, "=", &temp_equaltok);
|
||||||
if (equaltok == NULL) {
|
if (equaltok == NULL) {
|
||||||
fprintf(LOGFILE, "configuration tokenization failed \n");
|
fprintf(LOGFILE, "configuration tokenization failed \n");
|
||||||
@ -220,8 +208,8 @@ void read_config(const char* file_name) {
|
|||||||
//means value is commented so don't store the key
|
//means value is commented so don't store the key
|
||||||
if(equaltok[0] == '#') {
|
if(equaltok[0] == '#') {
|
||||||
free(line);
|
free(line);
|
||||||
free((void *)config.confdetails[config.size]->key);
|
free((void *)cfg->confdetails[cfg->size]->key);
|
||||||
free(config.confdetails[config.size]);
|
free(cfg->confdetails[cfg->size]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,27 +217,29 @@ void read_config(const char* file_name) {
|
|||||||
fprintf(LOGFILE, "read_config : Adding conf value : %s \n", equaltok);
|
fprintf(LOGFILE, "read_config : Adding conf value : %s \n", equaltok);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
config.confdetails[config.size]->value = (char *) malloc(
|
cfg->confdetails[cfg->size]->value = (char *) malloc(
|
||||||
sizeof(char) * (strlen(equaltok)+1));
|
sizeof(char) * (strlen(equaltok)+1));
|
||||||
strcpy((char *)config.confdetails[config.size]->value, equaltok);
|
strcpy((char *)cfg->confdetails[cfg->size]->value, equaltok);
|
||||||
if((config.size + 1) % MAX_SIZE == 0) {
|
if((cfg->size + 1) % MAX_SIZE == 0) {
|
||||||
config.confdetails = (struct confentry **) realloc(config.confdetails,
|
cfg->confdetails = (struct confentry **) realloc(cfg->confdetails,
|
||||||
sizeof(struct confentry **) * (MAX_SIZE + config.size));
|
sizeof(struct confentry **) * (MAX_SIZE + cfg->size));
|
||||||
if (config.confdetails == NULL) {
|
if (cfg->confdetails == NULL) {
|
||||||
fprintf(LOGFILE,
|
fprintf(LOGFILE,
|
||||||
"Failed re-allocating memory for configuration items\n");
|
"Failed re-allocating memory for configuration items\n");
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(config.confdetails[config.size] )
|
if(cfg->confdetails[cfg->size]) {
|
||||||
config.size++;
|
cfg->size++;
|
||||||
|
}
|
||||||
|
|
||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
//close the file
|
//close the file
|
||||||
fclose(conf_file);
|
fclose(conf_file);
|
||||||
|
|
||||||
if (config.size == 0) {
|
if (cfg->size == 0) {
|
||||||
fprintf(ERRORFILE, "Invalid configuration provided in %s\n", file_name);
|
fprintf(ERRORFILE, "Invalid configuration provided in %s\n", file_name);
|
||||||
exit(INVALID_CONFIG_FILE);
|
exit(INVALID_CONFIG_FILE);
|
||||||
}
|
}
|
||||||
@ -262,7 +252,7 @@ void read_config(const char* file_name) {
|
|||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
fclose(conf_file);
|
fclose(conf_file);
|
||||||
free_configurations();
|
free_configurations(cfg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,11 +262,11 @@ void read_config(const char* file_name) {
|
|||||||
* array, next time onwards used the populated array.
|
* array, next time onwards used the populated array.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
char * get_value(const char* key) {
|
char * get_value(const char* key, struct configuration *cfg) {
|
||||||
int count;
|
int count;
|
||||||
for (count = 0; count < config.size; count++) {
|
for (count = 0; count < cfg->size; count++) {
|
||||||
if (strcmp(config.confdetails[count]->key, key) == 0) {
|
if (strcmp(cfg->confdetails[count]->key, key) == 0) {
|
||||||
return strdup(config.confdetails[count]->value);
|
return strdup(cfg->confdetails[count]->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -286,11 +276,21 @@ char * get_value(const char* key) {
|
|||||||
* Function to return an array of values for a key.
|
* Function to return an array of values for a key.
|
||||||
* Value delimiter is assumed to be a ','.
|
* Value delimiter is assumed to be a ','.
|
||||||
*/
|
*/
|
||||||
char ** get_values(const char * key) {
|
char ** get_values(const char * key, struct configuration *cfg) {
|
||||||
char *value = get_value(key);
|
char *value = get_value(key, cfg);
|
||||||
return extract_values_delim(value, ",");
|
return extract_values_delim(value, ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to return an array of values for a key, using the specified
|
||||||
|
delimiter.
|
||||||
|
*/
|
||||||
|
char ** get_values_delim(const char * key, struct configuration *cfg,
|
||||||
|
const char *delim) {
|
||||||
|
char *value = get_value(key, cfg);
|
||||||
|
return extract_values_delim(value, delim);
|
||||||
|
}
|
||||||
|
|
||||||
char ** extract_values_delim(char *value, const char *delim) {
|
char ** extract_values_delim(char *value, const char *delim) {
|
||||||
char ** toPass = NULL;
|
char ** toPass = NULL;
|
||||||
char *tempTok = NULL;
|
char *tempTok = NULL;
|
||||||
|
@ -37,15 +37,33 @@ int check_configuration_permissions(const char* file_name);
|
|||||||
*/
|
*/
|
||||||
char *resolve_config_path(const char* file_name, const char *root);
|
char *resolve_config_path(const char* file_name, const char *root);
|
||||||
|
|
||||||
// read the given configuration file
|
// Config data structures.
|
||||||
void read_config(const char* config_file);
|
struct confentry {
|
||||||
|
const char *key;
|
||||||
|
const char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct configuration {
|
||||||
|
int size;
|
||||||
|
struct confentry **confdetails;
|
||||||
|
};
|
||||||
|
|
||||||
|
// read the given configuration file into the specified config struct.
|
||||||
|
void read_config(const char* config_file, struct configuration *cfg);
|
||||||
|
|
||||||
//method exposed to get the configurations
|
//method exposed to get the configurations
|
||||||
char *get_value(const char* key);
|
char *get_value(const char* key, struct configuration *cfg);
|
||||||
|
|
||||||
//function to return array of values pointing to the key. Values are
|
//function to return array of values pointing to the key. Values are
|
||||||
//comma seperated strings.
|
//comma seperated strings.
|
||||||
char ** get_values(const char* key);
|
char ** get_values(const char* key, struct configuration *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to return an array of values for a key, using the specified
|
||||||
|
delimiter.
|
||||||
|
*/
|
||||||
|
char ** get_values_delim(const char * key, struct configuration *cfg,
|
||||||
|
const char *delim);
|
||||||
|
|
||||||
// Extracts array of values from the comma separated list of values.
|
// Extracts array of values from the comma separated list of values.
|
||||||
char ** extract_values(char *value);
|
char ** extract_values(char *value);
|
||||||
@ -56,7 +74,7 @@ char ** extract_values_delim(char *value, const char *delim);
|
|||||||
void free_values(char** values);
|
void free_values(char** values);
|
||||||
|
|
||||||
//method to free allocated configuration
|
//method to free allocated configuration
|
||||||
void free_configurations();
|
void free_configurations(struct configuration *cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If str is a string of the form key=val, find 'key'
|
* If str is a string of the form key=val, find 'key'
|
||||||
|
@ -59,6 +59,8 @@ FILE* ERRORFILE = NULL;
|
|||||||
static uid_t nm_uid = -1;
|
static uid_t nm_uid = -1;
|
||||||
static gid_t nm_gid = -1;
|
static gid_t nm_gid = -1;
|
||||||
|
|
||||||
|
struct configuration executor_cfg = {.size=0, .confdetails=NULL};
|
||||||
|
|
||||||
char *concatenate(char *concat_pattern, char *return_path_name,
|
char *concatenate(char *concat_pattern, char *return_path_name,
|
||||||
int numArgs, ...);
|
int numArgs, ...);
|
||||||
|
|
||||||
@ -67,6 +69,21 @@ void set_nm_uid(uid_t user, gid_t group) {
|
|||||||
nm_gid = group;
|
nm_gid = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//function used to load the configurations present in the secure config
|
||||||
|
void read_executor_config(const char* file_name) {
|
||||||
|
read_config(file_name, &executor_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//function used to free executor configuration data
|
||||||
|
void free_executor_configurations() {
|
||||||
|
free_configurations(&executor_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Lookup nodemanager group from container executor configuration.
|
||||||
|
char *get_nodemanager_group() {
|
||||||
|
return get_value(NM_GROUP_KEY, &executor_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the executable filename.
|
* get the executable filename.
|
||||||
*/
|
*/
|
||||||
@ -658,7 +675,7 @@ static struct passwd* get_user_info(const char* user) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int is_whitelisted(const char *user) {
|
int is_whitelisted(const char *user) {
|
||||||
char **whitelist = get_values(ALLOWED_SYSTEM_USERS_KEY);
|
char **whitelist = get_values(ALLOWED_SYSTEM_USERS_KEY, &executor_cfg);
|
||||||
char **users = whitelist;
|
char **users = whitelist;
|
||||||
if (whitelist != NULL) {
|
if (whitelist != NULL) {
|
||||||
for(; *users; ++users) {
|
for(; *users; ++users) {
|
||||||
@ -686,7 +703,7 @@ struct passwd* check_user(const char *user) {
|
|||||||
fflush(LOGFILE);
|
fflush(LOGFILE);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char *min_uid_str = get_value(MIN_USERID_KEY);
|
char *min_uid_str = get_value(MIN_USERID_KEY, &executor_cfg);
|
||||||
int min_uid = DEFAULT_MIN_USERID;
|
int min_uid = DEFAULT_MIN_USERID;
|
||||||
if (min_uid_str != NULL) {
|
if (min_uid_str != NULL) {
|
||||||
char *end_ptr = NULL;
|
char *end_ptr = NULL;
|
||||||
@ -713,7 +730,7 @@ struct passwd* check_user(const char *user) {
|
|||||||
free(user_info);
|
free(user_info);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
char **banned_users = get_values(BANNED_USERS_KEY);
|
char **banned_users = get_values(BANNED_USERS_KEY, &executor_cfg);
|
||||||
banned_users = banned_users == NULL ?
|
banned_users = banned_users == NULL ?
|
||||||
(char**) DEFAULT_BANNED_USERS : banned_users;
|
(char**) DEFAULT_BANNED_USERS : banned_users;
|
||||||
char **banned_user = banned_users;
|
char **banned_user = banned_users;
|
||||||
@ -1062,7 +1079,7 @@ char* parse_docker_command_file(const char* command_file) {
|
|||||||
|
|
||||||
int run_docker(const char *command_file) {
|
int run_docker(const char *command_file) {
|
||||||
char* docker_command = parse_docker_command_file(command_file);
|
char* docker_command = parse_docker_command_file(command_file);
|
||||||
char* docker_binary = get_value(DOCKER_BINARY_KEY);
|
char* docker_binary = get_value(DOCKER_BINARY_KEY, &executor_cfg);
|
||||||
char* docker_command_with_binary = calloc(sizeof(char), EXECUTOR_PATH_MAX);
|
char* docker_command_with_binary = calloc(sizeof(char), EXECUTOR_PATH_MAX);
|
||||||
snprintf(docker_command_with_binary, EXECUTOR_PATH_MAX, "%s %s", docker_binary, docker_command);
|
snprintf(docker_command_with_binary, EXECUTOR_PATH_MAX, "%s %s", docker_binary, docker_command);
|
||||||
char **args = extract_values_delim(docker_command_with_binary, " ");
|
char **args = extract_values_delim(docker_command_with_binary, " ");
|
||||||
@ -1224,7 +1241,7 @@ int launch_docker_container_as_user(const char * user, const char *app_id,
|
|||||||
char buffer[BUFFER_SIZE];
|
char buffer[BUFFER_SIZE];
|
||||||
|
|
||||||
char *docker_command = parse_docker_command_file(command_file);
|
char *docker_command = parse_docker_command_file(command_file);
|
||||||
char *docker_binary = get_value(DOCKER_BINARY_KEY);
|
char *docker_binary = get_value(DOCKER_BINARY_KEY, &executor_cfg);
|
||||||
if (docker_binary == NULL) {
|
if (docker_binary == NULL) {
|
||||||
docker_binary = "docker";
|
docker_binary = "docker";
|
||||||
}
|
}
|
||||||
|
@ -95,10 +95,15 @@ extern FILE *LOGFILE;
|
|||||||
// the log file for error messages
|
// the log file for error messages
|
||||||
extern FILE *ERRORFILE;
|
extern FILE *ERRORFILE;
|
||||||
|
|
||||||
|
|
||||||
// get the executable's filename
|
// get the executable's filename
|
||||||
char* get_executable();
|
char* get_executable();
|
||||||
|
|
||||||
|
//function used to load the configurations present in the secure config
|
||||||
|
void read_executor_config(const char* file_name);
|
||||||
|
|
||||||
|
//Lookup nodemanager group from container executor configuration.
|
||||||
|
char *get_nodemanager_group();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the permissions on the container-executor to make sure that security is
|
* Check the permissions on the container-executor to make sure that security is
|
||||||
* permissible. For this, we need container-executor binary to
|
* permissible. For this, we need container-executor binary to
|
||||||
@ -111,6 +116,12 @@ char* get_executable();
|
|||||||
*/
|
*/
|
||||||
int check_executor_permissions(char *executable_file);
|
int check_executor_permissions(char *executable_file);
|
||||||
|
|
||||||
|
//function used to load the configurations present in the secure config.
|
||||||
|
void read_executor_config(const char* file_name);
|
||||||
|
|
||||||
|
//function used to free executor configuration data
|
||||||
|
void free_executor_configurations();
|
||||||
|
|
||||||
// initialize the application directory
|
// initialize the application directory
|
||||||
int initialize_app(const char *user, const char *app_id,
|
int initialize_app(const char *user, const char *app_id,
|
||||||
const char *credentials, char* const* local_dirs,
|
const char *credentials, char* const* local_dirs,
|
||||||
|
@ -112,11 +112,11 @@ static void assert_valid_setup(char *current_executable) {
|
|||||||
flush_and_close_log_files();
|
flush_and_close_log_files();
|
||||||
exit(INVALID_CONFIG_FILE);
|
exit(INVALID_CONFIG_FILE);
|
||||||
}
|
}
|
||||||
read_config(conf_file);
|
read_executor_config(conf_file);
|
||||||
free(conf_file);
|
free(conf_file);
|
||||||
|
|
||||||
// look up the node manager group in the config file
|
// look up the node manager group in the config file
|
||||||
char *nm_group = get_value(NM_GROUP_KEY);
|
char *nm_group = get_nodemanager_group();
|
||||||
if (nm_group == NULL) {
|
if (nm_group == NULL) {
|
||||||
fprintf(ERRORFILE, "Can't get configured value for %s.\n", NM_GROUP_KEY);
|
fprintf(ERRORFILE, "Can't get configured value for %s.\n", NM_GROUP_KEY);
|
||||||
flush_and_close_log_files();
|
flush_and_close_log_files();
|
||||||
|
@ -873,7 +873,7 @@ int main(int argc, char **argv) {
|
|||||||
if (write_config_file(TEST_ROOT "/test.cfg", 1) != 0) {
|
if (write_config_file(TEST_ROOT "/test.cfg", 1) != 0) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
read_config(TEST_ROOT "/test.cfg");
|
read_executor_config(TEST_ROOT "/test.cfg");
|
||||||
|
|
||||||
local_dirs = extract_values(strdup(NM_LOCAL_DIRS));
|
local_dirs = extract_values(strdup(NM_LOCAL_DIRS));
|
||||||
log_dirs = extract_values(strdup(NM_LOG_DIRS));
|
log_dirs = extract_values(strdup(NM_LOG_DIRS));
|
||||||
@ -945,14 +945,14 @@ int main(int argc, char **argv) {
|
|||||||
seteuid(0);
|
seteuid(0);
|
||||||
// test_delete_user must run as root since that's how we use the delete_as_user
|
// test_delete_user must run as root since that's how we use the delete_as_user
|
||||||
test_delete_user();
|
test_delete_user();
|
||||||
free_configurations();
|
free_executor_configurations();
|
||||||
|
|
||||||
printf("\nTrying banned default user()\n");
|
printf("\nTrying banned default user()\n");
|
||||||
if (write_config_file(TEST_ROOT "/test.cfg", 0) != 0) {
|
if (write_config_file(TEST_ROOT "/test.cfg", 0) != 0) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
read_config(TEST_ROOT "/test.cfg");
|
read_executor_config(TEST_ROOT "/test.cfg");
|
||||||
username = "bin";
|
username = "bin";
|
||||||
test_check_user(1);
|
test_check_user(1);
|
||||||
|
|
||||||
@ -963,6 +963,6 @@ int main(int argc, char **argv) {
|
|||||||
printf("\nFinished tests\n");
|
printf("\nFinished tests\n");
|
||||||
|
|
||||||
free(current_username);
|
free(current_username);
|
||||||
free_configurations();
|
free_executor_configurations();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user