From 08e30193b67b00c67c1782a8596231a110404d12 Mon Sep 17 00:00:00 2001 From: Alan King Date: Thu, 9 Jan 2025 10:54:43 -0500 Subject: [PATCH] [#164,#189,#273] Run all storage tiering ops as admin This commit makes a couple of changes: 1. Added proxy_connection::make_rodsadmin_connection. This function simply establishes a client connection as the local service account rodsadmin. Importantly, it also sets the authFlag in the created RcComm in order to appropriately indicate the privilege level of the client user. 2. All instances of establishing a connection with the local server to perform actions have been replaced with connections as the local service account rodsadmin. This allows storage tiering to do its job properly without needing to worry about user permissions. Note: Violating queries still select the USER_NAME and USER_ZONE, but they are no longer used. --- .../storage_tiering/proxy_connection.hpp | 57 +++++++++++++---- src/main.cpp | 64 ++++++++----------- src/storage_tiering.cpp | 43 ++++++------- 3 files changed, 89 insertions(+), 75 deletions(-) diff --git a/include/irods/private/storage_tiering/proxy_connection.hpp b/include/irods/private/storage_tiering/proxy_connection.hpp index d133b23..4ccba69 100644 --- a/include/irods/private/storage_tiering/proxy_connection.hpp +++ b/include/irods/private/storage_tiering/proxy_connection.hpp @@ -9,30 +9,59 @@ namespace irods { rErrMsg_t err_msg; rcComm_t* conn; - auto make(const std::string clientUser = "", const std::string clientZone = "") -> rcComm_t* + // Makes a proxy connection where the client is specified by the username in the parameters, and the proxy user + // is the service account rodsadmin for the local server. + auto make(const std::string& clientUser, const std::string& clientZone) -> rcComm_t* { rodsEnv env{}; _getRodsEnv(env); - conn = _rcConnect( - env.rodsHost, - env.rodsPort, - env.rodsUserName, - env.rodsZone, - !clientUser.empty() ? - clientUser.c_str() : - env.rodsUserName, - !clientZone.empty() ? - clientZone.c_str() : - env.rodsZone, - &err_msg, - 0, 0); + // TODO(#296): Handle any errors which occur in _rcConnect or clientLogin. + conn = _rcConnect(env.rodsHost, + env.rodsPort, + env.rodsUserName, + env.rodsZone, + clientUser.c_str(), + clientZone.c_str(), + &err_msg, + 0, + 0); clientLogin(conn); return conn; } // make + // Makes a proxy connection where both the proxy and client users are the service account rodsadmin for the + // local server. + auto make_rodsadmin_connection() -> RcComm* + { + rodsEnv env{}; + _getRodsEnv(env); + + // TODO(#296): Handle any errors which occur in _rcConnect or clientLogin. + conn = _rcConnect(env.rodsHost, + env.rodsPort, + env.rodsUserName, + env.rodsZone, + env.rodsUserName, + env.rodsZone, + &err_msg, + 0, + 0); + + clientLogin(conn); + + // Set the authFlag because auth plugin does not set it and the storage tiering plugin needs to know whether + // the client connection is privileged. This proxy connection uses the local client environment which should + // be the iRODS service account, a rodsadmin. If the local client environment is not a rodsadmin, the plugin + // will not function properly because it uses the ADMIN_KW and the server does not allow non-rodsadmins to + // use the ADMIN_KW. + conn->clientUser.authInfo.authFlag = LOCAL_PRIV_USER_AUTH; + + return conn; + } // make_rodsadmin_connection + ~proxy_connection() { rcDisconnect(conn); } }; // proxy_connection diff --git a/src/main.cpp b/src/main.cpp index 96e4f8f..70411f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,6 @@ #include #include "irods/private/storage_tiering/data_verification_utilities.hpp" #include -#include "irods/private/storage_tiering/exec_as_user.hpp" #include #include @@ -128,7 +127,7 @@ namespace { addKeyVal(&data_obj_inp.condInput, DEST_RESC_NAME_KW, _destination_resource.c_str()); if(_comm->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) { - addKeyVal(&data_obj_inp.condInput, ADMIN_KW, "true" ); + addKeyVal(&data_obj_inp.condInput, ADMIN_KW, ""); } transferStat_t* trans_stat{}; @@ -167,10 +166,7 @@ namespace { COPIES_KW, "1"); if(_comm->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) { - addKeyVal( - &obj_inp.condInput, - ADMIN_KW, - "true" ); + addKeyVal(&obj_inp.condInput, ADMIN_KW, ""); } const auto trim_err = rcDataObjTrim(_comm, &obj_inp); @@ -453,7 +449,7 @@ namespace { parser.first_resc(source_resource); auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make(_rei->rsComm->clientUser.userName, _rei->rsComm->clientUser.rodsZone); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); irods::storage_tiering st{comm, _rei, plugin_instance_name}; @@ -502,7 +498,7 @@ namespace { auto [object_path, resource_name] = opened_objects[l1_idx]; auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make(_rei->rsComm->clientUser.userName, _rei->rsComm->clientUser.rodsZone); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); irods::storage_tiering st{comm, _rei, plugin_instance_name}; st.migrate_object_to_minimum_restage_tier( @@ -689,7 +685,7 @@ irods::error exec_rule_text( delay_obj["storage-tier-groups"] = rule_obj["storage-tier-groups"]; auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make(); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); irods::storage_tiering st{comm, rei, plugin_instance_name}; st.schedule_storage_tiering_policy( @@ -749,7 +745,7 @@ irods::error exec_rule_expression( irods::storage_tiering::policy::storage_tiering == rule_obj.at("rule-engine-operation")) { try { auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make(); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); irods::storage_tiering st{comm, rei, plugin_instance_name}; for(const auto& group : rule_obj["storage-tier-groups"]) { @@ -773,34 +769,30 @@ irods::error exec_rule_expression( auto& pin = plugin_instance_name; auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make( rule_obj["user-name"], rule_obj["user-zone"]); - - auto status = irods::exec_as_user(comm, user_name, user_zone, [& pin, & rule_obj](auto& comm) -> int{ - return apply_data_movement_policy( - comm, - plugin_instance_name, - rule_obj["object-path"], - rule_obj["user-name"], - rule_obj["user-zone"], - rule_obj["source-replica-number"], - rule_obj["source-resource"], - rule_obj["destination-resource"], - rule_obj["preserve-replicas"], - rule_obj["verification-type"]); - }); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); + + // TODO(#297): Use get or get_ref for these parameters. + auto status = apply_data_movement_policy(comm, + plugin_instance_name, + rule_obj["object-path"], + rule_obj["user-name"], + rule_obj["user-zone"], + rule_obj["source-replica-number"], + rule_obj["source-resource"], + rule_obj["destination-resource"], + rule_obj["preserve-replicas"], + rule_obj["verification-type"]); irods::storage_tiering st{comm, rei, plugin_instance_name}; - status = irods::exec_as_user(comm, user_name, user_zone, [& st, & rule_obj](auto& comm) -> int{ - return apply_tier_group_metadata_policy( - st, - rule_obj["group-name"], - rule_obj["object-path"], - rule_obj["user-name"], - rule_obj["user-zone"], - rule_obj["source-replica-number"], - rule_obj["source-resource"], - rule_obj["destination-resource"]); - }); + // TODO(#297): Use get or get_ref for these parameters. + status = apply_tier_group_metadata_policy(st, + rule_obj["group-name"], + rule_obj["object-path"], + rule_obj["user-name"], + rule_obj["user-zone"], + rule_obj["source-replica-number"], + rule_obj["source-resource"], + rule_obj["destination-resource"]); } catch(const irods::exception& _e) { printErrorStack(&rei->rsComm->rError); diff --git a/src/storage_tiering.cpp b/src/storage_tiering.cpp index accded9..1632008 100644 --- a/src/storage_tiering.cpp +++ b/src/storage_tiering.cpp @@ -22,7 +22,6 @@ #include "irods/private/storage_tiering/data_verification_utilities.hpp" -#include "irods/private/storage_tiering/exec_as_user.hpp" #include #include @@ -626,7 +625,7 @@ namespace irods { object_is_processed[object_path] = 1; auto proxy_conn = irods::proxy_connection(); - rcComm_t* comm = proxy_conn.make(_results[2], _results[3]); + rcComm_t* comm = proxy_conn.make_rodsadmin_connection(); if(preserve_replicas) { if(skip_object_in_lower_tier( @@ -979,14 +978,12 @@ namespace irods { const_cast(access_time.c_str()), const_cast(config_.migration_scheduled_flag.c_str())}; - auto status = exec_as_user(_comm, _user_name, _user_zone, [&set_op](auto comm) -> int { - return rcModAVUMetadata(comm, &set_op); - }); - if(status < 0) { - THROW( - status, - boost::format("failed to set migration scheduled flag for [%s]") - % _object_path); + if (_comm->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) { + addKeyVal(&set_op.condInput, ADMIN_KW, ""); + } + + if (const auto ec = rcModAVUMetadata(_comm, &set_op); ec < 0) { + THROW(ec, fmt::format("failed to set migration scheduled flag for [{}]", _object_path)); } } // set_migration_metadata_flag_for_object @@ -1007,16 +1004,13 @@ namespace irods { const_cast(access_time.c_str()), nullptr}; - const auto status = exec_as_user(_comm, _user_name, _user_zone, [&set_op](auto comm) -> int { - return rcModAVUMetadata(comm, &set_op); - }); - if(status < 0) { - THROW( - status, - boost::format("failed to unset migration scheduled flag for [%s]") - % _object_path); + if (_comm->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) { + addKeyVal(&set_op.condInput, ADMIN_KW, ""); } + if (const auto ec = rcModAVUMetadata(_comm, &set_op); ec < 0) { + THROW(ec, fmt::format("failed to unset migration scheduled flag for [{}]", _object_path)); + } } // unset_migration_metadata_flag_for_object bool storage_tiering::object_has_migration_metadata_flag( @@ -1036,13 +1030,8 @@ namespace irods { % data_name % coll_name) }; - const auto status = exec_as_user(_comm, _user_name, _user_zone, [& query_str](auto& _comm) -> int { - query qobj{_comm, query_str, 1}; - return qobj.size(); - }); - - return status > 0; - + query qobj{_comm, query_str, 1}; + return qobj.size() > 0; } // object_has_migration_metadata_flag void storage_tiering::apply_tier_group_metadata_to_object( @@ -1073,6 +1062,10 @@ namespace irods { const_cast(_group_name.c_str()), const_cast(destination_replica_number.c_str())}; + if (comm_->clientUser.authInfo.authFlag >= LOCAL_PRIV_USER_AUTH) { + addKeyVal(&set_op.condInput, ADMIN_KW, ""); + } + auto status = rcModAVUMetadata(comm_, &set_op); if(status < 0) { THROW(