in source/credentials_provider_sts.c [303:426]
static void s_on_stream_complete_fn(struct aws_http_stream *stream, int error_code, void *user_data) {
int http_response_code = 0;
struct sts_creds_provider_user_data *provider_user_data = user_data;
struct aws_credentials_provider_sts_impl *provider_impl = provider_user_data->provider->impl;
struct aws_xml_parser *xml_parser = NULL;
provider_user_data->error_code = error_code;
if (provider_impl->function_table->aws_http_stream_get_incoming_response_status(stream, &http_response_code)) {
goto finish;
}
if (http_response_code != 200) {
provider_user_data->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_HTTP_STATUS_FAILURE;
}
provider_impl->function_table->aws_http_stream_release(stream);
AWS_LOGF_DEBUG(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p): AssumeRole call completed with http status %d",
(void *)provider_user_data->provider,
http_response_code);
if (error_code || http_response_code != AWS_HTTP_STATUS_CODE_200_OK) {
/* prevent connection reuse. */
provider_impl->function_table->aws_http_connection_close(provider_user_data->connection);
enum aws_retry_error_type error_type = http_response_code >= 400 && http_response_code < 500
? AWS_RETRY_ERROR_TYPE_CLIENT_ERROR
: AWS_RETRY_ERROR_TYPE_SERVER_ERROR;
if (s_is_transient_error(error_code)) {
error_type = AWS_RETRY_ERROR_TYPE_TRANSIENT;
}
/* server throttling us is retryable */
if (http_response_code == AWS_HTTP_STATUS_CODE_429_TOO_MANY_REQUESTS) {
/* force a new connection on this. */
error_type = AWS_RETRY_ERROR_TYPE_THROTTLING;
}
s_reset_request_specific_data(provider_user_data);
/* don't retry client errors at all. */
if (error_type != AWS_RETRY_ERROR_TYPE_CLIENT_ERROR) {
if (aws_retry_strategy_schedule_retry(
provider_user_data->retry_token, error_type, s_on_retry_ready, provider_user_data)) {
AWS_LOGF_ERROR(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p): failed to schedule retry: %s",
(void *)provider_user_data->provider,
aws_error_str(aws_last_error()));
goto finish;
}
return;
}
}
if (!error_code && http_response_code == AWS_HTTP_STATUS_CODE_200_OK) {
/* update the book keeping so we can let the retry strategy make determinations about when the service is
* healthy after an outage. */
if (aws_retry_token_record_success(provider_user_data->retry_token)) {
AWS_LOGF_ERROR(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p): failed to register operation success: %s",
(void *)provider_user_data->provider,
aws_error_str(aws_last_error()));
goto finish;
}
struct aws_xml_parser_options options;
AWS_ZERO_STRUCT(options);
options.doc = aws_byte_cursor_from_buf(&provider_user_data->output_buf);
xml_parser = aws_xml_parser_new(provider_user_data->provider->allocator, &options);
if (xml_parser == NULL) {
goto finish;
}
uint64_t now = UINT64_MAX;
if (provider_impl->system_clock_fn(&now) != AWS_OP_SUCCESS) {
goto finish;
}
uint64_t now_seconds = aws_timestamp_convert(now, AWS_TIMESTAMP_NANOS, AWS_TIMESTAMP_SECS, NULL);
if (aws_xml_parser_parse(xml_parser, s_on_node_encountered_fn, provider_user_data)) {
provider_user_data->error_code = aws_last_error();
AWS_LOGF_ERROR(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p): credentials parsing failed with error %s",
(void *)provider_user_data->credentials,
aws_error_debug_str(provider_user_data->error_code));
goto finish;
}
if (provider_user_data->access_key_id && provider_user_data->secret_access_key &&
provider_user_data->session_token) {
provider_user_data->credentials = aws_credentials_new_from_string(
provider_user_data->allocator,
provider_user_data->access_key_id,
provider_user_data->secret_access_key,
provider_user_data->session_token,
now_seconds + provider_impl->duration_seconds);
} else {
AWS_LOGF_ERROR(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
"(id=%p): credentials document was corrupted, treating as an error.",
(void *)provider_user_data->provider);
}
}
finish:
if (xml_parser != NULL) {
aws_xml_parser_destroy(xml_parser);
xml_parser = NULL;
}
s_clean_up_user_data(provider_user_data);
}