Skip to content

Commit a63c2a2

Browse files
authored
CCDB: handle access to CCDB via security proxy (#15724)
Gate tokens are minted per broker route, so a process facing both the writable test CCDB and production needs one token per endpoint. ALICEO2_CCDB_AUTH_TOKENS ("<url>=<tok>;<url>=<tok>") replaces the single ALICEO2_CCDB_AUTH_TOKEN, and the token is chosen by the URL each request targets: * header lists are built inside the hostsPool loops -- built once outside, every host received the first host's token; * matching stops at a path boundary, so a missing ".../ccdb-prod" entry cannot silently fall back to the ".../ccdb" token (an opaque 401); * CURLOPT_HTTPHEADER is set unconditionally: with per-host lists, skipping the set would leave a freed list installed on the handle. Incoming header values are trimmed before reuse: header_callback stores raw lines, so the ETag kept its CRLF and, spliced into If-None-Match, ended the request header block early -- dropping the Authorization header appended after it (401 instead of 304, testCcdbApi.cxx:461). DeadChannelMapCreator now checks the fetch before reading Valid-From/ Until, so an unreachable CCDB reports instead of throwing out_of_range. CalDetStreamerTest reads ALICEO2_CCDB_PRODUCTION_HOST (default unchanged): its pinned timestamp matches the production object, and the test instance holds a different object at that path.
1 parent 0d2ee8b commit a63c2a2

6 files changed

Lines changed: 176 additions & 72 deletions

File tree

CCDB/include/CCDB/CCDBDownloader.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ typedef struct DownloaderRequestData {
5353
HeaderObjectPair_t hoPair;
5454
std::map<std::string, std::string>* headers;
5555
std::string userAgent;
56-
curl_slist* optionsList;
56+
// One header list per entry of `hosts`, parallel to it. Per host and not one
57+
// shared list because the gate token a broker expects is per endpoint: a
58+
// multi-host pool can mix them, and tryNewHost() swapping only the URL left
59+
// the second host receiving the first host's token -- answered 401, so the
60+
// failover silently retrieved nothing (testCcdbApi multi_host_test).
61+
std::vector<curl_slist*> optionsLists;
5762

5863
std::function<bool(std::string)> localContentCallback;
5964
} DownloaderRequestData;
@@ -304,7 +309,8 @@ class CCDBDownloader
304309
int hostInd;
305310
int locInd;
306311
DownloaderRequestData* requestData;
307-
curl_slist** options;
312+
// Freed by transferFinished; indexed by hostInd, see DownloaderRequestData.
313+
std::vector<curl_slist*>* options;
308314
} PerformData;
309315
#endif
310316

CCDB/include/CCDB/CcdbApi.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define PROJECT_CCDBAPI_H
1919

2020
#include <string>
21+
#include <string_view>
2122
#include <memory>
2223
#include <map>
2324
#include <curl/curl.h>
@@ -581,7 +582,7 @@ class CcdbApi //: public DatabaseInterface
581582
void initCurlOptionsForRetrieve(CURL* curlHandle, void* pointer, CurlWriteCallback writeCallback, bool followRedirect = true) const;
582583

583584
/// initialize HTTPS header information for the CURL handle. Needs to be given an existing curl_slist* pointer to work with (may be nullptr), which needs to be free by the caller.
584-
void initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore) const;
585+
void initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*& option_list, long timestamp, std::map<std::string, std::string>* headers, std::string const& etag, const std::string& createdNotAfter, const std::string& createdNotBefore, std::string_view url) const;
585586

586587
bool receiveToFile(FILE* fileHandle, std::string const& path, std::map<std::string, std::string> const& metadata,
587588
long timestamp, std::map<std::string, std::string>* headers = nullptr, std::string const& etag = "",

CCDB/src/CCDBDownloader.cxx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,14 @@ void CCDBDownloader::tryNewHost(PerformData* performData, CURL* easy_handle)
365365
LOG(debug) << "Connecting to another host " << newUrl << "\n";
366366
requestData->hoPair.header.clear();
367367
curl_easy_setopt(easy_handle, CURLOPT_URL, newUrl.c_str());
368+
// The headers travel with the host, not with the request: a broker mints its
369+
// gate token per endpoint, so carrying the previous host's list here is what
370+
// made the failover arrive unauthenticated. The lists are built per host by
371+
// CcdbApi::scheduleDownload, which is where the token table is visible.
372+
if (performData->hostInd < static_cast<int>(requestData->optionsLists.size())) {
373+
curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER,
374+
requestData->optionsLists.at(performData->hostInd));
375+
}
368376
mHandlesToBeAdded.push_back(easy_handle);
369377
}
370378

@@ -568,7 +576,9 @@ void CCDBDownloader::transferFinished(CURL* easy_handle, CURLcode curlCode)
568576
}
569577
}
570578
--(*performData->requestsLeft);
571-
curl_slist_free_all(*performData->options);
579+
for (auto* optionList : *performData->options) {
580+
curl_slist_free_all(optionList);
581+
}
572582
delete requestData;
573583
delete performData->codeDestination;
574584
curl_easy_cleanup(easy_handle);
@@ -729,7 +739,7 @@ void CCDBDownloader::asynchSchedule(CURL* handle, size_t* requestCounter)
729739
curl_easy_getinfo(handle, CURLINFO_PRIVATE, &requestData);
730740
headerMap = &(requestData->hoPair.header);
731741
hostsPool = &(requestData->hosts);
732-
auto* options = &(requestData->optionsList);
742+
auto* options = &(requestData->optionsLists);
733743

734744
// Prepare temporary data about transfer
735745
auto* data = new CCDBDownloader::PerformData(); // Freed in transferFinished

0 commit comments

Comments
 (0)