Revision: 177
Author:
sma...@gmail.com
Date: Fri Mar 1 13:17:05 2013
Log: Change the managment interface message format to JSON (which
breaks the one previously existing mapdump command). Add new management
commands for certificate-based MAP Client management: addCertClient and
removeCertClient. See omapd.conf for info on these commands.
http://code.google.com/p/omapd/source/detail?r=177
Modified:
/trunk/managementserver.cpp
/trunk/managementserver.h
/trunk/mapsessions.cpp
/trunk/mapsessions.h
/trunk/omapd.conf
/trunk/
omapd.pro
=======================================
--- /trunk/managementserver.cpp Thu Jan 3 16:45:23 2013
+++ /trunk/managementserver.cpp Fri Mar 1 13:17:05 2013
@@ -20,7 +20,12 @@
*/
#include <QTcpSocket>
+#include <QVariantMap>
+
#include "managementserver.h"
+#include "json.h"
+#include "clientconfiguration.h"
+#include "mapsessions.h"
ManagementServer::ManagementServer(MapGraphInterface *mapGraph, QObject
*parent) :
QTcpServer(parent), _mapGraph(mapGraph)
@@ -77,18 +82,151 @@
{
QTcpSocket *clientConnection = (QTcpSocket *)sender();
- QByteArray requestData = clientConnection->readLine(128).trimmed();
+ QByteArray requestData =
clientConnection->readLine(MANAGEMENT_MSG_MAX_LENGTH).trimmed();
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
qDebug() << __PRETTY_FUNCTION__ << ":" << "Received management
request:"
<< requestData;
}
- if (requestData == "mapdump") {
+ bool parseOk;
+ //json is a QString containing the JSON data
+ QVariantMap parsedRequest = QtJson::parse(requestData,
parseOk).toMap();
+
+ if(!parseOk) {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Error parsing JSON
in management request";
+ }
+ return;
+ }
+
+ QString command = parsedRequest["cmd"].toString();
+
+ if (command == "mapdump") {
_mapGraph->dumpMap();
+ } else if (command == "addCertClient") {
+ // Note: Clients created through mgmt interface will not persist
across omapd restarts
+
+ /*
+ { "cmd":"addCertClient",
+ "type":"single",
+ "certPath":"/path/to/cert",
+ "caPath":"/path/to/clientCAChain",
+ "name":"clientName",
+ "authorization":"authzValue",
+ "metadataPolicy":"policyName" }
+ */
+
+ if (parsedRequest.contains("name") &&
+ parsedRequest.contains("type") &&
+ parsedRequest.contains("certPath") &&
+ parsedRequest.contains("caPath") &&
+ QFile::exists(parsedRequest["certPath"].toString()) &&
+ QFile::exists(parsedRequest["caPath"].toString())) {
+
+ QString clientType = parsedRequest["type"].toString();
+ QString clientName = parsedRequest["name"].toString();
+ QString certPath = parsedRequest["certPath"].toString();
+ QString certCAPath = parsedRequest["caPath"].toString();
+
+ unsigned int defaultAuthz =
_omapdConfig->valueFor("default_authorization").toUInt();
+ if (parsedRequest.contains("authorization")) {
+ bool ok = false;
+ unsigned int clientAuthz =
parsedRequest["authorization"].toString().toUInt(&ok, 16);
+ if (ok) defaultAuthz = clientAuthz;
+ } else {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Will apply
default authorization for client:" << clientName;
+ }
+ }
+
+ bool metadataPolicyOk = false;
+ QString metadataPolicy;
+ if (parsedRequest.contains("metadataPolicy") &&
+ !parsedRequest["metadataPolicy"].toString().isEmpty())
{
+ metadataPolicy =
parsedRequest["metadataPolicy"].toString();
+ if
(_omapdConfig->metadataPolicies().contains(metadataPolicy)) {
+ metadataPolicyOk = true;
+ }
+ } else {
+ metadataPolicyOk = true;
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "No metadata
policy specified for client:" << clientName;
+ }
+ }
+
+ // Create client
+ if (metadataPolicyOk) {
+ ClientConfiguration clientConfig;
+ if (clientType == "single") {
+ clientConfig.createCertAuthClient(clientName,
+ certPath,
+ certCAPath,
+
OmapdConfig::authzOptions(defaultAuthz),
+ metadataPolicy);
+
MapSessions::getInstance()->loadClientConfiguration(&clientConfig);
+ } else if (clientType == "CA") {
+ clientConfig.createCAAuthClient(clientName,
+ certPath,
+ certCAPath,
+
OmapdConfig::authzOptions(defaultAuthz),
+ metadataPolicy);
+
MapSessions::getInstance()->loadClientConfiguration(&clientConfig);
+ } else {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Invalid
clientType for client:" << clientName;
+ }
+ }
+ } else {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Invalid
metadataPolicy for client:" << clientName;
+ }
+ }
+ } else {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Invalid
parameters to addCertClient command";
+ }
+ }
+
+ } else if (command == "removeCertClient") {
+ // Note: Clients removed through mgmt interface but still defined
in omapd.conf
+ // will reappear when omapd restarts.
+
+ /*
+ { "cmd":"removeCertClient",
+ "type":"single",
+ "certPath":"/path/to/cert",
+ "caPath":"/path/to/clientCAChain" }
+ */
+
+ if (parsedRequest.contains("type") &&
+ parsedRequest.contains("certPath") &&
+ parsedRequest.contains("caPath") &&
+ QFile::exists(parsedRequest["certPath"].toString()) &&
+ QFile::exists(parsedRequest["caPath"].toString())) {
+
+ QString clientType = parsedRequest["type"].toString();
+ QString certPath = parsedRequest["certPath"].toString();
+ QString certCAPath = parsedRequest["caPath"].toString();
+
+ ClientConfiguration clientConfig;
+ if (clientType == "single") {
+ clientConfig.createCertAuthClient("", certPath,
certCAPath, 0, "");
+
MapSessions::getInstance()->removeClientConfiguration(&clientConfig);
+ } else if (clientType == "CA") {
+ clientConfig.createCAAuthClient("", certPath, certCAPath,
0, "");
+
MapSessions::getInstance()->removeClientConfiguration(&clientConfig);
+ } else {
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Invalid
clientType for removing client";
+ }
+ }
+
+ }
+
} else {
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowManagementRequests))
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Received
unrecognized management request:"
- << requestData;
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Received
unrecognized management command:"
+ << command;
}
}
}
=======================================
--- /trunk/managementserver.h Thu Jan 3 16:45:23 2013
+++ /trunk/managementserver.h Fri Mar 1 13:17:05 2013
@@ -26,6 +26,8 @@
#include <QTcpServer>
#include "mapgraphinterface.h"
+#define MANAGEMENT_MSG_MAX_LENGTH 1024
+
class ManagementServer : public QTcpServer
{
Q_OBJECT
=======================================
--- /trunk/mapsessions.cpp Sun Feb 24 14:35:44 2013
+++ /trunk/mapsessions.cpp Fri Mar 1 13:17:05 2013
@@ -76,93 +76,165 @@
QListIterator<ClientConfiguration *> clientIt(clientConfigurations);
while (clientIt.hasNext()) {
ClientConfiguration *client = clientIt.next();
- bool clientConfigOk = false;
+ loadClientConfiguration(client);
+ }
+}
- QString authToken;
+bool MapSessions::loadClientConfiguration(ClientConfiguration *client)
+{
+ bool clientConfigOk = false;
- if (client->authType() == MapRequest::AuthBasic) {
+ QString authToken;
- // TODO: Don't use password as part of authToken
- QString up = client->username() + ":" + client->password();
- authToken = QByteArray(up.toAscii()).toBase64();
+ if (client->authType() == MapRequest::AuthBasic) {
- if (!authToken.isEmpty())
- clientConfigOk = true;
+ // TODO: Don't use password as part of authToken
+ QString up = client->username() + ":" + client->password();
+ authToken = QByteArray(up.toAscii()).toBase64();
- } else if (client->authType() == MapRequest::AuthCert ||
- client->authType() == MapRequest::AuthCACert) {
+ if (!authToken.isEmpty())
+ clientConfigOk = true;
- if (client->haveClientCert()) {
- QFile certFile(client->certFileName());
- if (!certFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Client:" <<
client->name()
- << "has no certificate file:" <<
certFile.fileName();
- } else {
- QSslCertificate clientCert;
- // Try PEM format fail over to DER; since they are the
only 2
- // supported by the QSsl Certificate classes
- clientCert = QSslCertificate(&certFile, QSsl::Pem);
- if ( clientCert.isNull() )
- clientCert = QSslCertificate(&certFile, QSsl::Der);
+ } else if (client->authType() == MapRequest::AuthCert ||
+ client->authType() == MapRequest::AuthCACert) {
- if (!clientCert.isNull()) clientConfigOk = true;
+ if (client->haveClientCert()) {
+ QFile certFile(client->certFileName());
+ if (!certFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Client:" <<
client->name()
+ << "has no certificate file:" <<
certFile.fileName();
+ } else {
+ QSslCertificate clientCert;
+ // Try PEM format fail over to DER; since they are the
only 2
+ // supported by the QSsl Certificate classes
+ clientCert = QSslCertificate(&certFile, QSsl::Pem);
+ if ( clientCert.isNull() )
+ clientCert = QSslCertificate(&certFile, QSsl::Der);
- authToken = ClientHandler::buildDN(clientCert,
ClientHandler::Subject);
- if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Loaded
cert for client named:" << client->name();
- qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:"
<< authToken;
- }
+ if (!clientCert.isNull()) clientConfigOk = true;
- if (authToken.isEmpty())
- clientConfigOk = false;
-
+ authToken = ClientHandler::buildDN(clientCert,
ClientHandler::Subject);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Loaded cert
for client named:" << client->name();
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:" <<
authToken;
}
+
+ if (authToken.isEmpty())
+ clientConfigOk = false;
+
}
+ }
- // Add CA Certs to default Configuration
- QList<QSslCertificate> caCerts =
QSslCertificate::fromPath(client->caCertFileName());
- if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
- foreach(QSslCertificate cert, caCerts) {
- QString issuerDN = ClientHandler::buildDN(cert,
ClientHandler::Subject);
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Adding CA
Cert to SSL Configuration for client:" << client->name();
- qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:" <<
issuerDN;
- }
+ // Add CA Certs to default Configuration
+ QList<QSslCertificate> caCerts =
QSslCertificate::fromPath(client->caCertFileName());
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ foreach(QSslCertificate cert, caCerts) {
+ QString issuerDN = ClientHandler::buildDN(cert,
ClientHandler::Subject);
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Adding CA Cert
to SSL Configuration for client:" << client->name();
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:" <<
issuerDN;
}
- QSslConfiguration defaultConfig =
QSslConfiguration::defaultConfiguration();
-
defaultConfig.setCaCertificates(defaultConfig.caCertificates()+caCerts);
- QSslConfiguration::setDefaultConfiguration(defaultConfig);
}
+ QSslConfiguration defaultConfig =
QSslConfiguration::defaultConfiguration();
+
defaultConfig.setCaCertificates(defaultConfig.caCertificates()+caCerts);
+ QSslConfiguration::setDefaultConfiguration(defaultConfig);
+ }
- if (clientConfigOk) {
- if (client->authType() == MapRequest::AuthCACert) {
- MapClient mapClient(authToken, client->authType(),
client->authz(), "", client->metadataPolicy());
- _mapClientCAs.insert(authToken, mapClient);
- if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Created CA
Authentication MapClient for configuration named:" << client->name()
- << "authToken:" << authToken
- << "authz:" << client->authz()
- << "metadataPolicy" <<
client->metadataPolicy();
- }
+ if (clientConfigOk) {
+ if (client->authType() == MapRequest::AuthCACert) {
+ MapClient mapClient(authToken, client->authType(),
client->authz(), "", client->metadataPolicy());
+ _mapClientCAs.insert(authToken, mapClient);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Created CA
Authentication MapClient for configuration named:" << client->name()
+ << "authToken:" << authToken
+ << "authz:" <<
OmapdConfig::authzOptionsString(client->authz())
+ << "metadataPolicy" << client->metadataPolicy();
+ }
+ } else {
+ QString pubId;
+ if (_mapClients.contains(authToken)) {
+ // Don't create new publisher-id if replacing client config
+ pubId = _mapClients.value(authToken).pubId();
} else {
// Create a new publisher-id for this client
- QString pubId;
pubId.setNum(_pubIdIndex++);
+ }
- MapClient mapClient(authToken, client->authType(),
client->authz(), pubId, client->metadataPolicy());
- _mapClients.insert(authToken, mapClient);
+ MapClient mapClient(authToken, client->authType(),
client->authz(), pubId, client->metadataPolicy());
+ _mapClients.insert(authToken, mapClient);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Created
MapClient for client configuration named:" << client->name()
+ << "with publisher-id:" << pubId
+ << "authToken:" << authToken
+ << "authz:" <<
OmapdConfig::authzOptionsString(client->authz())
+ << "metadataPolicy:" << client->metadataPolicy();
+ }
+ }
+ } else {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Error creating
MapClient for client configuration named:" << client->name();
+ }
+
+ return clientConfigOk;
+}
+
+bool MapSessions::removeClientConfiguration(ClientConfiguration *client)
+{
+ bool clientConfigOk = false;
+
+ QString authToken;
+
+ if (client->authType() == MapRequest::AuthBasic) {
+ // TODO: Don't want mgmt API to need client password
+
+ } else if (client->authType() == MapRequest::AuthCert ||
+ client->authType() == MapRequest::AuthCACert) {
+
+ if (client->haveClientCert()) {
+ QFile certFile(client->certFileName());
+ if (!certFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Client:" <<
client->name()
+ << "has no certificate file:" <<
certFile.fileName();
+ } else {
+ QSslCertificate clientCert;
+ // Try PEM format fail over to DER; since they are the
only 2
+ // supported by the QSsl Certificate classes
+ clientCert = QSslCertificate(&certFile, QSsl::Pem);
+ if ( clientCert.isNull() )
+ clientCert = QSslCertificate(&certFile, QSsl::Der);
+
+ if (!clientCert.isNull()) clientConfigOk = true;
+
+ authToken = ClientHandler::buildDN(clientCert,
ClientHandler::Subject);
if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Created
MapClient for client configuration named:" << client->name()
- << "with publisher-id:" << pubId
- << "authToken:" << authToken
- << "authz:" << client->authz()
- << "metadataPolicy:" <<
client->metadataPolicy();
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Loaded cert
for client named:" << client->name();
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "-- DN:" <<
authToken;
}
+
+ if (authToken.isEmpty())
+ clientConfigOk = false;
+
+ }
+ }
+
+ // TODO: Remove CA Certs from default Configuration only if unused
by other clients
+ }
+
+ if (clientConfigOk) {
+ if (client->authType() == MapRequest::AuthCACert) {
+ _mapClientCAs.remove(authToken);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Removed CA
Authentication MapClient with authToken" << authToken;
}
} else {
- qDebug() << __PRETTY_FUNCTION__ << ":" << "Error creating
MapClient for client configuration named:" << client->name();
+ _mapClients.remove(authToken);
+ if
(_omapdConfig->valueFor("debug_level").value<OmapdConfig::IfmapDebugOptions>().testFlag(OmapdConfig::ShowClientOps))
{
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Removed
MapClient with authToken" << authToken;
+ }
}
+ } else {
+ qDebug() << __PRETTY_FUNCTION__ << ":" << "Error removing
MapClient";
}
+ return clientConfigOk;
}
QString MapSessions::generateSessionId()
=======================================
--- /trunk/mapsessions.h Sun Feb 24 14:35:44 2013
+++ /trunk/mapsessions.h Fri Mar 1 13:17:05 2013
@@ -76,6 +76,9 @@
QString generateSessionId();
+ bool loadClientConfiguration(ClientConfiguration *client);
+ bool removeClientConfiguration(ClientConfiguration *client);
+
private:
MapSessions(QObject *parent = 0);
~MapSessions();
=======================================
--- /trunk/omapd.conf Sun Feb 24 14:35:44 2013
+++ /trunk/omapd.conf Fri Mar 1 13:17:05 2013
@@ -48,11 +48,32 @@
<!-- Management Interface Documentation -->
<!-- For now, output is sent to the configured log location(s). -->
+ <!-- Management requests are JSON formatted. -->
<!-- Supported commands
- mapdump : dump contents of map graph database
+ * Dump contents of map graph database
+ { "cmd":"mapdump" }
+ * Add a certificate-based client. A missing authorization value
will apply
+ default authorization, as defined in the client_configuration
section.
+ A missing metadataPolicy value will not apply a metadata policy.
+ { "cmd":"addCertClient",
+ "type":"clientType", clientType:= {single, CA}
+ "name":"clientName",
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert",
+ "authorization":"authzValue", (optional)
+ "metadataPolicy":"policyName" (optional)
+ }
+ * Remove a certificate-based client.
+ { "cmd":"removeCertClient",
+ "type":"clientType", clientType:= {single, CA}
+ "certPath":"/path/to/clientCert",
+ "caPath":"/path/to/clientCACert"
+ }
-->
- <!-- Example usage:
- echo "mapdump" | nc localhost 8097
+ <!-- Example usages:
+ echo '{"cmd":"mapdump"}' | nc localhost 8097
+
echo '{"cmd":"addCertClient","type":"single","name":"clientName","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain","authorization":"0x1E","metadataPolicy":"policyName"}'
| nc localhost 8097
+
echo '{"cmd":"removeCertClient","type":"single","certPath":"/path/to/clientCert","caPath":"/path/to/clientCAChain"}'
| nc localhost 8097
-->
</management_configuration>
=======================================
--- /trunk/
omapd.pro Thu Jan 3 16:44:35 2013
+++ /trunk/
omapd.pro Fri Mar 1 13:17:05 2013
@@ -19,7 +19,8 @@
clientparser.cpp \
mapclient.cpp \
clientconfiguration.cpp \
- managementserver.cpp
+ managementserver.cpp \
+ json.cpp
HEADERS += server.h \
identifier.h \
metadata.h \
@@ -34,5 +35,6 @@
clientparser.h \
mapclient.h \
clientconfiguration.h \
- managementserver.h
+ managementserver.h \
+ json.h
INCLUDEPATH += $$[QT_INSTALL_PREFIX]/src/3rdparty/zlib