Skip to content

Commit 407208a

Browse files
authored
CCDB: add support for bearer token (#15711)
Allows authenticating with the soon to be deployed security proxy of the CI. Also make the endpoint configurable in tests. Solves the issues with CCDB on SLC10.
1 parent bf2bdf6 commit 407208a

4 files changed

Lines changed: 56 additions & 12 deletions

File tree

CCDB/src/CcdbApi.cxx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,29 @@ using namespace std;
6060
std::mutex gIOMutex; // to protect TMemFile IO operations
6161
unique_ptr<TJAlienCredentials> CcdbApi::mJAlienCredentials = nullptr;
6262

63+
namespace
64+
{
65+
/// Append the gate token, if ALICEO2_CCDB_AUTH_TOKEN names one, to a header list.
66+
///
67+
/// Set when CCDB is reached through a broker that authenticates its callers.
68+
/// The CI does this so the credential CCDB wants for writes -- a grid
69+
/// certificate -- stays in the broker and never enters the build container,
70+
/// which runs pull-request code. The broker consumes this header and does not
71+
/// forward it, so CCDB itself never sees it.
72+
///
73+
/// Read once into a static: getenv races setenv, and these paths run from
74+
/// several threads. Returns the list unchanged when no token is configured, so
75+
/// callers can apply it unconditionally.
76+
curl_slist* appendGateToken(curl_slist* list)
77+
{
78+
static const std::string header = []() -> std::string {
79+
const char* token = getenv("ALICEO2_CCDB_AUTH_TOKEN");
80+
return (token && *token) ? std::string("Authorization: Bearer ") + token : std::string();
81+
}();
82+
return header.empty() ? list : curl_slist_append(list, header.c_str());
83+
}
84+
} // namespace
85+
6386
/**
6487
* Object, encapsulating a semaphore, regulating
6588
* concurrent (multi-process) access to CCDB snapshot files.
@@ -428,6 +451,8 @@ int CcdbApi::storeAsBinaryFile(const char* buffer, size_t size, const std::strin
428451
static const char buf[] = "Expect:";
429452
headerlist = curl_slist_append(headerlist, buf);
430453

454+
headerlist = appendGateToken(headerlist);
455+
431456
curlSetSSLOptions(curl);
432457

433458
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
@@ -722,6 +747,8 @@ void CcdbApi::initCurlHTTPHeaderOptionsForRetrieve(CURL* curlHandle, curl_slist*
722747
curl_easy_setopt(curlHandle, CURLOPT_HEADERDATA, headers);
723748
}
724749

750+
option_list = appendGateToken(option_list);
751+
725752
if (option_list) {
726753
curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, option_list);
727754
}
@@ -795,7 +822,7 @@ bool CcdbApi::receiveObject(void* dataHolder, std::string const& path, std::map<
795822
TObject* CcdbApi::retrieve(std::string const& path, std::map<std::string, std::string> const& metadata,
796823
long timestamp) const
797824
{
798-
struct MemoryStruct chunk {
825+
struct MemoryStruct chunk{
799826
(char*)malloc(1) /*memory*/, 0 /*size*/
800827
};
801828

