EVOLUTION-MANAGER
Edit File: cpl_swift.cpp
/********************************************************************** * Project: CPL - Common Portability Library * Purpose: OpenStack Swift Object Storage routines * Author: Even Rouault <even.rouault at spatialys.com> * ********************************************************************** * Copyright (c) 2018, Even Rouault <even.rouault at spatialys.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINSwift IN THE SOFTWARE. ****************************************************************************/ #include "cpl_swift.h" #include "cpl_vsi_error.h" #include "cpl_http.h" #include "cpl_multiproc.h" // HOWTO setup a Docker-based SWIFT server: // https://github.com/MorrisJobke/docker-swift-onlyone //! @cond Doxygen_Suppress CPL_CVSID("$Id: cpl_swift.cpp cb24a371b2f1cce5b3f0090d14e6edca5aae7291 2018-03-15 14:22:59Z Even Rouault $") #ifdef HAVE_CURL static CPLMutex *g_hMutex = nullptr; static CPLString g_osLastAuthURL; static CPLString g_osLastUser; static CPLString g_osLastKey; static CPLString g_osLastStorageURL; static CPLString g_osLastAuthToken; /************************************************************************/ /* GetSwiftHeaders() */ /************************************************************************/ static struct curl_slist* GetSwiftHeaders( const CPLString& osAuthToken ) { struct curl_slist *headers=nullptr; headers = curl_slist_append( headers, "Accept: application/json"); headers = curl_slist_append( headers, CPLSPrintf("x-auth-token: %s", osAuthToken.c_str())); return headers; } /************************************************************************/ /* VSISwiftHandleHelper() */ /************************************************************************/ VSISwiftHandleHelper::VSISwiftHandleHelper(const CPLString& osStorageURL, const CPLString& osAuthToken, const CPLString& osBucket, const CPLString& osObjectKey) : m_osURL(BuildURL(osStorageURL, osBucket, osObjectKey)), m_osStorageURL(osStorageURL), m_osAuthToken(osAuthToken), m_osBucket(osBucket), m_osObjectKey(osObjectKey) { } /************************************************************************/ /* ~VSISwiftHandleHelper() */ /************************************************************************/ VSISwiftHandleHelper::~VSISwiftHandleHelper() { } /************************************************************************/ /* GetConfiguration() */ /************************************************************************/ bool VSISwiftHandleHelper::GetConfiguration(CPLString& osStorageURL, CPLString& osAuthToken) { osStorageURL = CPLGetConfigOption("SWIFT_STORAGE_URL", ""); if( !osStorageURL.empty() ) { osAuthToken = CPLGetConfigOption("SWIFT_AUTH_TOKEN", ""); if( osAuthToken.empty() ) { const char* pszMsg = "Missing SWIFT_AUTH_TOKEN"; CPLDebug("SWIFT", "%s", pszMsg); VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg); return false; } return true; } CPLString osAuthURL = CPLGetConfigOption("SWIFT_AUTH_V1_URL", ""); CPLString osUser = CPLGetConfigOption("SWIFT_USER", ""); CPLString osKey = CPLGetConfigOption("SWIFT_KEY", ""); if( osAuthURL.empty() || osUser.empty() || osKey.empty() ) { const char* pszMsg = "Missing SWIFT_STORAGE_URL+SWIFT_AUTH_TOKEN or " "SWIFT_AUTH_V1_URL+SWIFT_USER+SWIFT_KEY " "configuration options"; CPLDebug("SWIFT", "%s", pszMsg); VSIError(VSIE_AWSInvalidCredentials, "%s", pszMsg); return false; } // Re-use cached credentials if available { CPLMutexHolder oHolder( &g_hMutex ); // coverity[tainted_data] if( osAuthURL == g_osLastAuthURL && osUser == g_osLastUser && osKey == g_osLastKey ) { osStorageURL = g_osLastStorageURL; osAuthToken = g_osLastAuthToken; return true; } } char** papszHeaders = CSLSetNameValue(nullptr, "HEADERS", CPLSPrintf("X-Auth-User: %s\r\n" "X-Auth-Key: %s", osUser.c_str(), osKey.c_str())); CPLHTTPResult* psResult = CPLHTTPFetch(osAuthURL, papszHeaders); CSLDestroy(papszHeaders); if( psResult == nullptr ) return false; osStorageURL = CSLFetchNameValueDef(psResult->papszHeaders, "X-Storage-Url", ""); osAuthToken = CSLFetchNameValueDef(psResult->papszHeaders, "X-Auth-Token", ""); CPLString osErrorMsg = psResult->pabyData ? reinterpret_cast<const char*>(psResult->pabyData) : ""; CPLHTTPDestroyResult(psResult); if( osStorageURL.empty() || osAuthToken.empty() ) { CPLDebug("SWIFT", "Authentication failed: %s", osErrorMsg.c_str()); VSIError(VSIE_AWSInvalidCredentials, "Authentication failed: %s", osErrorMsg.c_str()); return false; } // Cache credentials { CPLMutexHolder oHolder( &g_hMutex ); g_osLastAuthURL = osAuthURL; g_osLastUser = osUser; g_osLastKey = osKey; g_osLastStorageURL = osStorageURL; g_osLastAuthToken = osAuthToken; } return true; } /************************************************************************/ /* BuildFromURI() */ /************************************************************************/ VSISwiftHandleHelper* VSISwiftHandleHelper::BuildFromURI( const char* pszURI, const char* /*pszFSPrefix*/ ) { CPLString osStorageURL; CPLString osAuthToken; if( !GetConfiguration(osStorageURL, osAuthToken) ) { return nullptr; } // pszURI == bucket/object const CPLString osBucketObject( pszURI ); CPLString osBucket(osBucketObject); CPLString osObjectKey; size_t nSlashPos = osBucketObject.find('/'); if( nSlashPos != std::string::npos ) { osBucket = osBucketObject.substr(0, nSlashPos); osObjectKey = osBucketObject.substr(nSlashPos+1); } return new VSISwiftHandleHelper( osStorageURL, osAuthToken, osBucket, osObjectKey ); } /************************************************************************/ /* BuildURL() */ /************************************************************************/ CPLString VSISwiftHandleHelper::BuildURL(const CPLString& osStorageURL, const CPLString& osBucket, const CPLString& osObjectKey) { CPLString osURL = osStorageURL; if( !osBucket.empty() ) osURL += "/" + CPLAWSURLEncode(osBucket,false); if( !osObjectKey.empty() ) osURL += "/" + CPLAWSURLEncode(osObjectKey,false); return osURL; } /************************************************************************/ /* RebuildURL() */ /************************************************************************/ void VSISwiftHandleHelper::RebuildURL() { m_osURL = BuildURL(m_osStorageURL, m_osBucket, m_osObjectKey); m_osURL += GetQueryString(false); } /************************************************************************/ /* GetCurlHeaders() */ /************************************************************************/ struct curl_slist * VSISwiftHandleHelper::GetCurlHeaders( const CPLString&, const struct curl_slist*, const void *, size_t ) const { return GetSwiftHeaders( m_osAuthToken ); } /************************************************************************/ /* CleanMutex() */ /************************************************************************/ void VSISwiftHandleHelper::CleanMutex() { if( g_hMutex != nullptr ) CPLDestroyMutex( g_hMutex ); g_hMutex = nullptr; } /************************************************************************/ /* ClearCache() */ /************************************************************************/ void VSISwiftHandleHelper::ClearCache() { CPLMutexHolder oHolder( &g_hMutex ); g_osLastAuthURL.clear(); g_osLastUser.clear(); g_osLastKey.clear(); g_osLastStorageURL.clear(); g_osLastAuthToken.clear(); } #endif //! @endcond