Skip to content

Commit

Permalink
HPCC-31394 WsSMC send roxie control cmd to ssl port if available
Browse files Browse the repository at this point in the history
Rather than default to port 9876, use the roxie farmer ports configured
for sending control messages to. Prefer an ssl port if available.

Update the smart pointer factory and ctors where required to accept a tls
config from bare-metal configurations. These configurations using transitional
APIs don't support all the properties and sync features of the containerized
versions.

A separate ticket would be required to determine if and how to add the full
complement of tls related configuration, behavior and secrets support to bare
metal that is currently in place in containerized code.

Signed-off-by: Terrence Asselin <[email protected]>
  • Loading branch information
asselitx committed Jun 7, 2024
1 parent 549d562 commit 83a1255
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 21 deletions.
14 changes: 8 additions & 6 deletions esp/services/ws_ecl/ws_ecl_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "xsdparser.hpp"
#include "httpclient.hpp"
#include "jsonhelpers.hpp"
#include "securesocket.hpp"

#define SDS_LOCK_TIMEOUT (5*60*1000) // 5mins, 30s a bit short

Expand Down Expand Up @@ -211,9 +212,8 @@ class WsEclSocketFactory : public CSmartSocketFactory
{
}

WsEclSocketFactory(const char *_socklist, bool _retry, bool includeTarget, const char *_alias, unsigned _dnsInterval, bool useTls) : CSmartSocketFactory(_socklist, _retry, 60, _dnsInterval), includeTargetInURL(includeTarget), alias(_alias)
WsEclSocketFactory(const char *_socklist, IPropertyTree *_tlsConfig, bool _retry, bool includeTarget, const char *_alias, unsigned _dnsInterval) : CSmartSocketFactory(_socklist, _tlsConfig, _retry, 60, _dnsInterval), includeTargetInURL(includeTarget), alias(_alias)
{
tlsService = useTls;
}
};

Expand Down Expand Up @@ -260,7 +260,8 @@ void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap,
const char *vip = NULL;
bool includeTargetInURL = true;
unsigned dnsInterval = (unsigned) -1;
bool useTls = false;

