Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: CPL - Common Portability Library 4 : * Purpose: Implement credential provider for accessing NASA Earthdata resources 5 : * Author: Even Rouault, even.rouault at spatialys.com 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2026, Even Rouault <even.rouault at spatialys.com> 9 : * 10 : * SPDX-License-Identifier: MIT 11 : ****************************************************************************/ 12 : 13 : #ifndef CPL_NASA_EARTHDATA_H 14 : #define CPL_NASA_EARTHDATA_H 15 : 16 : #ifdef HAVE_CURL 17 : 18 : #include <memory> 19 : #include <mutex> 20 : #include <string> 21 : 22 : /************************************************************************/ 23 : /* CPLNasaEarthdataCredentialProvider */ 24 : /************************************************************************/ 25 : 26 : // Cf https://earthaccess.readthedocs.io/en/latest/user/authenticate/ 27 : // and https://developmentseed.org/obstore/latest/api/auth/earthdata/ 28 : 29 : /** Credential provider for accessing NASA Earthdata resources with /vsis3/ 30 : */ 31 7 : class CPLNasaEarthdataCredentialProvider 32 : { 33 : public: 34 : /** Builds a new credential provider instance. 35 : * 36 : * Users generally want to use GetNasaEarthdataCredentialProviderFor() instead 37 : * that calls Build() with values from the environment. 38 : * 39 : * @param osGetCredentialsURL URL that returns a JSON document with S3 40 : * temporary credentials. Required 41 : * e.g. "https://data.asdc.earthdata.nasa.gov/s3credentials" 42 : * @param osEarthdataHost Hostname for NASA Earthdata authentication. 43 : * If empty, defaults to "urs.earthdata.nasa.gov" 44 : * @param osEarthdataToken Access token to osGetCredentialsURL obtained from osEarthdataHost 45 : * @param osEarthdataUsername Login to osEarthdataHost 46 : * @param osEarthdataPassword Password to osEarthdataHost 47 : * @param osNetrcFilename Full path to ".netrc" / "_netrc" file 48 : * 49 : * @return thread-safe new instance, or nullptr. 50 : */ 51 : static std::unique_ptr<CPLNasaEarthdataCredentialProvider> 52 : Build(const std::string &osGetCredentialsURL, 53 : const std::string &osEarthdataHost = std::string(), 54 : const std::string &osEarthdataToken = std::string(), 55 : const std::string &osEarthdataUsername = std::string(), 56 : const std::string &osEarthdataPassword = std::string(), 57 : const std::string &osNetrcFilename = std::string()); 58 : 59 : /** Returns a (cached) instance corresponding to /vsis3/ osFilename. 60 : * 61 : * Takes into account the following path-specific / configuration options: 62 : * 63 : * - VSIS3_EARTHDATA_CREDENTIALS_URL: Setting this one is required. 64 : * e.g. https://data.asdc.earthdata.nasa.gov/s3credentials . 65 : * - DEFAULT_EARTHDATA_HOST / EARTHDATA_HOST: defaults to "urs.earthdata.nasa.gov" 66 : * - EARTHDATA_TOKEN: access token to the URL pointed by VSIS3_EARTHDATA_CREDENTIALS_URL 67 : * - EARTHDATA_USERNAME + EARTHDATA_PASSWORD: alternate way of getting EARTHDATA_TOKEN 68 : * 69 : * @return thread-safe cached instance, or nullptr if VSIS3_EARTHDATA_CREDENTIALS_URL 70 : * is not set, or nullptr in case of error 71 : */ 72 : static std::shared_ptr<CPLNasaEarthdataCredentialProvider> 73 : Get(const std::string &osFilename, bool *pbErrorOccurred = nullptr); 74 : 75 : /** Returns S3 access key id, or empty string if invalid. 76 : * 77 : * This method takes care of refreshing credentials if needed. 78 : */ 79 15 : const std::string &GetAccessKeyId() 80 : { 81 15 : RefreshIfNeeded(); 82 15 : return m_osAccessKeyId; 83 : } 84 : 85 : /** Returns S3 secret access key, or empty string if invalid. 86 : * 87 : * This method takes care of refreshing credentials if needed. 88 : */ 89 15 : const std::string &GetSecretAccessKey() 90 : { 91 15 : RefreshIfNeeded(); 92 15 : return m_osSecretAccessKey; 93 : } 94 : 95 : /** Returns S3 session token, or empty string if invalid. 96 : * 97 : * This method takes care of refreshing credentials if needed. 98 : */ 99 15 : const std::string &GetSessionToken() 100 : { 101 15 : RefreshIfNeeded(); 102 15 : return m_osSessionToken; 103 : } 104 : 105 : /** Clear credentials cache */ 106 : static void ClearCache(); 107 : 108 : private: 109 : CPLNasaEarthdataCredentialProvider(); 110 : 111 : bool RefreshIfNeeded(); 112 : 113 : std::string m_osGetCredentialsURL{}; 114 : std::string m_osEarthdataToken{}; 115 : 116 : // Output of RefreshIfNeeded() 117 : std::mutex m_oMutex{}; 118 : std::string m_osAccessKeyId{}; 119 : std::string m_osSecretAccessKey{}; 120 : std::string m_osSessionToken{}; 121 : GIntBig m_nTokenExpirationTimestamp = 0; 122 : }; 123 : 124 : #endif // HAVE_CURL 125 : 126 : #endif