AWSClientAuth updated to use custom CognitoCachingCredentialsProvider (#5525)

Signed-off-by: Stanko <stankoa@amazon.com>
monroegm-disable-blank-issue-2
allisaurus 4 years ago committed by GitHub
parent 6651ae3d78
commit 3ad07a2295
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -12,6 +12,7 @@ import pytest
import ly_test_tools.log.log_monitor import ly_test_tools.log.log_monitor
from AWS.common import constants from AWS.common import constants
from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
# fixture imports # fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
@ -70,6 +71,41 @@ class TestAWSClientAuthWindows(object):
halt_on_unexpected=True, halt_on_unexpected=True,
) )
assert result, 'Anonymous credentials fetched successfully.' assert result, 'Anonymous credentials fetched successfully.'
@pytest.mark.parametrize('level', ['AWS/ClientAuth'])
def test_anonymous_credentials_no_global_accountid(self,
level: str,
launcher: pytest.fixture,
resource_mappings: pytest.fixture,
workspace: pytest.fixture,
asset_processor: pytest.fixture
):
"""
Test to verify AWS Cognito Identity pool anonymous authorization.
Setup: Updates resource mapping file using existing CloudFormation stacks.
Tests: Getting credentials when no credentials are configured
Verification: Log monitor looks for success credentials log.
"""
# Remove top-level account ID from resource mappings
resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
asset_processor.start()
asset_processor.wait_for_idle()
file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', level]
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(
expected_lines=['(Script) - Success anonymous credentials'],
unexpected_lines=['(Script) - Fail anonymous credentials'],
halt_on_unexpected=True,
)
assert result, 'Anonymous credentials fetched successfully.'
def test_password_signin_credentials(self, def test_password_signin_credentials(self,
launcher: pytest.fixture, launcher: pytest.fixture,

@ -0,0 +1,44 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
namespace AWSClientAuth
{
//! Cognito Caching Credentials Provider implementation that is derived from AWS Native SDK.
//! For use with authenticated credentials.
class AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider
: public Aws::Auth::CognitoCachingCredentialsProvider
{
public:
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient = nullptr);
protected:
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome GetCredentialsFromCognito() const override;
};
//! Cognito Caching Credentials Provider implementation that is eventually derived from AWS Native SDK.
//! For use with anonymous credentials.
class AWSClientAuthCachingAnonymousCredsProvider : public AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider
{
public:
AWSClientAuthCachingAnonymousCredsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient = nullptr);
protected:
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome GetCredentialsFromCognito() const override;
};
} // namespace AWSClientAuth

@ -9,6 +9,7 @@
#pragma once #pragma once
#include <Authorization/AWSCognitoAuthorizationBus.h> #include <Authorization/AWSCognitoAuthorizationBus.h>
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h> #include <Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h>
#include <Authentication/AuthenticationProviderBus.h> #include <Authentication/AuthenticationProviderBus.h>
#include <Credential/AWSCredentialBus.h> #include <Credential/AWSCredentialBus.h>
@ -51,8 +52,8 @@ namespace AWSClientAuth
std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentCognitoIdentityProvider; std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentCognitoIdentityProvider;
std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentAnonymousCognitoIdentityProvider; std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentAnonymousCognitoIdentityProvider;
std::shared_ptr<Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider> m_cognitoCachingCredentialsProvider; std::shared_ptr<AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider> m_cognitoCachingCredentialsProvider;
std::shared_ptr<Aws::Auth::CognitoCachingAnonymousCredentialsProvider> m_cognitoCachingAnonymousCredentialsProvider; std::shared_ptr<AWSClientAuthCachingAnonymousCredsProvider> m_cognitoCachingAnonymousCredentialsProvider;
AZStd::string m_cognitoIdentityPoolId; AZStd::string m_cognitoIdentityPoolId;
AZStd::string m_formattedCognitoUserPoolId; AZStd::string m_formattedCognitoUserPoolId;

