stephb9959
2022-11-07 15:00:39 -08:00
parent 1cba12b934
commit 5d66fe0d56
9 changed files with 130 additions and 20 deletions

2
build
View File

@@ -1 +1 @@
15
16

View File

@@ -68,4 +68,53 @@ namespace OpenWifi {
return RetrieveTokenInformation(SessionToken, UInfo, TID, Expired, Contacted, Sub);
}
bool AuthClient::RetrieveApiKeyInformation(const std::string & SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted) {
try {
Types::StringPairVec QueryData;
QueryData.push_back(std::make_pair("apikey",SessionToken));
OpenAPIRequestGet Req( uSERVICE_SECURITY,
"/api/v1/validateApiKey" ,
QueryData,
10000);
Poco::JSON::Object::Ptr Response;
auto StatusCode = Req.Do(Response);
if(StatusCode==Poco::Net::HTTPServerResponse::HTTP_GATEWAY_TIMEOUT) {
Contacted = false;
return false;
}
Contacted = true;
if(StatusCode==Poco::Net::HTTPServerResponse::HTTP_OK) {
if(Response->has("tokenInfo") && Response->has("userInfo") && Response->has("expiresOn")) {
UInfo.from_json(Response);
Expired = false;
ApiKeyCache_.update(SessionToken, ApiKeyCacheEntry{ .UserInfo = UInfo, .ExpiresOn = Response->get("expiresOn")});
return true;
} else {
return false;
}
}
} catch (...) {
poco_error(Logger(),fmt::format("Failed to retrieve api key={} for TID={}", SessionToken, TID));
}
Expired = false;
return false;
}
bool AuthClient::IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy &UInfo,
std::uint64_t TID, bool &Expired, bool &Contacted) {
auto User = ApiKeyCache_.get(SessionToken);
if (!User.isNull()) {
if(User->ExpiresOn < Utils::Now())
Expired = false;
UInfo = User->UserInfo;
return true;
}
return RetrieveApiKeyInformation(SessionToken, UInfo, TID, Expired, Contacted);
}
} // namespace OpenWifi

View File

