Grok 20.3.2
ADLSFetcher.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <ctime>
21
22#include "grk_config_private.h"
23#include "CurlFetcher.h"
24#include "FetchPathParser.h"
25
26#ifdef GRK_ENABLE_LIBCURL
27
28namespace grk
29{
30
31class ADLSFetcher : public CurlFetcher
32{
33protected:
34 void parse(const std::string& path) override
35 {
36 // Create a non-const copy of path for FetchPathParser
37 std::string mutable_path = path;
38 ParsedFetchPath parsed;
39 if(mutable_path.starts_with("/vsiadls/"))
40 {
41 // Parse /vsiadls/ path using FetchPathParser
42 std::string account;
43 if(!auth_.username_.empty())
44 {
45 account = auth_.username_;
46 grklog.debug("Using auth-provided account for vsiadls: %s", account.c_str());
47 }
48 else
49 {
50 grklog.error("No Azure account provided for /vsiadls/ path");
51 throw std::runtime_error("No Azure account provided for /vsiadls/ path");
52 }
53 FetchPathParser::parseVsiPath(mutable_path, parsed, "vsiadls");
54 parsed.host = account + ".dfs.core.windows.net";
55 parsed.port = 443;
56 }
57 else if(mutable_path.starts_with("https://"))
58 {
59 // Parse HTTPS path using FetchPathParser
60 FetchPathParser::parseHttpsPath(mutable_path, parsed);
61 if(!parsed.host.ends_with(".dfs.core.windows.net"))
62 {
63 grklog.error("Invalid ADLS HTTPS URL: host must end with .dfs.core.windows.net: %s",
64 parsed.host.c_str());
65 throw std::runtime_error(
66 "Invalid ADLS HTTPS URL: host must end with .dfs.core.windows.net");
67 }
68 }
69 else
70 {
71 grklog.error("Unsupported URL format for ADLS: %s", path.c_str());
72 throw std::runtime_error("Unsupported URL format for ADLS");
73 }
74
75 grklog.debug("Parsed ADLS URL - Host: %s, Port: %d, Filesystem: %s, Path: %s",
76 parsed.host.c_str(), parsed.port, parsed.bucket.c_str(), parsed.key.c_str());
77
78 // Construct the base URL without SAS token
79 url_ = "https://" + parsed.host + "/" + parsed.bucket + "/" + parsed.key;
80 grklog.debug("Parsed ADLSFetcher URL: %s", url_.c_str());
81 }
82
83 void auth(CURL* curl) override
84 {
85 // Apply parent auth settings (e.g., SSL verification)
86 CurlFetcher::auth(curl);
87
88 // ADLS Gen2 authentication logic
89 std::string final_url = url_;
90 std::string account = auth_.username_;
91 std::string secret = auth_.password_;
92
93 // Check environment variables for account and key/SAS token
94 if(account.empty())
95 {
96 if(const char* key = std::getenv("AZURE_STORAGE_ACCOUNT"))
97 {
98 account = key;
99 grklog.debug("Set ADLS account = %s", account.c_str());
100 }
101 }
102 if(secret.empty())
103 {
104 if(const char* key = std::getenv("AZURE_STORAGE_KEY"))
105 {
106 secret = key;
107 grklog.debug("Set ADLS key = %s", secret.c_str());
108 }
109 else if(const char* sas = std::getenv("AZURE_STORAGE_SAS_TOKEN"))
110 {
111 secret = sas;
112 grklog.debug("Set ADLS SAS token = %s", secret.c_str());
113 }
114 }
115
116 // Apply authentication
117 if(!account.empty() && !secret.empty() && secret.find("?") != 0)
118 {
119 // Use account key authentication
120 curl_easy_setopt(curl, CURLOPT_USERNAME, account.c_str());
121 curl_easy_setopt(curl, CURLOPT_PASSWORD, secret.c_str());
122 grklog.debug("Applied ADLS account key authentication for account: %s", account.c_str());
123 }
124 else if(!secret.empty() && secret.find("?") == 0)
125 {
126 // Append SAS token to URL
127 final_url += secret;
128 curl_easy_setopt(curl, CURLOPT_URL, final_url.c_str());
129 grklog.debug("Applied ADLS SAS token authentication, final URL: %s", final_url.c_str());
130 }
131 else
132 {
133 grklog.debug("No additional ADLS authentication applied (public access or other auth)");
134 }
135 }
136
137 curl_slist* prepareAuthHeaders(curl_slist* headers) override
138 {
139 time_t now;
140 time(&now);
141 char date_buf[64];
142 strftime(date_buf, sizeof(date_buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
143 std::string date_header = "x-ms-date: " + std::string(date_buf);
144 headers = curl_slist_append(headers, date_header.c_str());
145
146 return curl_slist_append(headers, "x-ms-version: 2020-04-08");
147 }
148};
149
150} // namespace grk
151
152#endif
ResWindow.
Definition CompressedChunkCache.h:36
ILogger & grklog
Definition Logger.cpp:24
virtual void error(const char *fmt,...)=0
virtual void debug(const char *fmt,...)=0