//------------------------------------------------------------------------------ //! file EosMgmHttpHandler.hh //------------------------------------------------------------------------------ /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2019 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #pragma once #include "XrdHttp/XrdHttpExtHandler.hh" #include "common/Logging.hh" #include "XrdVersion.hh" #include #include #include //! Forward declaration class XrdMgmOfs; class XrdAccAuthorize; class XrdSfsFileSystem; //------------------------------------------------------------------------------ //! Class EosMgmHttpHandler //------------------------------------------------------------------------------ class EosMgmHttpHandler: public XrdHttpExtHandler, public eos::common::LogId { public: using HdrsMapT = std::map; //---------------------------------------------------------------------------- //! Constructor //---------------------------------------------------------------------------- EosMgmHttpHandler() : mRedirectToHttps(false), mTokenHttpHandler(nullptr), mTokenAuthzHandler(nullptr), mMgmOfsHandler(nullptr) {} //---------------------------------------------------------------------------- //! Destructor //---------------------------------------------------------------------------- virtual ~EosMgmHttpHandler(); //---------------------------------------------------------------------------- //! Initialize the external request handler //! //! @param confg Name of the configuration file that was used //! //! @return 0 if successful, otherwise non-zero value //---------------------------------------------------------------------------- int Init(const char* confg) override { // We do the work in the Config method as we have all the parameters needed // there. return 0; } //---------------------------------------------------------------------------- //! Config the current request handler //! //! @param eDest -> The error object that must be used to print any errors or //! other messages (see XrdSysError.hh). //! @param confg -> Name of the configuration file that was used. This pointer //! may be null though that would be impossible. //! @param parms -> Argument string specified on the namelib directive. It may //! be null or point to a null string if no parms exist. //! @param myEnv -> Environment variables for configuring the external handler; //! it my be null. //! @return 0 if successful, otherwise non-zero value //---------------------------------------------------------------------------- int Config(XrdSysError* eDest, const char* confg, const char* parms, XrdOucEnv* myEnv); //---------------------------------------------------------------------------- //! Tells if the incoming path is recognizsed by the current plugin as one //! that needs to be processed. //! //! @param verb HTTP verb //! @param path request path //! //! @return true if current handler is to be invoked, otherwise false //---------------------------------------------------------------------------- bool MatchesPath(const char* verb, const char* path) override; //---------------------------------------------------------------------------- //! Process the HTTP request and send the response using by calling the //! XrdHttpProtocol directly //! //! @param req HTTP request //! //! @return 0 if successful, otherwise non-0 //---------------------------------------------------------------------------- int ProcessReq(XrdHttpExtReq& req) override; private: #ifdef IN_TEST_HARNESS public: #endif bool mRedirectToHttps; ///< Flag if http traffic should be redirected to https XrdHttpExtHandler* mTokenHttpHandler; ///< Macaroons ext http handler //! Authz plugin from libMacaroons/libXrdSciTokens XrdAccAuthorize* mTokenAuthzHandler; XrdMgmOfs* mMgmOfsHandler; ///< Pointer to the MGM OFS plugin //! Url to access rest api grpc-gateway const char* mRestApiGwUrl = "http://localhost:40054"; //! Path to rest api grpc-gateway const char* mRestApiGwPath = "/v1/eos/rest/gateway/"; //---------------------------------------------------------------------------- //! Copy XrdSecEntity info //! //! @param src source info //! @param dst newly populated objed //---------------------------------------------------------------------------- void CopyXrdSecEntity(const XrdSecEntity& src, XrdSecEntity& dst) const; //---------------------------------------------------------------------------- //! Get OFS library path from the given configuration //! //! @param cfg_line relevant config line from file i.e xrd.cf.mgm //! //! @return string representing the OFS library //---------------------------------------------------------------------------- std::string GetOfsLibPath(const std::string& cfg_line); //---------------------------------------------------------------------------- //! Get XrdHttpExHandler library path from the given configuration //! //! @param cfg_line relevant config line from file i.e xrd.cf.mgm //! //! @return string representing the OFS library //---------------------------------------------------------------------------- std::string GetHttpExtLibPath(const std::string& cfg_line); //---------------------------------------------------------------------------- //! Get list of external authorization libraries present in the configuration. //! If multiple are present then the order is kept to properly apply chaining //! to these libraries. //! //! @param cfg_line relevant config line from file i.e xrd.cf.mgm //! //! @return list of external authorization libraries configured //---------------------------------------------------------------------------- std::list GetAuthzLibPaths(const std::string& cfg_line); //---------------------------------------------------------------------------- //! Get a pointer to the MGM OFS plugin //! //! @param eDest error object that must be used to print any errors or msgs //! @param lib_path library path //! @param confg configuration file path //! //! @return true if successful, otherwise false //---------------------------------------------------------------------------- XrdMgmOfs* GetOfsPlugin(XrdSysError* eDest, const std::string& lib_path, const char* confg); //---------------------------------------------------------------------------- //! Get a pointer to the XrdHttpExtHandler plugin //! //! @param eDest error object that must be used to print any errors or msgs //! @param lib_path library path //! @param confg configuration file path //! @param myEnv environment variables for configuring the external handler; //! it my be null. //! //! @return true if successful, otherwise false //---------------------------------------------------------------------------- XrdHttpExtHandler* GetHttpExtPlugin(XrdSysError* eDest, const std::string& lib_path, const char* confg, XrdOucEnv* myEnv); //---------------------------------------------------------------------------- //! Get a pointer to the XrdAccAuthorize plugin present in the given library //! //! @param eDest error object that must be used to print any errors or msgs //! @param lib_path library path //! @param confg configuration file path //! @param myEnv environment variables for configuring the external handler; //! it may be null. //! @param to_chain XrdAccAuthorize plugin to chain to the newly loaded //! authorization plugin //! //! @return true if successful, otherwise false //---------------------------------------------------------------------------- XrdAccAuthorize* GetAuthzPlugin(XrdSysError* eDest, const std::string& lib_path, const char* confg, XrdOucEnv* myEnv, XrdAccAuthorize* to_chain); //---------------------------------------------------------------------------- //! Reads the body of the XrdHttpExtReq object and put it in the //! body string //! //! @param req the request from which we will read the body content from //! @param body, the string where the body from the request will be put on //! //! @return a return code if there was an error during the reading. Nothing //! otherwise, hence the optional. //---------------------------------------------------------------------------- std::optional readBody(XrdHttpExtReq& req, std::string& body); //---------------------------------------------------------------------------- //! Returns true if the request is a macaroon token request //! false otherwise //! @param req the request from which we will read the header and the HTTP verb //! //! @return true if the request is a macaroon token request, false otherwise //---------------------------------------------------------------------------- bool IsMacaroonRequest(const XrdHttpExtReq& req) const; //---------------------------------------------------------------------------- //! Process macaroon POST request //! //! @param req XrdHttp request object //! //! @return 0 if successful, otherwise non-0 //---------------------------------------------------------------------------- int ProcessMacaroonPOST(XrdHttpExtReq& req); //---------------------------------------------------------------------------- //! Returns true if the request is a rest api gateway token request //! false otherwise //! @param req the request from which we will read the header and the HTTP verb //! //! @return true if the request is a macaroon token request, false otherwise //---------------------------------------------------------------------------- bool IsRestApiRequest(const XrdHttpExtReq& req) const; //---------------------------------------------------------------------------- //! Process REST API gateway POST request //! //! @param req XrdHttp request object //! @param norm_hdrs normalized headers from the HTTP request //! //! @return 0 if successful, otherwise non-0 //---------------------------------------------------------------------------- int ProcessRestApiPost(XrdHttpExtReq& req, const HdrsMapT& norm_hdrs); //---------------------------------------------------------------------------- //! Forward the authentication relevant info as custom headers to the //! GRPC-gateway that will then send them further down to the GRPC server //! //! @note All appened headers need to start with the Grpc-Metadata- prefix //! so that they are forwarded by the GRPC gateway otherwise they will just //! be discarded! //! //! @param curl CURL handler where headers are appended //! @param client XrdSecEntity object from which information is extracted //! @param norm_hdrs normalized headers from the HTTP request //! //! @return true if successful, otherwise false //---------------------------------------------------------------------------- bool RestApiGwFrwAuthHeaders(CURL* curl, const XrdSecEntity& client, const HdrsMapT& norm_hdrs); //---------------------------------------------------------------------------- //! Function used to handle responses from grpc server //! //! @param contents pointer to the data received from the grpc server //! @param size the size of each data element received //! @param nmemb the number of data elements received //! @param output buffer where the received data from an HTTP response is //! stored //! //! @return number of bytes received if successful, otherwise non-0 //---------------------------------------------------------------------------- static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output); };