@@ -12,6 +12,7 @@
namespace OpenWifi {
class AuthClient : public SubSystemServer {
public:
explicit AuthClient() noexcept:
SubSystemServer("Authentication", "AUTH-CLNT", "authentication")
@@ -23,6 +24,11 @@ namespace OpenWifi {
return instance_;
}
struct ApiKeyCacheEntry {
OpenWifi::SecurityObjects::UserInfoAndPolicy UserInfo;
std::uint64_t ExpiresOn;
};
inline int Start() override {
return 0;
}
@@ -36,6 +42,7 @@ namespace OpenWifi {
inline void RemovedCachedToken(const std::string &Token) {
Cache_.remove(Token);
ApiKeyCache_.remove(Token);
}
inline static bool IsTokenExpired(const SecurityObjects::WebToken &T) {
@@ -46,12 +53,24 @@ namespace OpenWifi {
SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted, bool Sub=false);
bool RetrieveApiKeyInformation(const std::string & SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted);
bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted, bool Sub = false);
bool IsValidApiKey(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo,
std::uint64_t TID,
bool & Expired, bool & Contacted);
private:
Poco::ExpireLRUCache<std::string,OpenWifi::SecurityObjects::UserInfoAndPolicy> Cache_{512,1200000 };
Poco::ExpireLRUCache<std::string,ApiKeyCacheEntry> ApiKeyCache_{512,1200000 };
};
inline auto AuthClient() { return AuthClient::instance(); }

View File

@@ -246,27 +246,19 @@ namespace OpenWifi {
FileChannel->setProperty("purgeCount", "10");
FileChannel->setProperty("path", LoggingLocation);
if(UseAsyncLogs_) {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::AsyncChannel> Async_File(
new Poco::AsyncChannel(FileChannel));
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::PatternFormatter> Formatter(new Poco::PatternFormatter);
std::cout << __LINE__ << std::endl;
Formatter->setProperty("pattern", LoggingFormat);
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, Async_File));
std::cout << __LINE__ << std::endl;
if(DisableWebSocketLogging) {
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(FormattingChannel);
} else {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<WebSocketLogger> WSLogger(new WebSocketLogger);
Poco::AutoPtr<Poco::SplitterChannel> Splitter(new Poco::SplitterChannel);
Splitter->addChannel(WSLogger);
Splitter->addChannel(FormattingChannel);
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(Splitter);
}
@@ -276,18 +268,14 @@ namespace OpenWifi {
Poco::AutoPtr<Poco::FormattingChannel> FormattingChannel(
new Poco::FormattingChannel(Formatter, FileChannel));
if(DisableWebSocketLogging) {
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(FormattingChannel);
} else {
std::cout << __LINE__ << std::endl;
Poco::AutoPtr<Poco::SplitterChannel> Splitter(new Poco::SplitterChannel);
Poco::AutoPtr<WebSocketLogger> WSLogger(new WebSocketLogger);
Splitter->addChannel(WSLogger);
Splitter->addChannel(FormattingChannel);
std::cout << __LINE__ << std::endl;
Poco::Logger::root().setChannel(Splitter);
}
std::cout << __LINE__ << std::endl;
}
}
auto Level = Poco::Logger::parseLevel(MicroService::instance().ConfigGetString("logging.level", "debug"));

View File

@@ -26,6 +26,10 @@
#include "framework/AuthClient.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#if defined(TIP_SECURITY_SERVICE)
#include "AuthService.h"
#endif
using namespace std::chrono_literals;
namespace OpenWifi {
@@ -640,7 +644,8 @@ namespace OpenWifi {
};
#ifdef TIP_SECURITY_SERVICE
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired , bool Sub );
[[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken,
SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired , bool Sub );
#endif
inline bool RESTAPIHandler::IsAuthorized( bool & Expired , [[maybe_unused]] bool & Contacted , bool Sub ) {
if(Internal_ && Request->has("X-INTERNAL-NAME")) {
@@ -665,6 +670,35 @@ namespace OpenWifi {
}
}
return Allowed;
} else if(!Internal_ && Request->has("X-API-KEY")) {
SessionToken_ = Request->get("X-API-KEY", "");
#ifdef TIP_SECURITY_SERVICE
std::uint64_t expiresOn;
if (AuthService()->IsValidApiKey(SessionToken_, UserInfo_.webtoken, UserInfo_.userinfo, Expired, expiresOn)) {
#else
if (AuthClient()->IsValidApiKey( SessionToken_, UserInfo_, TransactionId_, Expired, Contacted)) {
#endif
REST_Requester_ = UserInfo_.userinfo.email;
if(Server_.LogIt(Request->getMethod(),true)) {
poco_debug(Logger_,fmt::format("X-REQ-ALLOWED({}): APIKEY-ACCESS TID={} User='{}@{}' Method={} Path={}",
UserInfo_.userinfo.email,
TransactionId_,
Utils::FormatIPv6(Request->clientAddress().toString()),
Request->clientAddress().toString(),
Request->getMethod(),
Request->getURI()));
}
return true;
} else {
if(Server_.LogBadTokens(true)) {
poco_debug(Logger_,fmt::format("X-REQ-DENIED({}): TID={} Method={} Path={}",
Utils::FormatIPv6(Request->clientAddress().toString()),
TransactionId_,
Request->getMethod(),
Request->getURI()));
}
}
return false;
} else {
if (SessionToken_.empty()) {
try {

View File

@@ -15,6 +15,10 @@
#include "fmt/format.h"
#if defined(TIP_SECURITY_SERVICE)
#include "AuthService.h"
#endif
#define DBG { std::cout << __LINE__ << std::endl; }
namespace OpenWifi {
@@ -216,9 +220,16 @@ namespace OpenWifi {
if (!Client->second->Authenticated_) {
std::string Frame{IncomingFrame.begin()};
auto Tokens = Utils::Split(Frame, ':');
bool Expired = false, Contacted = false;
bool Expired = false;
#if not defined(TIP_SECURITY_SERVICE)
bool Contacted = false;
#endif
if (Tokens.size() == 2 &&
#if defined(TIP_SECURITY_SERVICE)
AuthService()->IsAuthorized(Tokens[1], Client->second->UserInfo_, 0, Expired)) {
#else
AuthClient()->IsAuthorized(Tokens[1], Client->second->UserInfo_, 0, Expired, Contacted)) {
#endif
Client->second->Authenticated_ = true;
Client->second->UserName_ = Client->second->UserInfo_.userinfo.email;
poco_debug(Logger(),fmt::format("START({}): {} UI Client is starting WS connection.", Client->second->Id_, Client->second->UserName_));
@@ -234,7 +245,6 @@ namespace OpenWifi {
std::ostringstream OS;
WelcomeMessage.stringify(OS);
Client->second->WS_->sendFrame(OS.str().c_str(), (int) OS.str().size());
Client->second->WS_->sendFrame(OS.str().c_str(), (int) OS.str().size());
return EndConnection(G, Client);
}
} else {

View File

@@ -222,6 +222,12 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg DeviceRequiresSignature{1146,"Device requires device signature to be provided."};
static const struct msg ApiKeyNameAlreadyExists{1147,"API Key name must be unique."};
static const struct msg TooManyApiKeys{1148,"Too many API Keys have already been created."};
static const struct msg UserMustExist{1149,"User must exist."};
static const struct msg ApiKeyNameDoesNotExist{1150,"API Key name does not exist."};
static const struct msg ApiKeyDoesNotExist{1150,"API Key does not exist."};
}

View File

@@ -520,4 +520,8 @@ bool ExtractBase64CompressedData(const std::string &CompressedData,
return false;
}
bool IsAlphaNumeric(const std::string &s) {
return std::all_of(s.begin(),s.end(),[](char c) -> bool { return isalnum(c); });
}
}

View File

@@ -115,7 +115,7 @@ namespace OpenWifi::Utils {
[[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F);
[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
[[nodiscard]] bool wgets(const std::string &URL, std::string &Response);
[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
template< typename T >
std::string int_to_hex( T i )
{