@ -0,0 +1,122 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <AzCore/Debug/Trace.h>
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/cognito-identity/model/GetCredentialsForIdentityRequest.h>
#include <aws/cognito-identity/model/GetIdRequest.h>
#include <aws/core/utils/Outcome.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
namespace AWSClientAuth
{
static const char* AUTH_LOG_TAG = "AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider";
static const char* ANON_LOG_TAG = "AWSClientAuthCachingAnonymousCredsProvider";
// Modification of https://github.com/aws/aws-sdk-cpp/blob/main/aws-cpp-sdk-identity-management/source/auth/CognitoCachingCredentialsProvider.cpp#L92
// to work around account ID requirement. Account id is not required for call to succeed and is not set unless provided.
// see: https://github.com/aws/aws-sdk-cpp/issues/1448
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome FetchCredsFromCognito(
const Aws::CognitoIdentity::CognitoIdentityClient& cognitoIdentityClient,
Aws::Auth::PersistentCognitoIdentityProvider& identityRepository,
const char* logTag,
bool includeLogins)
{
auto logins = identityRepository.GetLogins();
Aws::Map<Aws::String, Aws::String> cognitoLogins;
for (auto& login : logins)
{
cognitoLogins[login.first] = login.second.accessToken;
}
if (!identityRepository.HasIdentityId())
{
auto accountId = identityRepository.GetAccountId();
auto identityPoolId = identityRepository.GetIdentityPoolId();
Aws::CognitoIdentity::Model::GetIdRequest getIdRequest;
getIdRequest.SetIdentityPoolId(identityPoolId);
if (!accountId.empty()) // new check
{
getIdRequest.SetAccountId(accountId);
AWS_LOGSTREAM_INFO(logTag, "Identity not found, requesting an id for accountId "
<< accountId << " identity pool id "
<< identityPoolId << " with logins.");
}
else
{
AWS_LOGSTREAM_INFO(
logTag, "Identity not found, requesting an id for identity pool id %s" << identityPoolId << " with logins.");
}
if (includeLogins)
{
getIdRequest.SetLogins(cognitoLogins);
}
auto getIdOutcome = cognitoIdentityClient.GetId(getIdRequest);
if (getIdOutcome.IsSuccess())
{
auto identityId = getIdOutcome.GetResult().GetIdentityId();
AWS_LOGSTREAM_INFO(logTag, "Successfully retrieved identity: " << identityId);
identityRepository.PersistIdentityId(identityId);
}
else
{
AWS_LOGSTREAM_ERROR(
logTag,
"Failed to retrieve identity. Error: " << getIdOutcome.GetError().GetExceptionName() << " "
<< getIdOutcome.GetError().GetMessage());
return Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome(getIdOutcome.GetError());
}
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityRequest getCredentialsForIdentityRequest;
getCredentialsForIdentityRequest.SetIdentityId(identityRepository.GetIdentityId());
if (includeLogins)
{
getCredentialsForIdentityRequest.SetLogins(cognitoLogins);
}
return cognitoIdentityClient.GetCredentialsForIdentity(getCredentialsForIdentityRequest);
}
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider::AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient)
: CognitoCachingCredentialsProvider(identityRepository, cognitoIdentityClient)
{
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider::GetCredentialsFromCognito() const
{
return FetchCredsFromCognito(*m_cognitoIdentityClient, *m_identityRepository, AUTH_LOG_TAG, true);
}
AWSClientAuthCachingAnonymousCredsProvider::AWSClientAuthCachingAnonymousCredsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient)
: AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(identityRepository, cognitoIdentityClient)
{
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome AWSClientAuthCachingAnonymousCredsProvider::
GetCredentialsFromCognito() const
{
return FetchCredsFromCognito(*m_cognitoIdentityClient, *m_identityRepository, ANON_LOG_TAG, false);
}
} // namespace AWSClientAuth

@ -8,6 +8,7 @@
#include <AWSClientAuthBus.h> #include <AWSClientAuthBus.h>
#include <AWSCoreBus.h> #include <AWSCoreBus.h>
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <Authorization/AWSCognitoAuthorizationController.h> #include <Authorization/AWSCognitoAuthorizationController.h>
#include <ResourceMapping/AWSResourceMappingBus.h> #include <ResourceMapping/AWSResourceMappingBus.h>
#include <AWSClientAuthResourceMappingConstants.h> #include <AWSClientAuthResourceMappingConstants.h>
@ -38,10 +39,12 @@ namespace AWSClientAuth
auto identityClient = AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIdentityClient(); auto identityClient = AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIdentityClient();
m_cognitoCachingCredentialsProvider = m_cognitoCachingCredentialsProvider =
std::make_shared<Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider>(m_persistentCognitoIdentityProvider, identityClient); std::make_shared<AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider>(
m_persistentCognitoIdentityProvider, identityClient);
m_cognitoCachingAnonymousCredentialsProvider = m_cognitoCachingAnonymousCredentialsProvider =
std::make_shared<Aws::Auth::CognitoCachingAnonymousCredentialsProvider>(m_persistentAnonymousCognitoIdentityProvider, identityClient); std::make_shared<AWSClientAuthCachingAnonymousCredsProvider>(
m_persistentAnonymousCognitoIdentityProvider, identityClient);
} }
AWSCognitoAuthorizationController::~AWSCognitoAuthorizationController() AWSCognitoAuthorizationController::~AWSCognitoAuthorizationController()
@ -65,9 +68,13 @@ namespace AWSClientAuth
AWSCore::AWSResourceMappingRequestBus::BroadcastResult( AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoIdentityPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoIdentityPoolIdResourceMappingKey); m_cognitoIdentityPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoIdentityPoolIdResourceMappingKey);
if (m_awsAccountId.empty() || m_cognitoIdentityPoolId.empty()) if (m_awsAccountId.empty())
{
AZ_TracePrintf("AWSCognitoAuthorizationController", "AWS account id not not configured. Proceeding without it.");
}
if (m_cognitoIdentityPoolId.empty())
{ {
AZ_Warning("AWSCognitoAuthorizationController", !m_awsAccountId.empty(), "Missing AWS account id not configured.");
AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings."); AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings.");
return false; return false;
} }

