diff --git a/CrestApi/CrestApi.h b/CrestApi/CrestApi.h index fcf7602c996d4a518c3fbbc77c2df656cfd5e00a..f6c0118a74bb76d60e821c4add1a1f287a4adb3b 100644 --- a/CrestApi/CrestApi.h +++ b/CrestApi/CrestApi.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2019-2023 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2019-2022 CERN for the benefit of the ATLAS collaboration */ @@ -132,6 +132,8 @@ namespace Crest { inline static const std::string s_CREST_CLIENT_VERSION = "4.0"; inline static const std::string s_MGMT_INFO_PATH_2 = "/actuator/info"; + inline static const bool s_CREST_AUTH = true; + enum CrestMode { SERVER_MODE = 1, FILESYSTEM_MODE = 2 }; @@ -861,7 +863,7 @@ namespace Crest { * json tag_info28 = myCrestClientF.findRunLumiInfo(params28); * </pre> */ - nlohmann::json findRunLumiInfo(const urlParameters& params); + nlohmann::json findRunLumiInfo(urlParameters params); /** @@ -1608,6 +1610,10 @@ namespace Crest { */ void checkCrestVersion2(); + //NEW methods: + + std::string getFileAsString(const std::string& path); + }; } // namespace diff --git a/scripts/curl-gettoken.sh b/scripts/curl-gettoken.sh new file mode 100644 index 0000000000000000000000000000000000000000..8cc19907cdea2ade17202e57c1162c922df0ae08 --- /dev/null +++ b/scripts/curl-gettoken.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +DEFAULT_AUTH_DOMAIN="auth.cern.ch/auth/realms/cern" +DEFAULT_AUTH_AUDIENCE="crest-server" +DEFAULT_CLIENT_ID="crest-client" +read -p "User: " usr +read -s -p "Password: " pss + +DIRECT_GRANT_RESPONSE=`curl -X POST "https://auth.cern.ch/auth/realms/cern/protocol/openid-connect/token" -H "Content-Type: application/x-www-form-urlencoded" -d "username=${usr}" -d "password=${pss}" -d "grant_type=password" -d "scope=openid" -d "client_id=crest-client"` + + +export ACCESS_TOKEN=$(echo $DIRECT_GRANT_RESPONSE | grep "access_token" | sed 's/.*\"access_token\":\"\([^\"]*\)\".*/\1/g'); + +startclientid=$DEFAULT_CLIENT_ID +subjtoken=$ACCESS_TOKEN +targetclientid=$DEFAULT_AUTH_AUDIENCE +DIRECT_GRANT_RESPONSE=`curl -X POST -d "client_id=${startclientid}" --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" -d "subject_token=${subjtoken}" --data-urlencode "requested_token_type=urn:ietf:params:oauth:token-type:refresh_token" -d "audience=${targetclientid}" https://auth.cern.ch/auth/realms/cern/protocol/openid-connect/token` + +export ACCESS_TOKEN=$(echo $DIRECT_GRANT_RESPONSE | grep "access_token" | sed 's/.*\"access_token\":\"\([^\"]*\)\".*/\1/g'); +echo -e "\n\nACCESS TOKEN IS \"$ACCESS_TOKEN\""; + +export AUTH_HEADER="\"Authorization: Bearer ${ACCESS_TOKEN}\"" +echo -e "\n\nHeader is $AUTH_HEADER" + +echo "Saving in: $PWD/.client-exchange-token.json" +echo ${ACCESS_TOKEN} > $PWD/.client-exchange-token.json diff --git a/setup.sh b/setup.sh index c3f76ff50f9b2f7e6a00b1556e200986f3e73dfc..8b0dc36cc541f89feccdb8e1dab322075a764651 100644 --- a/setup.sh +++ b/setup.sh @@ -2,6 +2,6 @@ export AtlasSetup=/afs/cern.ch/atlas/software/dist/AtlasSetup alias asetup='source $AtlasSetup/scripts/asetup.sh' # asetup 22.0.0,Athena # asetup 22.0.1,Athena -asetup 22.0.14,Athena +asetup 22.0.14,Athena # # asetup 22.0.20,Athena # asetup master,latest,Athena diff --git a/src/CrestApi.cxx b/src/CrestApi.cxx index d945649c22312e8c0c4f6496b890209dc4e98ca3..774078e35c7c52ce4c0d5bc6fa64491ad84a034e 100644 --- a/src/CrestApi.cxx +++ b/src/CrestApi.cxx @@ -85,6 +85,7 @@ namespace Crest { std::string CrestClient::make_url(const std::string &address) const{ std::string str("http://"); + if (s_CREST_AUTH == true) str = "https://"; str += m_host; str += ':'; str += m_port; @@ -1207,7 +1208,7 @@ namespace Crest { retv = performRequest(current_path, POST, body, method_name); } - nlohmann::json CrestClient::findRunLumiInfo(const urlParameters& params) { + nlohmann::json CrestClient::findRunLumiInfo(urlParameters params) { const char* method_name = "CrestClient::findRunLumiInfo"; checkFsException(method_name); @@ -1267,7 +1268,7 @@ namespace Crest { return newLength; } - + // std::string CrestClient::performRequest(const std::string& current_path, Action action, nlohmann::json& js, const char* method_name) { CURL* curl; @@ -1299,13 +1300,40 @@ namespace Crest { headers = curl_slist_append(headers, "Content-Type: application/json"); headers = curl_slist_append(headers, "Expect:"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_POST, 1L); /* set where to read from (on Windows you need to use READFUNCTION too) */ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, stt.c_str()); } + // MvG + if (s_CREST_AUTH == true){ + // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + // curl_easy_setopt(curl, CURLOPT_HEADER, 1); + + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + + std::string cert = getFileAsString("./.client-exchange-token.json"); + + while ( cert.find ("\n") != std::string::npos ){ + cert.erase ( cert.find ("\n"), 1 ); + } + + // std::cout << "certificate = " << cert << std::endl; + std::string auth = "Authorization: Bearer " + cert; + // const char * c = auth.c_str(); + // std::cout << "authorization code = " << c << std::endl; + headers = curl_slist_append(headers, auth.c_str()); + // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + // MvG (end) + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); @@ -1327,11 +1355,14 @@ namespace Crest { // error checking in the server response: checkResult(res, response_code, s, method_name); + // std::cout << "\n (RESULT) s = " << s << std::endl; + return s; } throw std::runtime_error(std::string("ERROR in ") + std::string(method_name) + " | CURL not init"); } + // // REQUEST OLD VERSION @@ -1504,6 +1535,30 @@ namespace Crest { headers = curl_slist_append(headers, "Accept: */*"); headers = curl_slist_append(headers, "Content-Type: multipart/form-data"); + // MvG + if (s_CREST_AUTH == true){ + // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + // curl_easy_setopt(curl, CURLOPT_HEADER, 1); + + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + + std::string cert = getFileAsString("./.client-exchange-token.json"); + + while ( cert.find ("\n") != std::string::npos ){ + cert.erase ( cert.find ("\n"), 1 ); + } + + std::string auth = "Authorization: Bearer " + cert; + headers = curl_slist_append(headers, auth.c_str()); + // curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + } + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + // MvG (end) + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Create the form for new version @@ -1633,8 +1688,16 @@ namespace Crest { void CrestClient::checkResult(CURLcode res, const long response_code, const std::string& st, const char* method_name) { - // Bad HTTP response: + /* + std::cout << "\n res = " << res << std::endl; + std::cout << "\n response_code = aaa" << response_code << "bbb" << std::endl; + std::cout << "\n st = " << st << std::endl; + */ + + //std::cout << "\n A: \n"; + + // Bad HTTP response: if (res != CURLE_OK) { std::string mes = "ERROR in "; mes += method_name; @@ -1642,16 +1705,33 @@ namespace Crest { throw std::runtime_error(mes + std::to_string(response_code)); } - // Errors, decoded from JSON CREST Server messages: + // std::cout << "\n B: \n"; + // Errors, decoded from JSON CREST Server messages: if (isJson(st)) { nlohmann::json respond = getJson(st); checkErrors(respond, method_name); } - // HTTP response code error interval: + // std::cout << "\n C: \n"; - if (response_code >= 400 || response_code == 303) { + + // MvG 2 + // HTTP response code error interval: + if (response_code == 400){ + std::string mes = "ERROR in "; + mes += method_name; + mes += " | Bad Request"; + throw std::runtime_error(mes); + } + else if (response_code == 401){ + std::string mes = "ERROR in "; + mes += method_name; + mes += " | Unauthorized"; + throw std::runtime_error(mes); + } + else if (response_code >= 402 || response_code == 303) { + // std::cout << "\n D: \n"; std::string s = ParseXMLOutput(st); // to remove HTML tags s = removeCR(s); // to remove end lines and carridge returns std::string mes = "ERROR in "; @@ -2834,4 +2914,17 @@ namespace Crest { } } +std::string CrestClient::getFileAsString(const std::string& path) { + try{ + std::ifstream ifs(path); + return std::string((std::istreambuf_iterator<char>(ifs)), + (std::istreambuf_iterator<char>())); + } + catch (const std::exception& e) { + // std::cout << std::endl << "test: getTagDataInfo (failed)" << std::endl; + // std::cout << e.what() << std::endl; + throw(std::runtime_error("Error in CrestClient::getFileAsString: cannot read a file " + path)); + } +} + } // namespace