stephb9959
2023-09-12 10:54:35 -07:00
parent ca7c618c16
commit 69dce68d1a
5 changed files with 210 additions and 145 deletions

View File

@@ -89,7 +89,7 @@ paths:
get:
tags:
- OpenRoaming-Global Reach
operationId: getOpenRoaminGlobalReachAccountList
operationId: getOpenRoamingGlobalReachAccountList
summary: Retrieve account list.
parameters:
- in: query
@@ -132,7 +132,7 @@ paths:
get:
tags:
- OpenRoaming-Global Reach
operationId: getOpenRoaminGlobalReachAccount
operationId: getOpenRoamingGlobalReachAccount
summary: Retrieve account information.
parameters:
- in: path
@@ -154,7 +154,7 @@ paths:
delete:
tags:
- OpenRoaming-Global Reach
operationId: deleteOpenRoaminGlobalReachAccount
operationId: deleteOpenRoamingGlobalReachAccount
summary: Delete account information.
parameters:
- in: path
@@ -176,7 +176,7 @@ paths:
post:
tags:
- OpenRoaming-Global Reach
operationId: createOpenRoaminGlobalReachAccount
operationId: createOpenRoamingGlobalReachAccount
summary: Create account information.
parameters:
- in: path
@@ -203,7 +203,7 @@ paths:
put:
tags:
- OpenRoaming-Global Reach
operationId: modifyOpenRoaminGlobalReachAccount
operationId: modifyOpenRoamingGlobalReachAccount
summary: Modify account information.
parameters:
- in: path
@@ -231,7 +231,7 @@ paths:
get:
tags:
- OpenRoaming-Global Reach Certificate
operationId: getOpenRoaminGlobalReachCertificateList
operationId: getOpenRoamingGlobalReachCertificateList
summary: Retrieve certificate list.
parameters:
- in: path
@@ -280,17 +280,17 @@ paths:
get:
tags:
- OpenRoaming-Global Reach Certificate
operationId: getOpenRoaminGlobalReachCertificate
operationId: getOpenRoamingGlobalReachCertificate
summary: Retrieve certificate information.
parameters:
- in: path
description: The account name
description: The account name - this is the provisioning ID for the account. Not the GlobalReach ID.
name: account
schema:
type: string
required: true
- in: path
description: The certificate id
description: The certificate id in provisioning - not the certificate_id from GlobalReach
name: id
schema:
type: string
@@ -308,17 +308,17 @@ paths:
delete:
tags:
- OpenRoaming-Global Reach Certificate
operationId: deleteOpenRoaminGlobalReachCertificate
operationId: deleteOpenRoamingGlobalReachCertificate
summary: Delete certificate information.
parameters:
- in: path
description: The account name
description: The account name - this is the provisioning ID for the account. Not the GlobalReach ID.
name: account
schema:
type: string
required: true
- in: path
description: The certificate id
description: The certificate id in provisioning - not the certificate_id from GlobalReach
name: id
schema:
type: string
@@ -336,17 +336,17 @@ paths:
post:
tags:
- OpenRoaming-Global Reach Certificate
operationId: createOpenRoaminGlobalReachCertificate
operationId: createOpenRoamingGlobalReachCertificate
summary: Create certificate information.
parameters:
- in: path
description: The account name
description: The account name - this is the provisioning ID for the account. Not the GlobalReach ID.
name: account
schema:
type: string
required: true
- in: path
description: The certificate id
description: Must be set to "0"
name: id
schema:
type: string
@@ -366,36 +366,3 @@ paths:
404:
$ref: '#/components/responses/NotFound'
put:
tags:
- OpenRoaming-Global Reach Certificate
operationId: modifyOpenRoaminGlobalReachCertificate
summary: Modify certificate information.
parameters:
- in: path
description: The account name
name: account
schema:
type: string
required: true
- in: path
description: The certificate id
name: id
schema:
type: string
required: true
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/GLBLRAccountInfo'
responses:
200:
$ref: '#/components/schemas/GLBLRAccountInfo'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -12,11 +12,13 @@
#include <Poco/JSON/Parser.h>
#include <framework/MicroServiceFuncs.h>
#include <StorageService.h>
namespace OpenWifi {
int OpenRoaming_GlobalReach::Start() {
poco_information(Logger(), "Starting...");
InitCache();
return 0;
}
@@ -25,111 +27,150 @@ namespace OpenWifi {
poco_information(Logger(), "Stopped...");
}
bool OpenRoaming_GlobalReach::GetAccountInfo(
[[maybe_unused]] const std::string &AccountName,
[[maybe_unused]] ProvObjects::GLBLRAccountInfo &Account) {
/* Poco::URI URI{"https://config.openro.am/v1/config"};
void OpenRoaming_GlobalReach::InitCache() {
std::string Path(URI.getPathAndQuery());
auto F=[&](const ProvObjects::GLBLRAccountInfo &Info) {
poco_information(Logger(),fmt::format("Adding {} to cache.",Info.info.name));
if(!Info.privateKey.empty() && !Info.GlobalReachAcctId.empty() ) {
MakeToken(Info.GlobalReachAcctId, Info.privateKey);
}
return true;
};
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
Poco::JSON::Parser P;
Result= P.parse(is).extract<Poco::JSON::Object::Ptr>();
std::cout << Response.getStatus() << " : " ;
Result->stringify(std::cout);
std::cout << std::endl;
*/
return true;
StorageService()->GLBLRAccountInfoDB().Iterate(F);
}
bool OpenRoaming_GlobalReach::CreateRadsecCertificate(
[[maybe_unused]] const std::string &AccountName,
[[maybe_unused]] ProvObjects::GLBLRCertificateInfo &NewCertificate) {
/*
Poco::URI URI{"https://config.openro.am/v1/radsec/issue"};
bool OpenRoaming_GlobalReach::CreateRADSECCertificate(
const std::string &GlobalReachAccountId,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
std::string Path(URI.getPathAndQuery());
try {
auto BearerToken = MakeToken(GlobalReachAccountId);
Poco::URI URI{"https://config.openro.am/v1/radsec/issue"};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
Request.add("Authorization", "Bearer " + BearerToken);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Poco::JSON::Object CertRequestBody;
CertRequestBody.set("name", Name);
CertRequestBody.set("csr", CSR);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
std::ostringstream os;
CertRequestBody.stringify(os);
Request.setContentType("application/json");
Request.setContentLength((long) os.str().size());
std::ostringstream os;
Body.stringify(os);
Request.setContentType("application/json");
Request.setContentLength(os.str().size());
auto &Body = Session.sendRequest(Request);
Body << os.str();
auto &body = Session.sendRequest(Request);
body << os.str();
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
Poco::JSON::Parser P;
Result= P.parse(is).extract<Poco::JSON::Object::Ptr>();
std::cout << Response.getStatus() << " : " ;
Result->stringify(std::cout);
std::cout << std::endl;
*/
return true;
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
NewCertificate.csr = Result->get("csr").toString();
NewCertificate.certificate = Result->get("certificate").toString();
NewCertificate.name = Result->get("name").toString();
NewCertificate.certificateChain = Result->get("certificate_chain").toString();
NewCertificate.certificateId = Result->get("certificate_id").toString();
NewCertificate.expiresAt = Result->get("expires_at");
return true;
}
} catch( const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Could not create a new RADSEC certificate: {},{}",E.name(),E.displayText()));
}
return false;
}
bool OpenRoaming_GlobalReach::GetRadsecCertificate(
[[maybe_unused]] const std::string &AccountName,
[[maybe_unused]] std::string &CertificateId,
[[maybe_unused]] ProvObjects::GLBLRCertificateInfo &NewCertificate) {
return true;
bool OpenRoaming_GlobalReach::GetRADSECCertificate(
const std::string &GlobalReachAccountId,
std::string &CertificateId,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
try {
Poco::URI URI{fmt::format("https://config.openro.am/v1/radsec/cert/{}", CertificateId)};
std::string Path(URI.getPathAndQuery());
Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, Path,
Poco::Net::HTTPMessage::HTTP_1_1);
auto BearerToken = MakeToken(GlobalReachAccountId);
Request.add("Authorization", "Bearer " + BearerToken);
Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort());
Session.setTimeout(Poco::Timespan(10000, 10000));
Session.sendRequest(Request);
Poco::Net::HTTPResponse Response;
std::istream &is = Session.receiveResponse(Response);
if (Response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK) {
Poco::JSON::Parser P;
auto Result = P.parse(is).extract<Poco::JSON::Object::Ptr>();
NewCertificate.csr = Result->get("csr").toString();
NewCertificate.certificate = Result->get("certificate").toString();
NewCertificate.name = Result->get("name").toString();
NewCertificate.certificateChain = Result->get("certificate_chain").toString();
NewCertificate.certificateId = Result->get("certificate_id").toString();
NewCertificate.expiresAt = Result->get("expires_at");
std::cout << Response.getStatus() << " : ";
Result->stringify(std::cout);
std::cout << std::endl;
return true;
}
} catch( const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Could not retrieve the certificate from GlobalReach: {},{}",E.name(),E.displayText()));
}
return false;
}
std::string OpenRoaming_GlobalReach::MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey) {
Poco::JWT::Token token;
try {
Poco::JWT::Token token;
token.setType("JWT");
token.setAlgorithm("ES256");
token.setIssuedAt(std::time(nullptr));
token.setType("JWT");
token.setAlgorithm("ES256");
token.setIssuedAt(std::time(nullptr));
token.payload().set("iss", GlobalReachAccountId);
token.payload().set("iat", (unsigned long) std::time(nullptr));
token.payload().set("iss", GlobalReachAccountId);
token.payload().set("iat", (unsigned long) std::time(nullptr));
Poco::SharedPtr<Poco::Crypto::ECKey> Key;
auto KeyHash = Utils::ComputeHash(PrivateKey);
auto KeyHint = PrivateKeys_.find(GlobalReachAccountId);
if (KeyHint != PrivateKeys_.end() && KeyHint->first == KeyHash) {
Key = KeyHint->second.second;
} else {
if (PrivateKey.empty()) {
return "";
}
Poco::TemporaryFile F;
std::ofstream ofs(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
ofs << PrivateKey;
ofs.close();
auto NewKey = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(), ""));
Key = NewKey;
PrivateKeys_[GlobalReachAccountId] = std::make_pair(KeyHash, NewKey);
}
Poco::SharedPtr<Poco::Crypto::ECKey> Key;
auto KeyHash = Utils::ComputeHash(PrivateKey);
auto KeyHint = PrivateKeys_.find(KeyHash);
if(KeyHint!=PrivateKeys_.end()) {
Key = KeyHint->second;
} else {
Poco::TemporaryFile F;
std::ofstream ofs(F.path().c_str(),std::ios_base::trunc|std::ios_base::out|std::ios_base::binary);
ofs << PrivateKey;
ofs.close();
auto NewKey = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(),""));
Key = PrivateKeys_[KeyHash] = NewKey;
Poco::JWT::Signer Signer;
Signer.setECKey(Key);
Signer.addAllAlgorithms();
return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256);
} catch (const Poco::Exception &E) {
poco_error(Logger(),fmt::format("Cannot create a Global Reach token: {},{}",E.name(),E.displayText()));
}
Poco::JWT::Signer Signer;
Signer.setECKey(Key);
Signer.addAllAlgorithms();
return Signer.sign(token, Poco::JWT::Signer::ALGO_ES256);
return "";
}
bool OpenRoaming_GlobalReach::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, [[
maybe_unused]] std::string &Name) {
bool OpenRoaming_GlobalReach::VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name) {
auto BearerToken = MakeToken(GlobalReachAccountId, PrivateKey);
Poco::URI URI{"https://config.openro.am/v1/config"};

View File

@@ -19,15 +19,18 @@ namespace OpenWifi {
int Start() override;
void Stop() override;
bool GetAccountInfo(const std::string &AccountName, ProvObjects::GLBLRAccountInfo &Account);
bool CreateRadsecCertificate(const std::string &AccountName, ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool GetRadsecCertificate(const std::string &AccountName, std::string & CertificateId, ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool CreateRADSECCertificate(const std::string &AccountName,
const std::string &Name,
const std::string &CSR,
ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool GetRADSECCertificate(const std::string &AccountName, std::string & CertificateId, ProvObjects::GLBLRCertificateInfo &NewCertificate);
bool VerifyAccount(const std::string &GlobalReachAccountId, const std::string &PrivateKey, std::string &Name);
void InitCache();
private:
std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey);
std::string MakeToken(const std::string &GlobalReachAccountId, const std::string &PrivateKey="");
std::map<std::string,Poco::SharedPtr<Poco::Crypto::ECKey>> PrivateKeys_;
std::map<std::string,std::pair<std::string,Poco::SharedPtr<Poco::Crypto::ECKey>>> PrivateKeys_;
OpenRoaming_GlobalReach() noexcept
: SubSystemServer("OpenRoaming_GlobalReach", "GLBL-REACH", "globalreach") {

View File

@@ -3,23 +3,78 @@
//
#include "RESTAPI_openroaming_gr_cert_handler.h"
#include <OpenRoamin_GlobalReach.h>
namespace OpenWifi {
void RESTAPI_openroaming_gr_cert_handler::DoGet() {
return BadRequest(RESTAPI::Errors::NotImplemented);
auto Account = GetBinding("account","");
auto Id = GetBinding("id","");
if(Account.empty() || Id.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(!StorageService()->GLBLRAccountInfoDB().Exists("id",Account)) {
return NotFound();
}
std::vector<ProvObjects::GLBLRCertificateInfo> Certificates;
DB_.GetRecords(0,1,Certificates,fmt::format(" accountId='{}' and id='{}' ", Account, Id));
if(Certificates.empty()) {
return NotFound();
}
return ReturnObject(Certificates[0]);
}
void RESTAPI_openroaming_gr_cert_handler::DoDelete() {
return BadRequest(RESTAPI::Errors::NotImplemented);
auto Account = GetBinding("account","");
auto Id = GetBinding("id","");
if(Account.empty() || Id.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
if(!StorageService()->GLBLRAccountInfoDB().Exists("id",Account)) {
return NotFound();
}
DB_.DeleteRecords(fmt::format(" accountId='{}' and id='{}' ", Account, Id));
return OK();
}
void RESTAPI_openroaming_gr_cert_handler::DoPost() {
return BadRequest(RESTAPI::Errors::NotImplemented);
}
auto Account = GetBinding("account","");
auto Id = GetBinding("id","");
void RESTAPI_openroaming_gr_cert_handler::DoPut() {
return BadRequest(RESTAPI::Errors::NotImplemented);
if(Account.empty() || Id.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRCertificateInfo NewObject;
if( !NewObject.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
if(NewObject.name.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo AccountInfo;
if(!StorageService()->GLBLRAccountInfoDB().GetRecord("id",Account, AccountInfo)) {
return BadRequest(RESTAPI::Errors::InvalidGlobalReachAccount);
}
if(OpenRoaming_GlobalReach()->CreateRADSECCertificate(AccountInfo.GlobalReachAcctId,NewObject.name,AccountInfo.CSR, NewObject)) {
NewObject.id = MicroServiceCreateUUID();
NewObject.accountId = Account;
DB_.CreateRecord(NewObject);
ProvObjects::GLBLRCertificateInfo CreatedObject;
DB_.GetRecord("id",NewObject.id,CreatedObject);
return ReturnObject(CreatedObject);
}
return BadRequest(RESTAPI::Errors::RecordNotCreated);
}
} // OpenWifi

View File

@@ -15,7 +15,6 @@ namespace OpenWifi {
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_PUT,
Poco::Net::HTTPRequest::HTTP_POST,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
@@ -25,7 +24,7 @@ namespace OpenWifi {
GLBLRCertsDB &DB_ = StorageService()->GLBLRCertsDB();
void DoGet() final;
void DoPost() final;
void DoPut() final;
void DoPut() final {};
void DoDelete() final;
};
} // namespace OpenWifi