123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807 |
- /*##############################################################################
- HPCC SYSTEMS software Copyright (C) 2020 HPCC Systems®.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ############################################################################## */
- #include "platform.h"
- #include "jlog.hpp"
- #include "jutil.hpp"
- #include "jexcept.hpp"
- #include "jmutex.hpp"
- #include "jfile.hpp"
- #include "jptree.hpp"
- #include "jerror.hpp"
- #include "jsecrets.hpp"
- //including cpp-httplib single header file REST client
- // doesn't work with format-nonliteral as an error
- //
- #if defined(__clang__) || defined(__GNUC__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wformat-nonliteral"
- #endif
- #ifdef _USE_OPENSSL
- #define CPPHTTPLIB_OPENSSL_SUPPORT
- #endif
- #undef INVALID_SOCKET
- #include "httplib.h"
- #if defined(__clang__) || defined(__GNUC__)
- #pragma GCC diagnostic pop
- #endif
- #ifdef _USE_OPENSSL
- #include <openssl/x509v3.h>
- #endif
- #include <vector>
- enum class CVaultKind { kv_v1, kv_v2 };
- CVaultKind getSecretType(const char *s)
- {
- if (isEmptyString(s))
- return CVaultKind::kv_v2;
- if (streq(s, "kv_v1"))
- return CVaultKind::kv_v1;
- return CVaultKind::kv_v2;
- }
- interface IVaultManager : extends IInterface
- {
- virtual bool getCachedSecretFromVault(const char *category, const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) = 0;
- virtual bool requestSecretFromVault(const char *category, const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) = 0;
- virtual bool getCachedSecretByCategory(const char *category, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) = 0;
- virtual bool requestSecretByCategory(const char *category, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) = 0;
- };
- static CriticalSection secretCacheCS;
- static Owned<IPropertyTree> secretCache;
- static CriticalSection mtlsInfoCacheCS;
- static Owned<IPropertyTree> mtlsInfoCache;
- static Owned<IVaultManager> vaultManager;
- static MemoryAttr udpKey;
- static bool udpKeyInitialized = false;
- MODULE_INIT(INIT_PRIORITY_SYSTEM)
- {
- secretCache.setown(createPTree());
- mtlsInfoCache.setown(createPTree());
- return true;
- }
- MODULE_EXIT()
- {
- vaultManager.clear();
- secretCache.clear();
- mtlsInfoCache.clear();
- udpKey.clear();
- }
- static void splitUrlAddress(const char *address, size_t len, StringBuffer &host, StringBuffer *port)
- {
- if (!address || len==0)
- return;
- const char *sep = (const char *)memchr(address, ':', len);
- if (!sep)
- host.append(len, address);
- else
- {
- host.append(sep - address, address);
- len = len - (sep - address) - 1;
- if (port)
- port->append(len, sep+1);
- else
- host.append(':').append(len, sep+1);
- }
- }
- static void splitUrlAuthority(const char *authority, size_t authorityLen, StringBuffer &user, StringBuffer &password, StringBuffer &host, StringBuffer *port)
- {
- if (!authority || authorityLen==0)
- return;
- const char *at = (const char *) memchr(authority, '@', authorityLen);
- if (!at)
- splitUrlAddress(authority, authorityLen, host, port);
- else
- {
- size_t userinfoLen = (at - authority);
- splitUrlAddress(at+1, authorityLen - userinfoLen - 1, host, port);
- const char *sep = (const char *) memchr(authority, ':', at - authority);
- if (!sep)
- user.append(at-authority, authority);
- else
- {
- user.append(sep-authority, authority);
- size_t passwordLen = (at - sep - 1);
- password.append(passwordLen, sep+1);
- }
- }
- }
- static inline void extractUrlProtocol(const char *&url, StringBuffer *scheme)
- {
- if (!url)
- throw makeStringException(-1, "Invalid empty URL");
- if (0 == strnicmp(url, "HTTPS://", 8))
- {
- url+=8;
- if (scheme)
- scheme->append("https://");
- }
- else if (0 == strnicmp(url, "HTTP://", 7))
- {
- url+=7;
- if (scheme)
- scheme->append("http://");
- }
- else
- throw MakeStringException(-1, "Invalid URL, protocol not recognized %s", url);
- }
- static void splitUrlSections(const char *url, const char * &authority, size_t &authorityLen, StringBuffer &fullpath, StringBuffer *scheme)
- {
- extractUrlProtocol(url, scheme);
- const char* path = strchr(url, '/');
- authority = url;
- if (!path)
- authorityLen = strlen(authority);
- else
- {
- authorityLen = path-url;
- fullpath.append(path);
- }
- }
- extern jlib_decl void splitFullUrl(const char *url, StringBuffer &user, StringBuffer &password, StringBuffer &host, StringBuffer &port, StringBuffer &path)
- {
- const char *authority = nullptr;
- size_t authorityLen = 0;
- splitUrlSections(url, authority, authorityLen, path, nullptr);
- splitUrlAuthority(authority, authorityLen, user, password, host, &port);
- }
- extern jlib_decl void splitUrlSchemeHostPort(const char *url, StringBuffer &user, StringBuffer &password, StringBuffer &schemeHostPort, StringBuffer &path)
- {
- const char *authority = nullptr;
- size_t authorityLen = 0;
- splitUrlSections(url, authority, authorityLen, path, &schemeHostPort);
- splitUrlAuthority(authority, authorityLen, user, password, schemeHostPort, nullptr);
- }
- //---------------------------------------------------------------------------------------------------------------------
- static StringBuffer secretDirectory;
- static CriticalSection secretCS;
- //there are various schemes for renewing kubernetes secrets and they are likely to vary greatly in how often
- // a secret gets updated this timeout determines the maximum amount of time before we'll pick up a change
- // 10 minutes for now we can change this as we gather more experience and user feedback
- static unsigned secretTimeoutMs = 10 * 60 * 1000;
- extern jlib_decl unsigned getSecretTimeout()
- {
- return secretTimeoutMs;
- }
- extern jlib_decl void setSecretTimeout(unsigned timeoutMs)
- {
- secretTimeoutMs = timeoutMs;
- }
- extern jlib_decl void setSecretMount(const char * path)
- {
- if (!path)
- {
- getPackageFolder(secretDirectory);
- addPathSepChar(secretDirectory).append("secrets");
- }
- else
- secretDirectory.set(path);
- }
- static inline bool checkSecretExpired(unsigned created)
- {
- if (!created)
- return false;
- unsigned age = msTick() - created;
- return age > getSecretTimeout();
- }
- class CVault
- {
- private:
- bool useKubernetesAuth = true;
- CVaultKind kind;
- CriticalSection vaultCS;
- Owned<IPropertyTree> cache;
- StringBuffer schemeHostPort;
- StringBuffer path;
- StringBuffer username;
- StringBuffer password;
- StringAttr name;
- StringAttr role;
- StringAttr token;
- public:
- CVault(IPropertyTree *vault)
- {
- cache.setown(createPTree());
- StringBuffer url;
- replaceEnvVariables(url, vault->queryProp("@url"), false);
- if (url.length())
- splitUrlSchemeHostPort(url.str(), username, password, schemeHostPort, path);
- name.set(vault->queryProp("@name"));
- kind = getSecretType(vault->queryProp("@kind"));
- if (vault->hasProp("@role"))
- role.set(vault->queryProp("@role"));
- else
- role.set("hpcc-vault-access");
- if (vault->hasProp("@client-secret"))
- {
- useKubernetesAuth = false;
- //for now only support direct access token. we can support other combinations for example login token, ldap login, etc later.
- Owned<IPropertyTree> clientSecret = getLocalSecret("system", vault->queryProp("@client-secret"));
- if (clientSecret)
- token.set(clientSecret->queryProp("token"));
- }
- }
- CVaultKind getVaultKind() const { return kind; }
- void kubernetesLogin()
- {
- CriticalBlock block(vaultCS);
- if (token.length())
- return;
- StringBuffer login_token;
- login_token.loadFile("/var/run/secrets/kubernetes.io/serviceaccount/token");
- if (login_token.length())
- {
- std::string json;
- json.append("{\"jwt\": \"").append(login_token.str()).append("\", \"role\": \"").append(role.str()).append("\"}");
- httplib::Client cli(schemeHostPort.str());
- if (username.length() && password.length())
- cli.set_basic_auth(username, password);
- httplib::Result res = cli.Post("/v1/auth/kubernetes/login", json, "application/json");
- if (res)
- {
- if (res->status == 200)
- {
- const char *response = res->body.c_str();
- if (!isEmptyString(response))
- {
- Owned<IPropertyTree> respTree = createPTreeFromJSONString(response);
- if (respTree)
- token.set(respTree->queryProp("auth/client_token"));
- }
- }
- else
- {
- Owned<IException> e = MakeStringException(0, "Vault kube auth error [%d](%d) - vault: %s - response: %s", res->status, res.error(), name.str(), res->body.c_str());
- OWARNLOG(e);
- throw e.getClear();
- }
- }
- }
- }
- bool getCachedSecret(CVaultKind &rkind, StringBuffer &content, const char *secret, const char *version)
- {
- CriticalBlock block(vaultCS);
- IPropertyTree *tree = cache->queryPropTree(secret);
- if (tree)
- {
- VStringBuffer vername("v.%s", isEmptyString(version) ? "latest" : version);
- IPropertyTree *envelope = tree->queryPropTree(vername);
- if (!envelope)
- return false;
- if (checkSecretExpired((unsigned) envelope->getPropInt("@created")))
- {
- tree->removeTree(envelope);
- return false;
- }
- const char *s = envelope->queryProp("");
- if (!isEmptyString(s))
- {
- rkind = kind;
- content.append(s);
- return true;
- }
- }
- return false;
- }
- void addCachedSecret(const char *content, const char *secret, const char *version)
- {
- VStringBuffer vername("v.%s", isEmptyString(version) ? "latest" : version);
- Owned<IPropertyTree> envelope = createPTree(vername);
- envelope->setPropInt("@created", (int) msTick());
- envelope->setProp("", content);
- {
- CriticalBlock block(vaultCS);
- IPropertyTree *parent = ensurePTree(cache, secret);
- parent->setPropTree(vername, envelope.getClear());
- }
- }
- bool requestSecret(CVaultKind &rkind, StringBuffer &content, const char *secret, const char *version)
- {
- if (isEmptyString(secret))
- return false;
- if (useKubernetesAuth && token.isEmpty())
- kubernetesLogin();
- if (token.isEmpty())
- {
- Owned<IException> e = MakeStringException(0, "Vault auth error - vault: %s - vault access token not provided", name.str());
- OERRLOG(e);
- throw e.getClear();
- }
- StringBuffer location(path);
- location.replaceString("${secret}", secret);
- location.replaceString("${version}", version ? version : "1");
- httplib::Client cli(schemeHostPort.str());
- if (username.length() && password.length())
- cli.set_basic_auth(username.str(), password.str());
- httplib::Headers headers = {
- { "X-Vault-Token", token.str() }
- };
- if (httplib::Result res = cli.Get(location, headers))
- {
- if (res->status == 200)
- {
- rkind = kind;
- content.append(res->body.c_str());
- addCachedSecret(content.str(), secret, version);
- return true;
- }
- else
- {
- DBGLOG("Vault %s error accessing secret %s.%s [%d](%d) - response: %s", name.str(), secret, version ? version : "", res->status, res.error(), res->body.c_str());
- }
- }
- return false;
- }
- };
- class CVaultSet
- {
- private:
- std::map<std::string, std::unique_ptr<CVault>> vaults;
- public:
- CVaultSet()
- {
- }
- void addVault(IPropertyTree *vault)
- {
- const char *name = vault->queryProp("@name");
- if (!isEmptyString(name))
- vaults.emplace(name, std::unique_ptr<CVault>(new CVault(vault)));
- }
- bool getCachedSecret(CVaultKind &kind, StringBuffer &content, const char *secret, const char *version)
- {
- auto it = vaults.begin();
- for (; it != vaults.end(); it++)
- {
- if (it->second->getCachedSecret(kind, content, secret, version))
- return true;
- }
- return false;
- }
- bool requestSecret(CVaultKind &kind, StringBuffer &content, const char *secret, const char *version)
- {
- auto it = vaults.begin();
- for (; it != vaults.end(); it++)
- {
- if (it->second->requestSecret(kind, content, secret, version))
- return true;
- }
- return false;
- }
- bool getCachedSecretFromVault(const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version)
- {
- if (isEmptyString(vaultId))
- return false;
- auto it = vaults.find(vaultId);
- if (it == vaults.end())
- return false;
- return it->second->getCachedSecret(kind, content, secret, version);
- }
- bool requestSecretFromVault(const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version)
- {
- if (isEmptyString(vaultId))
- return false;
- auto it = vaults.find(vaultId);
- if (it == vaults.end())
- return false;
- return it->second->requestSecret(kind, content, secret, version);
- }
- };
- class CVaultManager : public CInterfaceOf<IVaultManager>
- {
- private:
- std::map<std::string, std::unique_ptr<CVaultSet>> categories;
- public:
- CVaultManager()
- {
- IPropertyTree *config = nullptr;
- try
- {
- config = queryComponentConfig().queryPropTree("vaults");
- }
- catch (IException * e)
- {
- EXCLOG(e);
- e->Release();
- }
- if (!config)
- return;
- Owned<IPropertyTreeIterator> iter = config->getElements("*");
- ForEach (*iter)
- {
- IPropertyTree &vault = iter->query();
- const char *category = vault.queryName();
- auto it = categories.find(category);
- if (it == categories.end())
- {
- auto placed = categories.emplace(category, std::unique_ptr<CVaultSet>(new CVaultSet()));
- if (placed.second)
- it = placed.first;
- }
- if (it != categories.end())
- it->second->addVault(&vault);
- }
- }
- bool getCachedSecretFromVault(const char *category, const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) override
- {
- if (isEmptyString(category))
- return false;
- auto it = categories.find(category);
- if (it == categories.end())
- return false;
- return it->second->getCachedSecretFromVault(vaultId, kind, content, secret, version);
- }
- bool requestSecretFromVault(const char *category, const char *vaultId, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) override
- {
- if (isEmptyString(category))
- return false;
- auto it = categories.find(category);
- if (it == categories.end())
- return false;
- return it->second->requestSecretFromVault(vaultId, kind, content, secret, version);
- }
- bool getCachedSecretByCategory(const char *category, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) override
- {
- if (isEmptyString(category))
- return false;
- auto it = categories.find(category);
- if (it == categories.end())
- return false;
- return it->second->getCachedSecret(kind, content, secret, version);
- }
- bool requestSecretByCategory(const char *category, CVaultKind &kind, StringBuffer &content, const char *secret, const char *version) override
- {
- if (isEmptyString(category))
- return false;
- auto it = categories.find(category);
- if (it == categories.end())
- return false;
- return it->second->requestSecret(kind, content, secret, version);
- }
- };
- IVaultManager *ensureVaultManager()
- {
- CriticalBlock block(secretCS);
- if (!vaultManager)
- vaultManager.setown(new CVaultManager());
- return vaultManager;
- }
- static IPropertyTree *getCachedLocalSecret(const char *category, const char *name)
- {
- if (isEmptyString(name))
- return nullptr;
- Owned<IPropertyTree> secret;
- {
- CriticalBlock block(secretCacheCS);
- IPropertyTree *tree = secretCache->queryPropTree(category);
- if (!tree)
- return nullptr;
- secret.setown(tree->getPropTree(name));
- if (secret)
- {
- if (checkSecretExpired((unsigned) secret->getPropInt("@created")))
- {
- secretCache->removeProp(name);
- return nullptr;
- }
- return secret.getClear();
- }
- }
- return nullptr;
- }
- static void addCachedLocalSecret(const char *category, const char *name, IPropertyTree *secret)
- {
- if (!secret || isEmptyString(name) || isEmptyString(category))
- return;
- secret->setPropInt("@created", (int)msTick());
- {
- CriticalBlock block(secretCacheCS);
- IPropertyTree *tree = ensurePTree(secretCache, category);
- tree->setPropTree(name, LINK(secret));
- }
- }
- static const char *ensureSecretDirectory()
- {
- CriticalBlock block(secretCS);
- if (secretDirectory.isEmpty())
- setSecretMount(nullptr);
- return secretDirectory;
- }
- static StringBuffer &buildSecretPath(StringBuffer &path, const char *category, const char * name)
- {
- return addPathSepChar(path.append(ensureSecretDirectory())).append(category).append(PATHSEPCHAR).append(name).append(PATHSEPCHAR);
- }
- static IPropertyTree *loadLocalSecret(const char *category, const char * name)
- {
- StringBuffer path;
- buildSecretPath(path, category, name);
- Owned<IDirectoryIterator> entries = createDirectoryIterator(path);
- if (!entries || !entries->first())
- return nullptr;
- Owned<IPropertyTree> tree = createPTree(name);
- tree->setPropInt("@created", (int) msTick());
- ForEach(*entries)
- {
- if (entries->isDir())
- continue;
- StringBuffer name;
- entries->getName(name);
- if (!validateXMLTag(name))
- continue;
- MemoryBuffer content;
- Owned<IFileIO> io = entries->query().open(IFOread);
- read(io, 0, (size32_t)-1, content);
- if (!content.length())
- continue;
- tree->setPropBin(name, content.length(), content.bufferBase());
- }
- addCachedLocalSecret(category, name, tree);
- return tree.getClear();
- }
- extern jlib_decl IPropertyTree *getLocalSecret(const char *category, const char * name)
- {
- Owned<IPropertyTree> tree = getCachedLocalSecret(category, name);
- if (tree)
- return tree.getClear();
- return loadLocalSecret(category, name);
- }
- static IPropertyTree *createPTreeFromVaultSecret(const char *content, CVaultKind kind)
- {
- if (isEmptyString(content))
- return nullptr;
- Owned<IPropertyTree> tree = createPTreeFromJSONString(content);
- if (!tree)
- return nullptr;
- switch (kind)
- {
- case CVaultKind::kv_v1:
- tree.setown(tree->getPropTree("data"));
- break;
- default:
- case CVaultKind::kv_v2:
- tree.setown(tree->getPropTree("data/data"));
- break;
- }
- return tree.getClear();
- }
- static IPropertyTree *getCachedVaultSecret(const char *category, const char *vaultId, const char * name, const char *version)
- {
- CVaultKind kind;
- StringBuffer json;
- IVaultManager *vaultmgr = ensureVaultManager();
- if (isEmptyString(vaultId))
- {
- if (!vaultmgr->getCachedSecretByCategory(category, kind, json, name, version))
- return nullptr;
- }
- else
- {
- if (!vaultmgr->getCachedSecretFromVault(category, vaultId, kind, json, name, version))
- return nullptr;
- }
- return createPTreeFromVaultSecret(json.str(), kind);
- }
- static IPropertyTree *requestVaultSecret(const char *category, const char *vaultId, const char * name, const char *version)
- {
- CVaultKind kind;
- StringBuffer json;
- IVaultManager *vaultmgr = ensureVaultManager();
- if (isEmptyString(vaultId))
- {
- if (!vaultmgr->requestSecretByCategory(category, kind, json, name, version))
- return nullptr;
- }
- else
- {
- if (!vaultmgr->requestSecretFromVault(category, vaultId, kind, json, name, version))
- return nullptr;
- }
- return createPTreeFromVaultSecret(json.str(), kind);
- }
- extern jlib_decl IPropertyTree *getVaultSecret(const char *category, const char *vaultId, const char * name, const char *version)
- {
- CVaultKind kind;
- StringBuffer json;
- IVaultManager *vaultmgr = ensureVaultManager();
- if (isEmptyString(vaultId))
- {
- if (!vaultmgr->getCachedSecretByCategory(category, kind, json, name, version))
- vaultmgr->requestSecretByCategory(category, kind, json, name, version);
- }
- else
- {
- if (!vaultmgr->getCachedSecretFromVault(category, vaultId, kind, json, name, version))
- vaultmgr->requestSecretFromVault(category, vaultId, kind, json, name, version);
- }
- return createPTreeFromVaultSecret(json.str(), kind);
- }
- extern jlib_decl IPropertyTree *getSecret(const char *category, const char * name)
- {
- //check for any chached first
- Owned<IPropertyTree> secret = getCachedLocalSecret(category, name);
- if (!secret)
- secret.setown(getCachedVaultSecret(category, nullptr, name, nullptr));
- //now check local, then vaults
- if (!secret)
- secret.setown(loadLocalSecret(category, name));
- if (!secret)
- secret.setown(requestVaultSecret(category, nullptr, name, nullptr));
- return secret.getClear();
- }
- extern jlib_decl bool getSecretKeyValue(MemoryBuffer & result, IPropertyTree *secret, const char * key)
- {
- IPropertyTree *tree = secret->queryPropTree(key);
- if (tree)
- return tree->getPropBin(nullptr, result);
- return false;
- }
- extern jlib_decl bool getSecretKeyValue(StringBuffer & result, IPropertyTree *secret, const char * key)
- {
- IPropertyTree *tree = secret->queryPropTree(key);
- if (!tree)
- return false;
- if (tree->isBinary(nullptr))
- {
- MemoryBuffer mb;
- tree->getPropBin(nullptr, mb);
- //caller implies it's a string
- result.append(mb.length(), mb.toByteArray());
- return true;
- }
- const char *value = tree->queryProp(nullptr);
- if (value)
- {
- result.append(value);
- return true;
- }
- return false;
- }
- extern jlib_decl bool getSecretValue(StringBuffer & result, const char *category, const char * name, const char * key, bool required)
- {
- Owned<IPropertyTree> secret = getSecret(category, name);
- if (required && !secret)
- throw MakeStringException(-1, "secret %s.%s not found", category, name);
- bool found = getSecretKeyValue(result, secret, key);
- if (required && !found)
- throw MakeStringException(-1, "secret %s.%s missing key %s", category, name, key);
- return true;
- }
- void initSecretUdpKey()
- {
- if (udpKeyInitialized)
- return;
- //can find alternatives for old openssl in the future if necessary
- #if defined(_USE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
- StringBuffer path;
- BIO *in = BIO_new_file(buildSecretPath(path, "certificates", "udp").append("tls.key"), "r");
- if (in == nullptr)
- return;
- EC_KEY *eckey = PEM_read_bio_ECPrivateKey(in, nullptr, nullptr, nullptr);
- if (eckey)
- {
- unsigned char *priv = NULL;
- size_t privlen = EC_KEY_priv2buf(eckey, &priv);
- if (privlen != 0)
- {
- udpKey.set(privlen, priv);
- OPENSSL_clear_free(priv, privlen);
- }
- EC_KEY_free(eckey);
- }
- BIO_free(in);
- #endif
- udpKeyInitialized = true;
- }
- const MemoryAttr &getSecretUdpKey(bool required)
- {
- if (!udpKeyInitialized)
- throw makeStringException(-1, "UDP Key not initialized.");
- if (required && !udpKey.length())
- throw makeStringException(-1, "UDP Key not found, cert-manager integration/configuration required.");
- return udpKey;
- }
- IPropertyTree *queryMtlsSecretInfo(const char *name)
- {
- if (isEmptyString(name))
- return nullptr;
- CriticalBlock block(mtlsInfoCacheCS);
- IPropertyTree *info = mtlsInfoCache->queryPropTree(name);
- if (info)
- return info;
- StringBuffer filepath;
- StringBuffer secretpath;
- buildSecretPath(secretpath, "certificates", name);
- filepath.set(secretpath).append("tls.crt");
- if (!checkFileExists(filepath))
- return nullptr;
- info = mtlsInfoCache->setPropTree(name);
- info->setProp("certificate", filepath.str());
- filepath.set(secretpath).append("tls.key");
- if (checkFileExists(filepath))
- info->setProp("privatekey", filepath.str());
- IPropertyTree *verify = ensurePTree(info, "verify");
- if (verify)
- {
- filepath.set(secretpath).append("ca.crt");
- if (checkFileExists(filepath))
- {
- IPropertyTree *ca = ensurePTree(verify, "ca_certificates");
- if (ca)
- ca->setProp("@path", filepath.str());
- }
- verify->setPropBool("@enable", true);
- verify->setPropBool("@address_match", false);
- verify->setPropBool("@accept_selfsigned", false);
- verify->setProp("trusted_peers", "anyone");
- }
- return info;
- }
|