@@ -1237,6 +1264,7 @@ std::string CcdbApi::list(std::string const& path, bool latestOnly, std::string
12371264
if (createdNotBefore >= 0) {
12381265
headers = curl_slist_append(headers, ("If-Not-Before: " + std::to_string(createdNotBefore)).c_str());
12391266
}
1267+
headers = appendGateToken(headers);
12401268
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
12411269

12421270
curlSetSSLOptions(curl);
@@ -1453,6 +1481,7 @@ std::map<std::string, std::string> CcdbApi::retrieveHeaders(std::string const& p
14531481
if (curl != nullptr) {
14541482
struct curl_slist* list = nullptr;
14551483
list = curl_slist_append(list, ("If-None-Match: " + std::to_string(timestamp)).c_str());
1484+
list = appendGateToken(list);
14561485

14571486
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
14581487

@@ -1531,6 +1560,7 @@ bool CcdbApi::getCCDBEntryHeaders(std::string const& url, std::string const& eta
15311560

15321561
struct curl_slist* list = nullptr;
15331562
list = curl_slist_append(list, ("If-None-Match: " + etag).c_str());
1563+
list = appendGateToken(list);
15341564

15351565
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
15361566

CCDB/test/testBasicCCDBManager.cxx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "CCDB/BasicCCDBManager.h"
2424
#include "Framework/Logger.h"
2525
#include <boost/test/unit_test.hpp>
26+
#include <cstdlib>
2627

2728
using namespace o2::ccdb;
2829

@@ -37,6 +38,11 @@ struct Fixture {
3738
Fixture()
3839
{
3940
CcdbApi api;
41+
// These suites upload, so they need a WRITABLE instance -- ccdb-test by
42+
// default, not the official CCDB.
43+
if (const char* host = std::getenv("ALICEO2_CCDB_HOST")) {
44+
ccdbUrl = host;
45+
}
4046
api.init(ccdbUrl);
4147
std::cout << "ccdb url: " << ccdbUrl << std::endl;
4248
hostReachable = api.isHostReachable();
@@ -134,7 +140,7 @@ BOOST_AUTO_TEST_CASE(TestBasicCCDBManager)
134140
BOOST_CHECK(objB && (*objB) == ccdbObjO); // make sure correct object is loaded
135141

136142
// get object in TimeMachine mode in the past
137-
cdb.setCreatedNotAfter(1); // set upper object validity
143+
cdb.setCreatedNotAfter(1); // set upper object validity
138144
cdb.setFatalWhenNull(false);
139145
objA = cdb.get<std::string>(pathA); // should not be loaded
140146
BOOST_CHECK(!objA); // make sure correct object is not loaded

CCDB/test/testCcdbApi.cxx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
#define BOOST_TEST_DYN_LINK
2121

2222
#include "CCDB/CcdbApi.h"
23-
#include "CCDB/IdPath.h" // just as test object
23+
#include "CCDB/IdPath.h" // just as test object
2424
#include "CommonUtils/RootChain.h" // just as test object
2525
#include "CCDB/CCDBTimeStampUtils.h"
2626
#include <boost/test/unit_test.hpp>
2727
#include <filesystem>
2828
#include <iostream>
2929
#include <TH1F.h>
3030
#include <chrono>
31+
#include <cstdlib>
3132
#include <CommonUtils/StringUtils.h>
3233
#include <TStreamerInfo.h>
3334
#include <TGraph.h>
@@ -45,7 +46,7 @@ using namespace o2::ccdb;
4546
namespace utf = boost::unit_test;
4647
namespace tt = boost::test_tools;
4748

48-
static std::string ccdbUrl;
49+
static std::string ccdbUrl = "http://ccdb-test.cern.ch:8080";
4950
static std::string basePath;
5051
bool hostReachable = false;
5152

@@ -56,7 +57,11 @@ struct Fixture {
5657
Fixture()
5758
{
5859
CcdbApi api;
59-
ccdbUrl = "http://ccdb-test.cern.ch:8080";
60+
// These suites upload, so they need a WRITABLE instance -- ccdb-test by
61+
// default, not the official CCDB.
62+
if (const char* host = std::getenv("ALICEO2_CCDB_HOST")) {
63+
ccdbUrl = host;
64+
}
6065
api.init(ccdbUrl);
6166
cout << "ccdb url: " << ccdbUrl << endl;
6267
hostReachable = api.isHostReachable();
@@ -65,7 +70,7 @@ struct Fixture {
6570
gethostname(hostname, _POSIX_HOST_NAME_MAX);
6671
basePath = std::string("Test/TestCcdbApi/") + hostname + "/pid" + getpid() + "/";
6772
// Replace dashes by underscores to avoid problems in the creation of local directories
68-
std::replace(basePath.begin(), basePath.end(), '-','_');
73+
std::replace(basePath.begin(), basePath.end(), '-', '_');
6974
cout << "Path we will use in this test suite : " + basePath << endl;
7075
}
7176
~Fixture()
@@ -446,13 +451,13 @@ BOOST_AUTO_TEST_CASE(TestFetchingHeaders, *utf::precondition(if_reachable()))
446451
std::vector<std::string> headers;
447452
std::vector<std::string> pfns;
448453
std::string path = objectPath + "/" + std::to_string(getCurrentTimestamp());
449-
auto updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/" + path, etag, headers);
454+
auto updated = CcdbApi::getCCDBEntryHeaders(ccdbUrl + "/" + path, etag, headers);
450455
BOOST_CHECK_EQUAL(updated, true);
451456
BOOST_REQUIRE(headers.size() != 0);
452457
CcdbApi::parseCCDBHeaders(headers, pfns, etag);
453458
BOOST_REQUIRE(etag != "");
454459
BOOST_REQUIRE(pfns.size());
455-
updated = CcdbApi::getCCDBEntryHeaders("http://ccdb-test.cern.ch:8080/" + path, etag, headers);
460+
updated = CcdbApi::getCCDBEntryHeaders(ccdbUrl + "/" + path, etag, headers);
456461
BOOST_CHECK_EQUAL(updated, false);
457462
}
458463

@@ -557,7 +562,7 @@ BOOST_AUTO_TEST_CASE(TestUpdateMetadata, *utf::precondition(if_reachable()))
557562
BOOST_AUTO_TEST_CASE(multi_host_test)
558563
{
559564
CcdbApi api;
560-
api.init("http://bogus-host.cern.ch,http://ccdb-test.cern.ch:8080");
565+
api.init("http://bogus-host.cern.ch," + ccdbUrl);
561566
std::map<std::string, std::string> metadata;
562567
std::map<std::string, std::string> headers;
563568
o2::pmr::vector<char> dst;
@@ -569,7 +574,7 @@ BOOST_AUTO_TEST_CASE(multi_host_test)
569574
BOOST_AUTO_TEST_CASE(vectored)
570575
{
571576
CcdbApi api;
572-
api.init("http://ccdb-test.cern.ch:8080");
577+
api.init(ccdbUrl);
573578

574579
int TEST_SAMPLE_SIZE = 5;
575580
std::vector<o2::pmr::vector<char>> dests(TEST_SAMPLE_SIZE);

CCDB/test/testCcdbApiHeaders.cxx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "CCDB/CCDBTimeStampUtils.h"
2424
#include "CCDB/CcdbApi.h"
2525
#include <boost/test/unit_test.hpp>
26+
#include <cstdlib>
2627

2728
static std::string basePath;
2829
// std::string ccdbUrl = "http://localhost:8080";
@@ -37,8 +38,10 @@ struct Fixture {
3738
Fixture()
3839
{
3940
auto& ccdbManager = o2::ccdb::BasicCCDBManager::instance();
40-
if (std::getenv("ALICEO2_CCDB_HOST")) {
41-
ccdbUrl = std::string(std::getenv("ALICEO2_CCDB_HOST"));
41+
// These suites upload, so they need a WRITABLE instance -- ccdb-test by
42+
// default, not the official CCDB.
43+
if (const char* host = std::getenv("ALICEO2_CCDB_HOST")) {
44+
ccdbUrl = host;
4245
}
4346
ccdbManager.setURL(ccdbUrl);
4447
hostReachable = ccdbManager.getCCDBAccessor().isHostReachable();

0 commit comments

Comments
 (0)