From 38e6e1bbcf9f366ae357c689081a8503ca1d5848 Mon Sep 17 00:00:00 2001 From: Ned Wright Date: Wed, 22 Feb 2023 17:20:21 +0000 Subject: [PATCH] Feb 22nd 2023 update --- .../nginx_attachment/nginx_attachment.cc | 80 +++++++-------- .../orchestration/orchestration_comp.cc | 9 +- .../orchestration_ut/orchestration_ut.cc | 2 +- .../waap/waap_clib/WaapAssetState.cc | 4 +- .../waap/waap_clib/WaapOverride.h | 18 ++++ .../waap/waap_clib/WaapOverrideFunctor.cc | 10 ++ .../waap_clib/WaapResponseInspectReasons.cc | 22 ++++- .../waap_clib/WaapResponseInspectReasons.h | 3 + .../waap/waap_clib/Waf2Engine.cc | 23 +++++ .../security_apps/waap/waap_clib/Waf2Engine.h | 2 + .../waap/waap_clib/Waf2EngineGetters.cc | 1 + .../security_apps/waap/waap_clib/Waf2Util.cc | 24 ++++- .../interfaces/i_tenant_manager.h | 6 +- .../interfaces/mock/mock_tenant_manager.h | 5 +- .../resources/report/report_enums.h | 2 + core/report/tag_and_enum_management.cc | 1 + core/tenant_manager/tenant_manager.cc | 98 +++++++++++++++---- 17 files changed, 234 insertions(+), 76 deletions(-) diff --git a/components/attachment-intakers/nginx_attachment/nginx_attachment.cc b/components/attachment-intakers/nginx_attachment/nginx_attachment.cc index 801c818..43b8221 100755 --- a/components/attachment-intakers/nginx_attachment/nginx_attachment.cc +++ b/components/attachment-intakers/nginx_attachment/nginx_attachment.cc @@ -266,6 +266,10 @@ public: setActiveTenantAndProfile() { string container_id = inst_awareness->getFamilyID().unpack(); + if (container_id.empty()) { + dbgWarning(D_NGINX_ATTACHMENT) << "Failed getting a family ID"; + return false; + } dbgTrace(D_NGINX_ATTACHMENT) << "Found a family ID: " << container_id; I_ShellCmd *shell_cmd = Singleton::Consume::by(); @@ -273,59 +277,45 @@ public: string cmd = "docker inspect --format='{{.Name}}' " + container_id + " | awk -F'cp_nginx_gaia' '{print substr($2, index($2, \" \"))}'"; - auto maybe_tenant_id = shell_cmd->getExecOutput(cmd, 1000, false); + auto maybe_tenant_profile_ids = shell_cmd->getExecOutput(cmd, 1000, false); + dbgTrace(D_NGINX_ATTACHMENT) << "Checking for tenant and profile IDs with the command: " << cmd; - if (maybe_tenant_id.ok()) { - - string tenant_id = *maybe_tenant_id; - tenant_id.erase(remove(tenant_id.begin(), tenant_id.end(), '\n'), tenant_id.end()); - dbgTrace(D_NGINX_ATTACHMENT) << "The tenant ID found is :" << tenant_id; - - static string region; - if (region.empty()) { - const char *env_region = getenv("CP_NSAAS_REGION"); - if (env_region) { - region = env_region; - } else { - region = getProfileAgentSettingWithDefault("eu-west-1", "accessControl.region"); - } - dbgInfo(D_NGINX_ATTACHMENT) << "Resolved region is " << region; - } - - string profile_id = Singleton::Consume::by()->getProfileId( - tenant_id, - region - ); - - if (!profile_id.empty()) { - i_env->setActiveTenantAndProfile(tenant_id, profile_id); - dbgTrace(D_NGINX_ATTACHMENT) - << "NGINX attachment setting active context. Tenant ID: " - << tenant_id - << ", Profile ID: " - << profile_id - << ", Region: " - << region; - return true; - } else { - dbgWarning(D_NGINX_ATTACHMENT) - << "Received an empty profile ID. Tenant ID: " - << tenant_id - << ", Region: " - << region; - - return false; - } - } else { + if (!maybe_tenant_profile_ids.ok()) { dbgWarning(D_NGINX_ATTACHMENT) - << "Failed getting the tenant ID: " + << "Failed getting the tenant and progile IDs: " << cmd << ". Error :" - << maybe_tenant_id.getErr(); + << maybe_tenant_profile_ids.getErr(); return false; } + dbgWarning(D_NGINX_ATTACHMENT) + << "Parsing the tenant and profile IDs from the container name: " + << maybe_tenant_profile_ids.unpack(); + + string tenant_profile_ids = maybe_tenant_profile_ids.unpack(); + tenant_profile_ids.erase( + remove(tenant_profile_ids.begin(), tenant_profile_ids.end(), '\n'), tenant_profile_ids.end() + ); + + size_t delimeter_pos = tenant_profile_ids.find("_"); + if (delimeter_pos == string::npos) { + dbgWarning(D_NGINX_ATTACHMENT) + << "Couldn't parse tenant and profile IDs from the container name: " + << tenant_profile_ids; + return false; + } + string tenant_id = tenant_profile_ids.substr(0, delimeter_pos); + string profile_id = tenant_profile_ids.substr(delimeter_pos + 1); + + i_env->setActiveTenantAndProfile(tenant_id, profile_id); + dbgTrace(D_NGINX_ATTACHMENT) + << "NGINX attachment setting active context. Tenant ID: " + << tenant_id + << ", Profile ID: " + << profile_id; + return true; } diff --git a/components/security_apps/orchestration/orchestration_comp.cc b/components/security_apps/orchestration/orchestration_comp.cc index 95f5859..6f734a4 100755 --- a/components/security_apps/orchestration/orchestration_comp.cc +++ b/components/security_apps/orchestration/orchestration_comp.cc @@ -124,7 +124,10 @@ private: map field_types_status; }; -class setAgentUninstall : public ServerRest +class SetAgentUninstall + : + public ServerRest, + Singleton::Consume { public: void @@ -132,11 +135,13 @@ public: { dbgTrace(D_ORCHESTRATOR) << "Send 'agent uninstall process started' log to fog"; setConfiguration(false, "Logging", "Enable bulk of logs"); + string profile_id = Singleton::Consume::by()->getProfileId(); LogGen log ( "Agent started uninstall process", Audience::INTERNAL, Severity::INFO, Priority::URGENT, + LogField("profileId", profile_id), LogField("issuingEngine", "agentUninstallProvider"), Tags::ORCHESTRATOR ); @@ -167,7 +172,7 @@ public: auto rest = Singleton::Consume::by(); rest->addRestCall(RestAction::SHOW, "orchestration-status"); rest->addRestCall(RestAction::ADD, "proxy"); - rest->addRestCall(RestAction::SET, "agent-uninstall"); + rest->addRestCall(RestAction::SET, "agent-uninstall"); // Main loop of the Orchestration. Singleton::Consume::by()->addOneTimeRoutine( I_MainLoop::RoutineType::RealTime, diff --git a/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc b/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc index daf9d2a..e80dc65 100755 --- a/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc +++ b/components/security_apps/orchestration/orchestration_ut/orchestration_ut.cc @@ -312,7 +312,7 @@ TEST_F(OrchestrationTest, testAgentUninstallRest) EXPECT_CALL( rest, mockRestCall(RestAction::ADD, "proxy", _) - ).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandler))); + ).WillOnce(WithArg<2>(Invoke(this, &OrchestrationTest::restHandler))); init(); diff --git a/components/security_apps/waap/waap_clib/WaapAssetState.cc b/components/security_apps/waap/waap_clib/WaapAssetState.cc index 74a889a..bef3892 100755 --- a/components/security_apps/waap/waap_clib/WaapAssetState.cc +++ b/components/security_apps/waap/waap_clib/WaapAssetState.cc @@ -726,7 +726,7 @@ checkBinaryData(const std::string &line, bool binaryDataFound) for (size_t i=0; i(); ar(cereal::make_nvp("operand2", *m_operand2)); + m_isOverrideResponse = m_operand1->m_isOverrideResponse || m_operand2->m_isOverrideResponse; } else if (m_op == "not") { // If op is "NOT" get one operand m_operand1 = std::make_shared(); ar(cereal::make_nvp("operand1", *m_operand1)); + m_isOverrideResponse = m_operand1->m_isOverrideResponse; } } } @@ -113,6 +116,10 @@ public: return false; } + bool isOverrideResponse() const { + return m_isOverrideResponse; + } + private: std::string m_op; std::shared_ptr m_operand1; @@ -122,6 +129,7 @@ private: std::shared_ptr m_valueRegex; Waap::Util::CIDRData m_cidr; bool m_isCidr; + bool m_isOverrideResponse; }; class Behavior @@ -233,6 +241,9 @@ public: bool isChangingRequestData() const { return m_isChangingRequestData; } + bool isOverrideResponse() const { + return m_match.isOverrideResponse(); + } const std::string &getId() const { return m_id; @@ -251,6 +262,7 @@ public: Policy(_A &ar) { std::vector rules; ar(cereal::make_nvp("overrides", rules)); + m_isOverrideResponse = false; for (std::vector::const_iterator it = rules.begin(); it != rules.end(); ++it) { const Waap::Override::Rule& rule = *it; @@ -262,6 +274,7 @@ public: { m_ResponseOverrides.push_back(rule); } + m_isOverrideResponse |= rule.isOverrideResponse(); } } @@ -282,9 +295,14 @@ public: dbgTrace(D_WAAP_OVERRIDE) << "Finished matching override rules."; } + bool isOverrideResponse() const { + return m_isOverrideResponse; + } + private: std::vector m_RequestOverrides; //overrides that change request data std::vector m_ResponseOverrides; //overrides that change response/log data + bool m_isOverrideResponse; }; struct State { diff --git a/components/security_apps/waap/waap_clib/WaapOverrideFunctor.cc b/components/security_apps/waap/waap_clib/WaapOverrideFunctor.cc index 9f46f44..f13ddc4 100755 --- a/components/security_apps/waap/waap_clib/WaapOverrideFunctor.cc +++ b/components/security_apps/waap/waap_clib/WaapOverrideFunctor.cc @@ -99,6 +99,16 @@ bool WaapOverrideFunctor::operator()(const std::string& tag, const boost::regex& else if (tag == "paramlocation" || tag == "paramLocation") { return NGEN::Regex::regexMatch(__FILE__, __LINE__, waf2Transaction.getLocation().c_str(), what, rx); } + else if (tag == "responsebody" || tag == "responseBody") { + waf2Transaction.getResponseInspectReasons().setApplyOverride(true); + if (!waf2Transaction.getResponseBody().empty()) { + boost::smatch matcher; + return NGEN::Regex::regexSearch(__FILE__, __LINE__, + waf2Transaction.getResponseBody().c_str(), matcher, rx); + } else { + return false; + } + } } catch (std::runtime_error & e) { dbgDebug(D_WAAP_OVERRIDE) << "RegEx match for tag " << tag << " failed due to: " << e.what(); diff --git a/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.cc b/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.cc index d626057..b5de64f 100644 --- a/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.cc +++ b/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.cc @@ -24,7 +24,8 @@ openRedirect(false), errorDisclosure(false), errorLimiter(false), rateLimiting(false), -collectResponseForLog(false) +collectResponseForLog(false), +applyOverride(false) { } @@ -36,8 +37,9 @@ ResponseInspectReasons::shouldInspect() const " ErrorDisclosure=" << errorDisclosure << " RateLimiting=" << rateLimiting << " ErrorLimiter=" << errorLimiter << - " collectResponseForLog=" << collectResponseForLog; - return openRedirect || errorDisclosure || rateLimiting || errorLimiter || collectResponseForLog; + " collectResponseForLog=" << collectResponseForLog << + " applyOverride=" << applyOverride; + return openRedirect || errorDisclosure || rateLimiting || errorLimiter || collectResponseForLog || applyOverride; } void @@ -76,4 +78,18 @@ ResponseInspectReasons::setCollectResponseForLog(bool flag) collectResponseForLog = flag; } +void +ResponseInspectReasons::setApplyOverride(bool flag) +{ + dbgTrace(D_WAAP) << "Change ResponseInspectReasons(setApplyOverride) " << applyOverride << " to " << + flag; + applyOverride = flag; +} + +bool +ResponseInspectReasons::getApplyOverride(void) +{ + return applyOverride; +} + } diff --git a/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.h b/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.h index eb13c6c..7fd9ea0 100644 --- a/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.h +++ b/components/security_apps/waap/waap_clib/WaapResponseInspectReasons.h @@ -24,12 +24,15 @@ public: void setRateLimiting(bool flag); void setErrorLimiter(bool flag); void setCollectResponseForLog(bool flag); + void setApplyOverride(bool flag); + bool getApplyOverride(void); private: bool openRedirect; bool errorDisclosure; bool errorLimiter; bool rateLimiting; bool collectResponseForLog; + bool applyOverride; }; } diff --git a/components/security_apps/waap/waap_clib/Waf2Engine.cc b/components/security_apps/waap/waap_clib/Waf2Engine.cc index 598bfaa..4bf3315 100755 --- a/components/security_apps/waap/waap_clib/Waf2Engine.cc +++ b/components/security_apps/waap/waap_clib/Waf2Engine.cc @@ -2097,6 +2097,29 @@ bool Waf2Transaction::decideResponse() return false; // block } + + if (m_responseInspectReasons.getApplyOverride()) { + WaapConfigApplication ngenSiteConfig; + + dbgTrace(D_WAAP_OVERRIDE) << "Checking exceptions for response"; + if (WaapConfigApplication::getWaapSiteConfig(ngenSiteConfig)) { + dbgTrace(D_WAAP) + << "Waf2Transaction::decideResponse(): got relevant Application configuration from the I/S"; + m_overrideState = getOverrideState(&ngenSiteConfig); + // Apply overrides + if (m_overrideState.bForceBlock) { + dbgTrace(D_WAAP) + << "Waf2Transaction::decideResponse(): setting shouldBlock to true due to override"; + return false; // BLOCK + } + else if (m_overrideState.bForceException) { + dbgTrace(D_WAAP) + << "Waf2Transaction::decideResponse(): setting shouldBlock to false due to override"; + return true; // PASS + } + } + } + if (m_siteConfig) { const std::shared_ptr triggerPolicy = m_siteConfig->get_TriggerPolicy(); if (!triggerPolicy) { diff --git a/components/security_apps/waap/waap_clib/Waf2Engine.h b/components/security_apps/waap/waap_clib/Waf2Engine.h index 14920d5..514f8ff 100755 --- a/components/security_apps/waap/waap_clib/Waf2Engine.h +++ b/components/security_apps/waap/waap_clib/Waf2Engine.h @@ -219,6 +219,8 @@ public: Waap::OpenRedirect::State &getOpenRedirectState() { return m_openRedirectState; } IWaapConfig* getSiteConfig() { return m_siteConfig; } void addNote(const std::string ¬e) { m_notes.push_back(note); } + const std::string &getResponseBody(void) const { return m_response_body; } + Waap::ResponseInspectReasons &getResponseInspectReasons(void) { return m_responseInspectReasons; } private: int finalizeDecision(IWaapConfig *sitePolicy, bool shouldBlock); diff --git a/components/security_apps/waap/waap_clib/Waf2EngineGetters.cc b/components/security_apps/waap/waap_clib/Waf2EngineGetters.cc index a94a2fa..f485fa7 100755 --- a/components/security_apps/waap/waap_clib/Waf2EngineGetters.cc +++ b/components/security_apps/waap/waap_clib/Waf2EngineGetters.cc @@ -556,6 +556,7 @@ Waap::Override::State Waf2Transaction::getOverrideState(IWaapConfig* sitePolicy) Waap::Override::State overrideState; std::shared_ptr overridePolicy = sitePolicy->get_OverridePolicy(); if (overridePolicy) { // at first we will run request overrides (in order to set the source) + m_responseInspectReasons.setApplyOverride(overridePolicy->isOverrideResponse()); overrideState.applyOverride(*overridePolicy, WaapOverrideFunctor(*this), m_matchedOverrideIds, true); } diff --git a/components/security_apps/waap/waap_clib/Waf2Util.cc b/components/security_apps/waap/waap_clib/Waf2Util.cc index 7d1b3ca..a20df05 100755 --- a/components/security_apps/waap/waap_clib/Waf2Util.cc +++ b/components/security_apps/waap/waap_clib/Waf2Util.cc @@ -971,6 +971,7 @@ bool decodeBase64Chunk( int acc_bits = 0; // how many bits are filled in acc int terminatorCharsSeen = 0; // whether '=' character was seen, and how many of them. uint32_t nonPrintableCharsCount = 0; + uint32_t spacer_count = 0; dbgTrace(D_WAAP) << "decodeBase64Chunk: value='" << value << "' match='" << string(it, end) << "'"; @@ -1047,9 +1048,12 @@ bool decodeBase64Chunk( acc_bits -= 8; // Count non-printable characters seen - if (!isprint(code)) { + if (!isprint(code) && (code != '\n') && (code != '\t')) { nonPrintableCharsCount++; } + if (code == '\r') { + spacer_count++; + } decoded += (char)code; } @@ -1059,12 +1063,24 @@ bool decodeBase64Chunk( // end of encoded sequence decoded. - dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: decoded.size=" << decoded.size() << - ", nonPrintableCharsCount=" << nonPrintableCharsCount << "; decoded='" << decoded << "'"; + dbgTrace(D_WAAP_BASE64) + << "decodeBase64Chunk: decoded.size=" + << decoded.size() + << ", nonPrintableCharsCount=" + << nonPrintableCharsCount + << ", spacer_count = " + << spacer_count + << ", decoded size = " + << decoded.size() + << "; decoded='" + << decoded << "'"; // Return success only if decoded.size>=5 and there are less than 10% of non-printable // characters in output. if (decoded.size() >= 5) { + if (spacer_count > 1) { + nonPrintableCharsCount = nonPrintableCharsCount - spacer_count + 1; + } if (nonPrintableCharsCount * 10 < decoded.size()) { dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (decode/replace) decoded.size=" << decoded.size() << ", nonPrintableCharsCount=" << nonPrintableCharsCount << ": replacing with decoded data"; @@ -1074,6 +1090,8 @@ bool decodeBase64Chunk( ", nonPrintableCharsCount=" << nonPrintableCharsCount; decoded.clear(); } + dbgTrace(D_WAAP_BASE64) << "returning true: successfully decoded." + << " Returns decoded data in \"decoded\" parameter"; return true; // successfully decoded. Returns decoded data in "decoded" parameter } diff --git a/core/include/services_sdk/interfaces/i_tenant_manager.h b/core/include/services_sdk/interfaces/i_tenant_manager.h index d7b0175..326fd7b 100644 --- a/core/include/services_sdk/interfaces/i_tenant_manager.h +++ b/core/include/services_sdk/interfaces/i_tenant_manager.h @@ -41,7 +41,11 @@ public: virtual std::chrono::microseconds getTimeoutVal() const = 0; - virtual std::string getProfileId(const std::string &tenant_id, const std::string ®ion) const = 0; + virtual std::vector getProfileId( + const std::string &tenant_id, + const std::string ®ion, + const std::string &account_id = "" + ) const = 0; private: friend class LoadNewTenants; diff --git a/core/include/services_sdk/interfaces/mock/mock_tenant_manager.h b/core/include/services_sdk/interfaces/mock/mock_tenant_manager.h index b5fcd85..eb31390 100644 --- a/core/include/services_sdk/interfaces/mock/mock_tenant_manager.h +++ b/core/include/services_sdk/interfaces/mock/mock_tenant_manager.h @@ -25,7 +25,10 @@ public: MOCK_CONST_METHOD2(areTenantAndProfileActive, bool(const std::string &, const std::string &)); MOCK_METHOD2(addActiveTenantAndProfile, void(const std::string &, const std::string &)); MOCK_METHOD2(deactivateTenant, void(const std::string &, const std::string &)); - MOCK_CONST_METHOD2(getProfileId, std::string(const std::string &, const std::string &)); + MOCK_CONST_METHOD3( + getProfileId, + std::vector(const std::string &, const std::string &, const std::string &) + ); MOCK_CONST_METHOD0(getTimeoutVal, std::chrono::microseconds()); diff --git a/core/include/services_sdk/resources/report/report_enums.h b/core/include/services_sdk/resources/report/report_enums.h index 4c54206..70f6b4f 100755 --- a/core/include/services_sdk/resources/report/report_enums.h +++ b/core/include/services_sdk/resources/report/report_enums.h @@ -69,6 +69,7 @@ enum class AudienceTeam AGENT_INTELLIGENCE, CPVIEW_MONITORING, SIGNATURE_DEVELOPERS, + FILE_UPLOAD, IDENTITY_AWARENESS, NONE, @@ -140,6 +141,7 @@ enum class IssuingEngine { AGENT_CORE, IOT_NEXT, SDWAN, + FILE_UPLOAD, IDA_NEXT }; diff --git a/core/report/tag_and_enum_management.cc b/core/report/tag_and_enum_management.cc index 931d13e..95fe4be 100755 --- a/core/report/tag_and_enum_management.cc +++ b/core/report/tag_and_enum_management.cc @@ -257,6 +257,7 @@ TagAndEnumManagement::convertToString(const IssuingEngine &issuing_engine) case IssuingEngine::AGENT_CORE: return "Agent Core"; case IssuingEngine::IOT_NEXT: return "iotNext"; case IssuingEngine::SDWAN: return "sdwanGwSharing"; + case IssuingEngine::FILE_UPLOAD: return "fileUpload"; case IssuingEngine::IDA_NEXT: return "quantumMetaNotifyIdn"; } diff --git a/core/tenant_manager/tenant_manager.cc b/core/tenant_manager/tenant_manager.cc index 8da40aa..862b52e 100644 --- a/core/tenant_manager/tenant_manager.cc +++ b/core/tenant_manager/tenant_manager.cc @@ -27,6 +27,46 @@ using namespace std; USE_DEBUG_FLAG(D_TENANT_MANAGER); +class AccountRegionPair +{ +public: + void + load(cereal::JSONInputArchive &ar) + { + ar( + cereal::make_nvp("accountId", accountID), + cereal::make_nvp("regionName", regionName) + ); + } + + bool + operator<(const AccountRegionPair &other) const { + return accountID < other.getAccountID() && regionName < other.getRegion(); + } + + const string & getAccountID() const { return accountID; } + const string & getRegion() const { return regionName; } + +private: + string accountID; + string regionName; +}; + +class AccountRegionSet +{ +public: + void + load(cereal::JSONInputArchive &ar) + { + cereal::load(ar, account_region_map); + } + + const set & getAccoutRegionPairs() const { return account_region_map; } + +private: + set account_region_map; +}; + class TenantManager::Impl : Singleton::Provide::From @@ -49,7 +89,7 @@ public: chrono::microseconds getTimeoutVal() const override; - string getProfileId(const string &tenant_id, const string ®ion) const override; + vector getProfileId(const string &tenant_id, const string ®ion, const string &account) const override; void addInstance(const string &tenant_id, const string &profile_id, const string &instace_id) @@ -338,12 +378,13 @@ TenantManager::Impl::getProfileIds(const string &_tenant_id) const return tenant_id.profile_ids.get(); } -string -TenantManager::Impl::getProfileId(const string &tenant_id, const string ®ion) const + +vector +TenantManager::Impl::getProfileId(const string &tenant_id, const string ®ion, const string &account_id = "") const { if (region.empty()) { dbgWarning(D_TENANT_MANAGER) << "Can't find the profile ID. Region is empty"; - return ""; + return vector(); } vector profile_ids = fetchProfileIds(tenant_id); @@ -352,36 +393,56 @@ TenantManager::Impl::getProfileId(const string &tenant_id, const string ®ion) auto i_env = Singleton::Consume::by(); auto unset_tenant_on_exit = make_scope_exit([&]() { i_env->unsetActiveTenantAndProfile(); }); + + vector profiles_to_return; for (const string &profile_id : profile_ids) { + string account_dbg = account_id.empty() ? "" : (" in the account " + account_id); dbgDebug(D_TENANT_MANAGER) << "Checking if the profile ID: " << profile_id << " corresponds to the tenant ID: " << tenant_id << " and the region " - << region; + << region + << account_dbg; i_env->setActiveTenantAndProfile(tenant_id, profile_id); - auto maybe_region = getSetting("region"); - if (maybe_region.ok() && region == maybe_region.unpack()) { - dbgDebug(D_TENANT_MANAGER) << "The region corresponds to profile ID " << profile_id; - return profile_id; + auto maybe_account_region_set = getSetting("accountRegionSet"); + if (maybe_account_region_set.ok()) { + for (const AccountRegionPair &account : maybe_account_region_set.unpack().getAccoutRegionPairs()) { + if (region == account.getRegion() && (account_id.empty() || account_id == account.getAccountID())) { + dbgTrace(D_TENANT_MANAGER) << "Found a corresponding profile ID: " << profile_id; + profiles_to_return.push_back(profile_id); + } + } } else { - if (maybe_region.ok()) { - dbgTrace(D_TENANT_MANAGER) - << "The region does not corresponds to profile ID " - << profile_id - << " region " - << *maybe_region; + auto maybe_region = getSetting("region"); + if (maybe_region.ok() && region == maybe_region.unpack()) { + dbgDebug(D_TENANT_MANAGER) << "The region corresponds to profile ID " << profile_id; + profiles_to_return.push_back(profile_id); + return profiles_to_return; } else { - dbgDebug(D_TENANT_MANAGER) << "Failed to get region for profile ID " << profile_id; + if (maybe_region.ok()) { + dbgTrace(D_TENANT_MANAGER) + << "The region does not corresponds to profile ID " + << profile_id + << " region " + << *maybe_region; + } else { + dbgDebug(D_TENANT_MANAGER) << "Failed to match profile ID by accountRegionSet or region"; + } } } } - dbgWarning(D_TENANT_MANAGER) << "Found no profile ID for tenant " << tenant_id << " and region " << region; - return ""; + if (!profiles_to_return.empty()) { + dbgDebug(D_TENANT_MANAGER) << "Found " << profiles_to_return.size() << " profiles that correspond"; + return profiles_to_return; + } + + dbgWarning(D_TENANT_MANAGER) << "Found no corresponding profile ID"; + return vector(); } void @@ -520,5 +581,6 @@ TenantManager::preload() { registerExpectedConfiguration("Tenant Manager", "Tenant timeout"); registerExpectedConfiguration("Tenant Manager", "Tenant manager type"); + registerExpectedSetting("accountRegionSet"); registerExpectedSetting("region"); }