diff --git a/esp/services/esdl_svc_engine/esdl_binding.cpp b/esp/services/esdl_svc_engine/esdl_binding.cpp index e31d00007e2..ad4a8b10f41 100755 --- a/esp/services/esdl_svc_engine/esdl_binding.cpp +++ b/esp/services/esdl_svc_engine/esdl_binding.cpp @@ -750,6 +750,7 @@ void EsdlServiceImpl::configureTargets(IPropertyTree *cfg, const char *service) bool updateInlines = gateways->getPropBool("@updateInline"); bool doLegacyTransform = !isEmptyString(gateways->queryProp("@legacyTransformTarget")); TransactionSecrets secrets; + TTransactionSecretsWrapper wrappedSecrets(secrets); Owned gwIt(gateways->getElements("Gateway")); ForEach(*gwIt) { @@ -777,7 +778,7 @@ void EsdlServiceImpl::configureTargets(IPropertyTree *cfg, const char *service) gce.targetContext[key].set(handler.get()); // sanity check that a secret is identified; the updater is not to be retained GatewayUpdaters updaters; - Owned updater(handler->getUpdater(updaters, secrets)); + Owned updater(handler->getUpdater(updaters, wrappedSecrets)); updater.clear(); } else if (hasHttpPrefix(url)) @@ -1394,7 +1395,7 @@ EsdlServiceImpl::IUpdatableGateway* EsdlServiceImpl::createInlineGateway(const I return new CLegacyUrlGateway(gw, gwName, gwUrl); } -void EsdlServiceImpl::applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableGateways& updatables, GatewayUpdaters& updaters, IEsdlScriptContext* scriptContext) const +void EsdlServiceImpl::applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableGateways& updatables, GatewayUpdaters& updaters, ITransactionSecretsWrapper& secrets) const { ForEach(gwIt) { @@ -1405,7 +1406,7 @@ void EsdlServiceImpl::applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableG UpdatableGateways::const_iterator ugIt = updatables.find(name); if (updatables.end() == ugIt) continue; - Owned updater(ugIt->second->getUpdater(updaters, scriptContext)); + Owned updater(ugIt->second->getUpdater(updaters, secrets)); if (updater) updater->updateGateway(gw); } @@ -1787,7 +1788,7 @@ void EsdlServiceImpl::prepareFinalRequest(IEspContext &context, GatewaysCache::const_iterator mgcIt = m_methodGatewaysCache.find(mthName); Owned gwIt; GatewayUpdaters updaters; - TransactionSecrets secrets; + TTransactionSecretsWrapper wrappedSecrets(*scriptContext); if (tgtctx) { if (mgcIt != m_methodGatewaysCache.end() && !mgcIt->second.targetContext.empty()) @@ -1799,7 +1800,7 @@ void EsdlServiceImpl::prepareFinalRequest(IEspContext &context, if (ctxGateways) { gwIt.setown(ctxGateways->getElements("Gateway")); - applyGatewayUpdates(*gwIt, mgcIt->second.targetContext, updaters, scriptContext); + applyGatewayUpdates(*gwIt, mgcIt->second.targetContext, updaters, wrappedSecrets); } } toXML(tgtctx.get(), reqProcessed); @@ -1822,7 +1823,7 @@ void EsdlServiceImpl::prepareFinalRequest(IEspContext &context, // used in subsequent transactions. Owned copy(createPTreeFromIPT(cfgGateways)); gwIt.setown(copy->getElements("Gateway")); - applyGatewayUpdates(*gwIt, mgcIt->second.legacyTransform, updaters, scriptContext); + applyGatewayUpdates(*gwIt, mgcIt->second.legacyTransform, updaters, wrappedSecrets); } else gwIt.setown(cfgGateways->getElements("Gateway")); @@ -1905,7 +1906,7 @@ EsdlServiceImpl::~EsdlServiceImpl() } } -EsdlServiceImpl::IGatewayUpdater* EsdlServiceImpl::CUpdatableGateway::getUpdater(GatewayUpdaters& updaters, TransactionSecrets& secrets) const +EsdlServiceImpl::IGatewayUpdater* EsdlServiceImpl::CUpdatableGateway::getUpdater(GatewayUpdaters& updaters, ITransactionSecretsWrapper& secrets) const { GatewayUpdaters::iterator it = updaters.find(updatersKey); if (it != updaters.end()) @@ -1915,16 +1916,6 @@ EsdlServiceImpl::IGatewayUpdater* EsdlServiceImpl::CUpdatableGateway::getUpdater return spawned.getClear(); } -EsdlServiceImpl::IGatewayUpdater* EsdlServiceImpl::CUpdatableGateway::getUpdater(GatewayUpdaters& updaters, IEsdlScriptContext* scriptContext) const -{ - GatewayUpdaters::iterator it = updaters.find(updatersKey); - if (it != updaters.end()) - return it->second.getLink(); - Owned spawned(getUpdater(scriptContext)); - updaters[updatersKey].setown(spawned.getLink()); - return spawned.getClear(); -} - EsdlServiceImpl::CUpdatableGateway::CUpdatableGateway(const char* gwName) { updatersKey.assign(gwName); @@ -1963,12 +1954,7 @@ bool EsdlServiceImpl::CUpdatableGateway::updateURLCredentials(StringBuffer& url, return false; } -EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(TransactionSecrets&) const -{ - return LINK(const_cast(this)); -} - -EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(IEsdlScriptContext*) const +EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(ITransactionSecretsWrapper&) const { return LINK(const_cast(this)); } diff --git a/esp/services/esdl_svc_engine/esdl_binding.hpp b/esp/services/esdl_svc_engine/esdl_binding.hpp index 5b7ac65d52e..63d96aeef2a 100755 --- a/esp/services/esdl_svc_engine/esdl_binding.hpp +++ b/esp/services/esdl_svc_engine/esdl_binding.hpp @@ -73,6 +73,33 @@ typedef int (*cpp_service_method_t)(const char* CtxXML, const char* ReqXML, Stri class EsdlServiceImpl : public CInterface, implements IEspService { private: + /** + * @brief Utility wrapper interface for secret access. + * + * At service load, secrets are cached directly in a TransactionSecrets instance. When + * processing requests, secrets are cached in the script context. Both provide the same + * interface to obtain a secret. This wrapper decouples gateway secret updating from the + * cache in use. + */ + interface ITransactionSecretsWrapper + { + virtual IPTree* getSecret(const char* category, const SecretId& id) const = 0; + }; + + /** + * @brief Concrete implementation of `ITransactionSecretsWrapper` wrapping multiple caches. + * + * @tparam secret_cache_t + */ + template + struct TTransactionSecretsWrapper : public ITransactionSecretsWrapper + { + TTransactionSecretsWrapper(secret_cache_t& _wrapped) : wrapped(_wrapped) {} + virtual IPTree* getSecret(const char* category, const SecretId& id) const override { return wrapped.getSecret(category, id); } + private: + secret_cache_t& wrapped; + }; + /** * @brief Abstraction of a per-transaction gateway updater. * @@ -114,8 +141,7 @@ class EsdlServiceImpl : public CInterface, implements IEspService */ interface IUpdatableGateway : public IInterface { - virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, TransactionSecrets& secrets) const = 0; - virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, IEsdlScriptContext* scriptContext) const = 0; + virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, ITransactionSecretsWrapper& secrets) const = 0; }; using UpdatableGateways = std::map>; @@ -130,20 +156,19 @@ class EsdlServiceImpl : public CInterface, implements IEspService * - Insertion (or replacement) of user credentials in a URL string is available to any * subclass that needs it.. * - * All extensions must implement `getUpdater(TransactionSecrets&)`. In some cases this may entail creation - * of a new updater instance. In other cases a single instance may be reused. + * All extensions must implement `getUpdater(ITransactionSecretsWrapper&)`. In some cases + * this may entail creation of a new updater instance. In other cases a single instance may + * be reused. */ class CUpdatableGateway : public CInterfaceOf { public: - virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, TransactionSecrets& secrets) const override; - virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, IEsdlScriptContext* scriptContext) const override; + virtual IGatewayUpdater* getUpdater(GatewayUpdaters& updaters, ITransactionSecretsWrapper& secrets) const override; protected: std::string updatersKey; protected: CUpdatableGateway(const char* gwName); - virtual IGatewayUpdater* getUpdater(TransactionSecrets& secrets) const = 0; - virtual IGatewayUpdater* getUpdater(IEsdlScriptContext* scriptContext) const = 0; + virtual IGatewayUpdater* getUpdater(ITransactionSecretsWrapper& secrets) const = 0; bool updateURLCredentials(StringBuffer& url, const char* username, const char* password) const; }; @@ -163,8 +188,7 @@ class EsdlServiceImpl : public CInterface, implements IEspService class CLegacyUrlGateway : public CUpdatableGateway, public IGatewayUpdater { protected: // CUpdatableGateway - virtual CLegacyUrlGateway* getUpdater(TransactionSecrets&) const override; - virtual CLegacyUrlGateway* getUpdater(IEsdlScriptContext*) const override; + virtual CLegacyUrlGateway* getUpdater(ITransactionSecretsWrapper&) const override; public: // IGatewayUpdater virtual void updateGateway(IPTree& gw) override; protected: @@ -190,8 +214,7 @@ class EsdlServiceImpl : public CInterface, implements IEspService class TLocalSecretGateway : public CUpdatableGateway { protected: - template - class TUpdater : public CInterfaceOf + class CUpdater : public CInterfaceOf { friend class TLocalSecretGateway; static constexpr const char* category = "espUser"; @@ -206,22 +229,16 @@ class EsdlServiceImpl : public CInterface, implements IEspService Linked> entry; Owned secret; public: - TUpdater(const TLocalSecretGateway& _entry, secret_source_t& secrets) + CUpdater(const TLocalSecretGateway& _entry, ITransactionSecretsWrapper& secrets) { entry.set(&_entry); secret.setown(secrets.getSecret(category, entry->identity)); } }; protected: // CUpdatableGateway - virtual IGatewayUpdater* getUpdater(TransactionSecrets& secrets) const override - { - return new TUpdater(*this, secrets); - } - virtual IGatewayUpdater* getUpdater(IEsdlScriptContext* scriptContext) const override + virtual IGatewayUpdater* getUpdater(ITransactionSecretsWrapper& secrets) const override { - if (!scriptContext) - return nullptr; - return new TUpdater(*this, *scriptContext); + return new CUpdater(*this, secrets); } protected: StringBuffer identifier; @@ -492,7 +509,7 @@ class EsdlServiceImpl : public CInterface, implements IEspService * @param updaters cache of updaters used in the current transaction * @param secrets cache of secrets used in the current transaction */ - void applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableGateways& updatables, GatewayUpdaters& updaters, IEsdlScriptContext* scriptContext) const; + void applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableGateways& updatables, GatewayUpdaters& updaters, ITransactionSecretsWrapper& secrets) const; /** * @brief Implementation of legacy gateway transformation invoked only during preparation of