const std::string ZTSClient::getRoleToken()

in lib/auth/athenz/ZTSClient.cc [289:388]


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);

    std::string trustCertsFilePath;
    std::unique_ptr<CurlWrapper::TlsContext> tlsContext;
    if (!caCert_.scheme.empty()) {
        if (caCert_.scheme == "file") {
            tlsContext.reset(new CurlWrapper::TlsContext);
            tlsContext->trustCertsFilePath = caCert_.path;
        } else {
            LOG_ERROR("URI scheme not supported in caCert: " << caCert_.scheme);
        }
    }

    std::string header;
    if (enableX509CertChain_) {
        if (x509CertChain_.scheme == "file") {
            if (!tlsContext) {
                tlsContext.reset(new CurlWrapper::TlsContext);
            }
            tlsContext->certPath = x509CertChain_.path;
        } else {
            LOG_ERROR("URI scheme not supported in x509CertChain: " << x509CertChain_.scheme);
        }
        if (privateKeyUri_.scheme == "file") {
            if (!tlsContext) {
                tlsContext.reset(new CurlWrapper::TlsContext);
            }
            tlsContext->keyPath = privateKeyUri_.path;
        } else {
            LOG_ERROR("URI scheme not supported in privateKey: " << privateKeyUri_.scheme);
        }
    } else {
        header = principalHeader_ + ": " + getPrincipalToken();
    }

    CurlWrapper curl;
    if (!curl.init()) {
        LOG_ERROR("Failed to init curl");
        return "";
    }

    CurlWrapper::Options options;
    options.timeoutInSeconds = REQUEST_TIMEOUT;
    options.maxLookupRedirects = MAX_HTTP_REDIRECTS;
    auto result = curl.get(completeUrl, header, options, tlsContext.get());
    if (!result.error.empty()) {
        LOG_ERROR(completeUrl << " failed: " << result.error);
        return "";
    }
    auto res = result.code;
    const auto &responseData = result.responseData;
    long response_code = result.responseCode;

    switch (res) {
        case CURLE_OK:
            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;
    }

    return roleToken.token;
}