Added: Get configuration for OAuth2 service account.

This commit is contained in:
Преподобный Ален
2022-09-11 19:38:08 +03:00
parent 0a5cfdf325
commit fb2e9c5cb5
4 changed files with 306 additions and 121 deletions

View File

@@ -56,8 +56,7 @@ namespace Apostol {
CWebService::InitMethods();
//InitServerList();
Reload();
InitServerList();
}
//--------------------------------------------------------------------------------------------------------------
@@ -125,41 +124,116 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
void CWebService::UpdateOAuth2() {
const auto &oauth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
const auto &provider = CString(SYSTEM_PROVIDER_NAME);
const auto &application = CString(SERVICE_APPLICATION_NAME);
void CWebService::FetchOAuth2(CContext &Context) {
Log()->Debug(APP_LOG_DEBUG_CORE, "Trying to fetch a OAuth2 configuration file for module \"%s\" from: %s", Context.Name().c_str(), Context.URL().Origin().c_str());
auto OnRequest = [this, &Context](CHTTPClient *Sender, CHTTPRequest *ARequest) {
ARequest->ContentType = CHTTPRequest::text;
Apostol::PGP::CleartextSignature(
m_pgpPrivateKey,
m_pgpPassphrase,
BPS_PGP_HASH,
Context.Name(),
ARequest->Content);
CHTTPRequest::Prepare(ARequest, "POST", "/api/v1/dm/service");
const auto& caModuleAddress = m_Module["address"];
if (!caModuleAddress.IsEmpty())
ARequest->AddHeader("Module-Address", caModuleAddress);
DebugRequest(ARequest);
};
auto OnExecute = [this, &Context](CTCPConnection *AConnection) {
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
if (pConnection != nullptr) {
auto pReply = pConnection->Reply();
DebugReply(pReply);
if (Context.Status() == Context::csPreparing) {
if (pReply->Status == CHTTPReply::ok) {
const CJSON Json(pReply->Content);
Json.SaveToFile(m_OAuth2.c_str());
UpdateOAuth2(m_OAuth2);
} else {
Context.SetStatus(Context::csInitialization);
}
}
pConnection->CloseConnection(true);
}
return true;
};
auto OnException = [&Context](CTCPConnection *AConnection, const Delphi::Exception::Exception &E) {
auto pConnection = dynamic_cast<CHTTPClientConnection *> (AConnection);
if (pConnection != nullptr) {
auto pClient = dynamic_cast<CHTTPClient *> (pConnection->Client());
if (pClient != nullptr) {
Log()->Error(APP_LOG_EMERG, 0, "[%s:%d] %s", pClient->Host().c_str(), pClient->Port(), E.what());
}
DebugReply(pConnection->Reply());
}
Context.SetStatus(Context::csInitialization);
};
Context.SetStatus(Context::csPreparing);
auto pClient = GetClient(Context.URL().hostname, Context.URL().port == 0 ? BPS_SERVER_PORT : Context.URL().port);
pClient->OnRequest(OnRequest);
pClient->OnExecute(OnExecute);
pClient->OnException(OnException);
pClient->AutoFree(true);
pClient->Active(true);
}
//--------------------------------------------------------------------------------------------------------------
void CWebService::UpdateOAuth2(const CString &FileName) {
for (int i = 0; i < m_Servers.Count(); i++) {
auto &Context = m_Servers[i].Value();
if (!oauth2.empty() && Context.Status() == Context::csInitialization) {
LoadOAuth2(oauth2, provider, application, Context.Providers());
Context.SetStatus(Context::csInitialized);
if (Context.Status() == Context::csInitialization || Context.Status() == Context::csPreparing) {
if (LoadOAuth2(FileName, Context.Providers())) {
Context.SetStatus(Context::csInitialized);
Context.SetCheckDate(0);
} else {
if (Context.Status() != Context::csPreparing) {
FetchOAuth2(Context);
}
}
}
Context.SetCheckDate(0);
}
}
//--------------------------------------------------------------------------------------------------------------
void CWebService::LoadOAuth2(const CString &FileName, const CString &ProviderName, const CString &ApplicationName, CProviders &Providers) {
CString ConfigFile(FileName);
bool CWebService::LoadOAuth2(const CString &FileName, CProviders &Providers) {
const auto &caProviderName = CString(SYSTEM_PROVIDER_NAME);
const auto &caApplicationName = CString(SERVICE_APPLICATION_NAME);
if (!path_separator(ConfigFile.front())) {
ConfigFile = Config()->Prefix() + ConfigFile;
}
if (FileExists(ConfigFile.c_str())) {
if (FileExists(FileName.c_str())) {
CJSONObject Json;
Json.LoadFromFile(ConfigFile.c_str());
Json.LoadFromFile(FileName.c_str());
int index = Providers.IndexOfName(ProviderName);
int index = Providers.IndexOfName(caProviderName);
if (index == -1)
index = Providers.AddPair(ProviderName, CProvider(ProviderName));
index = Providers.AddPair(caProviderName, CProvider(caProviderName));
auto& Provider = Providers[index].Value();
Provider.Applications().AddPair(ApplicationName, Json);
} else {
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, ConfigFile.c_str());
Provider.Applications().AddPair(caApplicationName, Json);
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
@@ -650,21 +724,12 @@ namespace Apostol {
caClearText = pServerRequest->Content;
}
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
if (!FileExists(caPGPPrivateFile.c_str()))
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
CString sPGPPrivate;
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
if (pgpValue == "off" || pgpValue == "false") {
sPayload = caClearText.Text();
} else {
Apostol::PGP::CleartextSignature(
sPGPPrivate,
caPGPPassphrase,
m_pgpPrivateKey,
m_pgpPassphrase,
BPS_PGP_HASH,
caClearText.Text(),
sPayload);
@@ -1105,23 +1170,14 @@ namespace Apostol {
CheckDeal(Deal);
const auto& caPGPPrivateFile = Config()->IniFile().ReadString("pgp", "private", "");
const auto& caPGPPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
if (!FileExists(caPGPPrivateFile.c_str()))
throw Delphi::Exception::Exception("PGP: Private key file not opened.");
CString sPGPPrivate;
sPGPPrivate.LoadFromFile(caPGPPrivateFile.c_str());
const CString caClearText(YAML::Dump(Node));
if (pgpValue == "off" || pgpValue == "false") {
sPayload = caClearText;
} else {
Apostol::PGP::CleartextSignature(
sPGPPrivate,
caPGPPassphrase,
m_pgpPrivateKey,
m_pgpPassphrase,
BPS_PGP_HASH,
caClearText,
sPayload);
@@ -1157,7 +1213,9 @@ namespace Apostol {
if (!caOrigin.IsEmpty())
pProxyRequest->AddHeader("Origin", caOrigin);
AConnection->UpdateTimeOut(Now(), 60);
AConnection->TimeOutInterval(30 * 1000);
AConnection->UpdateTimeOut(Now());
AConnection->CloseConnection(false);
pProxy->Active(true);
@@ -1638,6 +1696,7 @@ namespace Apostol {
pClient->OnExecute(OnExecute);
pClient->OnException(OnException);
pClient->AutoFree(true);
pClient->Active(true);
}
//--------------------------------------------------------------------------------------------------------------
@@ -1645,16 +1704,30 @@ namespace Apostol {
void CWebService::Reload() {
Config()->IniFile().ReadSectionValues("module", &m_Module);
m_OAuth2 = Config()->IniFile().ReadString(CONFIG_SECTION_NAME, "oauth2", "oauth2/service.json");
if (!path_separator(m_OAuth2.front())) {
m_OAuth2 = Config()->Prefix() + m_OAuth2;
}
const auto& caPrivateKey = Config()->IniFile().ReadString("pgp", "private", "module.sec");
const auto& caPublicKey = Config()->IniFile().ReadString("pgp", "public", "dm.pub");
if (FileExists(caPublicKey.c_str())) {
CString Key;
Key.LoadFromFile(caPublicKey.c_str());
m_pgpPassphrase = Config()->IniFile().ReadString("pgp", "passphrase", "");
UpdateServerList(Key);
UpdateOAuth2();
if (FileExists(caPrivateKey.c_str())) {
m_pgpPrivateKey.LoadFromFile(caPrivateKey.c_str());
if (FileExists(caPublicKey.c_str())) {
CString Key;
Key.LoadFromFile(caPublicKey.c_str());
UpdateServerList(Key);
UpdateOAuth2(m_OAuth2);
} else {
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
}
} else {
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPublicKey.c_str());
Log()->Error(APP_LOG_WARN, 0, APP_FILE_NOT_FOUND, caPrivateKey.c_str());
}
}
//--------------------------------------------------------------------------------------------------------------
@@ -1663,14 +1736,19 @@ namespace Apostol {
for (int i = 0; i < m_Servers.Count(); i++) {
auto &Context = m_Servers[i].Value();
if (Now >= Context.CheckDate()) {
if ((Now >= Context.CheckDate()) && (Context.Status() == Context::csInitialization)) {
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
if (Context.Status() != Context::csAuthorization) {
FetchOAuth2(Context);
}
if ((Now >= Context.CheckDate()) && (Context.Status() >= Context::csInitialized)) {
Context.SetCheckDate(Now + (CDateTime) 30 / SecsPerDay); // 30 sec
if (Context.Status() == Context::csInitialized)
Context.SetStatus(Context::csAuthorization);
CheckProviders(Now, Context);
FetchProviders(Now, Context);
}
CheckProviders(Now, Context);
FetchProviders(Now, Context);
}
if (Context.Status() == Context::csAuthorized) {
@@ -1682,7 +1760,7 @@ namespace Apostol {
}
}
if (Context.Status() >= Context::csAuthorized) {
if (Context.Status() == Context::csRunning) {
if (Now >= m_NexServerTime) {
m_NexServerTime = GetRandomDate(10 * 60, m_SyncPeriod * 60, Now);
m_CurrentServer = Context;
@@ -1692,6 +1770,15 @@ namespace Apostol {
}
//--------------------------------------------------------------------------------------------------------------
void CWebService::Initialization(CModuleProcess *AProcess) {
CApostolModule::Initialization(AProcess);
if (Enabled()) {
Reload();
}
}
//--------------------------------------------------------------------------------------------------------------
bool CWebService::Enabled() {
if (m_ModuleStatus == msUnknown)
m_ModuleStatus = Config()->IniFile().ReadBool(SectionName().c_str(), "enable", true) ? msEnabled : msDisabled;