Prepare client binary
This commit is contained in:
parent
089c4ff743
commit
935f6d1fa4
17
client/client.pro
Normal file
17
client/client.pro
Normal file
@ -0,0 +1,17 @@
|
||||
include(../nymea-remoteproxy.pri)
|
||||
|
||||
TARGET = nymea-remoteproxy-client
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += ../libnymea-remoteproxy
|
||||
|
||||
LIBS += -L$$top_builddir/libnymea-remoteproxyclient/ -lnymea-remoteproxyclient
|
||||
|
||||
SOURCES += main.cpp \
|
||||
proxyclient.cpp
|
||||
|
||||
target.path = /usr/bin
|
||||
INSTALLS += target
|
||||
|
||||
HEADERS += \
|
||||
proxyclient.h
|
||||
47
client/main.cpp
Normal file
47
client/main.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include <QDir>
|
||||
#include <QUrl>
|
||||
#include <QtDebug>
|
||||
#include <QSslKey>
|
||||
#include <QDateTime>
|
||||
#include <QFileInfo>
|
||||
#include <QTextStream>
|
||||
#include <QMessageLogger>
|
||||
#include <QSslCertificate>
|
||||
#include <QCoreApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QLoggingCategory>
|
||||
#include <QSslConfiguration>
|
||||
#include <QCommandLineParser>
|
||||
#include <QCommandLineOption>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
QCoreApplication application(argc, argv);
|
||||
application.setApplicationName(SERVER_NAME_STRING);
|
||||
application.setOrganizationName("guh");
|
||||
application.setApplicationVersion(SERVER_VERSION_STRING);
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.setApplicationDescription(QString("\nThe nymea remote proxy server. This server allowes nymea-cloud users and "
|
||||
"registered nymea deamons to establish a tunnel connection.\n\n"
|
||||
"Server version: %1\n"
|
||||
"API version: %2\n\n"
|
||||
"Copyright %3 2018 Simon Stürz <simon.stuerz@guh.io>\n")
|
||||
.arg(SERVER_VERSION_STRING)
|
||||
.arg(API_VERSION_STRING)
|
||||
.arg(QChar(0xA9)));
|
||||
|
||||
|
||||
QCommandLineOption tokenOption(QStringList() << "t" << "token", "The AWS token for authentication.", "token");
|
||||
parser.addOption(tokenOption);
|
||||
|
||||
|
||||
parser.process(application);
|
||||
|
||||
|
||||
|
||||
return application.exec();
|
||||
}
|
||||
6
client/proxyclient.cpp
Normal file
6
client/proxyclient.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "proxyclient.h"
|
||||
|
||||
ProxyClient::ProxyClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
18
client/proxyclient.h
Normal file
18
client/proxyclient.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef PROXYCLIENT_H
|
||||
#define PROXYCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
class ProxyClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ProxyClient(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // PROXYCLIENT_H
|
||||
118
libnymea-remoteproxy/authentication/authenticationprocess.cpp
Normal file
118
libnymea-remoteproxy/authentication/authenticationprocess.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include "authenticationprocess.h"
|
||||
#include "loggingcategories.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QNetworkReply>
|
||||
#include <QJsonDocument>
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
AuthenticationProcess::AuthenticationProcess(QNetworkAccessManager *manager, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_manager(manager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AuthenticationProcess::useDynamicCredentials(bool dynamicCredentials)
|
||||
{
|
||||
m_dynamicCredentials = dynamicCredentials;
|
||||
}
|
||||
|
||||
void AuthenticationProcess::requestDynamicCredentials()
|
||||
{
|
||||
QNetworkReply *reply = m_manager->get(QNetworkRequest(QUrl("http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2-Remote-Connection-Proxy-Role")));
|
||||
connect(reply, &QNetworkReply::finished, this, &AuthenticationProcess::onDynamicCredentialsReady);
|
||||
}
|
||||
|
||||
void AuthenticationProcess::startVerificationProcess()
|
||||
{
|
||||
if (m_process->state() != QProcess::NotRunning) {
|
||||
qCWarning(dcAuthenticator()) << "Authentication process already running. Killing the running process and restart.";
|
||||
m_process->kill();
|
||||
m_process->deleteLater();
|
||||
m_process = nullptr;
|
||||
}
|
||||
|
||||
m_process = new QProcess(this);
|
||||
connect(m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &AuthenticationProcess::onProcessFinished);
|
||||
|
||||
// Create request map
|
||||
QVariantMap request;
|
||||
request.insert("token", m_token);
|
||||
|
||||
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert("AWS_DEFAULT_REGION", "eu-west-1");
|
||||
|
||||
if (m_dynamicCredentials) {
|
||||
env.insert("AWS_ACCESS_KEY_ID", m_awsAccessKeyId);
|
||||
env.insert("AWS_SECRET_ACCESS_KEY", m_awsSecretAccessKey);
|
||||
env.insert("AWS_SESSION_TOKEN", m_awsSessionToken);
|
||||
}
|
||||
|
||||
// Output file name
|
||||
m_resultFileName = "/tmp/" + QUuid::createUuid().toString().remove("{").remove("}").remove("-") + ".json";
|
||||
|
||||
qCDebug(dcAuthenticator()) << "Start authenticator process and store result in" << m_resultFileName;
|
||||
|
||||
m_process->start("aws", { "lambda", "invoke",
|
||||
"--function-name", "system-services-authorizer-dev-checkToken",
|
||||
"--invocation-type", "RequestResponse",
|
||||
"--payload", QString("'%1'").arg(QString::fromUtf8(QJsonDocument::fromVariant(request).toJson())),
|
||||
m_resultFileName });
|
||||
|
||||
}
|
||||
|
||||
void AuthenticationProcess::onDynamicCredentialsReady()
|
||||
{
|
||||
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
|
||||
reply->deleteLater();
|
||||
|
||||
if (reply->error()) {
|
||||
qCWarning(dcAuthenticator()) << "Dynamic credentials reply error: " << reply->errorString();
|
||||
emit authenticationFinished(Authenticator::AuthenticationErrorProxyError);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
|
||||
QJsonParseError error;
|
||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
|
||||
|
||||
if(error.error != QJsonParseError::NoError) {
|
||||
qCWarning(dcAuthenticator()) << "Failed to parse dynamic credentials reply data" << data << ":" << error.errorString();
|
||||
emit authenticationFinished(Authenticator::AuthenticationErrorProxyError);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QVariantMap response = jsonDoc.toVariant().toMap();
|
||||
qCDebug(dcAuthenticator()) << "-->" << response;
|
||||
|
||||
m_awsAccessKeyId = response.value("AccessKeyId").toString();
|
||||
m_awsSecretAccessKey = response.value("SecretAccessKey").toString();
|
||||
m_awsSessionToken = response.value("Token").toString();
|
||||
|
||||
startVerificationProcess();
|
||||
}
|
||||
|
||||
void AuthenticationProcess::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
qCDebug(dcAuthenticator()) << "Authentication process finished" << exitCode << exitStatus;
|
||||
}
|
||||
|
||||
void AuthenticationProcess::authenticate(const QString &token)
|
||||
{
|
||||
qCDebug(dcAuthenticator()) << "Start authentication process for token";
|
||||
m_token = token;
|
||||
|
||||
if (m_dynamicCredentials) {
|
||||
// Request the access information
|
||||
requestDynamicCredentials();
|
||||
} else {
|
||||
startVerificationProcess();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
49
libnymea-remoteproxy/authentication/authenticationprocess.h
Normal file
49
libnymea-remoteproxy/authentication/authenticationprocess.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef AUTHENTICATIONPROCESS_H
|
||||
#define AUTHENTICATIONPROCESS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "authenticator.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
class AuthenticationProcess : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AuthenticationProcess(QNetworkAccessManager *manager, QObject *parent = nullptr);
|
||||
|
||||
void useDynamicCredentials(bool dynamicCredentials);
|
||||
|
||||
private:
|
||||
QString m_token;
|
||||
QString m_resultFileName;
|
||||
|
||||
bool m_dynamicCredentials = true;
|
||||
QString m_awsAccessKeyId;
|
||||
QString m_awsSecretAccessKey;
|
||||
QString m_awsSessionToken;
|
||||
|
||||
QNetworkAccessManager *m_manager = nullptr;
|
||||
QProcess *m_process = nullptr;
|
||||
|
||||
void requestDynamicCredentials();
|
||||
void startVerificationProcess();
|
||||
|
||||
signals:
|
||||
void authenticationFinished(Authenticator::AuthenticationError error);
|
||||
|
||||
private slots:
|
||||
void onDynamicCredentialsReady();
|
||||
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
public slots:
|
||||
void authenticate(const QString &token);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // AUTHENTICATIONPROCESS_H
|
||||
@ -7,7 +7,11 @@ AuthenticationReply::AuthenticationReply(ProxyClient *proxyClient, QObject *pare
|
||||
QObject(parent),
|
||||
m_proxyClient(proxyClient)
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
m_timer->setInterval(10000);
|
||||
m_timer->setSingleShot(true);
|
||||
|
||||
m_process = new QProcess(this);
|
||||
}
|
||||
|
||||
ProxyClient *AuthenticationReply::proxyClient() const
|
||||
@ -37,6 +41,7 @@ void AuthenticationReply::setError(Authenticator::AuthenticationError error)
|
||||
|
||||
void AuthenticationReply::setFinished()
|
||||
{
|
||||
m_timer->stop();
|
||||
emit finished();
|
||||
}
|
||||
|
||||
@ -44,12 +49,16 @@ void AuthenticationReply::onTimeout()
|
||||
{
|
||||
m_timedOut = true;
|
||||
m_error = Authenticator::AuthenticationErrorTimeout;
|
||||
m_timer->stop();
|
||||
m_process->kill();
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void AuthenticationReply::abort()
|
||||
{
|
||||
m_error = Authenticator::AuthenticationErrorAborted;
|
||||
m_timer->stop();
|
||||
m_process->kill();
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#include <QUuid>
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include "authenticator.h"
|
||||
@ -25,9 +26,9 @@ public:
|
||||
|
||||
private:
|
||||
explicit AuthenticationReply(ProxyClient *proxyClient, QObject *parent = nullptr);
|
||||
|
||||
ProxyClient *m_proxyClient = nullptr;
|
||||
QTimer m_timer;
|
||||
QTimer *m_timer = nullptr;
|
||||
QProcess *m_process = nullptr;
|
||||
|
||||
bool m_timedOut = false;
|
||||
bool m_finished = false;
|
||||
|
||||
@ -19,7 +19,7 @@ public:
|
||||
AuthenticationErrorTimeout,
|
||||
AuthenticationErrorAborted,
|
||||
AuthenticationErrorAuthenticationFailed,
|
||||
AuthenticationErrorAuthenticationServerNotResponding
|
||||
AuthenticationErrorProxyError
|
||||
};
|
||||
Q_ENUM(AuthenticationError)
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#include "engine.h"
|
||||
#include "proxyclient.h"
|
||||
#include "awsauthenticator.h"
|
||||
#include "loggingcategories.h"
|
||||
@ -5,7 +6,8 @@
|
||||
namespace remoteproxy {
|
||||
|
||||
AwsAuthenticator::AwsAuthenticator(QObject *parent) :
|
||||
Authenticator(parent)
|
||||
Authenticator(parent),
|
||||
m_manager(new QNetworkAccessManager(this))
|
||||
{
|
||||
|
||||
}
|
||||
@ -20,13 +22,31 @@ QString AwsAuthenticator::name() const
|
||||
return "AWS authenticator";
|
||||
}
|
||||
|
||||
void AwsAuthenticator::onAuthenticationProcessFinished(Authenticator::AuthenticationError error)
|
||||
{
|
||||
AuthenticationProcess *process = static_cast<AuthenticationProcess *>(sender());
|
||||
AuthenticationReply *reply = m_runningProcesses.take(process);
|
||||
|
||||
setReplyError(reply, error);
|
||||
setReplyFinished(reply);
|
||||
|
||||
qCDebug(dcAuthenticator()) << "" << error;
|
||||
}
|
||||
|
||||
AuthenticationReply *AwsAuthenticator::authenticate(ProxyClient *proxyClient)
|
||||
{
|
||||
qCDebug(dcAuthenticator()) << name() << "Start authenticating" << proxyClient << "using token" << proxyClient->token();
|
||||
AuthenticationReply *reply = createAuthenticationReply(proxyClient, this);
|
||||
|
||||
// TODO: start authentication request
|
||||
AuthenticationProcess *process = new AuthenticationProcess(m_manager, this);
|
||||
process->useDynamicCredentials(!Engine::instance()->developerMode());
|
||||
connect(process, &AuthenticationProcess::authenticationFinished, this, &AwsAuthenticator::onAuthenticationProcessFinished);
|
||||
|
||||
// Configure process
|
||||
m_runningProcesses.insert(process, reply);
|
||||
|
||||
// Start authentication process
|
||||
process->authenticate(proxyClient->token());
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
@ -2,9 +2,11 @@
|
||||
#define AWSAUTHENTICATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "authenticator.h"
|
||||
#include "authenticationreply.h"
|
||||
#include "authenticationprocess.h"
|
||||
|
||||
namespace remoteproxy {
|
||||
|
||||
@ -18,7 +20,11 @@ public:
|
||||
QString name() const override;
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *m_manager = nullptr;
|
||||
QHash<AuthenticationProcess *, AuthenticationReply *> m_runningProcesses;
|
||||
|
||||
private slots:
|
||||
void onAuthenticationProcessFinished(Authenticator::AuthenticationError error);
|
||||
|
||||
public slots:
|
||||
AuthenticationReply *authenticate(ProxyClient *proxyClient) override;
|
||||
|
||||
@ -1,123 +0,0 @@
|
||||
#include "sigv4utils.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QCryptographicHash>
|
||||
#include <QMessageAuthenticationCode>
|
||||
#include <QtDebug>
|
||||
#include <QUrlQuery>
|
||||
#include <QList>
|
||||
|
||||
SigV4Utils::SigV4Utils()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCurrentDateTime()
|
||||
{
|
||||
return QDateTime::currentDateTime().toUTC().toString("yyyyMMddThhmmssZ").toUtf8();
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCanonicalQueryString(const QNetworkRequest &request, const QByteArray &accessKeyId, const QByteArray &secretAccessKey, const QByteArray &sessionToken, const QByteArray ®ion, const QByteArray &service, const QByteArray &payload)
|
||||
{
|
||||
QByteArray algorithm = "AWS4-HMAC-SHA256";
|
||||
QByteArray dateTime = getCurrentDateTime();
|
||||
QByteArray credentialScope = getCredentialScope(algorithm, dateTime, region, service);
|
||||
|
||||
QByteArray canonicalQueryString;
|
||||
canonicalQueryString += "X-Amz-Algorithm=AWS4-HMAC-SHA256";
|
||||
canonicalQueryString += "&X-Amz-Credential=" + QByteArray(accessKeyId + '/' + credentialScope).toPercentEncoding();
|
||||
canonicalQueryString += "&X-Amz-Date=" + dateTime;
|
||||
if (request.rawHeaderList().count() > 0){
|
||||
canonicalQueryString += "&X-Amz-SignedHeaders=" + request.rawHeaderList().join(';').toLower();
|
||||
}
|
||||
|
||||
QByteArray canonicalRequest = getCanonicalRequest(QNetworkAccessManager::GetOperation, request, payload);
|
||||
|
||||
QByteArray stringToSign = getStringToSign(canonicalRequest, dateTime, region, service);
|
||||
QByteArray signature = getSignature(stringToSign, secretAccessKey, dateTime, region, service);
|
||||
|
||||
canonicalQueryString += "&X-Amz-Signature=" + signature;
|
||||
|
||||
if (!sessionToken.isEmpty()) {
|
||||
canonicalQueryString += "&X-Amz-Security-Token=" + sessionToken.toPercentEncoding();
|
||||
}
|
||||
|
||||
return canonicalQueryString;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getSignatureKey(const QByteArray &key, const QByteArray &date, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Sha256;
|
||||
return QMessageAuthenticationCode::hash("aws4_request",
|
||||
QMessageAuthenticationCode::hash(service,
|
||||
QMessageAuthenticationCode::hash(region,
|
||||
QMessageAuthenticationCode::hash(date, "AWS4"+key,
|
||||
hashAlgorithm), hashAlgorithm), hashAlgorithm), hashAlgorithm);
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCanonicalRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload)
|
||||
{
|
||||
QByteArray canonicalRequest;
|
||||
|
||||
QByteArray method;
|
||||
switch (operation) {
|
||||
case QNetworkAccessManager::GetOperation:
|
||||
method = "GET";
|
||||
break;
|
||||
case QNetworkAccessManager::PostOperation:
|
||||
method = "POST";
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT_X(false, "Network operation not implemented", "SigV4Utils");
|
||||
}
|
||||
QByteArray uri = request.url().path().toUtf8();
|
||||
QUrlQuery query(request.url());
|
||||
QList<QPair<QString, QString> > queryItems = query.queryItems();
|
||||
QStringList queryItemStrings;
|
||||
for (int i = 0; i < queryItems.count(); i++) {
|
||||
QPair<QString, QString> queryItem = queryItems.at(i);
|
||||
queryItemStrings.append(queryItem.first + '=' + queryItem.second);
|
||||
}
|
||||
queryItemStrings.sort(Qt::CaseInsensitive);
|
||||
|
||||
QByteArray canonicalQueryString = queryItemStrings.join('&').toUtf8();
|
||||
|
||||
QByteArray canonicalHeaders;
|
||||
foreach(const QByteArray &headerName, request.rawHeaderList()) {
|
||||
canonicalHeaders += headerName.toLower() + ':' + request.rawHeader(headerName) + '\n';
|
||||
}
|
||||
|
||||
QByteArray payloadHash = QCryptographicHash::hash(payload, QCryptographicHash::Sha256).toHex();
|
||||
|
||||
canonicalRequest = method + '\n' + uri + '\n' + canonicalQueryString + '\n' + canonicalHeaders + '\n' + request.rawHeaderList().join(';').toLower() + '\n' + payloadHash;
|
||||
return canonicalRequest;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getCredentialScope(const QByteArray &algorithm, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
Q_UNUSED(algorithm)
|
||||
QByteArray credentialScope = dateTime.left(8) + '/' + region + '/' + service + "/aws4_request";
|
||||
return credentialScope;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getStringToSign(const QByteArray &canonicalRequest, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service)
|
||||
{
|
||||
QByteArray algorithm = "AWS4-HMAC-SHA256";
|
||||
QByteArray credentialScope = getCredentialScope(algorithm, dateTime, region, service);
|
||||
|
||||
QByteArray stringToSign = algorithm + '\n' + dateTime + '\n' + credentialScope + '\n' + QCryptographicHash::hash(canonicalRequest, QCryptographicHash::Sha256).toHex();
|
||||
return stringToSign;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getSignature(const QByteArray &stringToSign, const QByteArray &secretAccessKey, const QByteArray &dateTime, const QString ®ion, const QString &service)
|
||||
{
|
||||
QByteArray signingKey = getSignatureKey(secretAccessKey, dateTime.left(8), region.toUtf8(), service.toUtf8());
|
||||
QByteArray signature = QMessageAuthenticationCode::hash(stringToSign, signingKey, QCryptographicHash::Sha256).toHex();
|
||||
return signature;
|
||||
}
|
||||
|
||||
QByteArray SigV4Utils::getAuthorizationHeader(const QByteArray &accessKeyId, const QByteArray &dateTime, const QString ®ion, const QString &service, const QNetworkRequest &request, const QByteArray &signature)
|
||||
{
|
||||
QByteArray authHeader = "AWS4-HMAC-SHA256 Credential=" + accessKeyId + '/' + dateTime.left(8) + '/' + region.toUtf8() + '/' + service.toUtf8() + '/' + "aws4_request, SignedHeaders=" + request.rawHeaderList().join(';').toLower() + ", Signature=" + signature;
|
||||
return authHeader;
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
#ifndef SIGV4UTILS_H
|
||||
#define SIGV4UTILS_H
|
||||
|
||||
#include <QString>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
class SigV4Utils
|
||||
{
|
||||
public:
|
||||
SigV4Utils();
|
||||
|
||||
static QByteArray getCurrentDateTime();
|
||||
|
||||
|
||||
static QByteArray getCanonicalQueryString(const QNetworkRequest &request, const QByteArray &accessKeyId, const QByteArray &secretAccessKey, const QByteArray &sessionToken, const QByteArray ®ion, const QByteArray &service, const QByteArray &payload);
|
||||
static QByteArray getCanonicalRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, const QByteArray &payload);
|
||||
static QByteArray getCanonicalHeaders(const QNetworkRequest &request);
|
||||
static QByteArray getCredentialScope(const QByteArray &algorithm, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getStringToSign(const QByteArray &canonicalRequest, const QByteArray &dateTime, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getSignatureKey(const QByteArray &key, const QByteArray &date, const QByteArray ®ion, const QByteArray &service);
|
||||
static QByteArray getSignature(const QByteArray &stringToSign, const QByteArray &secretAccessKey, const QByteArray &dateTime, const QString ®ion, const QString &service);
|
||||
static QByteArray getAuthorizationHeader(const QByteArray &accessKeyId, const QByteArray &dateTime, const QString ®ion, const QString &service, const QNetworkRequest &request, const QByteArray &signature);
|
||||
|
||||
};
|
||||
|
||||
#endif // SIGV4UTILS_H
|
||||
@ -32,6 +32,10 @@ bool Engine::exists()
|
||||
|
||||
void Engine::start()
|
||||
{
|
||||
// Make sure an authenticator was registered
|
||||
Q_ASSERT_X(m_authenticator != nullptr, "Engine", "There is no authenticator registerd.");
|
||||
Q_ASSERT_X(m_configuration != nullptr, "Engine", "There is no configuration set.");
|
||||
|
||||
if (!m_running)
|
||||
qCDebug(dcEngine()) << "Start server engine";
|
||||
|
||||
@ -44,15 +48,12 @@ void Engine::start()
|
||||
|
||||
QUrl websocketServerUrl;
|
||||
websocketServerUrl.setScheme("wss");
|
||||
websocketServerUrl.setHost(m_webSocketServerHostAddress.toString());
|
||||
websocketServerUrl.setPort(m_webSocketServerPort);
|
||||
websocketServerUrl.setHost(m_configuration->webSocketServerHost().toString());
|
||||
websocketServerUrl.setPort(m_configuration->webSocketServerPort());
|
||||
m_webSocketServer->setServerUrl(websocketServerUrl);
|
||||
|
||||
m_proxyServer->registerTransportInterface(m_webSocketServer);
|
||||
|
||||
// Make sure an authenticator was registered
|
||||
Q_ASSERT_X(m_authenticator != nullptr, "Engine", "There is no authenticator registerd.");
|
||||
|
||||
qCDebug(dcEngine()) << "Starting proxy server";
|
||||
m_proxyServer->startServer();
|
||||
|
||||
@ -74,6 +75,11 @@ bool Engine::running() const
|
||||
return m_running;
|
||||
}
|
||||
|
||||
bool Engine::developerMode() const
|
||||
{
|
||||
return m_developerMode;
|
||||
}
|
||||
|
||||
QString Engine::serverName() const
|
||||
{
|
||||
return m_serverName;
|
||||
@ -84,36 +90,24 @@ void Engine::setServerName(const QString &serverName)
|
||||
m_serverName = serverName;
|
||||
}
|
||||
|
||||
void Engine::setWebSocketServerHostAddress(const QHostAddress &hostAddress)
|
||||
void Engine::setConfiguration(ProxyConfiguration *configuration)
|
||||
{
|
||||
qCDebug(dcEngine()) << "Websocket server host address:" << hostAddress;
|
||||
m_webSocketServerHostAddress = hostAddress;
|
||||
}
|
||||
|
||||
void Engine::setWebSocketServerPort(const quint16 &port)
|
||||
{
|
||||
qCDebug(dcEngine()) << "Websocket server port:" << port;
|
||||
m_webSocketServerPort = port;
|
||||
m_configuration = configuration;
|
||||
qCDebug(dcApplication()) << "Set configuration" << m_configuration;
|
||||
}
|
||||
|
||||
void Engine::setSslConfiguration(const QSslConfiguration &configuration)
|
||||
{
|
||||
qCDebug(dcEngine()) << "SSL certificate information:";
|
||||
qCDebug(dcEngine()) << " Common name:" << configuration.localCertificate().issuerInfo(QSslCertificate::CommonName);
|
||||
qCDebug(dcEngine()) << " Organisation:" << configuration.localCertificate().issuerInfo(QSslCertificate::Organization);
|
||||
qCDebug(dcEngine()) << " Organisation unit name:" << configuration.localCertificate().issuerInfo(QSslCertificate::OrganizationalUnitName);
|
||||
qCDebug(dcEngine()) << " Country name:" << configuration.localCertificate().issuerInfo(QSslCertificate::CountryName);
|
||||
qCDebug(dcEngine()) << " Locality name:" << configuration.localCertificate().issuerInfo(QSslCertificate::LocalityName);
|
||||
qCDebug(dcEngine()) << " State/Province:" << configuration.localCertificate().issuerInfo(QSslCertificate::StateOrProvinceName);
|
||||
qCDebug(dcEngine()) << " Email address:" << configuration.localCertificate().issuerInfo(QSslCertificate::EmailAddress);
|
||||
|
||||
m_sslConfiguration = configuration;
|
||||
}
|
||||
|
||||
void Engine::setAuthenticationServerUrl(const QUrl &url)
|
||||
{
|
||||
qCDebug(dcEngine()) << "Authentication server URL" << url.toString();
|
||||
m_authenticationServerUrl = url;
|
||||
qCDebug(dcEngine()) << "SSL certificate information:";
|
||||
qCDebug(dcEngine()) << " Common name:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::CommonName);
|
||||
qCDebug(dcEngine()) << " Organisation:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::Organization);
|
||||
qCDebug(dcEngine()) << " Organisation unit name:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::OrganizationalUnitName);
|
||||
qCDebug(dcEngine()) << " Country name:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::CountryName);
|
||||
qCDebug(dcEngine()) << " Locality name:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::LocalityName);
|
||||
qCDebug(dcEngine()) << " State/Province:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::StateOrProvinceName);
|
||||
qCDebug(dcEngine()) << " Email address:" << m_sslConfiguration.localCertificate().issuerInfo(QSslCertificate::EmailAddress);
|
||||
}
|
||||
|
||||
void Engine::setAuthenticator(Authenticator *authenticator)
|
||||
@ -132,6 +126,11 @@ void Engine::setAuthenticator(Authenticator *authenticator)
|
||||
// FIXME: connect
|
||||
}
|
||||
|
||||
void Engine::setDeveloperModeEnabled(bool enabled)
|
||||
{
|
||||
m_developerMode = enabled;
|
||||
}
|
||||
|
||||
Authenticator *Engine::authenticator() const
|
||||
{
|
||||
return m_authenticator;
|
||||
@ -172,7 +171,6 @@ void Engine::clean()
|
||||
}
|
||||
|
||||
if (m_configuration) {
|
||||
delete m_configuration;
|
||||
m_configuration = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,17 +26,17 @@ public:
|
||||
void stop();
|
||||
|
||||
bool running() const;
|
||||
bool developerMode() const;
|
||||
|
||||
QString serverName() const;
|
||||
void setServerName(const QString &serverName);
|
||||
|
||||
void setWebSocketServerHostAddress(const QHostAddress &hostAddress);
|
||||
void setWebSocketServerPort(const quint16 &port);
|
||||
void setConfiguration(ProxyConfiguration *configuration);
|
||||
void setSslConfiguration(const QSslConfiguration &configuration);
|
||||
void setAuthenticationServerUrl(const QUrl &url);
|
||||
|
||||
void setAuthenticator(Authenticator *authenticator);
|
||||
|
||||
void setDeveloperModeEnabled(bool enabled);
|
||||
|
||||
Authenticator *authenticator() const;
|
||||
ProxyServer *proxyServer() const;
|
||||
WebSocketServer *webSocketServer() const;
|
||||
@ -47,13 +47,10 @@ private:
|
||||
static Engine *s_instance;
|
||||
|
||||
bool m_running = false;
|
||||
bool m_developerMode = false;
|
||||
QString m_serverName;
|
||||
|
||||
quint16 m_webSocketServerPort = 1212;
|
||||
QHostAddress m_webSocketServerHostAddress = QHostAddress::LocalHost;
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
QUrl m_authenticationServerUrl;
|
||||
|
||||
ProxyConfiguration *m_configuration = nullptr;
|
||||
Authenticator *m_authenticator = nullptr;
|
||||
ProxyServer *m_proxyServer = nullptr;
|
||||
|
||||
@ -26,7 +26,7 @@ HEADERS += \
|
||||
authentication/authenticationreply.h \
|
||||
proxyconfiguration.h \
|
||||
tunnelconnection.h \
|
||||
authentication/sigv4utils.h
|
||||
authentication/authenticationprocess.h
|
||||
|
||||
SOURCES += \
|
||||
engine.cpp \
|
||||
@ -45,7 +45,7 @@ SOURCES += \
|
||||
authentication/authenticationreply.cpp \
|
||||
proxyconfiguration.cpp \
|
||||
tunnelconnection.cpp \
|
||||
authentication/sigv4utils.cpp
|
||||
authentication/authenticationprocess.cpp
|
||||
|
||||
|
||||
# install header file with relative subdirectory
|
||||
|
||||
@ -14,18 +14,18 @@ ProxyConfiguration::ProxyConfiguration(QObject *parent) :
|
||||
bool ProxyConfiguration::loadConfiguration(const QString &fileName)
|
||||
{
|
||||
QFileInfo fileInfo(fileName);
|
||||
|
||||
if (!fileInfo.exists()) {
|
||||
qCWarning(dcApplication()) << "Could not find configuration file" << fileName;
|
||||
qCWarning(dcApplication()) << "Configuration: Could not find configuration file" << fileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fileInfo.isReadable()) {
|
||||
qCWarning(dcApplication()) << "Cannot read configuration file" << fileName;
|
||||
qCWarning(dcApplication()) << "Configuration: Cannot read configuration file" << fileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
QSettings settings(fileName, QSettings::IniFormat);
|
||||
qCDebug(dcApplication()) << settings.childGroups();
|
||||
|
||||
settings.beginGroup("General");
|
||||
setWriteLogFile(settings.value("writeLogs", false).toBool());
|
||||
@ -127,6 +127,25 @@ void ProxyConfiguration::setTcpServerPort(quint16 port)
|
||||
m_tcpServerPort = port;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, ProxyConfiguration *configuration)
|
||||
{
|
||||
debug.nospace() << endl << "========== ProxyConfiguration ==========" << endl;
|
||||
debug.nospace() << "General" << endl;
|
||||
debug.nospace() << " - write logfile:" << configuration->writeLogFile() << endl;
|
||||
debug.nospace() << " - logfile:" << configuration->logFileName() << endl;
|
||||
debug.nospace() << " - certificate:" << configuration->sslCertificateFileName() << endl;
|
||||
debug.nospace() << " - certificate key:" << configuration->sslCertificateKeyFileName() << endl;
|
||||
debug.nospace() << "WebSocketServer" << endl;
|
||||
debug.nospace() << " - host:" << configuration->webSocketServerHost().toString() << endl;
|
||||
debug.nospace() << " - port:" << configuration->webSocketServerPort() << endl;
|
||||
debug.nospace() << "TcpServer" << endl;
|
||||
debug.nospace() << " - host:" << configuration->tcpServerHost().toString() << endl;
|
||||
debug.nospace() << " - port:" << configuration->tcpServerPort() << endl;
|
||||
debug.nospace() << "========== ProxyConfiguration ==========" << endl;
|
||||
|
||||
return debug; return debug;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -59,6 +59,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
QDebug operator<< (QDebug debug, ProxyConfiguration *configuration);
|
||||
|
||||
}
|
||||
|
||||
#endif // PROXYCONFIGURATION_H
|
||||
|
||||
13
nymea-remoteproxy.conf
Normal file
13
nymea-remoteproxy.conf
Normal file
@ -0,0 +1,13 @@
|
||||
[General]
|
||||
writeLogs=false
|
||||
logFile=/var/log/nymea-remoteproxy.log
|
||||
certificate=/etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
certificateKey=/etc/ssl/private/ssl-cert-snakeoil.key
|
||||
|
||||
[WebSocketServer]
|
||||
host=0.0.0.0
|
||||
port=443
|
||||
|
||||
[TcpServer]
|
||||
host=0.0.0.0
|
||||
port=80
|
||||
@ -1,11 +1,11 @@
|
||||
include(nymea-remoteproxy.pri)
|
||||
|
||||
TEMPLATE=subdirs
|
||||
SUBDIRS += server libnymea-remoteproxy libnymea-remoteproxyclient tests
|
||||
SUBDIRS += server client libnymea-remoteproxy libnymea-remoteproxyclient tests
|
||||
|
||||
server.depends = libnymea-remoteproxy
|
||||
tests.depends = libnymea-remoteproxy libnymea-remoteproxyclient
|
||||
|
||||
client.depends = libnymea-remoteproxyclient
|
||||
|
||||
message("----------------------------------------------------------")
|
||||
message("Building nymea-remoteproxy $${SERVER_VERSION}")
|
||||
|
||||
136
server/main.cpp
136
server/main.cpp
@ -19,6 +19,7 @@
|
||||
|
||||
#include "engine.h"
|
||||
#include "loggingcategories.h"
|
||||
#include "proxyconfiguration.h"
|
||||
#include "authentication/awsauthenticator.h"
|
||||
|
||||
using namespace remoteproxy;
|
||||
@ -115,28 +116,30 @@ int main(int argc, char *argv[])
|
||||
"logfile", "/var/log/nymea-remoteproxy.log");
|
||||
parser.addOption(logfileOption);
|
||||
|
||||
QCommandLineOption serverOption(QStringList() << "s" << "server", "The server address this proxy will listen on. "
|
||||
"Default is 127.0.0.1", "hostaddress", "127.0.0.1");
|
||||
parser.addOption(serverOption);
|
||||
QCommandLineOption developmentOption(QStringList() << "d" << "development", "Enable the development mode. This enabled the server "
|
||||
"assumes there are static AWS credentials provided to aws-cli.");
|
||||
parser.addOption(developmentOption);
|
||||
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", "The proxy server port. Default is 1212", "port", "1212");
|
||||
parser.addOption(portOption);
|
||||
|
||||
QCommandLineOption certOption(QStringList() << "c" <<"certificate", "The path to the SSL certificate used for "
|
||||
"this proxy server.", "certificate");
|
||||
certOption.setDefaultValue("/etc/ssl/certs/ssl-cert-snakeoil.pem");
|
||||
parser.addOption(certOption);
|
||||
|
||||
QCommandLineOption certKeyOption(QStringList() << "k" << "certificate-key", "The path to the SSL certificate key "
|
||||
"used for this proxy server.", "certificate-key");
|
||||
certKeyOption.setDefaultValue("/etc/ssl/private/ssl-cert-snakeoil.key");
|
||||
parser.addOption(certKeyOption);
|
||||
QCommandLineOption configOption(QStringList() << "c" <<"config", "The path to the proxy server configuration file. The default is /etc/nymea-remoteproxy/nymea-remoteproxy.conf", "configuration");
|
||||
configOption.setDefaultValue("/etc/nymea-remoteproxy/nymea-remoteproxy.conf");
|
||||
parser.addOption(configOption);
|
||||
|
||||
QCommandLineOption verboseOption(QStringList() << "v" << "verbose", "Print more verbose.");
|
||||
parser.addOption(verboseOption);
|
||||
|
||||
parser.process(application);
|
||||
|
||||
// Create a default configuration
|
||||
ProxyConfiguration *configuration = new ProxyConfiguration(nullptr);
|
||||
if (parser.isSet(configOption)) {
|
||||
qCDebug(dcApplication()) << "Loading configuration file from" << parser.value(configOption);
|
||||
if (!configuration->loadConfiguration(parser.value(configOption))) {
|
||||
qCCritical(dcApplication()) << "Invalid configuration file passed" << parser.value(configOption);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (parser.isSet(verboseOption)) {
|
||||
s_loggingFilters["Debug"] = true;
|
||||
s_loggingFilters["WebSocketServerTraffic"] = true;
|
||||
@ -144,84 +147,62 @@ int main(int argc, char *argv[])
|
||||
|
||||
QLoggingCategory::installFilter(loggingCategoryFilter);
|
||||
|
||||
// Open the logfile, if any specified
|
||||
if (parser.isSet(logfileOption)) {
|
||||
QFileInfo fi(parser.value(logfileOption));
|
||||
QDir logDir(fi.absolutePath());
|
||||
if (!logDir.exists() && !logDir.mkpath(logDir.absolutePath())) {
|
||||
qCCritical(dcApplication()) << "Error opening log file" << parser.value(logfileOption);
|
||||
return 1;
|
||||
}
|
||||
s_logFile.setFileName(parser.value(logfileOption));
|
||||
if (!s_logFile.open(QFile::WriteOnly | QFile::Append)) {
|
||||
qCCritical(dcApplication()) << "Error opening log file" << parser.value(logfileOption);
|
||||
return 1;
|
||||
}
|
||||
s_loggingEnabled = true;
|
||||
}
|
||||
|
||||
// Proxy server host address
|
||||
QHostAddress serverHostAddress = QHostAddress(parser.value(serverOption));
|
||||
if (serverHostAddress.isNull()) {
|
||||
qCCritical(dcApplication()) << "Invalid hostaddress for the proxy server:" << parser.value(serverOption);
|
||||
// Verify webserver configuration
|
||||
if (configuration->webSocketServerHost().isNull()) {
|
||||
qCCritical(dcApplication()) << "Invalid web socket host address passed.";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Port
|
||||
bool ok = false;
|
||||
uint port = parser.value(portOption).toUInt(&ok);
|
||||
if (!ok) {
|
||||
qCCritical(dcApplication()) << "Invalid port value:" << parser.value(portOption);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (port > 65535) {
|
||||
qCCritical(dcApplication()) << "Port value is out of range:" << parser.value(portOption);
|
||||
// Verify tcp server configuration
|
||||
if (configuration->tcpServerHost().isNull()) {
|
||||
qCCritical(dcApplication()) << "Invalid TCP server host address passed.";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// SSL certificate
|
||||
QSslConfiguration sslConfiguration;
|
||||
if (parser.isSet(certOption)) {
|
||||
// Load certificate
|
||||
QFile certFile(parser.value(certOption));
|
||||
if (!certFile.open(QIODevice::ReadOnly)) {
|
||||
qCCritical(dcApplication()) << "Could not open certificate file:" << parser.value(certOption) << certFile.errorString();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
QSslCertificate certificate(&certFile, QSsl::Pem);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate" << parser.value(certOption);
|
||||
certFile.close();
|
||||
|
||||
// Create SSL configuration
|
||||
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
sslConfiguration.setLocalCertificate(certificate);
|
||||
sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
// Load certificate
|
||||
QFile certFile(configuration->sslCertificateFileName());
|
||||
if (!certFile.open(QIODevice::ReadOnly)) {
|
||||
qCCritical(dcApplication()) << "Could not open certificate file" << configuration->sslCertificateFileName() << certFile.errorString();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
QSslCertificate certificate(&certFile, QSsl::Pem);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate" << configuration->sslCertificateFileName();
|
||||
certFile.close();
|
||||
|
||||
// Create SSL configuration
|
||||
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
|
||||
sslConfiguration.setLocalCertificate(certificate);
|
||||
sslConfiguration.setProtocol(QSsl::TlsV1_2OrLater);
|
||||
|
||||
// SSL key
|
||||
if (parser.isSet(certKeyOption)) {
|
||||
QFile certKeyFile(parser.value(certKeyOption));
|
||||
if (!certKeyFile.open(QIODevice::ReadOnly)) {
|
||||
qCCritical(dcApplication()) << "Could not open certificate key file:" << parser.value(certKeyOption) << certKeyFile.errorString();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
QSslKey sslKey(&certKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate key" << parser.value(certKeyOption);
|
||||
certKeyFile.close();
|
||||
sslConfiguration.setPrivateKey(sslKey);
|
||||
QFile certKeyFile(configuration->sslCertificateKeyFileName());
|
||||
if (!certKeyFile.open(QIODevice::ReadOnly)) {
|
||||
qCCritical(dcApplication()) << "Could not open certificate key file:" << configuration->sslCertificateKeyFileName() << certKeyFile.errorString();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
QSslKey sslKey(&certKeyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
|
||||
qCDebug(dcApplication()) << "Loaded successfully certificate key" << configuration->sslCertificateKeyFileName();
|
||||
certKeyFile.close();
|
||||
sslConfiguration.setPrivateKey(sslKey);
|
||||
|
||||
if (sslConfiguration.isNull()) {
|
||||
qCCritical(dcApplication()) << "No SSL configuration specified. The server does not suppoert insecure connections.";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
qCDebug(dcApplication()) << "==============================================";
|
||||
if (parser.isSet(developmentOption)) {
|
||||
qCWarning(dcApplication()) << "##########################################################";
|
||||
qCWarning(dcApplication()) << "# DEVELOPMENT MODE #";
|
||||
qCWarning(dcApplication()) << "##########################################################";
|
||||
}
|
||||
|
||||
qCDebug(dcApplication()) << "==========================================================";
|
||||
qCDebug(dcApplication()) << "Starting" << application.applicationName() << application.applicationVersion();
|
||||
qCDebug(dcApplication()) << "==============================================";
|
||||
qCDebug(dcApplication()) << "==========================================================";
|
||||
|
||||
if (s_loggingEnabled)
|
||||
qCDebug(dcApplication()) << "Logging enabled. Writing logs to" << s_logFile.fileName();
|
||||
@ -230,10 +211,11 @@ int main(int argc, char *argv[])
|
||||
AwsAuthenticator *authenticator = new AwsAuthenticator(nullptr);
|
||||
|
||||
// Configure and start the engines
|
||||
Engine::instance()->setAuthenticator(authenticator);
|
||||
Engine::instance()->setWebSocketServerHostAddress(serverHostAddress);
|
||||
Engine::instance()->setWebSocketServerPort(static_cast<quint16>(port));
|
||||
Engine::instance()->setConfiguration(configuration);
|
||||
Engine::instance()->setDeveloperModeEnabled(parser.isSet(developmentOption));
|
||||
Engine::instance()->setSslConfiguration(sslConfiguration);
|
||||
Engine::instance()->setAuthenticator(authenticator);
|
||||
|
||||
Engine::instance()->start();
|
||||
|
||||
return application.exec();
|
||||
|
||||
@ -13,6 +13,8 @@
|
||||
RemoteProxyTests::RemoteProxyTests(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
m_configuration = new ProxyConfiguration(this);
|
||||
|
||||
QFile certificateFile(":/test-certificate.crt");
|
||||
if (!certificateFile.open(QIODevice::ReadOnly)) {
|
||||
qWarning() << "Could not open resource file" << certificateFile.fileName();
|
||||
@ -72,11 +74,10 @@ void RemoteProxyTests::startEngine()
|
||||
if (!Engine::exists()) {
|
||||
QString serverName = "nymea-remoteproxy-testserver";
|
||||
Engine::instance()->setAuthenticator(m_authenticator);
|
||||
Engine::instance()->setAuthenticationServerUrl(QUrl("https://localhost"));
|
||||
Engine::instance()->setServerName(serverName);
|
||||
Engine::instance()->setWebSocketServerPort(m_port);
|
||||
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
|
||||
Engine::instance()->setConfiguration(m_configuration);
|
||||
Engine::instance()->setSslConfiguration(m_sslConfiguration);
|
||||
Engine::instance()->setDeveloperModeEnabled(true);
|
||||
|
||||
QVERIFY(Engine::exists());
|
||||
QVERIFY(Engine::instance()->serverName() == serverName);
|
||||
@ -89,6 +90,8 @@ void RemoteProxyTests::startServer()
|
||||
|
||||
if (!Engine::instance()->running()) {
|
||||
QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged);
|
||||
Engine::instance()->setConfiguration(m_configuration);
|
||||
Engine::instance()->setDeveloperModeEnabled(true);
|
||||
Engine::instance()->start();
|
||||
runningSpy.wait();
|
||||
QVERIFY(runningSpy.count() == 1);
|
||||
@ -217,9 +220,8 @@ void RemoteProxyTests::webserverConnectionBlocked()
|
||||
dummyServer.listen(QHostAddress::LocalHost, m_port);
|
||||
|
||||
// Start proxy webserver
|
||||
Engine::instance()->setWebSocketServerPort(m_port);
|
||||
Engine::instance()->setConfiguration(m_configuration);
|
||||
Engine::instance()->setAuthenticator(m_authenticator);
|
||||
Engine::instance()->setWebSocketServerHostAddress(QHostAddress::LocalHost);
|
||||
Engine::instance()->setSslConfiguration(m_sslConfiguration);
|
||||
|
||||
QSignalSpy runningSpy(Engine::instance(), &Engine::runningChanged);
|
||||
@ -324,7 +326,7 @@ void RemoteProxyTests::authenticate_data()
|
||||
<< 100 << Authenticator::AuthenticationErrorAuthenticationFailed;
|
||||
|
||||
QTest::newRow("not responding") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 200 << Authenticator::AuthenticationErrorAuthenticationServerNotResponding;
|
||||
<< 200 << Authenticator::AuthenticationErrorProxyError;
|
||||
|
||||
QTest::newRow("aborted") << QUuid::createUuid().toString() << "Testclient, hello form the test!" << m_testToken
|
||||
<< 100 << Authenticator::AuthenticationErrorAborted;
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "jsonrpc/jsontypes.h"
|
||||
#include "mockauthenticator.h"
|
||||
#include "proxyconfiguration.h"
|
||||
#include "remoteproxyconnection.h"
|
||||
|
||||
using namespace remoteproxy;
|
||||
@ -24,8 +25,11 @@ public:
|
||||
explicit RemoteProxyTests(QObject *parent = nullptr);
|
||||
|
||||
private:
|
||||
ProxyConfiguration *m_configuration = nullptr;
|
||||
|
||||
quint16 m_port = 1212;
|
||||
QHostAddress m_serverAddress = QHostAddress::LocalHost;
|
||||
|
||||
QSslConfiguration m_sslConfiguration;
|
||||
MockAuthenticator *m_authenticator = nullptr;
|
||||
QString m_testToken;
|
||||
|
||||
Reference in New Issue
Block a user