@ -62,6 +62,14 @@ TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Success)
ASSERT_TRUE(m_mockController->m_cognitoIdentityPoolId == AWSClientAuthUnitTest::TEST_RESOURCE_NAME_ID); ASSERT_TRUE(m_mockController->m_cognitoIdentityPoolId == AWSClientAuthUnitTest::TEST_RESOURCE_NAME_ID);
} }
TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Success_GetAWSAccountEmpty)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(2);
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1).WillOnce(testing::Return(""));
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultRegion()).Times(1);
ASSERT_TRUE(m_mockController->Initialize());
}
TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_WithLogins_Success) TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_WithLogins_Success)
{ {
AWSClientAuth::AuthenticationTokens tokens( AWSClientAuth::AuthenticationTokens tokens(
@ -121,7 +129,7 @@ TEST_F(AWSCognitoAuthorizationControllerTest, MultipleCalls_UsesCacheCredentials
m_mockController->RequestAWSCredentialsAsync(); m_mockController->RequestAWSCredentialsAsync();
} }
TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_Fail_GetIdError) TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_Fail_GetIdError) // fail
{ {
AWSClientAuth::AuthenticationTokens cognitoTokens( AWSClientAuth::AuthenticationTokens cognitoTokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
@ -321,7 +329,7 @@ TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersisted
EXPECT_TRUE(actualCredentialsProvider == m_mockController->m_cognitoCachingAnonymousCredentialsProvider); EXPECT_TRUE(actualCredentialsProvider == m_mockController->m_cognitoCachingAnonymousCredentialsProvider);
} }
TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersistedLogins_NoAnonymousCredentials_ResultNullPtr) TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersistedLogins_NoAnonymousCredentials_ResultNullPtr) // fails
{ {
Aws::Client::AWSError<Aws::CognitoIdentity::CognitoIdentityErrors> error; Aws::Client::AWSError<Aws::CognitoIdentity::CognitoIdentityErrors> error;
error.SetExceptionName(AWSClientAuthUnitTest::TEST_EXCEPTION); error.SetExceptionName(AWSClientAuthUnitTest::TEST_EXCEPTION);
@ -431,11 +439,3 @@ TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Fail_GetResourceNameEmp
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1); EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1);
ASSERT_FALSE(m_mockController->Initialize()); ASSERT_FALSE(m_mockController->Initialize());
} }
TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Fail_GetAWSAccountEmpty)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1);
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1).WillOnce(testing::Return(""));
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultRegion()).Times(0);
ASSERT_FALSE(m_mockController->Initialize());
}

@ -24,6 +24,7 @@ set(FILES
Include/Private/Authorization/AWSCognitoAuthorizationController.h Include/Private/Authorization/AWSCognitoAuthorizationController.h
Include/Private/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h Include/Private/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h
Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h
Include/Private/Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h
Include/Private/UserManagement/AWSCognitoUserManagementController.h Include/Private/UserManagement/AWSCognitoUserManagementController.h
Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h
@ -45,6 +46,7 @@ set(FILES
Source/Authorization/ClientAuthAWSCredentials.cpp Source/Authorization/ClientAuthAWSCredentials.cpp
Source/Authorization/AWSCognitoAuthorizationController.cpp Source/Authorization/AWSCognitoAuthorizationController.cpp
Source/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.cpp Source/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.cpp
Source/Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.cpp
Source/UserManagement/AWSCognitoUserManagementController.cpp Source/UserManagement/AWSCognitoUserManagementController.cpp
) )

Loading…
Cancel
Save