stephb9959
2023-01-30 13:48:19 -08:00
parent ce1818c93c
commit ffb7dd890e
6 changed files with 152 additions and 4 deletions

2
build
View File

@@ -1 +1 @@
9
11

View File

@@ -1983,9 +1983,19 @@ paths:
schema:
type: string
required: true
- in: query
name: all
schema:
type: boolean
required: false
responses:
200:
$ref: '#/components/schemas/SystemSecretEntry'
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/SystemSecretEntry'
- $ref: '#/components/schemas/SystemSecretEntryList'
403:
$ref: '#/components/responses/Unauthorized'
404:

View File

@@ -28,6 +28,7 @@
#include "TotpCache.h"
#include "framework/RESTAPI_RateLimiter.h"
#include "framework/UI_WebSocketClientServer.h"
#include <SecretStore.h>
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
@@ -47,7 +48,8 @@ namespace OpenWifi {
RESTAPI_RateLimiter(),
TotpCache(),
AuthService(),
UI_WebSocketClientServer()
UI_WebSocketClientServer(),
SecretStore()
});
}
return instance_;

View File

@@ -3,6 +3,7 @@
//
#include "RESTAPI_systemSecret_handler.h"
#include <SecretStore.h>
namespace OpenWifi {
@@ -10,6 +11,35 @@ namespace OpenWifi {
if(!Internal_ && UserInfo_.userinfo.userRole!=SecurityObjects::ROOT) {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
if(GetBoolParameter("all")) {
auto Store = SecretStore()->Store();
Poco::JSON::Array Entries;
Poco::JSON::Object List;
for(const auto &[Key,Value]:Store) {
Poco::JSON::Object E;
E.set("key",Key);
E.set("value",Value);
Entries.add(E);
}
List.set("secrets",Entries);
return ReturnObject(List);
}
auto Key = GetBinding("secret");
if(Key.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
std::string Value;
if(SecretStore()->Get(Key,Value,"")) {
Poco::JSON::Object Answer;
Answer.set("key", Key);
Answer.set("value", Value);
return ReturnObject(Answer);
}
return NotFound();
}
void RESTAPI_systemSecret_handler::DoDelete() {
@@ -17,6 +47,14 @@ namespace OpenWifi {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
auto Key = GetBinding("secret");
if(Key.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
SecretStore()->Remove(Key);
return OK();
}
void RESTAPI_systemSecret_handler::DoPut() {
@@ -24,6 +62,17 @@ namespace OpenWifi {
return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
}
auto Key = GetBinding("secret");
auto Value = GetParameter("value","_______no_value_____");
if(Key.empty() || Value == "_______no_value_____") {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
SecretStore()->Set(Key,Value);
Poco::JSON::Object Answer;
Answer.set("key", Key);
Answer.set("value", Value);
return ReturnObject(Answer);
}
} // OpenWifi

View File

@@ -2,15 +2,91 @@
// Created by stephane bourque on 2023-01-25.
//
#include <fstream>
#include "SecretStore.h"
#include <framework/MicroServiceFuncs.h>
#include <Poco/File.h>
#include <Poco/JSON/Parser.h>
namespace OpenWifi {
int SecretStore::Start() {
std::lock_guard G(Mutex_);
ReadStore();
return 0;
}
void SecretStore::Stop() {
std::lock_guard G(Mutex_);
SaveStore();
}
void SecretStore::ReadStore() {
Poco::File StoreFileName(MicroServiceDataDirectory() + "/secrets.json");
if(StoreFileName.exists() && StoreFileName.isFile()) {
try {
std::ostringstream OS;
std::ifstream IF(StoreFileName.path().c_str());
Poco::StreamCopier::copyStream(IF, OS);
Poco::JSON::Parser P;
auto Doc = P.parse(OS.str()).extract<Poco::JSON::Object::Ptr>();
if(Doc->isArray("secrets")) {
auto Secrets = Doc->getArray("secrets");
for(const auto &secret:*Secrets) {
const auto &entry = secret.extract<Poco::JSON::Object::Ptr>();
if(entry->has("key") && entry->has("value")) {
Store_[entry->get("key")] = entry->get("value").toString();
}
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
}
}
void SecretStore::SaveStore() {
Poco::JSON::Object StoreJSON;
Poco::JSON::Array Secrets;
for(const auto &[key,value]:Store_) {
Poco::JSON::Object Entry;
Entry.set("key", key);
Entry.set("value", value);
Secrets.add(Entry);
}
StoreJSON.set("secrets",Secrets);
Poco::File StoreFileName(MicroServiceDataDirectory() + "/secrets.json");
std::ofstream OF(StoreFileName.path(),std::ios_base::trunc);
StoreJSON.stringify(OF);
}
bool SecretStore::Get(const std::string & key, std::string & value, const std::string & default_value) {
std::lock_guard G(Mutex_);
auto It = Store_.find(key);
if(It!=end(Store_)) {
value = It->second;
return true;
} else {
value = default_value;
return false;
}
}
void SecretStore::Set(const std::string & key, const std::string & value ) {
std::lock_guard G(Mutex_);
Store_[key] = value;
SaveStore();
}
void SecretStore::Remove(const std::string & key) {
std::lock_guard G(Mutex_);
Store_.erase(key);
SaveStore();
}
} // OpenWifi

View File

@@ -10,6 +10,8 @@ namespace OpenWifi {
class SecretStore : public SubSystemServer {
public:
using SecretStoreType = std::map<std::string,std::string>;
static SecretStore *instance() {
static auto *instance_ = new SecretStore;
return instance_;
@@ -17,9 +19,18 @@ namespace OpenWifi {
int Start() final;
void Stop() final;
void ReadStore();
void SaveStore();
bool Get(const std::string & key, std::string & value, const std::string & default_value);
void Set(const std::string & key, const std::string & value );
void Remove(const std::string &key);
inline SecretStoreType Store() {
std::lock_guard G(Mutex_);
return Store_;
}
private:
SecretStoreType Store_;
SecretStore() noexcept:
SubSystemServer("SecretStore", "SECRET-SVR", "secret.store")
{