Skip to content

Commit

Permalink
Secrets cache abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Klemm committed Nov 16, 2023
1 parent 8a23f37 commit 512cc33
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 45 deletions.
32 changes: 9 additions & 23 deletions esp/services/esdl_svc_engine/esdl_binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<IPTreeIterator> gwIt(gateways->getElements("Gateway"));
ForEach(*gwIt)
{
Expand Down Expand Up @@ -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<IGatewayUpdater> updater(handler->getUpdater(updaters, secrets));
Owned<IGatewayUpdater> updater(handler->getUpdater(updaters, wrappedSecrets));
updater.clear();
}
else if (hasHttpPrefix(url))
Expand Down Expand Up @@ -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)
{
Expand All @@ -1405,7 +1406,7 @@ void EsdlServiceImpl::applyGatewayUpdates(IPTreeIterator& gwIt, const UpdatableG
UpdatableGateways::const_iterator ugIt = updatables.find(name);
if (updatables.end() == ugIt)
continue;
Owned<IGatewayUpdater> updater(ugIt->second->getUpdater(updaters, scriptContext));
Owned<IGatewayUpdater> updater(ugIt->second->getUpdater(updaters, secrets));
if (updater)
updater->updateGateway(gw);
}
Expand Down Expand Up @@ -1787,7 +1788,7 @@ void EsdlServiceImpl::prepareFinalRequest(IEspContext &context,
GatewaysCache::const_iterator mgcIt = m_methodGatewaysCache.find(mthName);
Owned<IPTreeIterator> gwIt;
GatewayUpdaters updaters;
TransactionSecrets secrets;
TTransactionSecretsWrapper wrappedSecrets(*scriptContext);
if (tgtctx)
{
if (mgcIt != m_methodGatewaysCache.end() && !mgcIt->second.targetContext.empty())
Expand All @@ -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);
Expand All @@ -1822,7 +1823,7 @@ void EsdlServiceImpl::prepareFinalRequest(IEspContext &context,
// used in subsequent transactions.
Owned<IPTree> 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"));
Expand Down Expand Up @@ -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())
Expand All @@ -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<IGatewayUpdater> spawned(getUpdater(scriptContext));
updaters[updatersKey].setown(spawned.getLink());
return spawned.getClear();
}

EsdlServiceImpl::CUpdatableGateway::CUpdatableGateway(const char* gwName)
{
updatersKey.assign(gwName);
Expand Down Expand Up @@ -1963,12 +1954,7 @@ bool EsdlServiceImpl::CUpdatableGateway::updateURLCredentials(StringBuffer& url,
return false;
}

EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(TransactionSecrets&) const
{
return LINK(const_cast<CLegacyUrlGateway*>(this));
}

EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(IEsdlScriptContext*) const
EsdlServiceImpl::CLegacyUrlGateway* EsdlServiceImpl::CLegacyUrlGateway::getUpdater(ITransactionSecretsWrapper&) const
{
return LINK(const_cast<CLegacyUrlGateway*>(this));
}
Expand Down
61 changes: 39 additions & 22 deletions esp/services/esdl_svc_engine/esdl_binding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename secret_cache_t>
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.
*
Expand Down Expand Up @@ -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<std::string, Owned<IUpdatableGateway>>;

Expand All @@ -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<IUpdatableGateway>
{
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;
};

Expand All @@ -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:
Expand All @@ -190,8 +214,7 @@ class EsdlServiceImpl : public CInterface, implements IEspService
class TLocalSecretGateway : public CUpdatableGateway
{
protected:
template <typename secret_source_t>
class TUpdater : public CInterfaceOf<IGatewayUpdater>
class CUpdater : public CInterfaceOf<IGatewayUpdater>
{
friend class TLocalSecretGateway<secret_identity_t>;
static constexpr const char* category = "espUser";
Expand All @@ -206,22 +229,16 @@ class EsdlServiceImpl : public CInterface, implements IEspService
Linked<const TLocalSecretGateway<secret_identity_t>> entry;
Owned<IPTree> secret;
public:
TUpdater(const TLocalSecretGateway<secret_identity_t>& _entry, secret_source_t& secrets)
CUpdater(const TLocalSecretGateway<secret_identity_t>& _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<TransactionSecrets>(*this, secrets);
}
virtual IGatewayUpdater* getUpdater(IEsdlScriptContext* scriptContext) const override
virtual IGatewayUpdater* getUpdater(ITransactionSecretsWrapper& secrets) const override
{
if (!scriptContext)
return nullptr;
return new TUpdater<IEsdlScriptContext>(*this, *scriptContext);
return new CUpdater(*this, secrets);
}
protected:
StringBuffer identifier;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 512cc33

Please sign in to comment.