Owned<IPropertyTree> tlsConfig = createPTree("none");
if (vips)
{
IPropertyTree *pc = vips->queryPropTree(xpath.clear().appendf("ProcessCluster[@name='%s']", process.str()));
Expand All @@ -269,7 +270,8 @@ void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap,
vip = pc->queryProp("@vip");
includeTargetInURL = pc->getPropBool("@includeTargetInURL", true);
dnsInterval = (unsigned) pc->getPropInt("@dnsInterval", -1);
useTls = pc->getPropBool("@tls", false);
if (pc->getPropBool("@tls", false))
tlsConfig.setown(createSecureSocketConfig(nullptr, nullptr, nullptr));
}
}
StringBuffer list;
Expand Down Expand Up @@ -297,7 +299,7 @@ void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap,
farmerPort = port;
const char *protocol = farmer.queryProp("@protocol");
if (protocol && streq(protocol, "ssl"))
useTls = true;
tlsConfig.setown(createSecureSocketConfig(farmer.queryProp("@certificateFileName"), farmer.queryProp("@privateKeyFileName"), nullptr));
break; //use the first one without port==0
}
Owned<IPropertyTreeIterator> servers = roxieCluster->getElements("RoxieServerProcess");
Expand All @@ -308,7 +310,7 @@ void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory> &connMap,
if (list.length())
{
StringAttr alias(clusterInfo->getAlias());
Owned<ISmartSocketFactory> sf = new WsEclSocketFactory(list.str(), !loadBalanced, includeTargetInURL, loadBalanced ? alias.str() : NULL, dnsInterval, useTls);
Owned<ISmartSocketFactory> sf = new WsEclSocketFactory(list.str(), tlsConfig, !loadBalanced, includeTargetInURL, loadBalanced ? alias.str() : NULL, dnsInterval);
connMap.setValue(target.str(), sf.get());
if (alias.length() && !connMap.getValue(alias.str())) //only need one vip per alias for routing purposes
connMap.setValue(alias.str(), sf.get());
Expand Down
14 changes: 8 additions & 6 deletions esp/services/ws_smc/ws_smcService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ void CWsSMCEx::init(IPropertyTree *cfg, const char *process, const char *service

#ifdef _CONTAINERIZED
initContainerRoxieTargets(roxieConnMap);
#else
initBareMetalRoxieTargets(roxieConnMap);
#endif

xpath.setf("Software/EspProcess[@name=\"%s\"]/EspService[@name=\"%s\"]/ActivityInfoCacheSeconds", process, service);
Expand Down Expand Up @@ -2305,18 +2307,18 @@ bool CWsSMCEx::onRoxieControlCmd(IEspContext &context, IEspRoxieControlCmdReques
if (isEmptyString(process))
throw makeStringException(ECLWATCH_MISSING_PARAMS, "Process cluster not specified.");

SocketEndpointArray addrs;
getRoxieProcessServers(process, addrs);
if (!addrs.length())
throw makeStringException(ECLWATCH_CANNOT_GET_ENV_INFO, "Process cluster not found.");
Owned<IPropertyTree> controlResp = sendRoxieControlAllNodes(addrs.item(0), controlReq, true, req.getWait());
ISmartSocketFactory *conn = roxieConnMap.getValue(process);
if (!conn)
throw makeStringExceptionV(ECLWATCH_CANNOT_GET_ENV_INFO, "Connection info for '%s' process cluster not found.", process);

Owned<IPropertyTree> controlResp = sendRoxieControlAllNodes(conn, controlReq, true, req.getWait(), ROXIECONNECTIONTIMEOUT);
#else
const char *target = req.getTargetCluster();
if (isEmptyString(target))
target = req.getProcessCluster(); //backward compatible
if (isEmptyString(target))
throw makeStringException(ECLWATCH_MISSING_PARAMS, "Target cluster not specified.");

ISmartSocketFactory *conn = roxieConnMap.getValue(target);
if (!conn)
throw makeStringExceptionV(ECLWATCH_CANNOT_GET_ENV_INFO, "roxie target cluster not mapped: %s", target);
Expand Down
5 changes: 5 additions & 0 deletions esp/smc/SMCLib/TpContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,11 @@ extern TPWRAPPER_API void initContainerRoxieTargets(MapStringToMyClass<ISmartSoc
}
}

extern TPWRAPPER_API void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory>& connMap)
{
IWARNLOG("UNIMPLEMENTED: CONTAINERIZED(CTpWrapper::initBareMetalRoxieTargets)");
}

extern TPWRAPPER_API void getRoxieTargetsSupportingPublishedQueries(StringArray& names)
{
Owned<IPropertyTreeIterator> queues = getComponentConfigSP()->getElements("queues[@type='roxie']");
Expand Down
70 changes: 70 additions & 0 deletions esp/smc/SMCLib/TpWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,76 @@ extern TPWRAPPER_API void initContainerRoxieTargets(MapStringToMyClass<ISmartSoc
}
}

void appendServerAddress(StringBuffer& list, IPropertyTree& env, IPropertyTree& server, const char* farmerPort)
{
//just in case, for backward compatability with old environment.xml files, allow server rather than farmer to specify port
const char *port = server.queryProp("@port");
if (!port)
port = farmerPort;
if (port && streq(port, "0")) //0 == roxie listening on queue rather than port
return;

const char *netAddress = server.queryProp("@netAddress");
if (!netAddress && server.hasProp("@computer"))
{
VStringBuffer xpath("Hardware/Computer[@name='%s']/@netAddress", server.queryProp("@computer"));
netAddress = env.queryProp(xpath.str());
}
if (!netAddress || !*netAddress)
return;
if (list.length())
list.append('|');
list.append(netAddress).append(':').append(port);
}

extern TPWRAPPER_API void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory>& connMap)
{
Owned<IEnvironmentFactory> factory = getEnvironmentFactory(false);
Owned<IConstEnvironment> env = factory->openEnvironment();
Owned<IPropertyTree> envRoot = &env->getPTree();

Owned<IPropertyTreeIterator> roxieClusters = envRoot->getElements("Software/RoxieCluster");
ForEach(*roxieClusters)
{
IPropertyTree& roxieCluster = roxieClusters->query();
const char* name = roxieCluster.queryProp("@name");
if (isEmptyString(name))
continue;

StringBuffer addressList;
StringBuffer port("");
Owned<IPropertyTree> tlsConfig = createPTree("none");

Owned<IPropertyTreeIterator> roxieFarms = roxieCluster.getElements("RoxieFarmProcess");
ForEach(*roxieFarms)
{
IPropertyTree& farm = roxieFarms->query();
const char* farmPort = farm.queryProp("@port");
if (!isEmptyString(farmPort) && !streq(farmPort, "0"))
{
const char *protocol = farm.queryProp("@protocol");
if (!isEmptyString(protocol) && strieq(protocol, "ssl"))
{
port.set(farmPort);
tlsConfig.setown(createSecureSocketConfig(farm.queryProp("@certificateFileName"), farm.queryProp("@privateKeyFileName"), nullptr));
break;
}
else if (isEmptyString(port.str()))
{
port.set(farmPort);
}
}
}

Owned<IPropertyTreeIterator> roxieServers = roxieCluster.getElements("RoxieServerProcess");
ForEach(*roxieServers)
appendServerAddress(addressList, *envRoot, roxieServers->query(), port.str());

Owned<ISmartSocketFactory> sf = streq(tlsConfig->queryName(), "ssl") ? createSecureSmartSocketFactory(addressList, tlsConfig) : createSmartSocketFactory(addressList);
connMap.setValue(name, sf.get());
}
}

