Прикрепляющий отладчик дает мне учетные данные, удаляет его, и учетные данные пусты

#c #amazon-web-services #qt

#c #amazon-web-services #qt

Вопрос:

У меня проблема с AWS sdk в приложении Qt.
Я получаю токены STS от Cognito после нажатия кнопки QML.
Функция работает отлично и печатает мне токен… пока отладчик подключен [F5]. Если я запускаю проект без отладчика (зеленая стрелка без ошибки на нем), возвращаемый объект пуст.

Без подключенного отладчика в журналах aws у меня есть следующее, чего у меня нет в противном случае:

[ИНФОРМАЦИЯ] 2020-09-18 12:33:02.569 CognitoCachingCredentialsProvider [140678610167936] Родительский идентификатор был от cognito, который отличается от анонимного идентификатора. Заменяем это сейчас.
[ИНФОРМАЦИЯ] 2020-09-18 12:33:02.569 CognitoCachingCredentialsProvider [140678610167936] Срок действия учетных данных истекает в 0

Другие журналы выглядят одинаково, у меня даже есть токен STS, показанный на пару строк выше этого в обоих случаях:

[DEBUG] 2020-09-18 12:33:02.569 CURL [140678610167936] (dataIn) {«Credentials»:{«AccessKeyId»:»###»,»Expiration»:1.600435982E9,»SecretKey»:»###»,»SessionToken»:»##########»},»identity_id»:»<MY_IDENTITY_ID>»}

Я даже отредактировал SDK и добавил следующие журналы, которые привели к этому (при подключенном отладчике также <MY_IDENTITY_ID> отображается первая строка).

 AWS_LOGSTREAM_INFO("TOTO", "parentIdentityId" << parentIdentityId);
AWS_LOGSTREAM_INFO("TOTO", "m_identityRepository->GetIdentityId() " << m_identityRepository->GetIdentityId()) ;
  

[ИНФОРМАЦИЯ] 2020-09-18 12:33:02.569 TOTO [140678610167936] parentIdentityId
[ИНФОРМАЦИЯ] 2020-09-18 12:33:02.569 ИТОГО [140678610167936] m_identityRepository->GetIdentityId() <MY_IDENTITY_ID>

Добавлено здесь https://github.com/aws/aws-sdk-cpp/blob/6d6dcdbfa377393306bf79585f61baea524ac124/aws-cpp-sdk-identity-management/source/auth/CognitoCachingCredentialsProvider.cpp#L52 Отсутствие комментариев к строке 56 не решает мою проблему.

Прилагается мой минимальный проект для воспроизведения поведения, если вы хотите (вам потребуется настройка AWS и поставщик OpenID).
Я попробовал чистый C , и я получаю все даже без отладчика.
Проблема возникает при создании экземпляра QtCoreApplication .
В базовом приложении я попытался установить a QTimer::singleShot(100, /*...*/) , и у меня все еще возникла проблема.

Вы можете установить aws SDK отсюда https://github.com/aws/aws-sdk-cpp и если вы не хотите устанавливать весь SDK целиком, проекту нужна только небольшая часть sdk, поэтому добавьте -DBUILD_ONLY="identity-management" в cmake только необходимую часть.

Qt 5.12.5
aws-sdk-cpp по тегу: 1.8.42 (была такая же проблема из предыдущей версии исправления и последнее изменение очень часто)

Вопрос

What magic attaching the debugger do to allow an application that instanciated a QCoreApplication getting tokens from the aws sdk ?

I am saying it again here: I do not have a DEBUG and a RELEASE build, I just use the arrow vs arrow with a bug on it in qtcreator. As far as I know the environment is the same, just qtcreator attach or not the debugger.
Indeed in release I have the same problem (STS shown when the debugger is attached, empty when not).

Minimal working example

main.cpp (The commented code should do the same as credentials = cognitoAuth.GetAWSCredentials(); , and so I have the same behaviour.)

 #include <QCoreApplication>
#include <QDebug>
#include <QFile>

#include <aws/cognito-identity/model/GetCredentialsForIdentityRequest.h>
#include <aws/cognito-identity/model/GetIdRequest.h>
#include <aws/core/Aws.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>

Aws::String m_region = Aws::Region::<PICK_YOUR_REGION>;
Aws::String m_providerUrl = "<PROVIDER_URL>";
Aws::String m_accountId = "<ACCOUNT_ID>";
Aws::String m_identityPoolId = "<IDENTITY_POOL_ID>";

Aws::Auth::AWSCredentials getSTS(const std::string idToken) {
  const char *persistentFile = "/tmp/aws.identities";
  QFile::remove(persistentFile);

  Aws::Auth::AWSCredentials credentials;
  //    Aws::CognitoIdentity::Model::Credentials credentials;

  std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient> cognitoClient;
  Aws::SDKOptions options;
  options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;

  Aws::InitAPI(options);
  {
    Aws::Client::ClientConfiguration config;
    config.region = m_region;
    cognitoClient =
        std::make_shared<Aws::CognitoIdentity::CognitoIdentityClient>(config);
    std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider_JsonFileImpl>
        identityProvider = std::make_shared<
            Aws::Auth::PersistentCognitoIdentityProvider_JsonFileImpl>(
            m_identityPoolId, m_accountId, persistentFile);
    Aws::Map<Aws::String, Aws::Auth::LoginAccessTokens> logins;
    Aws::Auth::LoginAccessTokens loginAccessTokens;
    loginAccessTokens.accessToken = idToken;
    logins[m_providerUrl] = loginAccessTokens;
    identityProvider->PersistLogins(logins);

    // QThread::sleep(5);

    Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider cognitoAuth{
        identityProvider, cognitoClient};
    ///////////////////////////////////////////////////////////////////////////
    // Aws::CognitoIdentity::Model::GetIdRequest idRequest;
    // idRequest.SetIdentityPoolId(m_identityPoolId.c_str());
    // idRequest.AddLogins(m_providerUrl, idToken.c_str());
    ////idRequest.SetIdentityPoolId((region   ":"   identityPoolId).c_str());
    //
    // auto idResult = cognitoClient->GetId(idRequest);
    // if(!idResult.IsSuccess())
    //{
    //    qCWarning(mqttAwsWebsocket) << "(GetId): " <<
    //    idResult.GetError().GetExceptionName().c_str() << ":"
    //                                <<
    //                                idResult.GetError().GetMessage().c_str();
    //    // throw
    //}
    //
    // QThread::sleep(5);
    //
    // Aws::CognitoIdentity::Model::GetCredentialsForIdentityRequest
    // credForIdRequest;
    // credForIdRequest.SetIdentityId(idResult.GetResult().GetIdentityId());
    // credForIdRequest.AddLogins(m_providerUrl, idToken.c_str());
    //
    // auto credForIdResult =
    // cognitoClient->GetCredentialsForIdentity(credForIdRequest);
    // if(!idResult.IsSuccess())
    //{
    //    qCWarning(mqttAwsWebsocket) << "(GetCredentialsForIdentity): "
    //                                <<
    //                                credForIdResult.GetError().GetExceptionName().c_str()
    //                                << ":"
    //                                <<
    //                                credForIdResult.GetError().GetMessage().c_str();
    //    // throw
    //}
    //
    // qDebug() << "COGNITO STS TOKEN RESULTS";
    // qDebug() << "cognitoClient->GetId: " << idResult.IsSuccess();
    // qDebug() << "cognitoClient->GetCredentialsForIdentity: " <<
    // credForIdResult.IsSuccess(); credentials =
    // credForIdResult.GetResult().GetCredentials();
    ///////////////////////////////////////////////////////////////////////////
    // QThread::sleep(5);

    credentials = cognitoAuth.GetAWSCredentials();

    qDebug() << credentials.IsEmpty() << tries;
    qDebug() << credentials.GetAWSAccessKeyId().c_str();
    qDebug() << credentials.GetAWSSecretKey().c_str();
    qDebug() << credentials.GetSessionToken().c_str();
    qDebug() << credentials.IsExpired()
             << credentials.GetExpiration()
                    .ToLocalTimeString(Aws::Utils::DateFormat::RFC822)
                    .c_str();
  }
  Aws::ShutdownAPI(options);

  return credentials;
}

int main(int argc, char **argv) {
  // Comment just this line and the problem is fixed.
  QCoreApplication app(argc, argv);

  getSTS("<PAST_OPEN_ID_TOKEN_GOTTEN_FROM_REAL_APP>");
  return 0;
}
  

CMakeLists.txt

 cmake_minimum_required(VERSION 3.5)

project(aws-sts LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt5 COMPONENTS Core)

set(BUILD_SHARED_LIBS ON)
find_package(AWSSDK REQUIRED COMPONENTS identity-management)

add_executable(aws-sts main.cpp)

target_link_libraries(aws-sts PRIVATE
    Qt5::Core
    ${AWSSDK_LINK_LIBRARIES}
    )
  

Обновить

Я упростил минимальный рабочий пример, поскольку на самом деле для воспроизведения поведения достаточно просто добавить (или прокомментировать ot) QCoreApplication app(argc, argv); . Я имею в виду только создание объекта, нет необходимости, чтобы он был QGuiApplication или запускал цикл событий app.exec() .

Комментарии:

1. По моему опыту, такие проблемы связаны с задержками и сроками. Попробуйте добавить некоторый код распечатки, задержки и т. Д.

2. Я попытался вызвать getSTS() QTimer. Кроме того, вся работа выполняется с помощью SDK credentials = cognitoAuth.GetAWSCredentials(); . Я попытался добавить некоторые QThread::sleep(5); здесь и там, но безуспешно (как в прокомментированной части между GetId GetCredentialsForIdentity запросами and вместо вызова cognitoAuth.GetAWSCredentials(); ).

3. Я бы сравнил данные, отправленные в 2 режимах, используя Wireshark или какой-либо аналогичный инструмент.

4. У вас есть хороший учебник по wireshark для просмотра зашифрованных (https) пакетов? Также в журнале AWS я получаю ответный пакет от CURL. «Обходным путем» может быть запрос учетных данных aws, ожидание возврата пустого объекта и … анализ последнего журнала.

Ответ №1:

Оказывается, что aws sdk использует cJSON, который при разборе чисел может получать или не получать локальную среду для декодирования десятичной точки. Но в обоих случаях он будет вызывать double strtod(const char *nptr, char **endptr); преобразование строки в double, на странице руководства, которую мы можем прочитать (выделение мое)

Десятичное число состоит из непустой последовательности десятичных цифр, возможно, содержащей символ основания (десятичная точка, зависящая от локали, обычно ‘.’), за которым необязательно следует десятичный показатель степени. […]

По-видимому, cJSON нужна эта переменная компиляции для компиляции на Android.

AWS скопировал здесь библиотеку, но не скопировал переменную компиляции ENABLE_LOCALES , которая должна быть включена по умолчанию, как указано в проблеме, связанной выше.

Я на Ubuntu 18.04, среда на английском языке, но даты / число на французском (десятичная точка находится ',' здесь, во Франции).

Я создаю проблему в репозитории AWS SDK для установки переменной компиляции ENABLE_LOCALES и в cJSON для обсуждения и предотвращения дальнейших ошибок, подобных этой.

Потенциальным исправлением также может быть принудительное использование приложением английских языков, но это не всегда возможно.