void IotRoleCredentialsProvider::Refresh()

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