in aws_common/src/sdk_utils/auth/service_credentials_provider.cpp [412:505]
void IotRoleCredentialsProvider::Refresh()
{
CURLcode res;
CURL * curl = nullptr;
struct curl_slist * headers = nullptr;
AWS_LOG_INFO(AWS_LOG_TAG, "Retrieving IOT credentials!");
std::lock_guard<std::mutex> lock(creds_mutex_);
if (!IsTimeExpired()) { return; }
// Make at most 1 tps for new creds, we also have a 30s grace buffer
expiry_.store(Aws::Utils::DateTime::Now().SecondsWithMSPrecision() + EXPIRATION_GRACE_BUFFER + 1.0);
curl = curl_easy_init();
if (curl == nullptr) {
AWS_LOG_ERROR(AWS_LOG_TAG, "Could not initialize curl!");
} else {
Aws::StringStream url_stream;
url_stream << "https://" << config_.host << "/role-aliases/" << config_.role << "/credentials";
// Setup SSL options
if (!SetCurlOpt(curl, CURLOPT_SSL_VERIFYPEER, 1L)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_SSL_VERIFYHOST, 2L)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_HTTPGET, 1L)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_HEADER, 0L)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_CONNECTTIMEOUT_MS, config_.connect_timeout_ms)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_TIMEOUT_MS, config_.total_timeout_ms)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_URL, url_stream.str().c_str())) { goto cleanup_curl; }
// Configure client auth
if (!SetCurlOpt(curl, CURLOPT_CAINFO, config_.cafile.c_str())) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_SSLCERTTYPE, "PEM")) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_SSLCERT, config_.certfile.c_str())) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_SSLKEYTYPE, "PEM")) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_SSLKEY, config_.keyfile.c_str())) { goto cleanup_curl; }
// Setup response handler
RequestContext ctx;
if (!SetCurlOpt(curl, CURLOPT_WRITEFUNCTION, &RequestContext::WriteData)) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_WRITEDATA, &ctx)) { goto cleanup_curl; }
// Setup request headers
if (!AppendHeader(&headers, "Accept", "application/json")) { goto cleanup_curl; }
if (!AppendHeader(&headers, "Host", config_.host.c_str())) { goto cleanup_curl; }
if (!AppendHeader(&headers, HEADER_THING_NAME, config_.name.c_str())) { goto cleanup_curl; }
if (!SetCurlOpt(curl, CURLOPT_HTTPHEADER, headers)) { goto cleanup_curl; }
// Make the request
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
AWS_LOG_ERROR(AWS_LOG_TAG, "Error when curling endpoint: %s", curl_easy_strerror(res));
goto cleanup_curl;
}
// Parse JSON response
auto value = ctx.GetValue();
if (!ValidateResponse(value)) { goto cleanup_curl; }
auto creds_obj = value.View().GetObject(FIELD_CREDENTIALS);
// Retrieve expiration date
auto expires_str = creds_obj.GetString(FIELD_EXPIRATION);
Aws::Utils::DateTime expiration(expires_str, Aws::Utils::DateFormat::ISO_8601);
if (!expiration.WasParseSuccessful()) {
AWS_LOG_ERROR(AWS_LOG_TAG, "Unable to parse expiration: %s", expires_str.c_str());
goto cleanup_curl;
}
AWS_LOG_INFO(AWS_LOG_TAG, "Retrieved AWS creds from IoT, next expiration %s",
expires_str.c_str());
cached_.SetAWSAccessKeyId(creds_obj.GetString(FIELD_ACCESS_KEY));
cached_.SetAWSSecretKey(creds_obj.GetString(FIELD_SECRET_KEY));
cached_.SetSessionToken(creds_obj.GetString(FIELD_SESSION_TOKEN));
expiry_.store(expiration.SecondsWithMSPrecision());
}
cleanup_curl:
if (headers != nullptr) {
curl_slist_free_all(headers);
headers = nullptr;
}
if (curl != nullptr) {
curl_easy_cleanup(curl);
curl = nullptr;
}
}