Add required support for GameLift TLS certificate (#7564)

* Add required support for GameLift TLS certificate
* Update based on feedback
This commit is contained in:
Vincent Liu
2022-02-17 13:44:44 -08:00
committed by GitHub
parent bc2589f3e8
commit 2589cb20e5
12 changed files with 227 additions and 43 deletions
@@ -406,8 +406,30 @@ namespace AWSGameLift
AZ::IO::Path AWSGameLiftServerManager::GetExternalSessionCertificate()
{
// TODO: Add support to get TLS cert file path
return AZ::IO::Path();
auto certificateOutcome = m_gameLiftServerSDKWrapper->GetInstanceCertificate();
if (certificateOutcome.IsSuccess())
{
return AZ::IO::Path(certificateOutcome.GetResult().GetCertificatePath().c_str());
}
else
{
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerInstanceCertificateErrorMessage);
return AZ::IO::Path();
}
}
AZ::IO::Path AWSGameLiftServerManager::GetExternalSessionPrivateKey()
{
auto certificateOutcome = m_gameLiftServerSDKWrapper->GetInstanceCertificate();
if (certificateOutcome.IsSuccess())
{
return AZ::IO::Path(certificateOutcome.GetResult().GetPrivateKeyPath().c_str());
}
else
{
AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerInstancePrivateKeyErrorMessage);
return AZ::IO::Path();
}
}
AZ::IO::Path AWSGameLiftServerManager::GetInternalSessionCertificate()
@@ -416,6 +438,12 @@ namespace AWSGameLift
return AZ::IO::Path();
}
AZ::IO::Path AWSGameLiftServerManager::GetInternalSessionPrivateKey()
{
// GameLift doesn't support it, return empty path
return AZ::IO::Path();
}
void AWSGameLiftServerManager::InitializeGameLiftServerSDK()
{
if (m_serverSDKInitialized)
@@ -537,6 +565,10 @@ namespace AWSGameLift
{
UpdateGameSessionData(gameSession);
Multiplayer::SessionConfig sessionConfig = BuildSessionConfig(gameSession);
if (!AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get())
{
AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Register(this);
}
bool createSessionResult = true;
AZ::EBusReduceResult<bool&, AZStd::logical_and<bool>> result(createSessionResult);
@@ -551,11 +583,6 @@ namespace AWSGameLift
if (activationOutcome.IsSuccess())
{
AZ_TracePrintf(AWSGameLiftServerManagerName, "ActivateGameSession request against Amazon GameLift service succeeded.");
// Register server manager as handler once game session has been activated
if (!AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get())
{
AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Register(this);
}
Multiplayer::SessionNotificationBus::Broadcast(&Multiplayer::SessionNotifications::OnCreateSessionEnd);
}
else
@@ -56,6 +56,10 @@ namespace AWSGameLift
static constexpr const char AWSGameLiftServerPlayerConnectionMissingErrorMessage[] =
"Player connection id %d does not exist.";
static constexpr const char AWSGameLiftServerInstanceCertificateErrorMessage[] =
"Failed to locate Amazon GameLift TLS certificate file.";
static constexpr const char AWSGameLiftServerInstancePrivateKeyErrorMessage[] =
"Failed to locate Amazon GameLift TLS private key file.";
static constexpr const char AWSGameLiftServerInitSDKErrorMessage[] =
"Failed to initialize Amazon GameLift Server SDK. ErrorMessage: %s";
static constexpr const char AWSGameLiftServerProcessReadyErrorMessage[] =
@@ -120,7 +124,9 @@ namespace AWSGameLift
bool ValidatePlayerJoinSession(const Multiplayer::PlayerConnectionConfig& playerConnectionConfig) override;
void HandlePlayerLeaveSession(const Multiplayer::PlayerConnectionConfig& playerConnectionConfig) override;
AZ::IO::Path GetExternalSessionCertificate() override;
AZ::IO::Path GetExternalSessionPrivateKey() override;
AZ::IO::Path GetInternalSessionCertificate() override;
AZ::IO::Path GetInternalSessionPrivateKey() override;
protected:
void SetGameLiftServerSDKWrapper(AZStd::unique_ptr<GameLiftServerSDKWrapper> gameLiftServerSDKWrapper);
@@ -33,6 +33,11 @@ namespace AWSGameLift
return Aws::GameLift::Server::InitSDK();
}
Aws::GameLift::GetInstanceCertificateOutcome GameLiftServerSDKWrapper::GetInstanceCertificate()
{
return Aws::GameLift::Server::GetInstanceCertificate();
}
Aws::GameLift::GenericOutcome GameLiftServerSDKWrapper::ProcessReady(
const Aws::GameLift::Server::ProcessParameters& processParameters)
{
@@ -41,6 +41,13 @@ namespace AWSGameLift
virtual Aws::GameLift::DescribePlayerSessionsOutcome DescribePlayerSessions(
const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest& describePlayerSessionsRequest);
//! Retrieves the file location of a pem-encoded TLS certificate that is associated with the fleet and its
//! instances. This certificate is generated when a new fleet is created with the certificate configuration set to
//! GENERATED. Use this certificate to establish a secure connection with a game client and to encrypt client server communication.
//! @return If successful, returns a GetInstanceCertificateOutcome object containing the location of the fleet's TLS certificate file,
//! which is stored on the instance. If not successful, returns an error message.
virtual Aws::GameLift::GetInstanceCertificateOutcome GetInstanceCertificate();
//! Initializes the GameLift SDK.
//! Should be called when the server starts, before any GameLift-dependent initialization happens.
//! @return If successful, returns an InitSdkOutcome object indicating that the server process is ready to call ProcessReady().
@@ -356,10 +356,12 @@ R"({
EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(false));
EXPECT_CALL(handlerMock, OnCreateSessionEnd()).Times(0);
EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(handlerMock, OnDestroySessionEnd()).Times(1);
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessEnding()).Times(1);
AZ_TEST_START_TRACE_SUPPRESSION;
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onStartGameSessionFunc(Aws::GameLift::Server::Model::GameSession());
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_FALSE(AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get());
}
TEST_F(GameLiftServerManagerTest, OnStartGameSession_ActivateGameSessionSucceeds_RegisterAsHandler)
@@ -369,7 +371,6 @@ R"({
SessionNotificationsHandlerMock handlerMock;
EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(handlerMock, OnCreateSessionEnd()).Times(1);
EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ActivateGameSession())
.Times(1)
.WillOnce(testing::Return(Aws::GameLift::GenericOutcome(nullptr)));
@@ -380,7 +381,13 @@ R"({
testSession.AddGameProperties(testProperty);
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onStartGameSessionFunc(testSession);
EXPECT_TRUE(AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get());
// clean up
EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(handlerMock, OnDestroySessionEnd()).Times(1);
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ProcessEnding()).Times(1);
m_serverManager->HandleDestroySession();
EXPECT_FALSE(AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get());
}
TEST_F(GameLiftServerManagerTest, OnStartGameSession_ActivateGameSessionFails_TerminationNotificationSent)
@@ -391,6 +398,7 @@ R"({
EXPECT_CALL(handlerMock, OnCreateSessionBegin(testing::_)).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(handlerMock, OnCreateSessionEnd()).Times(0);
EXPECT_CALL(handlerMock, OnDestroySessionBegin()).Times(1).WillOnce(testing::Return(true));
EXPECT_CALL(handlerMock, OnDestroySessionEnd()).Times(1);
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), ActivateGameSession())
.Times(1)
.WillOnce(testing::Return(Aws::GameLift::GenericOutcome()));
@@ -398,6 +406,7 @@ R"({
AZ_TEST_START_TRACE_SUPPRESSION;
m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onStartGameSessionFunc(Aws::GameLift::Server::Model::GameSession());
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_FALSE(AZ::Interface<Multiplayer::ISessionHandlingProviderRequests>::Get());
}
TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithUnknownReason_OnUpdateSessionGetCalledOnce)
@@ -735,6 +744,72 @@ R"({
EXPECT_TRUE(actualResult[0].m_playerAttributes.size() == 4);
}
TEST_F(GameLiftServerManagerTest, GetExternalSessionCertificate_CallWithTLSEnabled_GetExpectedResult)
{
AZStd::string expectedResult = "gameliftunittestcertificate.pem";
Aws::GameLift::Server::Model::GetInstanceCertificateResult certificateResult;
certificateResult.SetCertificatePath(expectedResult.c_str());
Aws::GameLift::GetInstanceCertificateOutcome certificateOutcome(certificateResult);
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), GetInstanceCertificate())
.Times(1)
.WillOnce(Return(certificateOutcome));
auto actualResult = m_serverManager->GetExternalSessionCertificate();
EXPECT_STREQ(actualResult.c_str(), expectedResult.c_str());
}
TEST_F(GameLiftServerManagerTest, GetExternalSessionCertificate_CallWithTLSDisabled_GetEmptyResult)
{
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), GetInstanceCertificate())
.Times(1)
.WillOnce(Return(Aws::GameLift::GetInstanceCertificateOutcome()));
AZ_TEST_START_TRACE_SUPPRESSION;
auto actualResult = m_serverManager->GetExternalSessionCertificate();
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_STREQ(actualResult.c_str(), "");
}
TEST_F(GameLiftServerManagerTest, GetExternalSessionPrivateKey_CallWithTLSEnabled_GetExpectedResult)
{
AZStd::string expectedResult = "gameliftunittestprivatekey.pem";
Aws::GameLift::Server::Model::GetInstanceCertificateResult certificateResult;
certificateResult.SetPrivateKeyPath(expectedResult.c_str());
Aws::GameLift::GetInstanceCertificateOutcome certificateOutcome(certificateResult);
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), GetInstanceCertificate())
.Times(1)
.WillOnce(Return(certificateOutcome));
auto actualResult = m_serverManager->GetExternalSessionPrivateKey();
EXPECT_STREQ(actualResult.c_str(), expectedResult.c_str());
}
TEST_F(GameLiftServerManagerTest, GetExternalSessionPrivateKey_CallWithTLSDisabled_GetEmptyResult)
{
EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), GetInstanceCertificate())
.Times(1)
.WillOnce(Return(Aws::GameLift::GetInstanceCertificateOutcome()));
AZ_TEST_START_TRACE_SUPPRESSION;
auto actualResult = m_serverManager->GetExternalSessionPrivateKey();
AZ_TEST_STOP_TRACE_SUPPRESSION(1);
EXPECT_STREQ(actualResult.c_str(), "");
}
TEST_F(GameLiftServerManagerTest, GetInternalSessionCertificate_Call_GetEmptyResult)
{
auto actualResult = m_serverManager->GetInternalSessionCertificate();
EXPECT_STREQ(actualResult.c_str(), "");
}
TEST_F(GameLiftServerManagerTest, GetInternalSessionPrivateKey_Call_GetEmptyResult)
{
auto actualResult = m_serverManager->GetInternalSessionPrivateKey();
EXPECT_STREQ(actualResult.c_str(), "");
}
TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithMultiDescribePlayerButError_GetEmptyResult)
{
m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA, 50);
@@ -47,6 +47,7 @@ namespace UnitTest
MOCK_METHOD1(ProcessReady, GenericOutcome(const Server::ProcessParameters& processParameters));
MOCK_METHOD0(ProcessEnding, GenericOutcome());
MOCK_METHOD1(RemovePlayerSession, GenericOutcome(const AZStd::string& playerSessionId));
MOCK_METHOD0(GetInstanceCertificate, Aws::GameLift::GetInstanceCertificateOutcome());
MOCK_METHOD0(GetTerminationTime, AZStd::string());
MOCK_METHOD1(StartMatchBackfill, StartMatchBackfillOutcome(
const Aws::GameLift::Server::Model::StartMatchBackfillRequest&));