Coverage Report

Created: 2026-09-26 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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