/src/gdal/port/cpl_nasa_earthdata.h
Line | Count | Source |
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 | | 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 | | const std::string &GetAccessKeyId() |
80 | 0 | { |
81 | 0 | std::lock_guard oLock(m_oMutex); |
82 | 0 | RefreshIfNeededUnderLock(); |
83 | 0 | return m_osAccessKeyId; |
84 | 0 | } |
85 | | |
86 | | /** Returns S3 secret access key, or empty string if invalid. |
87 | | * |
88 | | * This method takes care of refreshing credentials if needed. |
89 | | */ |
90 | | const std::string &GetSecretAccessKey() |
91 | 0 | { |
92 | 0 | std::lock_guard oLock(m_oMutex); |
93 | 0 | RefreshIfNeededUnderLock(); |
94 | 0 | return m_osSecretAccessKey; |
95 | 0 | } |
96 | | |
97 | | /** Returns S3 session token, or empty string if invalid. |
98 | | * |
99 | | * This method takes care of refreshing credentials if needed. |
100 | | */ |
101 | | const std::string &GetSessionToken() |
102 | 0 | { |
103 | 0 | std::lock_guard oLock(m_oMutex); |
104 | 0 | RefreshIfNeededUnderLock(); |
105 | 0 | return m_osSessionToken; |
106 | 0 | } |
107 | | |
108 | | /** Clear credentials cache */ |
109 | | static void ClearCache(); |
110 | | |
111 | | private: |
112 | | CPLNasaEarthdataCredentialProvider(); |
113 | | |
114 | | bool RefreshIfNeededUnderLock(); |
115 | | |
116 | | std::string m_osGetCredentialsURL{}; |
117 | | std::string m_osEarthdataToken{}; |
118 | | |
119 | | // Output of RefreshIfNeededUnderLock() |
120 | | std::mutex m_oMutex{}; |
121 | | std::string m_osAccessKeyId{}; |
122 | | std::string m_osSecretAccessKey{}; |
123 | | std::string m_osSessionToken{}; |
124 | | GIntBig m_nTokenExpirationTimestamp = 0; |
125 | | }; |
126 | | |
127 | | #endif // HAVE_CURL |
128 | | |
129 | | #endif |