mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 10:20:26 +00:00
Add API call for list/register/revoke SSL Certificate management (auth system: alternate for the user/password combo). I don't have a way to test this just yet (still need to write the other side of the system in the client first), but here is the expected inputs:
Namespace: "sysadm"
Name: "settings"
Arguments structure needs the "action" variable/value for all calls:
Action: "list_ssl_certs"
- No additional input needed: will list the known/registered certificates organized by <username> : { <public_key> : <certificate as text> }
Action: "register_ssl_cert"
Example Payload: {"action" : "register_ssl_cert", "pub_key" : <public_key> }
The <public_key> string needs to match the public key of one of the certificates currently loaded into the server/client connection. This will register that certificate on the server and allow that user to authenticate without a password as long as that same certificate is loaded up in any future connections. No special outputs are send back (just overall error/ok status).
Action: "revoke_ssl_cert"
Example Payload: {"action" : "revoke_ssl_cert", "pub_key" : <public_key>, "user" : <optional-username> }
The <public_key> string needs to match one of the keys given by the list function (does not need to match any currently-loaded certs). The "user" field is optional, and allows a connection with full admin privileges to revoke certs belonging to other users.
Note about current user/connection permissions level:
If the current user has full admin access, the "list_ssl_certs" API call will return the registered certificates for all users on the system - otherwise it will only return the certificates for the current user. Similarly, the "revoke_ssl_cert" may be used to remove certs registered to other users only if the current user/connection has full admin access - otherwise it may only be used to manage the current user's certificates.
This commit is contained in:
@@ -90,8 +90,7 @@ bool AuthorizationManager::RevokeCertificate(QString token, QString key, QString
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonObject AuthorizationManager::ListCertificates(QString token){
|
||||
QJsonObject obj;
|
||||
void AuthorizationManager::ListCertificates(QString token, QJsonObject *out){
|
||||
QStringList keys; //Format: "RegisteredCerts/<user>/<key>"
|
||||
if( hasFullAccess(token) ){
|
||||
//Read all user's certs
|
||||
@@ -106,14 +105,12 @@ QJsonObject AuthorizationManager::ListCertificates(QString token){
|
||||
QJsonObject user; QString username;
|
||||
for(int i=0; i<keys.length(); i++){
|
||||
if(username!=keys[i].section("/",1,1)){
|
||||
if(!user.isEmpty()){ obj.insert(username, user); user = QJsonObject(); } //save the current info to the output
|
||||
if(!user.isEmpty()){ out->insert(username, user); user = QJsonObject(); } //save the current info to the output
|
||||
username = keys[i].section("/",1,1); //save the new username for later
|
||||
}
|
||||
user.insert(keys[i].section("/",2,3000), CONFIG->value(keys[i]).toString() ); //just in case the key has additional "/" in it
|
||||
}
|
||||
if(!user.isEmpty() && !username.isEmpty()){ obj.insert(username, user); }
|
||||
|
||||
return obj;
|
||||
if(!user.isEmpty() && !username.isEmpty()){ out->insert(username, user); }
|
||||
}
|
||||
|
||||
//Generic functions
|
||||
|
||||
@@ -19,10 +19,10 @@ public:
|
||||
bool checkAuth(QString token); //see if the given token is valid
|
||||
bool hasFullAccess(QString token); //see if the token is associated with a full-access account
|
||||
|
||||
//SSL Certificate register/revoke/list
|
||||
//SSL Certificate register/revoke/list (should only run if the current token is valid)
|
||||
bool RegisterCertificate(QString token, QSslCertificate cert); //if token is valid, register the given cert for future logins
|
||||
bool RevokeCertificate(QString token, QString key, QString user=""); //user will be the current user if not empty - cannot touch other user's certs without full perms on current session
|
||||
QJsonObject ListCertificates(QString token);
|
||||
void ListCertificates(QString token, QJsonObject *out);
|
||||
|
||||
int checkAuthTimeoutSecs(QString token); //Return the number of seconds that a token is valid for
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ RestOutputStruct::ExitCode WebSocket::AvailableSubsystems(bool allaccess, QJsonO
|
||||
<namespace2/name2> : <read/write/other>,
|
||||
}
|
||||
*/
|
||||
|
||||
// - server settings (always available)
|
||||
out->insert("sysadm/settings","read/write");
|
||||
|
||||
// - syscache
|
||||
if(QFile::exists("/var/run/syscache.pipe")){
|
||||
out->insert("rpc/syscache","read"); //no write to syscache - only reads
|
||||
@@ -95,7 +97,9 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
|
||||
}
|
||||
|
||||
//Go through and forward this request to the appropriate sub-system
|
||||
if(namesp=="rpc" && name=="dispatcher"){
|
||||
if(namesp=="sysadm" && name=="settings"){
|
||||
return EvaluateSysadmSettingsRequest(IN.args, out);
|
||||
}else if(namesp=="rpc" && name=="dispatcher"){
|
||||
return EvaluateDispatcherRequest(IN.fullaccess, IN.args, out);
|
||||
}else if(namesp=="sysadm" && name=="beadm"){
|
||||
return EvaluateSysadmBEADMRequest(IN.args, out);
|
||||
@@ -119,6 +123,40 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
|
||||
|
||||
}
|
||||
|
||||
// === SYSADM SETTINGS ===
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmSettingsRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
if(!in_args.isObject()){ return RestOutputStruct::BADREQUEST; }
|
||||
QJsonObject argsO = in_args.toObject();
|
||||
QStringList keys = argsO.keys();
|
||||
if(!keys.contains("action")){ return RestOutputStruct::BADREQUEST; }
|
||||
QString act = argsO.value("action").toString();
|
||||
bool ok = false;
|
||||
if(act=="register_ssl_cert" && keys.contains("pub_key")){
|
||||
//Additional arguments: "pub_key" (String), and the cert with that key must already be loaded into the connection
|
||||
QString pub_key = argsO.value("pub_key").toString();\
|
||||
//Now find the currently-loaded certificate with the given public key
|
||||
QList<QSslCertificate> certs;
|
||||
if(SOCKET!=0){ certs = SOCKET->sslConfiguration().peerCertificateChain(); }
|
||||
else if(TSOCKET!=0){ certs = TSOCKET->peerCertificateChain(); }
|
||||
for(int i=0; i<certs.length() && !ok; i++){
|
||||
if(certs[i].publicKey().toPem()==pub_key){
|
||||
//Certificate found - register it
|
||||
ok = AUTHSYSTEM->RegisterCertificate(SockAuthToken, certs[i]);
|
||||
}
|
||||
}
|
||||
}else if(act=="list_ssl_certs"){
|
||||
AUTHSYSTEM->ListCertificates(SockAuthToken, out);
|
||||
ok = true; //always works for current user (even if nothing found)
|
||||
}else if(act=="revoke_ssl_cert" && keys.contains("pub_key") ){
|
||||
//Additional arguments: "user" (optional), "pub_key" (String)
|
||||
QString user; if(keys.contains("user")){ user = argsO.value("user").toString(); }
|
||||
ok = AUTHSYSTEM->RevokeCertificate(SockAuthToken,argsO.value("pub_key").toString(), user);
|
||||
}
|
||||
|
||||
if(ok){ return RestOutputStruct::OK; }
|
||||
else{ return RestOutputStruct::BADREQUEST; }
|
||||
}
|
||||
|
||||
//==== SYSCACHE ====
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateSyscacheRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
//syscache only needs a list of sub-commands at the moment (might change later)
|
||||
|
||||
@@ -43,8 +43,14 @@ private:
|
||||
RestOutputStruct::ExitCode AvailableSubsystems(bool fullaccess, QJsonObject *out);
|
||||
// -- Main subsystem parser
|
||||
RestOutputStruct::ExitCode EvaluateBackendRequest(const RestInputStruct&, QJsonObject *out);
|
||||
|
||||
|
||||
// -- Individual subsystems
|
||||
// -- Server Settings Modification API
|
||||
RestOutputStruct::ExitCode EvaluateSysadmSettingsRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
// -- rpc syscache API
|
||||
RestOutputStruct::ExitCode EvaluateSyscacheRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
// -- rpc dispatcher API
|
||||
RestOutputStruct::ExitCode EvaluateDispatcherRequest(bool allaccess, const QJsonValue in_args, QJsonObject *out);
|
||||
// -- sysadm beadm API
|
||||
RestOutputStruct::ExitCode EvaluateSysadmBEADMRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
|
||||
Reference in New Issue
Block a user