From 9c575ee4e394f31cc58b186ffd1f5c35c9e161ff Mon Sep 17 00:00:00 2001 From: Danny Auble <da@schedmd.com> Date: Fri, 19 Dec 2014 10:18:54 -0800 Subject: [PATCH] Improve security for a coordinator so they can only give access to the QOS they have access to in the account they are coordinator over. --- .../accounting_storage/mysql/as_mysql_assoc.c | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/src/plugins/accounting_storage/mysql/as_mysql_assoc.c b/src/plugins/accounting_storage/mysql/as_mysql_assoc.c index 4a0d5751540..6fa08bbf705 100644 --- a/src/plugins/accounting_storage/mysql/as_mysql_assoc.c +++ b/src/plugins/accounting_storage/mysql/as_mysql_assoc.c @@ -264,6 +264,66 @@ end_it: return rc; } +/* assoc_mgr_lock_t should be clear before coming in here. */ +static int _check_coord_qos(mysql_conn_t *mysql_conn, char *cluster_name, + char *account, char *coord_name, List qos_list) +{ + char *query; + bitstr_t *request_qos, *valid_qos; + MYSQL_RES *result; + MYSQL_ROW row; + int rc = SLURM_SUCCESS; + assoc_mgr_lock_t locks = { NO_LOCK, NO_LOCK, READ_LOCK, + NO_LOCK, NO_LOCK, NO_LOCK }; + + if (!qos_list || !list_count(qos_list)) + return SLURM_SUCCESS; + + /* If there is a variable cleared here we need to make + sure we get the parent's information, if any. */ + query = xstrdup_printf( + "call get_coord_qos('%s', '%s', '%s', '%s');", + assoc_table, account, + cluster_name, coord_name); + debug4("%d(%s:%d) query\n%s", + mysql_conn->conn, THIS_FILE, __LINE__, query); + if (!(result = mysql_db_query_ret(mysql_conn, query, 1))) { + xfree(query); + return SLURM_ERROR; + } + xfree(query); + + if (!(row = mysql_fetch_row(result)) || !row[0]) { + mysql_free_result(result); + return SLURM_ERROR; + } + + /* First set the values of the valid ones this coordinator has + access to. + */ + + assoc_mgr_lock(&locks); + valid_qos = bit_alloc(g_qos_count); + request_qos = bit_alloc(g_qos_count); + assoc_mgr_unlock(&locks); + + set_qos_bitstr_from_string(valid_qos, row[0]); + + mysql_free_result(result); + + /* Now set the ones they are requesting */ + set_qos_bitstr_from_list(request_qos, qos_list); + + /* If they are authorized their list should be in the super set */ + if (!bit_super_set(request_qos, valid_qos)) + rc = SLURM_ERROR; + + FREE_NULL_BITMAP(valid_qos); + FREE_NULL_BITMAP(request_qos); + + return rc; +} + /* This needs to happen to make since 2.1 code doesn't have enough * smarts to figure out it isn't adding a default account if just * adding an association to the mix. @@ -1476,6 +1536,28 @@ static int _process_modify_assoc_results(mysql_conn_t *mysql_conn, rc = ESLURM_ACCESS_DENIED; goto end_it; + } else if (_check_coord_qos(mysql_conn, cluster_name, + account, user->name, + assoc->qos_list) + == SLURM_ERROR) { + assoc_mgr_lock_t locks = { + NO_LOCK, NO_LOCK, READ_LOCK, + NO_LOCK, NO_LOCK, NO_LOCK }; + char *requested_qos; + + assoc_mgr_lock(&locks); + requested_qos = get_qos_complete_str( + assoc_mgr_qos_list, assoc->qos_list); + assoc_mgr_unlock(&locks); + error("Coordinator %s(%d) does not have the " + "access to all the qos requested (%s), " + "so they can't modify account " + "%s with it.", + user->name, user->uid, requested_qos, + account); + xfree(requested_qos); + rc = ESLURM_ACCESS_DENIED; + goto end_it; } } @@ -2440,6 +2522,7 @@ extern int as_mysql_add_assocs(mysql_conn_t *mysql_conn, uint32_t uid, char *last_parent = NULL, *last_cluster = NULL; List local_cluster_list = NULL; List added_user_list = NULL; + bool is_coord = false; if (!assoc_list) { error("No association list given"); @@ -2489,6 +2572,7 @@ extern int as_mysql_add_assocs(mysql_conn_t *mysql_conn, uint32_t uid, user.name, user.uid); return ESLURM_ACCESS_DENIED; } + is_coord = true; } local_cluster_list = list_create(NULL); @@ -2506,6 +2590,30 @@ extern int as_mysql_add_assocs(mysql_conn_t *mysql_conn, uint32_t uid, continue; } + if (is_coord && _check_coord_qos(mysql_conn, object->cluster, + object->acct, user_name, + object->qos_list) + == SLURM_ERROR) { + assoc_mgr_lock_t locks = { + NO_LOCK, NO_LOCK, READ_LOCK, + NO_LOCK, NO_LOCK, NO_LOCK }; + char *requested_qos; + + assoc_mgr_lock(&locks); + requested_qos = get_qos_complete_str( + assoc_mgr_qos_list, object->qos_list); + assoc_mgr_unlock(&locks); + error("Coordinator %s(%d) does not have the " + "access to all the qos requested (%s), " + "so they can't add to account " + "%s with it.", + user_name, uid, requested_qos, + object->acct); + xfree(requested_qos); + rc = ESLURM_ACCESS_DENIED; + break; + } + /* When adding if this isn't a default might as well force it to be 0 to avoid confusion since uninitialized it is NO_VAL. -- GitLab