in lib/auth/athenz/ZTSClient.cc [296:409]
const std::string ZTSClient::getRoleToken() {
RoleToken roleToken;
// locked block
{
std::lock_guard<std::mutex> lock(cacheMtx_);
roleToken = roleTokenCache_;
}
if (!roleToken.token.empty() && roleToken.expiryTime > (long long)time(NULL) + FETCH_EPSILON) {
LOG_DEBUG("Got cached role token " << roleToken.token);
return roleToken.token;
}
std::string completeUrl = ztsUrl_ + "/zts/v1/domain/" + providerDomain_ + "/token";
completeUrl += "?minExpiryTime=" + std::to_string(ROLE_TOKEN_EXPIRATION_MIN_TIME_SEC);
completeUrl += "&maxExpiryTime=" + std::to_string(ROLE_TOKEN_EXPIRATION_MAX_TIME_SEC);
CURL *handle;
CURLcode res;
std::string responseData;
handle = curl_easy_init();
// set URL
curl_easy_setopt(handle, CURLOPT_URL, completeUrl.c_str());
// Write callback
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlWriteCallback);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &responseData);
// New connection is made for each call
curl_easy_setopt(handle, CURLOPT_FRESH_CONNECT, 1L);
curl_easy_setopt(handle, CURLOPT_FORBID_REUSE, 1L);
// Skipping signal handling - results in timeouts not honored during the DNS lookup
curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);
// Timer
curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, REQUEST_TIMEOUT);
// Redirects
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(handle, CURLOPT_MAXREDIRS, MAX_HTTP_REDIRECTS);
// Fail if HTTP return code >= 400
curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1L);
if (!caCert_.scheme.empty()) {
if (caCert_.scheme == "file") {
curl_easy_setopt(handle, CURLOPT_CAINFO, caCert_.path.c_str());
} else {
LOG_ERROR("URI scheme not supported in caCert: " << caCert_.scheme);
}
}
struct curl_slist *list = NULL;
if (enableX509CertChain_) {
if (x509CertChain_.scheme == "file") {
curl_easy_setopt(handle, CURLOPT_SSLCERT, x509CertChain_.path.c_str());
} else {
LOG_ERROR("URI scheme not supported in x509CertChain: " << x509CertChain_.scheme);
}
if (privateKeyUri_.scheme == "file") {
curl_easy_setopt(handle, CURLOPT_SSLKEY, privateKeyUri_.path.c_str());
} else {
LOG_ERROR("URI scheme not supported in privateKey: " << privateKeyUri_.scheme);
}
} else {
std::string httpHeader = principalHeader_ + ": " + getPrincipalToken();
list = curl_slist_append(list, httpHeader.c_str());
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, list);
}
// Make get call to server
res = curl_easy_perform(handle);
// Free header list
curl_slist_free_all(list);
switch (res) {
case CURLE_OK:
long response_code;
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
LOG_DEBUG("Response received for url " << completeUrl << " code " << response_code);
if (response_code == 200) {
ptree::ptree root;
std::stringstream stream;
stream << responseData;
try {
ptree::read_json(stream, root);
} catch (ptree::json_parser_error &e) {
LOG_ERROR("Failed to parse json of ZTS response: " << e.what()
<< "\nInput Json = " << responseData);
break;
}
roleToken.token = root.get<std::string>("token");
roleToken.expiryTime = root.get<uint32_t>("expiryTime");
std::lock_guard<std::mutex> lock(cacheMtx_);
roleTokenCache_ = roleToken;
LOG_DEBUG("Got role token " << roleToken.token)
} else {
LOG_ERROR("Response failed for url " << completeUrl << ". response Code " << response_code)
}
break;
default:
LOG_ERROR("Response failed for url " << completeUrl << ". Error Code " << res);
break;
}
curl_easy_cleanup(handle);
return roleToken.token;
}