extern TPWRAPPER_API void getRoxieTargetsSupportingPublishedQueries(StringArray& names)
{
CConstWUClusterInfoArray clusters;
Expand Down
1 change: 1 addition & 0 deletions esp/smc/SMCLib/TpWrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ extern TPWRAPPER_API unsigned getWUClusterInfo(CConstWUClusterInfoArray& cluster
extern TPWRAPPER_API IConstWUClusterInfo* getWUClusterInfoByName(const char* clustName);

extern TPWRAPPER_API void initContainerRoxieTargets(MapStringToMyClass<ISmartSocketFactory>& connMap);
extern TPWRAPPER_API void initBareMetalRoxieTargets(MapStringToMyClass<ISmartSocketFactory>& connMap);
extern TPWRAPPER_API unsigned getThorClusterNames(StringArray& targetNames, StringArray& queueNames);
extern TPWRAPPER_API void getRoxieTargetsSupportingPublishedQueries(StringArray& names);
extern TPWRAPPER_API void validateTargetName(const char* target);
Expand Down
2 changes: 1 addition & 1 deletion roxie/roxiepipe/roxiepipe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ int main(int argc, char *argv[])
{
#ifdef _USE_OPENSSL
if (useSSL)
smartSocketFactory = createSecureSmartSocketFactory(hosts.str(), retryMode);
smartSocketFactory = createSecureSmartSocketFactory(hosts.str(), createSecureSocketConfig(nullptr, nullptr, nullptr), retryMode);
else
#endif
smartSocketFactory = createSmartSocketFactory(hosts.str(), retryMode);
Expand Down
12 changes: 9 additions & 3 deletions system/jlib/jsmartsock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,19 @@ CSmartSocketFactory::CSmartSocketFactory(IPropertyTree &service, bool _retry, un
}
}

CSmartSocketFactory::CSmartSocketFactory(const char *_socklist, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
CSmartSocketFactory::CSmartSocketFactory(const char *_socklist, IPropertyTree* _tlsConfig, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
{
PROGLOG("CSmartSocketFactory::CSmartSocketFactory(%s)",_socklist?_socklist:"NULL");
PROGLOG("CSmartSocketFactory::CSmartSocketFactory(%s, tlsConfig(%s))",_socklist?_socklist:"NULL", _tlsConfig?"yes":"no");
SmartSocketListParser slp(_socklist);
if (slp.getSockets(sockArray) == 0)
throw createSmartSocketException(0, "no endpoints defined");

if (_tlsConfig != nullptr)
{
tlsService = true;
tlsConfig.setown(createSyncedPropertyTree(_tlsConfig));
}

shuffleEndpoints();

nextEndpointIndex = 0;
Expand Down Expand Up @@ -491,5 +497,5 @@ ISmartSocketFactory *createSmartSocketFactory(IPropertyTree &service, bool _retr

ISmartSocketFactory *createSmartSocketFactory(const char *_socklist, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
{
return new CSmartSocketFactory(_socklist, _retry, _retryInterval, _dnsInterval);
return new CSmartSocketFactory(_socklist, nullptr, _retry, _retryInterval, _dnsInterval);
}
2 changes: 1 addition & 1 deletion system/jlib/jsmartsock.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected:
public:
IMPLEMENT_IINTERFACE_USING(Thread);

CSmartSocketFactory(const char *_socklist, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned)-1);
CSmartSocketFactory(const char *_socklist, IPropertyTree *_tlsConfig, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned)-1);
CSmartSocketFactory(IPropertyTree &service, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned)-1);
~CSmartSocketFactory();
int run();
Expand Down
6 changes: 3 additions & 3 deletions system/security/securesocket/securesocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2188,7 +2188,7 @@ class CSecureSmartSocketFactory : public CSmartSocketFactory
public:
Owned<ISecureSocketContext> secureContext;

CSecureSmartSocketFactory(const char *_socklist, bool _retry, unsigned _retryInterval, unsigned _dnsInterval) : CSmartSocketFactory(_socklist, _retry, _retryInterval, _dnsInterval)
CSecureSmartSocketFactory(const char *_socklist, IPropertyTree *_tlsConfig, bool _retry, unsigned _retryInterval, unsigned _dnsInterval) : CSmartSocketFactory(_socklist, _tlsConfig, _retry, _retryInterval, _dnsInterval)
{
secureContext.setown(createSecureSocketContext(ClientSocket));
}
Expand Down Expand Up @@ -2221,9 +2221,9 @@ class CSecureSmartSocketFactory : public CSmartSocketFactory
}
};

ISmartSocketFactory *createSecureSmartSocketFactory(const char *_socklist, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
ISmartSocketFactory *createSecureSmartSocketFactory(const char *_socklist, IPropertyTree* _tlsConfig, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
{
return new CSecureSmartSocketFactory(_socklist, _retry, _retryInterval, _dnsInterval);
return new CSecureSmartSocketFactory(_socklist, _tlsConfig, _retry, _retryInterval, _dnsInterval);
}

ISmartSocketFactory *createSecureSmartSocketFactory(IPropertyTree &service, bool _retry, unsigned _retryInterval, unsigned _dnsInterval)
Expand Down
2 changes: 1 addition & 1 deletion system/security/securesocket/securesocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ SECURESOCKET_API int signCertificate(const char* csr, const char* ca_certificate
};


SECURESOCKET_API ISmartSocketFactory *createSecureSmartSocketFactory(const char *_socklist, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned) -1);
SECURESOCKET_API ISmartSocketFactory *createSecureSmartSocketFactory(const char *_socklist, IPropertyTree* _tlsConfig, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned) -1);
SECURESOCKET_API ISmartSocketFactory *createSecureSmartSocketFactory(IPropertyTree &service, bool _retry = false, unsigned _retryInterval = 60, unsigned _dnsInterval = (unsigned) -1);

SECURESOCKET_API IConversation *createSingletonSecureSocketConnection(unsigned short port,SocketEndpoint *_ep=nullptr);
Expand Down

0 comments on commit 83a1255

Please sign in to comment.