stephb9959
2023-09-11 22:35:44 -07:00
parent 5cc00a2e72
commit 21f8742bd8
22 changed files with 794 additions and 284 deletions

View File

@@ -209,7 +209,7 @@ add_executable(owprov
src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h
src/Tasks/VenueRebooter.h src/Tasks/VenueUpgrade.h
src/sdks/SDK_fms.cpp src/sdks/SDK_fms.h
src/RESTAPI/RESTAPI_overrides_handler.cpp src/RESTAPI/RESTAPI_overrides_handler.h src/OpenRoamin_GlobalReach.cpp src/OpenRoamin_GlobalReach.h src/storage/storage_glblraccounts.cpp src/storage/storage_glblraccounts.h src/storage/storage_glblrcerts.cpp src/storage/storage_glblrcerts.h)
src/RESTAPI/RESTAPI_overrides_handler.cpp src/RESTAPI/RESTAPI_overrides_handler.h src/OpenRoamin_GlobalReach.cpp src/OpenRoamin_GlobalReach.h src/storage/storage_glblraccounts.cpp src/storage/storage_glblraccounts.h src/storage/storage_glblrcerts.cpp src/storage/storage_glblrcerts.h src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.h src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_acct_handler.h src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.cpp src/RESTAPI/RESTAPI_openroaming_gr_list_certificates.h src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.cpp src/RESTAPI/RESTAPI_openroaming_gr_cert_handler.h)
target_link_libraries(owprov PUBLIC
${Poco_LIBRARIES}

2
build
View File

@@ -1 +1 @@
12
20

View File

@@ -0,0 +1,399 @@
openapi: 3.0.1
info:
title: OpenWiFi Provisioning Model
description: Definitions and APIs to manages an OpenWiFi network.
version: 2.5.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://localhost:16005/api/v1'
security:
- bearerAuth: []
- ApiKeyAuth: []
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-KEY
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
responses:
NotFound:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound'
Unauthorized:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized'
Success:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success'
BadRequest:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest'
schemas:
GLBLRAccountInfo:
type: object
properties:
allOf:
$ref: 'https://github.com/Telecominfraproject/wlan-cloud-owprov/blob/main/openpapi/owprov.yaml#/components/schemas/ObjectInfo'
privateKey:
type: string
country:
type: string
province:
type: string
city:
type: string
organization:
type: string
commonName:
type: string
CSR:
type: string
GLBLRCertificateInfo:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
accountId:
type: string
format: uuid
csr:
type: string
certificate:
type: string
certificateChain:
type: string
certificateId:
type: string
expiresAt:
type: integer
format: int64
created:
type: integer
format: int64
paths:
/openroaming/globalreach/accounts:
get:
tags:
- OpenRoaming-Global Reach
operationId: getOpenRoaminGlobalReachAccountList
summary: Retrieve account list.
parameters:
- in: query
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: offset
schema:
type: integer
required: false
- in: query
description: Maximum number of entries to return (if absent, no limit is assumed)
name: limit
schema:
type: integer
required: false
- in: query
description: return the number of accounts
name: countOnly
schema:
type: boolean
required: false
responses:
200:
description: The list of accounts
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/GLBLRAccountInfo'
$ref: '#/components/responses/Success'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/openroaming/globalreach/account/{name}:
get:
tags:
- OpenRoaming-Global Reach
operationId: getOpenRoaminGlobalReachAccount
summary: Retrieve account information.
parameters:
- in: path
description: The account name
name: name
schema:
type: string
required: true
responses:
200:
$ref: '#/components/schemas/GLBLRAccountInfo'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- OpenRoaming-Global Reach
operationId: deleteOpenRoaminGlobalReachAccount
summary: Delete account information.
parameters:
- in: path
description: The account name
name: name
schema:
type: string
required: true
responses:
200:
$ref: '#/components/responses/Success'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- OpenRoaming-Global Reach
operationId: createOpenRoaminGlobalReachAccount
summary: Create account information.
parameters:
- in: path
description: The account name
name: name
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'
put:
tags:
- OpenRoaming-Global Reach
operationId: modifyOpenRoaminGlobalReachAccount
summary: Modify account information.
parameters:
- in: path
description: The account name
name: name
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'
/openroaming/globalreach/certificates/{account}:
get:
tags:
- OpenRoaming-Global Reach Certificate
operationId: getOpenRoaminGlobalReachCertificateList
summary: Retrieve certificate list.
parameters:
- in: path
description: The account name
name: account
schema:
type: string
required: true
- in: query
description: Pagination start (starts at 1. If not specified, 1 is assumed)
name: offset
schema:
type: integer
required: false
- in: query
description: Maximum number of entries to return (if absent, no limit is assumed)
name: limit
schema:
type: integer
required: false
- in: query
description: return the number of certificates
name: countOnly
schema:
type: boolean
required: false
responses:
200:
description: The list of certificates
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/GLBLRCertificateInfo'
$ref: '#/components/responses/Success'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
/openroaming/globalreach/certificate/{account}/{id}:
get:
tags:
- OpenRoaming-Global Reach Certificate
operationId: getOpenRoaminGlobalReachCertificate
summary: Retrieve 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
responses:
200:
$ref: '#/components/schemas/GLBLRCertificateInfo'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- OpenRoaming-Global Reach Certificate
operationId: deleteOpenRoaminGlobalReachCertificate
summary: Delete 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
responses:
200:
$ref: '#/components/responses/Success'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
tags:
- OpenRoaming-Global Reach Certificate
operationId: createOpenRoaminGlobalReachCertificate
summary: Create 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/GLBLRCertificateInfo'
responses:
200:
$ref: '#/components/schemas/GLBLRCertificateInfo'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
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

@@ -1,268 +0,0 @@
openapi: 3.0.1
info:
title: OpenWiFi Open roaming Ameriband Provisioning Model
description: Registration of an OpenRoaming profile with Ameriband for TIP OpenWifi.
version: 1.0.0
license:
name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
servers:
- url: 'https://tip.regiatration.ameriband.com:8001/api/v1'
security:
- bearerAuth: []
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
responses:
NotFound:
description: The specified resource was not found.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
enum:
- 0 # Success
- 8 # INVALID_TOKEN
- 9 # EXPIRED_TOKEN
ErrorDetails:
type: string
ErrorDescription:
type: string
Success:
description: The requested operation was performed.
content:
application/json:
schema:
properties:
Operation:
type: string
Details:
type: string
Code:
type: integer
BadRequest:
description: The requested operation failed.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: integer
schemas:
RegistrationRequest:
type: object
properties:
orgRequestId:
type: string
format: uuid
minLength: 36
maxLength: 36
example:
Client will generate a UUID that must be returned in the response.
orgAcceptedTermsAndConditions:
type: boolean
default: false
orgLegalName:
type: string
minLength: 1
orgWebSite:
type: string
format: url
minLength: 1
orgContact:
type: string
minLength: 1
example:
John Smith
orgEmail:
type: string
format: email
minLength: 1
orgPhone:
type: string
example:
(607)555-1234 or +1(223)555-1222
orgLocation:
type: string
example:
Boston, NH - LA, CA
orgCertificate:
type: string
minLength: 1
example:
This must be the entire PEM file content of the certificate, encoded using base64
RegistrationResponse:
type: object
properties:
orgRequestId:
type: string
format: uuid
minLength: 36
maxLength: 36
example:
This should be the same orgRequestId passed during registration.
orgNASID:
type: string
minLength: 10
description:
This is the NASID generated by Ameriband. It will be used by the operator as NASID when contacting Ameriband.
ameribandCertificate:
type: string
minLength: 1
example:
This must be the entire PEM file content of the certificate, encoded using base64
RegistrationInformationRequest:
type: object
properties:
link:
description: This should be the link where a potential registrant can read the terms and conditions of registering with Ameriband.
type: string
format: url
minLength: 1
example:
https://ameriband.com/romain-registration.html
paths:
/termsAndConditions:
get:
summary: The registrant must be given a chance to view the terms and conditions of the relationship they are entering into
operationId: getTermsAndConditions
responses:
200:
description: Sucessfully retrieved Terms and Conditions
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationInformationRequest'
404:
$ref: '#/components/responses/Unauthorized'
/registration:
get:
tags:
- Registration
operationId: getRegistrationInformation
summary: This should return the information from a registration based on the NASID
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
responses:
200:
$ref: '#/components/schemas/RegistrationResponse'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
post:
summary: Called when the registrant ahs read the T&Cs and iw willing to submit their information to enter in a partnership
tags:
- Registration
operationId: createRegistration
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationRequest'
responses:
200:
description: Succesfully registered
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationResponse'
400:
description: Registration failed due to missing or incomplete information
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
put:
summary: Called when the registrant needs to update its information with Ameriband. The does not generate a new NASID.
tags:
- Registration
operationId: updateRegistration
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationRequest'
responses:
200:
description: Succesfully found the information based on the orgNASID
content:
application/json:
schema:
$ref: '#/components/schemas/RegistrationResponse'
400:
$ref: '#/components/responses/BadRequest'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'
delete:
tags:
- Registration
summary: When a registrant wants to terminate a relationship with Ameriband. Ameriband should also delete all information from the registrant
operationId: deleteRegistration
parameters:
- in: query
name: orgNASID
schema:
type: string
required: true
example:
This is the orgNASID returned during registration.
responses:
204:
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
$ref: '#/components/responses/NotFound'

View File

@@ -16,7 +16,9 @@ namespace OpenWifi {
poco_information(Logger(), "Stopped...");
}
bool OpenRoaming_GlobalReach::GetAccountInfo(const std::string &AccountName, ProvObjects::GLBLRAccountInfo &Account) {
bool OpenRoaming_GlobalReach::GetAccountInfo(
[[maybe_unused]] const std::string &AccountName,
[[maybe_unused]] ProvObjects::GLBLRAccountInfo &Account) {
/* Poco::URI URI{"https://config.openro.am/v1/config"};
std::string Path(URI.getPathAndQuery());
@@ -43,7 +45,9 @@ namespace OpenWifi {
return true;
}
bool OpenRoaming_GlobalReach::CreateRadsecCertificate(const std::string &AccountName, ProvObjects::GLBLRCertificateInfo &NewCertificate) {
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"};
@@ -77,8 +81,10 @@ namespace OpenWifi {
return true;
}
bool OpenRoaming_GlobalReach::GetRadsecCertificate(const std::string &AccountName, std::string &CertificateId,
ProvObjects::GLBLRCertificateInfo &NewCertificate) {
bool OpenRoaming_GlobalReach::GetRadsecCertificate(
[[maybe_unused]] const std::string &AccountName,
[[maybe_unused]] std::string &CertificateId,
[[maybe_unused]] ProvObjects::GLBLRCertificateInfo &NewCertificate) {
return true;
}

View File

@@ -0,0 +1,120 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "RESTAPI_openroaming_gr_acct_handler.h"
namespace OpenWifi {
void RESTAPI_openroaming_gr_acct_handler::DoGet() {
auto Account = GetBinding("account","");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo Record;
if(DB_.GetRecord("id",Account,Record)) {
return ReturnObject(Record);
}
return NotFound();
}
void RESTAPI_openroaming_gr_acct_handler::DoDelete() {
auto Account = GetBinding("account","");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
ProvObjects::GLBLRAccountInfo Record;
if(!DB_.GetRecord("id",Account,Record)) {
return NotFound();
}
StorageService()->GLBLRCertsDB().DeleteRecords(fmt::format(" accountId='{}' ", Account));
DB_.DeleteRecord("id", Account);
return OK();
}
void RESTAPI_openroaming_gr_acct_handler::DoPost() {
auto Account = GetBinding("account","");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRAccountInfo NewObject;
if( !NewObject.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
if(RawObject->has("privateKey")) {
if(!NewObject.privateKey.empty() && !Utils::VerifyECKey(NewObject.privateKey)) {
return BadRequest(RESTAPI::Errors::NotAValidECKey);
}
}
if( NewObject.commonName.empty() || NewObject.organization.empty() ||
NewObject.city.empty() || NewObject.province.empty() || NewObject.country.empty() ) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
NewObject.CSR = Utils::CreateX509CSR(NewObject.country,NewObject.province, NewObject.city, NewObject.organization, NewObject.commonName);
ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewObject.info);
if(DB_.CreateRecord(NewObject)) {
ProvObjects::GLBLRAccountInfo StoredObject;
DB_.GetRecord("id",NewObject.info.id,StoredObject);
return ReturnObject(StoredObject);
}
return BadRequest(RESTAPI::Errors::RecordNotCreated);
}
void RESTAPI_openroaming_gr_acct_handler::DoPut() {
auto Account = GetBinding("account","");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
const auto &RawObject = ParsedBody_;
ProvObjects::GLBLRAccountInfo Modify;
if(!Modify.from_json(RawObject)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
ProvObjects::GLBLRAccountInfo Existing;
if(!DB_.GetRecord("id",Account,Existing)) {
return NotFound();
}
if(!ProvObjects::UpdateObjectInfo(RawObject,UserInfo_.userinfo,Existing.info)) {
return BadRequest(OpenWifi::RESTAPI::Errors::InvalidJSONDocument);
}
if(RawObject->has("privateKey")) {
if(!Modify.privateKey.empty() && !Utils::VerifyECKey(Modify.privateKey)) {
return BadRequest(RESTAPI::Errors::NotAValidECKey);
}
Existing.privateKey = Modify.privateKey;
}
auto Modified = AssignIfPresent(RawObject,"country",Existing.country) ||
AssignIfPresent(RawObject,"commonName",Existing.commonName) ||
AssignIfPresent(RawObject,"city",Existing.city) ||
AssignIfPresent(RawObject,"province",Existing.province) ||
AssignIfPresent(RawObject,"organization",Existing.organization);
if(Modified) {
Existing.CSR = Utils::CreateX509CSR(Existing.country,Existing.province, Existing.city, Existing.organization, Existing.commonName);
}
if(DB_.UpdateRecord("id",Existing.info.id,Existing)) {
ProvObjects::GLBLRAccountInfo StoredObject;
DB_.GetRecord("id",Existing.info.id,StoredObject);
return ReturnObject(StoredObject);
}
return BadRequest(RESTAPI::Errors::RecordNotUpdated);
}
} // OpenWifi

View File

@@ -0,0 +1,31 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_openroaming_gr_acct_handler : public RESTAPIHandler {
public:
RESTAPI_openroaming_gr_acct_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: 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) {}
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/account/{id}"}; };
private:
GLBLRAccountInfoDB &DB_ = StorageService()->GLBLRAccountInfoDB();
void DoGet() final;
void DoPost() final;
void DoPut() final;
void DoDelete() final;
};
} // namespace OpenWifi

View File

@@ -0,0 +1,25 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "RESTAPI_openroaming_gr_cert_handler.h"
namespace OpenWifi {
void RESTAPI_openroaming_gr_cert_handler::DoGet() {
return BadRequest(RESTAPI::Errors::NotImplemented);
}
void RESTAPI_openroaming_gr_cert_handler::DoDelete() {
return BadRequest(RESTAPI::Errors::NotImplemented);
}
void RESTAPI_openroaming_gr_cert_handler::DoPost() {
return BadRequest(RESTAPI::Errors::NotImplemented);
}
void RESTAPI_openroaming_gr_cert_handler::DoPut() {
return BadRequest(RESTAPI::Errors::NotImplemented);
}
} // OpenWifi

View File

@@ -0,0 +1,31 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_openroaming_gr_cert_handler : public RESTAPIHandler {
public:
RESTAPI_openroaming_gr_cert_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: 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) {}
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/certificate/{account}/{id}"}; };
private:
GLBLRCertsDB &DB_ = StorageService()->GLBLRCertsDB();
void DoGet() final;
void DoPost() final;
void DoPut() final;
void DoDelete() final;
};
} // namespace OpenWifi

View File

@@ -0,0 +1,20 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "RESTAPI_openroaming_gr_list_acct_handler.h"
namespace OpenWifi {
void RESTAPI_openroaming_gr_list_acct_handler::DoGet() {
if(GetBoolParameter("countOnly")) {
return ReturnCountOnly(DB_.Count());
}
std::vector<ProvObjects::GLBLRAccountInfo> Accounts;
DB_.GetRecords(QB_.Offset,QB_.Limit,Accounts);
return ReturnObject(Accounts);
}
} // OpenWifi

View File

@@ -0,0 +1,29 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_openroaming_gr_list_acct_handler : public RESTAPIHandler {
public:
RESTAPI_openroaming_gr_list_acct_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/accounts"}; };
private:
GLBLRAccountInfoDB &DB_ = StorageService()->GLBLRAccountInfoDB();
void DoGet() final;
void DoPost() final{};
void DoPut() final{};
void DoDelete() final{};
};
} // namespace OpenWifi

View File

@@ -0,0 +1,27 @@
//
// Created by stephane bourque on 2023-09-11.
//
#include "RESTAPI_openroaming_gr_list_certificates.h"
namespace OpenWifi {
void RESTAPI_openroaming_gr_list_certificates::DoGet() {
auto Account = GetParameter("account","");
if(Account.empty()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
auto Where = fmt::format(" accountId='{}'", Account);
if(GetBoolParameter("countOnly")) {
return ReturnCountOnly(DB_.Count(Where));
}
std::vector<ProvObjects::GLBLRCertificateInfo> Certificates;
DB_.GetRecords(QB_.Offset,QB_.Limit,Certificates, Where);
return ReturnObject(Certificates);
}
} // OpenWifi

View File

@@ -0,0 +1,29 @@
//
// Created by stephane bourque on 2023-09-11.
//
#pragma once
#include "StorageService.h"
#include "framework/RESTAPI_Handler.h"
namespace OpenWifi {
class RESTAPI_openroaming_gr_list_certificates : public RESTAPIHandler {
public:
RESTAPI_openroaming_gr_list_certificates(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L,
RESTAPI_GenericServerAccounting &Server, uint64_t TransactionId,
bool Internal)
: RESTAPIHandler(bindings, L,
std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, TransactionId, Internal) {}
static auto PathName() { return std::list<std::string>{"/api/v1/openroaming/globalreach/certificates/{account}"}; };
private:
GLBLRCertsDB &DB_ = StorageService()->GLBLRCertsDB();
void DoGet() final;
void DoPost() final{};
void DoPut() final{};
void DoDelete() final{};
};
} // namespace OpenWifi

View File

@@ -35,6 +35,10 @@
#include "RESTAPI/RESTAPI_variables_list_handler.h"
#include "RESTAPI/RESTAPI_venue_handler.h"
#include "RESTAPI/RESTAPI_venue_list_handler.h"
#include "RESTAPI/RESTAPI_openroaming_gr_acct_handler.h"
#include "RESTAPI/RESTAPI_openroaming_gr_list_acct_handler.h"
#include "RESTAPI/RESTAPI_openroaming_gr_cert_handler.h"
#include "RESTAPI/RESTAPI_openroaming_gr_list_certificates.h"
#include "framework/RESTAPI_SystemCommand.h"
#include "framework/RESTAPI_WebSocketServer.h"
@@ -60,7 +64,9 @@ namespace OpenWifi {
RESTAPI_operators_list_handler, RESTAPI_service_class_handler,
RESTAPI_service_class_list_handler, RESTAPI_op_contact_handler,
RESTAPI_op_contact_list_handler, RESTAPI_op_location_handler,
RESTAPI_op_location_list_handler, RESTAPI_asset_server, RESTAPI_overrides_handler>(
RESTAPI_op_location_list_handler, RESTAPI_asset_server, RESTAPI_overrides_handler,
RESTAPI_openroaming_gr_acct_handler, RESTAPI_openroaming_gr_list_acct_handler,
RESTAPI_openroaming_gr_cert_handler, RESTAPI_openroaming_gr_list_certificates>(
Path, Bindings, L, S, TransactionId);
}
@@ -82,7 +88,9 @@ namespace OpenWifi {
RESTAPI_operators_list_handler, RESTAPI_service_class_handler,
RESTAPI_service_class_list_handler, RESTAPI_op_contact_handler,
RESTAPI_op_contact_list_handler, RESTAPI_op_location_handler,
RESTAPI_op_location_list_handler, RESTAPI_overrides_handler>(Path, Bindings, L, S,
RESTAPI_op_location_list_handler, RESTAPI_overrides_handler,
RESTAPI_openroaming_gr_acct_handler, RESTAPI_openroaming_gr_list_acct_handler,
RESTAPI_openroaming_gr_cert_handler, RESTAPI_openroaming_gr_list_certificates>(Path, Bindings, L, S,
TransactionId);
}
} // namespace OpenWifi

View File

@@ -1202,6 +1202,7 @@ namespace OpenWifi::ProvObjects {
field_to_json(Obj, "city", city);
field_to_json(Obj, "organization", organization);
field_to_json(Obj, "commonName", commonName);
field_to_json(Obj, "CSR", CSR);
}
bool GLBLRAccountInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -1213,6 +1214,7 @@ namespace OpenWifi::ProvObjects {
field_from_json(Obj, "city", city);
field_from_json(Obj, "organization", organization);
field_from_json(Obj, "commonName", commonName);
field_from_json(Obj, "CSR", CSR);
return true;
} catch (const Poco::Exception &E) {

View File

@@ -751,6 +751,7 @@ namespace OpenWifi::ProvObjects {
ObjectInfo info;
std::string privateKey;
std::string country, province, city, organization, commonName;
std::string CSR;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -584,6 +584,26 @@ namespace OpenWifi {
return ReturnRawJSON(os.str());
}
template<class T> void ReturnObject(const std::vector<T> &Objects) {
Poco::JSON::Array Arr;
for(const auto &Object:Objects) {
Poco::JSON::Object O;
Object.to_json(O);
Arr.add(O);
}
std::ostringstream os;
Arr.stringify(os);
return ReturnRawJSON(os.str());
}
template<class T> void ReturnObject(const T &Object) {
Poco::JSON::Object O;
Object.to_json(O);
std::ostringstream os;
O.stringify(os);
return ReturnRawJSON(os.str());
}
inline void ReturnRawJSON(const std::string &json_doc) {
PrepareResponse();
if (Request != nullptr) {

View File

@@ -407,6 +407,7 @@ namespace OpenWifi::RESTAPI::Errors {
};
static const struct msg DefFirmwareNameExists { 1172, "Firmware name already exists." };
static const struct msg NotAValidECKey { 1173, "Provided key supplied is not valid." };
static const struct msg SimulationDoesNotExist {
7000, "Simulation Instance ID does not exist."

View File

@@ -4,7 +4,7 @@
#include "Poco/Path.h"
#include "Poco/TemporaryFile.h"
#include "Poco/Crypto/ECKey.h"
#include "framework/AppServiceRegistry.h"
#include "framework/utils.h"
@@ -609,7 +609,7 @@ namespace OpenWifi::Utils {
return DT.timestamp().epochTime();
}
bool CreateX509CSR(const std::string &Country, const std::string &Province, const std::string &City,
std::string CreateX509CSR(const std::string &Country, const std::string &Province, const std::string &City,
const std::string &Organization, const std::string &CommonName, int bits ) {
int ret = 0;
RSA *r = nullptr;
@@ -632,8 +632,11 @@ namespace OpenWifi::Utils {
const char *szCommon = CommonName.c_str();
Poco::TemporaryFile CsrPath;
std::string Result;
std::ifstream ifs;
std::ostringstream ss;
// 1. generate rsa key
// 1. generate rsa key
bne = BN_new();
ret = BN_set_word(bne,e);
if(ret != 1){
@@ -700,6 +703,10 @@ namespace OpenWifi::Utils {
out = BIO_new_file(CsrPath.path().c_str(),"w");
ret = PEM_write_bio_X509_REQ(out, x509_req);
ifs.open(CsrPath.path().c_str(),std::ios_base::binary|std::ios_base::in);
Poco::StreamCopier::copyStream(ifs,ss);
ifs.close();
Result = ss.str();
// 6. free
free_all:
X509_REQ_free(x509_req);
@@ -708,8 +715,25 @@ namespace OpenWifi::Utils {
EVP_PKEY_free(pKey);
BN_free(bne);
return (ret == 1);
return Result;
}
bool VerifyECKey(const std::string &key) {
try {
Poco::TemporaryFile F;
std::ofstream of(F.path().c_str(), std::ios_base::trunc | std::ios_base::out | std::ios_base::binary);
of << key;
of.close();
auto Key = Poco::SharedPtr<Poco::Crypto::ECKey>(
new Poco::Crypto::ECKey("", F.path(),""));
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
} // namespace OpenWifi::Utils

View File

@@ -247,6 +247,7 @@ namespace OpenWifi::Utils {
return count;
}
bool CreateX509CSR(const std::string &Country, const std::string &Province, const std::string &City,
std::string CreateX509CSR(const std::string &Country, const std::string &Province, const std::string &City,
const std::string &Organization, const std::string &CommonName, int bits=2048);
bool VerifyECKey(const std::string &key);
} // namespace OpenWifi::Utils

View File

@@ -11,7 +11,7 @@
namespace OpenWifi {
static ORM::FieldVec GLBLRAccountInfoDB_Fields{// object info
static ORM::FieldVec GLBLRAccountInfoDB_Fields{
ORM::Field{"id", 64, true},
ORM::Field{"name", ORM::FieldType::FT_TEXT},
ORM::Field{"description", ORM::FieldType::FT_TEXT},
@@ -23,7 +23,8 @@ namespace OpenWifi {
ORM::Field{"province", ORM::FieldType::FT_TEXT},
ORM::Field{"city", ORM::FieldType::FT_TEXT},
ORM::Field{"organization", ORM::FieldType::FT_TEXT},
ORM::Field{"commonName", ORM::FieldType::FT_TEXT}
ORM::Field{"commonName", ORM::FieldType::FT_TEXT},
ORM::Field{"CSR", ORM::FieldType::FT_TEXT}
};
static ORM::IndexVec GLBLRAccountInfoDB_Indexes{
@@ -65,6 +66,7 @@ void ORM::DB<OpenWifi::GLBLRAccountsDBRecordType, OpenWifi::ProvObjects::GLBLRAc
Out.city = In.get<9>();
Out.organization = In.get<10>();
Out.commonName = In.get<11>();
Out.CSR = In.get<12>();
}
template <>
@@ -82,4 +84,5 @@ void ORM::DB<OpenWifi::GLBLRAccountsDBRecordType, OpenWifi::ProvObjects::GLBLRAc
Out.set<9>(In.city);
Out.set<10>(In.organization);
Out.set<11>(In.commonName);
Out.set<12>(In.CSR);
}

View File

@@ -17,6 +17,7 @@ namespace OpenWifi {
std::string,
std::string,
std::string,
std::string,
std::string>
GLBLRAccountsDBRecordType;